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 "log_catcher_utils.h"
22 #include "securec.h"
23 #include "time_util.h"
24 namespace OHOS {
25 namespace HiviewDFX {
26 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-ShellCatcher");
ShellCatcher()27 ShellCatcher::ShellCatcher() : EventLogCatcher()
28 {
29 name_ = "ShellCatcher";
30 }
31
Initialize(const std::string & cmd,int type,int catcherPid)32 bool ShellCatcher::Initialize(const std::string& cmd, int type, int catcherPid)
33 {
34 catcherCmd_ = cmd;
35 catcherType_ = CATCHER_TYPE(type);
36 pid_ = catcherPid;
37 description_ = "catcher cmd: " + catcherCmd_ + " ";
38 return true;
39 }
40
SetEvent(std::shared_ptr<SysEvent> event)41 void ShellCatcher::SetEvent(std::shared_ptr<SysEvent> event)
42 {
43 event_ = event;
44 }
45
DoChildProcesscatcher(int writeFd)46 int ShellCatcher::DoChildProcesscatcher(int writeFd)
47 {
48 int ret = -1;
49 switch (catcherType_) {
50 case CATCHER_INPUT_EVENT_HILOG:
51 ret = execl("/system/bin/hilog", "hilog", "-T", "InputKeyFlow", "-e",
52 std::to_string(pid_).c_str(), "-x", nullptr);
53 break;
54 case CATCHER_INPUT_HILOG:
55 ret = execl("/system/bin/hilog", "hilog", "-T", "InputKeyFlow", "-x", nullptr);
56 break;
57 case CATCHER_EEC:
58 {
59 std::string cmd = "-b EventExclusiveCommander getAllEventExclusiveCaller";
60 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
61 }
62 break;
63 case CATCHER_GEC:
64 {
65 std::string cmd = "-b SCBGestureManager getAllGestureEnableCaller";
66 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
67 }
68 break;
69 case CATCHER_UI:
70 {
71 std::string cmd = "-p 0";
72 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
73 }
74 break;
75 default:
76 break;
77 }
78 return ret;
79 }
80
CaDoInChildProcesscatcher(int writeFd)81 int ShellCatcher::CaDoInChildProcesscatcher(int writeFd)
82 {
83 int ret = -1;
84 switch (catcherType_) {
85 case CATCHER_HILOG:
86 ret = execl("/system/bin/hilog", "hilog", "-x", nullptr);
87 break;
88 case CATCHER_LIGHT_HILOG:
89 ret = execl("/system/bin/hilog", "hilog", "-z", "1000", "-P", std::to_string(pid_).c_str(),
90 nullptr);
91 break;
92 case CATCHER_DAM:
93 ret = execl("/system/bin/hidumper", "hidumper", "-s", "1910", "-a", "DumpAppMap", nullptr);
94 break;
95 case CATCHER_SCBWMS:
96 case CATCHER_SCBWMSEVT:
97 {
98 if (event_ == nullptr || focusWindowId_.empty()) {
99 HIVIEW_LOGI("check param error %{public}d", focusWindowId_.empty());
100 break;
101 }
102 std::string cmdSuffix = (catcherType_ == CATCHER_SCBWMS) ? " -simplify" : " -event";
103 std::string cmd = "-w " + focusWindowId_ + cmdSuffix;
104 ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a",
105 cmd.c_str(), nullptr);
106 }
107 break;
108 case CATCHER_SNAPSHOT:
109 {
110 std::string path = "/data/log/eventlog/snapshot_display_";
111 path += TimeUtil::TimestampFormatToDate(TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC,
112 "%Y%m%d%H%M%S");
113 path += ".jpeg";
114 ret = execl("/system/bin/snapshot_display", "snapshot_display", "-f", path.c_str(), nullptr);
115 }
116 break;
117 case CATCHER_SCBSESSION:
118 case CATCHER_SCBVIEWPARAM:
119 {
120 std::string cmd = (catcherType_ == CATCHER_SCBSESSION) ? "-b SCBScenePanel getContainerSession" :
121 "-b SCBScenePanel getViewParam";
122 ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
123 }
124 break;
125 default:
126 ret = DoChildProcesscatcher(writeFd);
127 break;
128 }
129 return ret;
130 }
131
DoChildProcess(int writeFd)132 void ShellCatcher::DoChildProcess(int writeFd)
133 {
134 if (focusWindowId_.empty() && (catcherType_ == CATCHER_SCBWMS || catcherType_ == CATCHER_SCBWMSEVT)) {
135 GetFocusWindowId();
136 }
137 if (writeFd < 0 || dup2(writeFd, STDOUT_FILENO) == -1 ||
138 dup2(writeFd, STDIN_FILENO) == -1 || dup2(writeFd, STDERR_FILENO) == -1) {
139 HIVIEW_LOGE("dup2 writeFd fail");
140 _exit(-1);
141 }
142
143 int ret = -1;
144 switch (catcherType_) {
145 case CATCHER_AMS:
146 ret = execl("/system/bin/hidumper", "hidumper", "-s", "AbilityManagerService", "-a", "-a", nullptr);
147 break;
148 case CATCHER_WMS:
149 ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a", "-a", nullptr);
150 break;
151 case CATCHER_CPU:
152 ret = execl("/system/bin/hidumper", "hidumper", "--cpuusage", nullptr);
153 break;
154 case CATCHER_PMS:
155 ret = execl("/system/bin/hidumper", "hidumper", "-s", "PowerManagerService", "-a", "-s", nullptr);
156 break;
157 case CATCHER_DPMS:
158 ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayPowerManagerService", nullptr);
159 break;
160 case CATCHER_RS:
161 ret = execl("/system/bin/hidumper", "hidumper", "-s", "RenderService", "-a", "allInfo", nullptr);
162 break;
163 case CATCHER_MMI:
164 ret = execl("/system/bin/hidumper", "hidumper", "-s", "MultimodalInput", "-a", "-w", nullptr);
165 break;
166 case CATCHER_DMS:
167 ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayManagerService", "-a", "-a", nullptr);
168 break;
169 default:
170 ret = CaDoInChildProcesscatcher(writeFd);
171 break;
172 }
173 if (ret < 0) {
174 HIVIEW_LOGE("execl %{public}d, errno: %{public}d", ret, errno);
175 _exit(-1);
176 }
177 }
178
GetFocusWindowId()179 std::string ShellCatcher::GetFocusWindowId()
180 {
181 if (focusWindowId_.empty()) {
182 ParseFocusWindowId();
183 }
184 return focusWindowId_;
185 }
186
ParseFocusWindowId()187 void ShellCatcher::ParseFocusWindowId()
188 {
189 FILE *file = popen("/system/bin/hidumper -s WindowManagerService -a -a", "r");
190 if (file == nullptr) {
191 HIVIEW_LOGE("parse focus window id error");
192 return;
193 }
194 std::smatch result;
195 std::string line = "";
196 auto windowIdRegex = std::regex("Focus window: ([0-9]+)");
197 char *buffer = nullptr;
198 size_t length = 0;
199 while (getline(&buffer, &length, file) != -1) {
200 line = buffer;
201 if (regex_search(line, result, windowIdRegex)) {
202 focusWindowId_ = result[1];
203 break;
204 }
205 }
206 if (buffer != nullptr) {
207 free(buffer);
208 buffer = nullptr;
209 }
210 pclose(file);
211 file = nullptr;
212 }
213
ReadShellToFile(int writeFd,const std::string & cmd)214 bool ShellCatcher::ReadShellToFile(int writeFd, const std::string& cmd)
215 {
216 int childPid = fork();
217 if (childPid < 0) {
218 HIVIEW_LOGE("fork fail");
219 return false;
220 } else if (childPid == 0) {
221 DoChildProcess(writeFd);
222 } else {
223 if (waitpid(childPid, nullptr, 0) != childPid) {
224 HIVIEW_LOGE("waitpid fail, pid: %{public}d, errno: %{public}d", childPid, errno);
225 return false;
226 }
227 HIVIEW_LOGI("waitpid %{public}d success", childPid);
228 }
229 return true;
230 }
231
Catch(int fd,int jsonFd)232 int ShellCatcher::Catch(int fd, int jsonFd)
233 {
234 auto originSize = GetFdSize(fd);
235 if (catcherCmd_.empty()) {
236 HIVIEW_LOGE("catcherCmd empty");
237 return -1;
238 }
239
240 ReadShellToFile(fd, catcherCmd_);
241 logSize_ = GetFdSize(fd) - originSize;
242 return logSize_;
243 }
244 } // namespace HiviewDFX
245 } // namespace OHOS
246