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
28 namespace OHOS {
29 namespace Rosen {
30 namespace {
31 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayDumper"};
32
33 constexpr int SCREEN_NAME_MAX_LENGTH = 20;
34 const std::string ARG_DUMP_HELP = "-h";
35 const std::string ARG_DUMP_ALL = "-a";
36 const std::string ARG_DUMP_SCREEN = "-s";
37 const std::string ARG_DUMP_DISPLAY = "-d";
38 }
39
DisplayDumper(const sptr<AbstractDisplayController> & abstractDisplayController,const sptr<AbstractScreenController> & abstractScreenController,std::recursive_mutex & mutex)40 DisplayDumper::DisplayDumper(const sptr<AbstractDisplayController>& abstractDisplayController,
41 const sptr<AbstractScreenController>& abstractScreenController, std::recursive_mutex& mutex)
42 : abstractDisplayController_(abstractDisplayController), abstractScreenController_(abstractScreenController),
43 mutex_(mutex)
44 {
45 }
46
Dump(int fd,const std::vector<std::u16string> & args) const47 DMError DisplayDumper::Dump(int fd, const std::vector<std::u16string>& args) const
48 {
49 WLOGFI("Dump begin fd: %{public}d", fd);
50 if (fd < 0) {
51 return DMError::DM_ERROR_INVALID_PARAM;
52 }
53 (void) signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE crash
54 UniqueFd ufd = UniqueFd(fd); // auto close
55 fd = ufd.Get();
56 std::vector<std::string> params;
57 for (auto& arg : args) {
58 params.emplace_back(Str16ToStr8(arg));
59 }
60
61 std::string dumpInfo;
62 if (params.empty()) {
63 ShowHelpInfo(dumpInfo);
64 } else if (params.size() == 1 && params[0] == ARG_DUMP_HELP) { // 1: params num
65 ShowHelpInfo(dumpInfo);
66 } else {
67 DMError errCode = DumpInfo(params, dumpInfo);
68 if (errCode != DMError::DM_OK) {
69 ShowIllegalArgsInfo(dumpInfo, errCode);
70 }
71 }
72 int ret = dprintf(fd, "%s\n", dumpInfo.c_str());
73 if (ret < 0) {
74 WLOGFE("dprintf error");
75 return DMError::DM_ERROR_UNKNOWN;
76 }
77 WLOGFI("Dump end");
78 return DMError::DM_OK;
79 }
80
ShowHelpInfo(std::string & dumpInfo) const81 void DisplayDumper::ShowHelpInfo(std::string& dumpInfo) const
82 {
83 dumpInfo.append("Usage:\n")
84 .append(" -h ")
85 .append("|help text for the tool\n")
86 .append(" -s -a ")
87 .append("|dump all screen information in the system\n")
88 .append(" -d -a ")
89 .append("|dump all display information in the system\n")
90 .append(" -s {screen id} ")
91 .append("|dump specified screen information\n")
92 .append(" -d {display id} ")
93 .append("|dump specified display information\n");
94 }
95
ShowIllegalArgsInfo(std::string & dumpInfo,DMError errCode) const96 void DisplayDumper::ShowIllegalArgsInfo(std::string& dumpInfo, DMError errCode) const
97 {
98 switch (errCode) {
99 case DMError::DM_ERROR_INVALID_PARAM:
100 dumpInfo.append("The arguments are illegal and you can enter '-h' for help.");
101 break;
102 case DMError::DM_ERROR_NULLPTR:
103 dumpInfo.append("The screen or display is invalid, ")
104 .append("you can enter '-s -a' or '-d -a' to get valid screen or display id.");
105 break;
106 default:
107 break;
108 }
109 }
110
DumpInfo(const std::vector<std::string> & args,std::string & dumpInfo) const111 DMError DisplayDumper::DumpInfo(const std::vector<std::string>& args, std::string& dumpInfo) const
112 {
113 if (args.size() != 2) { // 2: params num
114 return DMError::DM_ERROR_INVALID_PARAM;
115 }
116
117 if (args[0] == ARG_DUMP_SCREEN && args[1] == ARG_DUMP_ALL) {
118 return DumpAllScreenInfo(dumpInfo);
119 } else if (args[0] == ARG_DUMP_DISPLAY && args[1] == ARG_DUMP_ALL) {
120 return DumpAllDisplayInfo(dumpInfo);
121 } else if (args[0] == ARG_DUMP_SCREEN && IsValidDigitString(args[1])) {
122 ScreenId screenId = std::stoull(args[1]);
123 return DumpSpecifiedScreenInfo(screenId, dumpInfo);
124 } else if (args[0] == ARG_DUMP_DISPLAY && IsValidDigitString(args[1])) {
125 DisplayId displayId = std::stoull(args[1]);
126 return DumpSpecifiedDisplayInfo(displayId, dumpInfo);
127 } else {
128 return DMError::DM_ERROR_INVALID_PARAM;
129 }
130 }
131
DumpAllScreenInfo(std::string & dumpInfo) const132 DMError DisplayDumper::DumpAllScreenInfo(std::string& dumpInfo) const
133 {
134 std::map<ScreenId, sptr<AbstractScreenGroup>> screenGroups;
135 std::vector<ScreenId> screenIds = abstractScreenController_->GetAllScreenIds();
136 std::ostringstream oss;
137 oss << "--------------------------------------Free Screen"
138 << "--------------------------------------"
139 << std::endl;
140 oss << "ScreenName Type IsGroup DmsId RsId ActiveIdx VPR Rotation Orientation "
141 << "RequestOrientation NodeId IsMirrored MirrorNodeId"
142 << std::endl;
143 std::lock_guard<std::recursive_mutex> lock(mutex_);
144 for (ScreenId screenId : screenIds) {
145 auto screen = abstractScreenController_->GetAbstractScreen(screenId);
146 if (screen == nullptr) {
147 WLOGFE("screen is null");
148 return DMError::DM_ERROR_NULLPTR;
149 }
150 if (SCREEN_ID_INVALID == screen->groupDmsId_ || screen->isScreenGroup_) {
151 GetScreenInfo(screen, oss);
152 }
153 if (screen->isScreenGroup_) {
154 auto screenGroup = abstractScreenController_->GetAbstractScreenGroup(screenId);
155 screenGroups.insert(std::make_pair(screenId, screenGroup));
156 }
157 }
158 oss << "total screen num: " << screenIds.size() << std::endl;
159 dumpInfo.append(oss.str());
160 for (auto it = screenGroups.begin(); it != screenGroups.end(); it++) {
161 DMError ret = DumpScreenInfo(it->second, dumpInfo);
162 if (ret != DMError::DM_OK) {
163 return ret;
164 }
165 }
166 return DMError::DM_OK;
167 }
168
DumpScreenInfo(const sptr<AbstractScreenGroup> & screenGroup,std::string & dumpInfo) const169 DMError DisplayDumper::DumpScreenInfo(const sptr<AbstractScreenGroup>& screenGroup, std::string& dumpInfo) const
170 {
171 if (screenGroup == nullptr) {
172 WLOGFE("screenGroup is null");
173 return DMError::DM_ERROR_NULLPTR;
174 }
175 std::ostringstream oss;
176 oss << "-------------------------------------ScreenGroup " << screenGroup->dmsId_
177 << "-------------------------------------"
178 << std::endl;
179 oss << "ScreenName Type IsGroup DmsId RsId "
180 << "ActiveIdx VPR Rotation Orientation "
181 << "RequestOrientation NodeId IsMirrored MirrorNodeId"
182 << std::endl;
183 auto childrenScreen = screenGroup->GetChildren();
184 for (auto screen : childrenScreen) {
185 GetScreenInfo(screen, oss);
186 }
187 dumpInfo.append(oss.str());
188 return DMError::DM_OK;
189 }
190
DumpSpecifiedScreenInfo(ScreenId screenId,std::string & dumpInfo) const191 DMError DisplayDumper::DumpSpecifiedScreenInfo(ScreenId screenId, std::string& dumpInfo) const
192 {
193 auto screen = abstractScreenController_->GetAbstractScreen(screenId);
194 if (screen == nullptr) {
195 WLOGFE("screen is null");
196 return DMError::DM_ERROR_NULLPTR;
197 }
198 const std::string& screenName = screen->name_.size() <= SCREEN_NAME_MAX_LENGTH ?
199 screen->name_ : screen->name_.substr(0, SCREEN_NAME_MAX_LENGTH);
200 std::string isGroup = screen->isScreenGroup_ ? "true" : "false";
201 std::string screenType = TransferTypeToString(screen->type_);
202 std::string isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false";
203 NodeId nodeId = (screen->rsDisplayNode_ == nullptr) ? SCREEN_ID_INVALID : screen->rsDisplayNode_->GetId();
204 std::ostringstream oss;
205 oss << "ScreenName: " << screenName << std::endl;
206 oss << "Type: " << screenType << std::endl;
207 oss << "IsGroup: " << isGroup << std::endl;
208 oss << "DmsId: " << screen->dmsId_ << std::endl;
209 oss << "RsId: " << screen->rsId_ << std::endl;
210 oss << "GroupDmsId: " << screen->groupDmsId_ << std::endl;
211 oss << "ActiveIdx: " << screen->activeIdx_ << std::endl;
212 oss << "VPR: " << screen->virtualPixelRatio_ << std::endl;
213 oss << "Rotation: " << static_cast<uint32_t>(screen->rotation_) << std::endl;
214 oss << "Orientation: " << static_cast<uint32_t>(screen->orientation_) << std::endl;
215 oss << "RequestOrientation: " << static_cast<uint32_t>(screen->screenRequestedOrientation_) << std::endl;
216 oss << "NodeId: " << nodeId << std::endl;
217 oss << "IsMirrored: " << isMirrored << std::endl;
218 oss << "MirrorNodeId: " << screen->rSDisplayNodeConfig_.mirrorNodeId << std::endl;
219 dumpInfo.append(oss.str());
220 return DMError::DM_OK;
221 }
222
DumpAllDisplayInfo(std::string & dumpInfo) const223 DMError DisplayDumper::DumpAllDisplayInfo(std::string& dumpInfo) const
224 {
225 std::vector<DisplayId> displayIds = abstractDisplayController_->GetAllDisplayIds();
226 std::ostringstream oss;
227 oss << "--------------------------------------Display Info"
228 << "--------------------------------------"
229 << std::endl;
230 oss << "DisplayId ScreenId RefreshRate VPR Rotation Orientation FreezeFlag [ x y w h ]"
231 << std::endl;
232 std::lock_guard<std::recursive_mutex> lock(mutex_);
233 for (DisplayId displayId : displayIds) {
234 auto display = abstractDisplayController_->GetAbstractDisplay(displayId);
235 if (display == nullptr) {
236 WLOGFE("display is null");
237 return DMError::DM_ERROR_NULLPTR;
238 }
239 GetDisplayInfo(display, oss);
240 }
241 dumpInfo.append(oss.str());
242 return DMError::DM_OK;
243 }
244
DumpSpecifiedDisplayInfo(DisplayId displayId,std::string & dumpInfo) const245 DMError DisplayDumper::DumpSpecifiedDisplayInfo(DisplayId displayId, std::string& dumpInfo) const
246 {
247 auto display = abstractDisplayController_->GetAbstractDisplay(displayId);
248 if (display == nullptr) {
249 WLOGFE("display is null");
250 return DMError::DM_ERROR_NULLPTR;
251 }
252 std::ostringstream oss;
253 oss << "DisplayId: " << display->GetId() << std::endl;
254 oss << "ScreenId: " << display->GetAbstractScreenId() << std::endl;
255 oss << "RefreshRate: " << display->GetRefreshRate() << std::endl;
256 oss << "VPR: " << display->GetVirtualPixelRatio() << std::endl;
257 oss << "Rotation: " << static_cast<uint32_t>(display->GetRotation()) << std::endl;
258 oss << "Orientation: " << static_cast<uint32_t>(display->GetOrientation()) << std::endl;
259 oss << "FreezeFlag: " << static_cast<uint32_t>(display->GetFreezeFlag()) << std::endl;
260 oss << "DisplayRect: " << "[ "
261 << display->GetOffsetX() << ", " << display->GetOffsetY() << ", "
262 << display->GetWidth() << ", " << display->GetHeight() << " ]" << std::endl;
263 dumpInfo.append(oss.str());
264 return DMError::DM_OK;
265 }
266
IsValidDigitString(const std::string & idStr) const267 bool DisplayDumper::IsValidDigitString(const std::string& idStr) const
268 {
269 if (idStr.empty()) {
270 return false;
271 }
272 for (char ch : idStr) {
273 if ((ch >= '0' && ch <= '9')) {
274 continue;
275 }
276 WLOGFE("invalid id");
277 return false;
278 }
279 return true;
280 }
281
TransferTypeToString(ScreenType type) const282 std::string DisplayDumper::TransferTypeToString(ScreenType type) const
283 {
284 std::string screenType;
285 switch (type) {
286 case ScreenType::REAL:
287 screenType = "REAL";
288 break;
289 case ScreenType::VIRTUAL:
290 screenType = "VIRTUAL";
291 break;
292 default:
293 screenType = "UNDEFINED";
294 break;
295 }
296 return screenType;
297 }
298
GetScreenInfo(const sptr<AbstractScreen> & screen,std::ostringstream & oss) const299 void DisplayDumper::GetScreenInfo(const sptr<AbstractScreen>& screen, std::ostringstream& oss) const
300 {
301 if (screen == nullptr) {
302 WLOGFE("screen is null");
303 return;
304 }
305 const std::string& screenName = screen->name_.size() <= SCREEN_NAME_MAX_LENGTH ?
306 screen->name_ : screen->name_.substr(0, SCREEN_NAME_MAX_LENGTH);
307 std::string isGroup = screen->isScreenGroup_ ? "true" : "false";
308 std::string screenType = TransferTypeToString(screen->type_);
309 std::string isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false";
310 NodeId nodeId = (screen->rsDisplayNode_ == nullptr) ? SCREEN_ID_INVALID : screen->rsDisplayNode_->GetId();
311 // std::setw is used to set the output width and different width values are set to keep the format aligned.
312 oss << std::left << std::setw(21) << screenName
313 << std::left << std::setw(9) << screenType
314 << std::left << std::setw(8) << isGroup
315 << std::left << std::setw(6) << screen->dmsId_
316 << std::left << std::setw(21) << screen->rsId_
317 << std::left << std::setw(10) << screen->activeIdx_
318 << std::left << std::setw(4) << screen->virtualPixelRatio_
319 << std::left << std::setw(9) << static_cast<uint32_t>(screen->rotation_)
320 << std::left << std::setw(12) << static_cast<uint32_t>(screen->orientation_)
321 << std::left << std::setw(19) << static_cast<uint32_t>(screen->screenRequestedOrientation_)
322 << std::left << std::setw(21) << nodeId
323 << std::left << std::setw(11) << isMirrored
324 << std::left << std::setw(13) << screen->rSDisplayNodeConfig_.mirrorNodeId
325 << std::endl;
326 }
327
GetDisplayInfo(const sptr<AbstractDisplay> & display,std::ostringstream & oss) const328 void DisplayDumper::GetDisplayInfo(const sptr<AbstractDisplay>& display, std::ostringstream& oss) const
329 {
330 if (display == nullptr) {
331 WLOGFE("display is null");
332 return;
333 }
334 // std::setw is used to set the output width and different width values are set to keep the format aligned.
335 oss << std::left << std::setw(10) << display->GetId()
336 << std::left << std::setw(9) << display->GetAbstractScreenId()
337 << std::left << std::setw(12) << display->GetRefreshRate()
338 << std::left << std::setw(4) << display->GetVirtualPixelRatio()
339 << std::left << std::setw(9) << static_cast<uint32_t>(display->GetRotation())
340 << std::left << std::setw(12) << static_cast<uint32_t>(display->GetOrientation())
341 << std::left << std::setw(11) << static_cast<uint32_t>(display->GetFreezeFlag())
342 << "[ "
343 << std::left << std::setw(5) << display->GetOffsetX()
344 << std::left << std::setw(5) << display->GetOffsetY()
345 << std::left << std::setw(5) << display->GetWidth()
346 << std::left << std::setw(5) << display->GetHeight()
347 << "]"
348 << std::endl;
349 }
350 }
351 }