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