1 /*
2 * Copyright (C) 2023 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 #include "shell_catcher.h"
16 #include <regex>
17 #include <unistd.h>
18 #include <sys/wait.h>
19 #include "hiview_logger.h"
20 #include "common_utils.h"
21 #include "cpu_collector.h"
22 #include "log_catcher_utils.h"
23 #include "securec.h"
24 #include "time_util.h"
25 namespace OHOS {
26 namespace HiviewDFX {
27 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-ShellCatcher");
ShellCatcher()28 ShellCatcher::ShellCatcher() : EventLogCatcher()
29 {
30 name_ = "ShellCatcher";
31 }
32
Initialize(const std::string & cmd,int type,int catcherPid)33 bool ShellCatcher::Initialize(const std::string& cmd, int type, int catcherPid)
34 {
35 catcherCmd_ = cmd;
36 catcherType_ = CATCHER_TYPE(type);
37 pid_ = catcherPid;
38 description_ = "catcher cmd: " + catcherCmd_ + " ";
39 return true;
40 }
41
SetEvent(std::shared_ptr<SysEvent> event)42 void ShellCatcher::SetEvent(std::shared_ptr<SysEvent> event)
43 {
44 event_ = event;
45 }
46
47
DoOtherChildProcesscatcher(int writeFd)48 int ShellCatcher::DoOtherChildProcesscatcher(int writeFd)
49 {
50 int ret = -1;
51 switch (catcherType_) {
52 case CATCHER_TAGHILOG:
53 ret = execl("/system/bin/hilog",
54 "hilog",
55 "-T",
56 "PowerState,PowerSuspend,PowerInput,DisplayState,DfxFaultLogger",
57 nullptr);
58 break;
59 default:
60 break;
61 }
62 return ret;
63 }
64
DoChildProcesscatcher(int writeFd)65 int ShellCatcher::DoChildProcesscatcher(int writeFd)
66 {
67 int ret = -1;
68 switch (catcherType_) {
69 case CATCHER_INPUT_EVENT_HILOG:
70 ret = execl("/system/bin/hilog", "hilog", "-T", "InputKeyFlow", "-e",
71 std::to_string(pid_).c_str(), "-x", nullptr);
72 break;
73 case CATCHER_INPUT_HILOG:
74 ret = execl("/system/bin/hilog", "hilog", "-T", "InputKeyFlow", "-x", nullptr);
75 break;
76 case CATCHER_EEC:
77 {
78 std::string cmd = "-b EventExclusiveCommander getAllEventExclusiveCaller";
79 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
80 }
81 break;
82 case CATCHER_GEC:
83 {
84 std::string cmd = "-b SCBGestureManager getAllGestureEnableCaller";
85 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
86 }
87 break;
88 case CATCHER_UI:
89 {
90 std::string cmd = "-p 0";
91 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
92 }
93 break;
94 default:
95 ret = DoOtherChildProcesscatcher(writeFd);
96 break;
97 }
98 return ret;
99 }
100
CaDoInChildProcesscatcher(int writeFd)101 int ShellCatcher::CaDoInChildProcesscatcher(int writeFd)
102 {
103 int ret = -1;
104 switch (catcherType_) {
105 case CATCHER_HILOG:
106 ret = execl("/system/bin/hilog", "hilog", "-x", nullptr);
107 break;
108 case CATCHER_LIGHT_HILOG:
109 ret = execl("/system/bin/hilog", "hilog", "-z", "1000", "-P", std::to_string(pid_).c_str(),
110 nullptr);
111 break;
112 case CATCHER_DAM:
113 ret = execl("/system/bin/hidumper", "hidumper", "-s", "1910", "-a", "DumpAppMap", nullptr);
114 break;
115 case CATCHER_SCBWMS:
116 case CATCHER_SCBWMSEVT:
117 {
118 if (event_ == nullptr || focusWindowId_.empty()) {
119 HIVIEW_LOGI("check param error %{public}d", focusWindowId_.empty());
120 break;
121 }
122 std::string cmdSuffix = (catcherType_ == CATCHER_SCBWMS) ? " -simplify" : " -event";
123 std::string cmd = "-w " + focusWindowId_ + cmdSuffix;
124 ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a",
125 cmd.c_str(), nullptr);
126 }
127 break;
128 case CATCHER_SNAPSHOT:
129 {
130 std::string path = "/data/log/eventlog/snapshot_display_";
131 path += TimeUtil::TimestampFormatToDate(TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC,
132 "%Y%m%d%H%M%S");
133 path += ".jpeg";
134 ret = execl("/system/bin/snapshot_display", "snapshot_display", "-f", path.c_str(), nullptr);
135 }
136 break;
137 case CATCHER_SCBSESSION:
138 case CATCHER_SCBVIEWPARAM:
139 {
140 std::string cmd = (catcherType_ == CATCHER_SCBSESSION) ? "-b SCBScenePanel getContainerSession" :
141 "-b SCBScenePanel getViewParam";
142 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
143 }
144 break;
145 default:
146 ret = DoChildProcesscatcher(writeFd);
147 break;
148 }
149 return ret;
150 }
151
DoChildProcess(int writeFd)152 void ShellCatcher::DoChildProcess(int writeFd)
153 {
154 if (focusWindowId_.empty() && (catcherType_ == CATCHER_SCBWMS || catcherType_ == CATCHER_SCBWMSEVT)) {
155 GetFocusWindowId();
156 }
157 if (writeFd < 0 || dup2(writeFd, STDOUT_FILENO) == -1 ||
158 dup2(writeFd, STDIN_FILENO) == -1 || dup2(writeFd, STDERR_FILENO) == -1) {
159 HIVIEW_LOGE("dup2 writeFd fail");
160 _exit(-1);
161 }
162
163 int ret = -1;
164 switch (catcherType_) {
165 case CATCHER_AMS:
166 ret = execl("/system/bin/hidumper", "hidumper", "-s", "AbilityManagerService", "-a", "-a", nullptr);
167 break;
168 case CATCHER_WMS:
169 ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a", "-a", nullptr);
170 break;
171 case CATCHER_CPU:
172 GetCpuCoreFreqInfo(writeFd);
173 ret = execl("/system/bin/hidumper", "hidumper", "--cpuusage", nullptr);
174 break;
175 case CATCHER_PMS:
176 ret = execl("/system/bin/hidumper", "hidumper", "-s", "PowerManagerService", "-a", "-s", nullptr);
177 break;
178 case CATCHER_DPMS:
179 ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayPowerManagerService", nullptr);
180 break;
181 case CATCHER_RS:
182 ret = execl("/system/bin/hidumper", "hidumper", "-s", "RenderService", "-a", "allInfo", nullptr);
183 break;
184 case CATCHER_MMI:
185 ret = execl("/system/bin/hidumper", "hidumper", "-s", "MultimodalInput", "-a", "-w", nullptr);
186 break;
187 case CATCHER_DMS:
188 ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayManagerService", "-a", "-a", nullptr);
189 break;
190 default:
191 ret = CaDoInChildProcesscatcher(writeFd);
192 break;
193 }
194 if (ret < 0) {
195 HIVIEW_LOGE("execl %{public}d, errno: %{public}d", ret, errno);
196 _exit(-1);
197 }
198 }
199
GetFocusWindowId()200 std::string ShellCatcher::GetFocusWindowId()
201 {
202 if (focusWindowId_.empty()) {
203 ParseFocusWindowId();
204 }
205 return focusWindowId_;
206 }
207
ParseFocusWindowId()208 void ShellCatcher::ParseFocusWindowId()
209 {
210 FILE *file = popen("/system/bin/hidumper -s WindowManagerService -a -a", "r");
211 if (file == nullptr) {
212 HIVIEW_LOGE("parse focus window id error");
213 return;
214 }
215 std::smatch result;
216 std::string line = "";
217 auto windowIdRegex = std::regex("Focus window: ([0-9]+)");
218 char *buffer = nullptr;
219 size_t length = 0;
220 while (getline(&buffer, &length, file) != -1) {
221 line = buffer;
222 if (regex_search(line, result, windowIdRegex)) {
223 focusWindowId_ = result[1];
224 break;
225 }
226 }
227 if (buffer != nullptr) {
228 free(buffer);
229 buffer = nullptr;
230 }
231 pclose(file);
232 file = nullptr;
233 }
234
ReadShellToFile(int writeFd,const std::string & cmd)235 bool ShellCatcher::ReadShellToFile(int writeFd, const std::string& cmd)
236 {
237 int childPid = fork();
238 if (childPid < 0) {
239 HIVIEW_LOGE("fork fail");
240 return false;
241 } else if (childPid == 0) {
242 DoChildProcess(writeFd);
243 } else {
244 if (waitpid(childPid, nullptr, 0) != childPid) {
245 HIVIEW_LOGE("waitpid fail, pid: %{public}d, errno: %{public}d", childPid, errno);
246 return false;
247 }
248 HIVIEW_LOGI("waitpid %{public}d success", childPid);
249 }
250 return true;
251 }
252
Catch(int fd,int jsonFd)253 int ShellCatcher::Catch(int fd, int jsonFd)
254 {
255 auto originSize = GetFdSize(fd);
256 if (catcherCmd_.empty()) {
257 HIVIEW_LOGE("catcherCmd empty");
258 return -1;
259 }
260
261 ReadShellToFile(fd, catcherCmd_);
262 logSize_ = GetFdSize(fd) - originSize;
263 return logSize_;
264 }
265
GetCpuCoreFreqInfo(int fd) const266 void ShellCatcher::GetCpuCoreFreqInfo(int fd) const
267 {
268 std::shared_ptr<UCollectUtil::CpuCollector> collector =
269 UCollectUtil::CpuCollector::Create();
270 CollectResult<SysCpuUsage> resultInfo = collector->CollectSysCpuUsage(true);
271 if (resultInfo.retCode != UCollect::UcError::SUCCESS) {
272 FileUtil::SaveStringToFd(fd, "\n Get each cpu info failed.\n");
273 return;
274 }
275
276 const SysCpuUsage& sysCpuUsage = resultInfo.data;
277 std::string temp = "";
278 for (auto i = 0; i < sysCpuUsage.cpuInfos.size(); i++) {
279 temp = "\n" + sysCpuUsage.cpuInfos[i].cpuId +
280 ", userUsage=" + std::to_string(sysCpuUsage.cpuInfos[i].userUsage) + "\n";
281 FileUtil::SaveStringToFd(fd, temp);
282 temp = "";
283 }
284 CollectResult<std::vector<CpuFreq>> resultCpuFreq = collector->CollectCpuFrequency();
285 if (resultCpuFreq.retCode != UCollect::UcError::SUCCESS) {
286 FileUtil::SaveStringToFd(fd, "\n Get each cpu freq failed.\n");
287 return;
288 }
289
290 const std::vector<CpuFreq>& cpuFreqs = resultCpuFreq.data;
291 for (auto i = 0; i < cpuFreqs.size(); i++) {
292 temp = "\ncpu" + std::to_string(cpuFreqs[i].cpuId) + ", cpuFreq=" + std::to_string(cpuFreqs[i].curFreq) +
293 ", minFreq=" + std::to_string(cpuFreqs[i].minFreq) + ", maxFreq=" + std::to_string(cpuFreqs[i].maxFreq) +
294 "\n";
295 FileUtil::SaveStringToFd(fd, temp);
296 temp = "";
297 }
298 }
299 } // namespace HiviewDFX
300 } // namespace OHOS
301