• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "window_dumper.h"
17 
18 #include <cinttypes>
19 #include <csignal>
20 #include <iomanip>
21 #include <map>
22 #include <sstream>
23 
24 #include "display_manager_service_inner.h"
25 #include "string_ex.h"
26 #include "unique_fd.h"
27 #include "window_manager_hilog.h"
28 #include "window_manager_service.h"
29 #include "wm_common.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace {
34     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowDumper"};
35 
36     constexpr int WINDOW_NAME_MAX_LENGTH = 20;
37     const std::string ARG_DUMP_HELP = "-h";
38     const std::string ARG_DUMP_ALL = "-a";
39     const std::string ARG_DUMP_WINDOW = "-w";
40 }
41 
Dump(int fd,const std::vector<std::u16string> & args)42 WMError WindowDumper::Dump(int fd, const std::vector<std::u16string>& args)
43 {
44     WLOGFI("Dump begin fd: %{public}d", fd);
45     if (fd < 0) {
46         return WMError::WM_ERROR_INVALID_PARAM;
47     }
48     (void) signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE crash
49     UniqueFd ufd = UniqueFd(fd); // auto close
50     fd = ufd.Get();
51     std::vector<std::string> params;
52     for (auto& arg : args) {
53         params.emplace_back(Str16ToStr8(arg));
54     }
55 
56     std::string dumpInfo;
57     if (params.empty()) {
58         ShowHelpInfo(dumpInfo);
59     } else if (params.size() == 1 && params[0] == ARG_DUMP_HELP) { // 1: params num
60         ShowHelpInfo(dumpInfo);
61     } else {
62         WMError errCode = DumpWindowInfo(params, dumpInfo);
63         if (errCode != WMError::WM_OK) {
64             ShowIllegalArgsInfo(dumpInfo, errCode);
65         }
66     }
67     int ret = dprintf(fd, "%s\n", dumpInfo.c_str());
68     if (ret < 0) {
69         WLOGFE("dprintf error");
70         return WMError::WM_ERROR_INVALID_OPERATION;
71     }
72     WLOGFI("Dump end");
73     return WMError::WM_OK;
74 }
75 
DumpScreenGroupWindowInfo(ScreenId screenGroupId,const sptr<WindowNodeContainer> & windowNodeContainer,std::string & dumpInfo)76 WMError WindowDumper::DumpScreenGroupWindowInfo(ScreenId screenGroupId,
77     const sptr<WindowNodeContainer>& windowNodeContainer, std::string& dumpInfo)
78 {
79     if (windowNodeContainer == nullptr) {
80         WLOGFE("windowNodeContainer is null");
81         return WMError::WM_ERROR_NULLPTR;
82     }
83     std::ostringstream oss;
84     oss << "-------------------------------------ScreenGroup " << screenGroupId
85         << "-------------------------------------"
86         << std::endl;
87     oss << "WindowName           DisplayId Pid     WinId Type Mode Flag ZOrd Orientation [ x    y    w    h    ]"
88         << std::endl;
89     std::vector<sptr<WindowNode>> windowNodes;
90     windowNodeContainer->TraverseContainer(windowNodes);
91     int zOrder = static_cast<int32_t>(windowNodes.size());
92     windowRoot_->GetBackgroundNodesByScreenId(screenGroupId, windowNodes);
93     for (auto& windowNode : windowNodes) {
94         if (zOrder < 0) {
95             zOrder = 0;
96         } else if (zOrder == 0) {
97             oss << "---------------------------------------------------------------------------------------"
98                 << std::endl;
99         }
100         if (windowNode == nullptr) {
101             --zOrder;
102             break;
103         }
104         Rect rect = windowNode->GetWindowRect();
105         const std::string& windowName = windowNode->GetWindowName().size() <= WINDOW_NAME_MAX_LENGTH ?
106             windowNode->GetWindowName() : windowNode->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH);
107         // std::setw is used to set the output width and different width values are set to keep the format aligned.
108         oss << std::left << std::setw(21) << windowName
109             << std::left << std::setw(10) << windowNode->GetDisplayId()
110             << std::left << std::setw(8) << windowNode->GetCallingPid()
111             << std::left << std::setw(6) << windowNode->GetWindowId()
112             << std::left << std::setw(5) << static_cast<uint32_t>(windowNode->GetWindowType())
113             << std::left << std::setw(5) << static_cast<uint32_t>(windowNode->GetWindowMode())
114             << std::left << std::setw(5) << windowNode->GetWindowFlags()
115             << std::left << std::setw(5) << --zOrder
116             << std::left << std::setw(12) << static_cast<uint32_t>(windowNode->GetRequestedOrientation())
117             << "[ "
118             << std::left << std::setw(5) << rect.posX_
119             << std::left << std::setw(5) << rect.posY_
120             << std::left << std::setw(5) << rect.width_
121             << std::left << std::setw(5) << rect.height_
122             << "]"
123             << std::endl;
124     }
125     oss << "Focus window: " << windowNodeContainer->GetFocusWindow() << std::endl;
126     oss << "total window num: " << windowRoot_->GetTotalWindowNum()<< std::endl;
127     dumpInfo.append(oss.str());
128     return WMError::WM_OK;
129 }
130 
DumpAllWindowInfo(std::string & dumpInfo)131 WMError WindowDumper::DumpAllWindowInfo(std::string& dumpInfo)
132 {
133     std::map<ScreenId, sptr<WindowNodeContainer>> windowNodeContainers;
134     std::vector<DisplayId> displayIds = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds();
135     for (DisplayId displayId : displayIds) {
136         auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
137         if (!windowNodeContainer) {
138             return WMError::WM_ERROR_NULLPTR;
139         }
140         ScreenId screenGroupId = DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(displayId);
141         if (windowNodeContainers.count(screenGroupId) == 0) {
142             windowNodeContainers.insert(std::make_pair(screenGroupId, windowNodeContainer));
143         }
144     }
145     for (auto it = windowNodeContainers.begin(); it != windowNodeContainers.end(); it++) {
146         WMError ret = DumpScreenGroupWindowInfo(it->first, it->second, dumpInfo);
147         if (ret != WMError::WM_OK) {
148             return ret;
149         }
150     }
151     return WMError::WM_OK;
152 }
153 
IsValidDigitString(const std::string & windowIdStr)154 bool WindowDumper::IsValidDigitString(const std::string& windowIdStr)
155 {
156     if (windowIdStr.empty()) {
157         return false;
158     }
159     for (char ch : windowIdStr) {
160         if ((ch >= '0' && ch <= '9')) {
161             continue;
162         }
163         WLOGFE("invalid window id");
164         return false;
165     }
166     return true;
167 }
168 
DumpSpecifiedWindowInfo(uint32_t windowId,const std::vector<std::string> & params,std::string & dumpInfo)169 WMError WindowDumper::DumpSpecifiedWindowInfo(uint32_t windowId, const std::vector<std::string>& params,
170     std::string& dumpInfo)
171 {
172     auto node = windowRoot_->GetWindowNode(windowId);
173     if (node == nullptr) {
174         WLOGFE("invalid window");
175         return WMError::WM_ERROR_NULLPTR;
176     }
177     Rect rect = node->GetWindowRect();
178     std::string isShown_ = node->startingWindowShown_ ? "true" : "false";
179     std::string isVisible = node->isVisible_ ? "true" : "false";
180     std::ostringstream oss;
181     oss << "WindowName: " << node->GetWindowName()  << std::endl;
182     oss << "DisplayId: " << node->GetDisplayId() << std::endl;
183     oss << "WinId: " << node->GetWindowId() << std::endl;
184     oss << "Pid: " << node->GetCallingPid() << std::endl;
185     oss << "Type: " << static_cast<uint32_t>(node->GetWindowType()) << std::endl;
186     oss << "Mode: " << static_cast<uint32_t>(node->GetWindowMode()) << std::endl;
187     oss << "Flag: " << node->GetWindowFlags() << std::endl;
188     oss << "Orientation: " << static_cast<uint32_t>(node->GetRequestedOrientation()) << std::endl;
189     oss << "IsStartingWindow: " << isShown_ << std::endl;
190     oss << "FirstFrameCallbackCalled: " << node->firstFrameAvaliable_ << std::endl;
191     oss << "IsVisible: " << isVisible << std::endl;
192     oss << "WindowRect: " << "[ "
193         << rect.posX_ << ", " << rect.posY_ << ", " << rect.width_ << ", " << rect.height_
194         << " ]" << std::endl;
195     oss << "TouchHotAreas: ";
196     std::vector<Rect> touchHotAreas;
197     node->GetTouchHotAreas(touchHotAreas);
198     int index = 0;
199     for (const auto& area : touchHotAreas) {
200         oss << "[ " << area.posX_ << ", " << area.posY_ << ", " << area.width_ << ", " << area.height_ << " ]";
201         index++;
202         if (index < static_cast<int32_t>(touchHotAreas.size())) {
203             oss <<", ";
204         }
205     }
206     oss << std::endl;
207     dumpInfo.append(oss.str());
208     if (node->GetWindowToken() != nullptr) {
209         std::vector<std::string> resetParams;
210         resetParams.assign(params.begin() + 2, params.end()); // 2: params num
211         if (resetParams.empty()) {
212             WLOGFI("do not dump ui info");
213             return WMError::WM_OK;
214         }
215         dumpInfoFuture_.ResetLock({});
216         node->GetWindowToken()->DumpInfo(resetParams);
217         auto infos = dumpInfoFuture_.GetResult(2000); // 2000: wait for 2000ms
218         for (auto& info: infos) {
219             dumpInfo.append(info).append("\n");
220         }
221     }
222     return WMError::WM_OK;
223 }
224 
DumpWindowInfo(const std::vector<std::string> & args,std::string & dumpInfo)225 WMError WindowDumper::DumpWindowInfo(const std::vector<std::string>& args, std::string& dumpInfo)
226 {
227     if (args.empty()) {
228         return WMError::WM_ERROR_INVALID_PARAM;
229     }
230     if (args.size() == 1 && args[0] == ARG_DUMP_ALL) { // 1: params num
231         return DumpAllWindowInfo(dumpInfo);
232     } else if (args.size() >= 2 && args[0] == ARG_DUMP_WINDOW && IsValidDigitString(args[1])) { // 2: params num
233         uint32_t windowId = std::stoul(args[1]);
234         return DumpSpecifiedWindowInfo(windowId, args, dumpInfo);
235     } else {
236         return WMError::WM_ERROR_INVALID_PARAM;
237     }
238 }
239 
ShowIllegalArgsInfo(std::string & dumpInfo,WMError errCode)240 void WindowDumper::ShowIllegalArgsInfo(std::string& dumpInfo, WMError errCode)
241 {
242     switch (errCode) {
243         case WMError::WM_ERROR_INVALID_PARAM:
244             dumpInfo.append("The arguments are illegal and you can enter '-h' for help.");
245             break;
246         case WMError::WM_ERROR_NULLPTR:
247             dumpInfo.append("The window is invalid, you can enter '-a' to get valid window id.");
248             break;
249         default:
250             break;
251     }
252 }
253 
ShowHelpInfo(std::string & dumpInfo)254 void WindowDumper::ShowHelpInfo(std::string& dumpInfo)
255 {
256     dumpInfo.append("Usage:\n")
257         .append(" -h                             ")
258         .append("|help text for the tool\n")
259         .append(" -a                             ")
260         .append("|dump all window information in the system\n")
261         .append(" -w {window id} [ArkUI Option]  ")
262         .append("|dump specified window information\n")
263         .append(" ------------------------------------[ArkUI Option]------------------------------------ \n");
264     ShowAceDumpHelp(dumpInfo);
265 }
266 
ShowAceDumpHelp(std::string & dumpInfo)267 void WindowDumper::ShowAceDumpHelp(std::string& dumpInfo)
268 {
269     auto node = windowRoot_->GetWindowForDumpAceHelpInfo();
270     if (node == nullptr) {
271         WLOGFE("invalid window");
272         return;
273     }
274     if (node->GetWindowToken() != nullptr) {
275         std::vector<std::string> params;
276         params.emplace_back(ARG_DUMP_HELP);
277         dumpInfoFuture_.ResetLock({});
278         node->GetWindowToken()->DumpInfo(params);
279         auto infos = dumpInfoFuture_.GetResult(2000); // 2000: wait for 2000ms
280         for (auto& info: infos) {
281             dumpInfo.append(info).append("\n");
282         }
283     }
284 }
285 }
286 }