1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "display_dumper.h" 17 18#include <cinttypes> 19#include <csignal> 20#include <iomanip> 21#include <map> 22#include <sstream> 23#include <string_ex.h> 24#include <unique_fd.h> 25 26#include "window_manager_hilog.h" 27 28namespace OHOS { 29namespace Rosen { 30namespace { 31constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayDumper"}; 32 33constexpr int SCREEN_NAME_MAX_LENGTH = 20; 34const std::string ARG_DUMP_HELP = "-h"; 35const std::string ARG_DUMP_ALL = "-a"; 36const std::string ARG_DUMP_SCREEN = "-s"; 37const std::string ARG_DUMP_DISPLAY = "-d"; 38// set the output width of screen 39constexpr int W_SCREEN_NAME = 21; 40constexpr int W_SCREEN_TYPE = 9; 41constexpr int W_GROUP_TYPE = 8; 42constexpr int W_DMS_ID = 6; 43constexpr int W_RS_ID = 21; 44constexpr int W_ACTIVE_IDX = 10; 45constexpr int W_VIR_PIXEL_RATIO = 4; 46constexpr int W_SCREEN_ROTATION = 9; 47constexpr int W_ORIENTATION = 12; 48constexpr int W_REQUESTED_ORIENTATION = 19; 49constexpr int W_NODE_ID = 21; 50constexpr int W_MIRROR_TYPE = 11; 51constexpr int W_MIRROR_NODE_ID = 13; 52// set the output width of display 53constexpr int W_DISPLAY_ID = 10; 54constexpr int W_ABSTR_SCREEN_ID = 9; 55constexpr int W_REFRESH_RATE = 12; 56constexpr int W_DISPLAY_ROTATION = 9; 57constexpr int W_DISPLAY_ORIENTATION = 18; 58constexpr int W_DISPLAY_FREEZE_FLAG = 11; 59constexpr int W_DISPLAY_OFFSET_X = 5; 60constexpr int W_DISPLAY_OFFSET_Y = 5; 61constexpr int W_DISPLAY_WIDTH = 5; 62constexpr int W_DISPLAY_HEITHT = 5; 63} 64 65DisplayDumper::DisplayDumper(const sptr<AbstractDisplayController>& abstractDisplayController, 66 const sptr<AbstractScreenController>& abstractScreenController, std::recursive_mutex& mutex) 67 : abstractDisplayController_(abstractDisplayController), abstractScreenController_(abstractScreenController), 68 mutex_(mutex) 69{ 70} 71 72DMError DisplayDumper::Dump(int fd, const std::vector<std::u16string>& args) const 73{ 74 WLOGFI("Dump begin fd: %{public}d", fd); 75 if (fd < 0) { 76 return DMError::DM_ERROR_INVALID_PARAM; 77 } 78 (void) signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE crash 79 UniqueFd ufd = UniqueFd(fd); // auto close 80 fd = ufd.Get(); 81 std::vector<std::string> params; 82 for (auto& arg : args) { 83 params.emplace_back(Str16ToStr8(arg)); 84 } 85 86 std::string dumpInfo; 87 if (params.empty()) { 88 ShowHelpInfo(dumpInfo); 89 } else if (params.size() == 1 && params[0] == ARG_DUMP_HELP) { // 1: params num 90 ShowHelpInfo(dumpInfo); 91 } else { 92 DMError errCode = DumpInfo(params, dumpInfo); 93 if (errCode != DMError::DM_OK) { 94 ShowIllegalArgsInfo(dumpInfo, errCode); 95 } 96 } 97 int ret = dprintf(fd, "%s\n", dumpInfo.c_str()); 98 if (ret < 0) { 99 WLOGFE("dprintf error"); 100 return DMError::DM_ERROR_UNKNOWN; 101 } 102 WLOGFI("Dump end"); 103 return DMError::DM_OK; 104} 105 106void DisplayDumper::ShowHelpInfo(std::string& dumpInfo) const 107{ 108 dumpInfo.append("Usage:\n") 109 .append(" -h ") 110 .append("|help text for the tool\n") 111 .append(" -s -a ") 112 .append("|dump all screen information in the system\n") 113 .append(" -d -a ") 114 .append("|dump all display information in the system\n") 115 .append(" -s {screen id} ") 116 .append("|dump specified screen information\n") 117 .append(" -d {display id} ") 118 .append("|dump specified display information\n"); 119} 120 121void DisplayDumper::ShowIllegalArgsInfo(std::string& dumpInfo, DMError errCode) const 122{ 123 switch (errCode) { 124 case DMError::DM_ERROR_INVALID_PARAM: 125 dumpInfo.append("The arguments are illegal and you can enter '-h' for help."); 126 break; 127 case DMError::DM_ERROR_NULLPTR: 128 dumpInfo.append("The screen or display is invalid, ") 129 .append("you can enter '-s -a' or '-d -a' to get valid screen or display id."); 130 break; 131 default: 132 break; 133 } 134} 135 136DMError DisplayDumper::DumpInfo(const std::vector<std::string>& args, std::string& dumpInfo) const 137{ 138 if (args.size() != 2) { // 2: params num 139 return DMError::DM_ERROR_INVALID_PARAM; 140 } 141 142 if (args[0] == ARG_DUMP_SCREEN && args[1] == ARG_DUMP_ALL) { 143 return DumpAllScreenInfo(dumpInfo); 144 } else if (args[0] == ARG_DUMP_DISPLAY && args[1] == ARG_DUMP_ALL) { 145 return DumpAllDisplayInfo(dumpInfo); 146 } else if (args[0] == ARG_DUMP_SCREEN && IsValidDigitString(args[1])) { 147 ScreenId screenId = std::stoull(args[1]); 148 return DumpSpecifiedScreenInfo(screenId, dumpInfo); 149 } else if (args[0] == ARG_DUMP_DISPLAY && IsValidDigitString(args[1])) { 150 DisplayId displayId = std::stoull(args[1]); 151 return DumpSpecifiedDisplayInfo(displayId, dumpInfo); 152 } else { 153 return DMError::DM_ERROR_INVALID_PARAM; 154 } 155} 156 157DMError DisplayDumper::DumpAllScreenInfo(std::string& dumpInfo) const 158{ 159 std::map<ScreenId, sptr<AbstractScreenGroup>> screenGroups; 160 std::vector<ScreenId> screenIds = abstractScreenController_->GetAllScreenIds(); 161 std::ostringstream oss; 162 oss << "--------------------------------------Free Screen" 163 << "--------------------------------------" 164 << std::endl; 165 oss << "ScreenName Type IsGroup DmsId RsId ActiveIdx VPR Rotation Orientation " 166 << "RequestOrientation NodeId IsMirrored MirrorNodeId" 167 << std::endl; 168 std::lock_guard<std::recursive_mutex> lock(mutex_); 169 for (ScreenId screenId : screenIds) { 170 auto screen = abstractScreenController_->GetAbstractScreen(screenId); 171 if (screen == nullptr) { 172 WLOGFE("screen is null"); 173 return DMError::DM_ERROR_NULLPTR; 174 } 175 if (SCREEN_ID_INVALID == screen->groupDmsId_ || screen->isScreenGroup_) { 176 GetScreenInfo(screen, oss); 177 } 178 if (screen->isScreenGroup_) { 179 auto screenGroup = abstractScreenController_->GetAbstractScreenGroup(screenId); 180 screenGroups.insert(std::make_pair(screenId, screenGroup)); 181 } 182 } 183 oss << "total screen num: " << screenIds.size() << std::endl; 184 dumpInfo.append(oss.str()); 185 for (auto it = screenGroups.begin(); it != screenGroups.end(); it++) { 186 DMError ret = DumpScreenInfo(it->second, dumpInfo); 187 if (ret != DMError::DM_OK) { 188 return ret; 189 } 190 } 191 return DMError::DM_OK; 192} 193 194DMError DisplayDumper::DumpScreenInfo(const sptr<AbstractScreenGroup>& screenGroup, std::string& dumpInfo) const 195{ 196 if (screenGroup == nullptr) { 197 WLOGFE("screenGroup is null"); 198 return DMError::DM_ERROR_NULLPTR; 199 } 200 std::ostringstream oss; 201 oss << "-------------------------------------ScreenGroup " << screenGroup->dmsId_ 202 << "-------------------------------------" 203 << std::endl; 204 oss << "ScreenName Type IsGroup DmsId RsId " 205 << "ActiveIdx VPR Rotation Orientation " 206 << "RequestOrientation NodeId IsMirrored MirrorNodeId" 207 << std::endl; 208 auto childrenScreen = screenGroup->GetChildren(); 209 for (auto screen : childrenScreen) { 210 GetScreenInfo(screen, oss); 211 } 212 dumpInfo.append(oss.str()); 213 return DMError::DM_OK; 214} 215 216DMError DisplayDumper::DumpSpecifiedScreenInfo(ScreenId screenId, std::string& dumpInfo) const 217{ 218 auto screen = abstractScreenController_->GetAbstractScreen(screenId); 219 if (screen == nullptr) { 220 WLOGFE("screen is null"); 221 return DMError::DM_ERROR_NULLPTR; 222 } 223 224 const std::string& name = screen->GetScreenName(); 225 const std::string& screenName = name.size() <= SCREEN_NAME_MAX_LENGTH ? 226 name : name.substr(0, SCREEN_NAME_MAX_LENGTH); 227 std::string isGroup = screen->isScreenGroup_ ? "true" : "false"; 228 std::string screenType = TransferTypeToString(screen->type_); 229 std::string isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false"; 230 NodeId nodeId = (screen->rsDisplayNode_ == nullptr) ? SCREEN_ID_INVALID : screen->rsDisplayNode_->GetId(); 231 std::ostringstream oss; 232 oss << "ScreenName: " << screenName << std::endl; 233 oss << "Type: " << screenType << std::endl; 234 oss << "IsGroup: " << isGroup << std::endl; 235 oss << "DmsId: " << screen->dmsId_ << std::endl; 236 oss << "RsId: " << screen->rsId_ << std::endl; 237 oss << "GroupDmsId: " << screen->groupDmsId_ << std::endl; 238 oss << "ActiveIdx: " << screen->activeIdx_ << std::endl; 239 oss << "VPR: " << screen->virtualPixelRatio_ << std::endl; 240 oss << "Rotation: " << static_cast<uint32_t>(screen->rotation_) << std::endl; 241 oss << "Orientation: " << static_cast<uint32_t>(screen->orientation_) << std::endl; 242 oss << "RequestOrientation: " << static_cast<uint32_t>(screen->screenRequestedOrientation_) << std::endl; 243 oss << "NodeId: " << nodeId << std::endl; 244 oss << "IsMirrored: " << isMirrored << std::endl; 245 oss << "MirrorNodeId: " << screen->rSDisplayNodeConfig_.mirrorNodeId << std::endl; 246 dumpInfo.append(oss.str()); 247 return DMError::DM_OK; 248} 249 250DMError DisplayDumper::DumpAllDisplayInfo(std::string& dumpInfo) const 251{ 252 std::vector<DisplayId> displayIds = abstractDisplayController_->GetAllDisplayIds(); 253 std::ostringstream oss; 254 oss << "--------------------------------------Display Info" 255 << "--------------------------------------" 256 << std::endl; 257 oss << "DisplayId ScreenId RefreshRate VPR Rotation Orientation DisplayOrientation FreezeFlag [ x y w h ]" 258 << std::endl; 259 std::lock_guard<std::recursive_mutex> lock(mutex_); 260 for (DisplayId displayId : displayIds) { 261 auto display = abstractDisplayController_->GetAbstractDisplay(displayId); 262 if (display == nullptr) { 263 WLOGFE("display is null"); 264 return DMError::DM_ERROR_NULLPTR; 265 } 266 GetDisplayInfo(display, oss); 267 } 268 dumpInfo.append(oss.str()); 269 return DMError::DM_OK; 270} 271 272DMError DisplayDumper::DumpSpecifiedDisplayInfo(DisplayId displayId, std::string& dumpInfo) const 273{ 274 auto display = abstractDisplayController_->GetAbstractDisplay(displayId); 275 if (display == nullptr) { 276 WLOGFE("display is null"); 277 return DMError::DM_ERROR_NULLPTR; 278 } 279 std::ostringstream oss; 280 oss << "DisplayId: " << display->GetId() << std::endl; 281 oss << "ScreenId: " << display->GetAbstractScreenId() << std::endl; 282 oss << "RefreshRate: " << display->GetRefreshRate() << std::endl; 283 oss << "VPR: " << display->GetVirtualPixelRatio() << std::endl; 284 oss << "Rotation: " << static_cast<uint32_t>(display->GetRotation()) << std::endl; 285 oss << "Orientation: " << static_cast<uint32_t>(display->GetOrientation()) << std::endl; 286 oss << "DisplayOrientation: " << static_cast<uint32_t>(display->GetDisplayOrientation()) << std::endl; 287 oss << "FreezeFlag: " << static_cast<uint32_t>(display->GetFreezeFlag()) << std::endl; 288 oss << "DisplayRect: " << "[ " 289 << display->GetOffsetX() << ", " << display->GetOffsetY() << ", " 290 << display->GetWidth() << ", " << display->GetHeight() << " ]" << std::endl; 291 dumpInfo.append(oss.str()); 292 return DMError::DM_OK; 293} 294 295bool DisplayDumper::IsValidDigitString(const std::string& idStr) const 296{ 297 if (idStr.empty()) { 298 return false; 299 } 300 for (char ch : idStr) { 301 if ((ch >= '0' && ch <= '9')) { 302 continue; 303 } 304 WLOGFE("invalid id"); 305 return false; 306 } 307 return true; 308} 309 310std::string DisplayDumper::TransferTypeToString(ScreenType type) const 311{ 312 std::string screenType; 313 switch (type) { 314 case ScreenType::REAL: 315 screenType = "REAL"; 316 break; 317 case ScreenType::VIRTUAL: 318 screenType = "VIRTUAL"; 319 break; 320 default: 321 screenType = "UNDEFINED"; 322 break; 323 } 324 return screenType; 325} 326 327void DisplayDumper::GetScreenInfo(const sptr<AbstractScreen>& screen, std::ostringstream& oss) const 328{ 329 if (screen == nullptr) { 330 WLOGFE("screen is null"); 331 return; 332 } 333 334 const std::string& name = screen->GetScreenName(); 335 const std::string& screenName = name.size() <= SCREEN_NAME_MAX_LENGTH ? 336 name : name.substr(0, SCREEN_NAME_MAX_LENGTH); 337 std::string isGroup = screen->isScreenGroup_ ? "true" : "false"; 338 std::string screenType = TransferTypeToString(screen->type_); 339 std::string isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false"; 340 NodeId nodeId = (screen->rsDisplayNode_ == nullptr) ? SCREEN_ID_INVALID : screen->rsDisplayNode_->GetId(); 341 // std::setw is used to set the output width and different width values are set to keep the format aligned. 342 oss << std::left << std::setw(W_SCREEN_NAME) << screenName 343 << std::left << std::setw(W_SCREEN_TYPE) << screenType 344 << std::left << std::setw(W_GROUP_TYPE) << isGroup 345 << std::left << std::setw(W_DMS_ID) << screen->dmsId_ 346 << std::left << std::setw(W_RS_ID) << screen->rsId_ 347 << std::left << std::setw(W_ACTIVE_IDX) << screen->activeIdx_ 348 << std::left << std::setw(W_VIR_PIXEL_RATIO) << screen->virtualPixelRatio_ 349 << std::left << std::setw(W_SCREEN_ROTATION) << static_cast<uint32_t>(screen->rotation_) 350 << std::left << std::setw(W_ORIENTATION) << static_cast<uint32_t>(screen->orientation_) 351 << std::left << std::setw(W_REQUESTED_ORIENTATION) << static_cast<uint32_t>(screen->screenRequestedOrientation_) 352 << std::left << std::setw(W_NODE_ID) << nodeId 353 << std::left << std::setw(W_MIRROR_TYPE) << isMirrored 354 << std::left << std::setw(W_MIRROR_NODE_ID) << screen->rSDisplayNodeConfig_.mirrorNodeId 355 << std::endl; 356} 357 358void DisplayDumper::GetDisplayInfo(const sptr<AbstractDisplay>& display, std::ostringstream& oss) const 359{ 360 if (display == nullptr) { 361 WLOGFE("display is null"); 362 return; 363 } 364 // std::setw is used to set the output width and different width values are set to keep the format aligned. 365 oss << std::left << std::setw(W_DISPLAY_ID) << display->GetId() 366 << std::left << std::setw(W_ABSTR_SCREEN_ID) << display->GetAbstractScreenId() 367 << std::left << std::setw(W_REFRESH_RATE) << display->GetRefreshRate() 368 << std::left << std::setw(W_VIR_PIXEL_RATIO) << display->GetVirtualPixelRatio() 369 << std::left << std::setw(W_DISPLAY_ROTATION) << static_cast<uint32_t>(display->GetRotation()) 370 << std::left << std::setw(W_ORIENTATION) << static_cast<uint32_t>(display->GetOrientation()) 371 << std::left << std::setw(W_DISPLAY_ORIENTATION) << static_cast<uint32_t>(display->GetDisplayOrientation()) 372 << std::left << std::setw(W_DISPLAY_FREEZE_FLAG) << static_cast<uint32_t>(display->GetFreezeFlag()) 373 << "[ " 374 << std::left << std::setw(W_DISPLAY_OFFSET_X) << display->GetOffsetX() 375 << std::left << std::setw(W_DISPLAY_OFFSET_Y) << display->GetOffsetY() 376 << std::left << std::setw(W_DISPLAY_WIDTH) << display->GetWidth() 377 << std::left << std::setw(W_DISPLAY_HEITHT) << display->GetHeight() 378 << "]" 379 << std::endl; 380} 381} 382}