• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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