1020a203aSopenharmony_ci/*
2020a203aSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4020a203aSopenharmony_ci * you may not use this file except in compliance with the License.
5020a203aSopenharmony_ci * You may obtain a copy of the License at
6020a203aSopenharmony_ci *
7020a203aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8020a203aSopenharmony_ci *
9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12020a203aSopenharmony_ci * See the License for the specific language governing permissions and
13020a203aSopenharmony_ci * limitations under the License.
14020a203aSopenharmony_ci */
15020a203aSopenharmony_ci#include "shell_catcher.h"
16020a203aSopenharmony_ci#include <regex>
17020a203aSopenharmony_ci#include <unistd.h>
18020a203aSopenharmony_ci#include <sys/wait.h>
19020a203aSopenharmony_ci#include "hiview_logger.h"
20020a203aSopenharmony_ci#include "common_utils.h"
21020a203aSopenharmony_ci#include "log_catcher_utils.h"
22020a203aSopenharmony_ci#include "securec.h"
23020a203aSopenharmony_ci#include "time_util.h"
24020a203aSopenharmony_cinamespace OHOS {
25020a203aSopenharmony_cinamespace HiviewDFX {
26020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "EventLogger-ShellCatcher");
27020a203aSopenharmony_ciShellCatcher::ShellCatcher() : EventLogCatcher()
28020a203aSopenharmony_ci{
29020a203aSopenharmony_ci    name_ = "ShellCatcher";
30020a203aSopenharmony_ci}
31020a203aSopenharmony_ci
32020a203aSopenharmony_cibool ShellCatcher::Initialize(const std::string& cmd, int type, int catcherPid)
33020a203aSopenharmony_ci{
34020a203aSopenharmony_ci    catcherCmd_ = cmd;
35020a203aSopenharmony_ci    catcherType_ = CATCHER_TYPE(type);
36020a203aSopenharmony_ci    pid_ = catcherPid;
37020a203aSopenharmony_ci    description_ = "catcher cmd: " + catcherCmd_ + " ";
38020a203aSopenharmony_ci    return true;
39020a203aSopenharmony_ci}
40020a203aSopenharmony_ci
41020a203aSopenharmony_civoid ShellCatcher::SetEvent(std::shared_ptr<SysEvent> event)
42020a203aSopenharmony_ci{
43020a203aSopenharmony_ci    event_ = event;
44020a203aSopenharmony_ci}
45020a203aSopenharmony_ci
46020a203aSopenharmony_ciint ShellCatcher::DoChildProcesscatcher(int writeFd)
47020a203aSopenharmony_ci{
48020a203aSopenharmony_ci    int ret = -1;
49020a203aSopenharmony_ci    switch (catcherType_) {
50020a203aSopenharmony_ci        case CATCHER_INPUT_EVENT_HILOG:
51020a203aSopenharmony_ci            ret = execl("/system/bin/hilog", "hilog", "-T", "InputKeyFlow", "-e",
52020a203aSopenharmony_ci                std::to_string(pid_).c_str(), "-x", nullptr);
53020a203aSopenharmony_ci            break;
54020a203aSopenharmony_ci        case CATCHER_INPUT_HILOG:
55020a203aSopenharmony_ci            ret = execl("/system/bin/hilog", "hilog", "-T", "InputKeyFlow", "-x", nullptr);
56020a203aSopenharmony_ci            break;
57020a203aSopenharmony_ci        case CATCHER_EEC:
58020a203aSopenharmony_ci            {
59020a203aSopenharmony_ci                std::string cmd = "-b EventExclusiveCommander getAllEventExclusiveCaller";
60020a203aSopenharmony_ci                ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
61020a203aSopenharmony_ci            }
62020a203aSopenharmony_ci            break;
63020a203aSopenharmony_ci        case CATCHER_GEC:
64020a203aSopenharmony_ci            {
65020a203aSopenharmony_ci                std::string cmd = "-b SCBGestureManager getAllGestureEnableCaller";
66020a203aSopenharmony_ci                ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
67020a203aSopenharmony_ci            }
68020a203aSopenharmony_ci            break;
69020a203aSopenharmony_ci        case CATCHER_UI:
70020a203aSopenharmony_ci            {
71020a203aSopenharmony_ci                std::string cmd = "-p 0";
72020a203aSopenharmony_ci                ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
73020a203aSopenharmony_ci            }
74020a203aSopenharmony_ci            break;
75020a203aSopenharmony_ci        default:
76020a203aSopenharmony_ci            break;
77020a203aSopenharmony_ci    }
78020a203aSopenharmony_ci    return ret;
79020a203aSopenharmony_ci}
80020a203aSopenharmony_ci
81020a203aSopenharmony_ciint ShellCatcher::CaDoInChildProcesscatcher(int writeFd)
82020a203aSopenharmony_ci{
83020a203aSopenharmony_ci    int ret = -1;
84020a203aSopenharmony_ci    switch (catcherType_) {
85020a203aSopenharmony_ci        case CATCHER_HILOG:
86020a203aSopenharmony_ci            ret = execl("/system/bin/hilog", "hilog", "-x", nullptr);
87020a203aSopenharmony_ci            break;
88020a203aSopenharmony_ci        case CATCHER_LIGHT_HILOG:
89020a203aSopenharmony_ci            ret = execl("/system/bin/hilog", "hilog", "-z", "1000", "-P", std::to_string(pid_).c_str(),
90020a203aSopenharmony_ci                nullptr);
91020a203aSopenharmony_ci            break;
92020a203aSopenharmony_ci        case CATCHER_DAM:
93020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "1910", "-a", "DumpAppMap", nullptr);
94020a203aSopenharmony_ci            break;
95020a203aSopenharmony_ci        case CATCHER_SCBWMS:
96020a203aSopenharmony_ci        case CATCHER_SCBWMSEVT:
97020a203aSopenharmony_ci            {
98020a203aSopenharmony_ci                std::string cmdSuffix = (catcherType_ == CATCHER_SCBWMS) ? " -simplify" : " -event";
99020a203aSopenharmony_ci                std::string cmd = "-w " + focusWindowId_ + cmdSuffix;
100020a203aSopenharmony_ci                ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a",
101020a203aSopenharmony_ci                    cmd.c_str(), nullptr);
102020a203aSopenharmony_ci            }
103020a203aSopenharmony_ci            break;
104020a203aSopenharmony_ci        case CATCHER_SNAPSHOT:
105020a203aSopenharmony_ci            {
106020a203aSopenharmony_ci                std::string path = "/data/log/eventlog/snapshot_display_";
107020a203aSopenharmony_ci                path += TimeUtil::TimestampFormatToDate(TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC,
108020a203aSopenharmony_ci                    "%Y%m%d%H%M%S");
109020a203aSopenharmony_ci                path += ".jpeg";
110020a203aSopenharmony_ci                ret = execl("/system/bin/snapshot_display", "snapshot_display", "-f", path.c_str(), nullptr);
111020a203aSopenharmony_ci            }
112020a203aSopenharmony_ci            break;
113020a203aSopenharmony_ci        case CATCHER_SCBSESSION:
114020a203aSopenharmony_ci        case CATCHER_SCBVIEWPARAM:
115020a203aSopenharmony_ci            {
116020a203aSopenharmony_ci                std::string cmd = (catcherType_ == CATCHER_SCBSESSION) ? "-b SCBScenePanel getContainerSession" :
117020a203aSopenharmony_ci                    "-b SCBScenePanel getViewParam";
118020a203aSopenharmony_ci                ret = execl("/system/bin/hidumper", "hidumper", "-s", "4606", "-a", cmd.c_str(), nullptr);
119020a203aSopenharmony_ci            }
120020a203aSopenharmony_ci            break;
121020a203aSopenharmony_ci        default:
122020a203aSopenharmony_ci            ret = DoChildProcesscatcher(writeFd);
123020a203aSopenharmony_ci            break;
124020a203aSopenharmony_ci    }
125020a203aSopenharmony_ci    return ret;
126020a203aSopenharmony_ci}
127020a203aSopenharmony_ci
128020a203aSopenharmony_civoid ShellCatcher::DoChildProcess(int writeFd)
129020a203aSopenharmony_ci{
130020a203aSopenharmony_ci    if (writeFd < 0 || dup2(writeFd, STDOUT_FILENO) == -1 ||
131020a203aSopenharmony_ci        dup2(writeFd, STDIN_FILENO) == -1 || dup2(writeFd, STDERR_FILENO) == -1) {
132020a203aSopenharmony_ci        HIVIEW_LOGE("dup2 writeFd fail");
133020a203aSopenharmony_ci        _exit(-1);
134020a203aSopenharmony_ci    }
135020a203aSopenharmony_ci
136020a203aSopenharmony_ci    int ret = -1;
137020a203aSopenharmony_ci    switch (catcherType_) {
138020a203aSopenharmony_ci        case CATCHER_AMS:
139020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "AbilityManagerService", "-a", "-a", nullptr);
140020a203aSopenharmony_ci            break;
141020a203aSopenharmony_ci        case CATCHER_WMS:
142020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "WindowManagerService", "-a", "-a", nullptr);
143020a203aSopenharmony_ci            break;
144020a203aSopenharmony_ci        case CATCHER_CPU:
145020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "--cpuusage", nullptr);
146020a203aSopenharmony_ci            break;
147020a203aSopenharmony_ci        case CATCHER_PMS:
148020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "PowerManagerService", "-a", "-s", nullptr);
149020a203aSopenharmony_ci            break;
150020a203aSopenharmony_ci        case CATCHER_DPMS:
151020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayPowerManagerService", nullptr);
152020a203aSopenharmony_ci            break;
153020a203aSopenharmony_ci        case CATCHER_RS:
154020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "RenderService", "-a", "allInfo", nullptr);
155020a203aSopenharmony_ci            break;
156020a203aSopenharmony_ci        case CATCHER_MMI:
157020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "MultimodalInput", "-a", "-w", nullptr);
158020a203aSopenharmony_ci            break;
159020a203aSopenharmony_ci        case CATCHER_DMS:
160020a203aSopenharmony_ci            ret = execl("/system/bin/hidumper", "hidumper", "-s", "DisplayManagerService", "-a", "-a", nullptr);
161020a203aSopenharmony_ci            break;
162020a203aSopenharmony_ci        default:
163020a203aSopenharmony_ci            ret = CaDoInChildProcesscatcher(writeFd);
164020a203aSopenharmony_ci            break;
165020a203aSopenharmony_ci    }
166020a203aSopenharmony_ci    if (ret < 0) {
167020a203aSopenharmony_ci        HIVIEW_LOGE("execl %{public}d, errno: %{public}d", ret, errno);
168020a203aSopenharmony_ci        _exit(-1);
169020a203aSopenharmony_ci    }
170020a203aSopenharmony_ci}
171020a203aSopenharmony_ci
172020a203aSopenharmony_civoid ShellCatcher::SetFocusWindowId(const std::string& focusWindowId)
173020a203aSopenharmony_ci{
174020a203aSopenharmony_ci    focusWindowId_ = focusWindowId;
175020a203aSopenharmony_ci}
176020a203aSopenharmony_ci
177020a203aSopenharmony_cibool ShellCatcher::ReadShellToFile(int writeFd, const std::string& cmd)
178020a203aSopenharmony_ci{
179020a203aSopenharmony_ci    int childPid = fork();
180020a203aSopenharmony_ci    if (childPid < 0) {
181020a203aSopenharmony_ci        HIVIEW_LOGE("fork fail");
182020a203aSopenharmony_ci        return false;
183020a203aSopenharmony_ci    } else if (childPid == 0) {
184020a203aSopenharmony_ci        DoChildProcess(writeFd);
185020a203aSopenharmony_ci    } else {
186020a203aSopenharmony_ci        if (waitpid(childPid, nullptr, 0) != childPid) {
187020a203aSopenharmony_ci            HIVIEW_LOGE("waitpid fail, pid: %{public}d, errno: %{public}d", childPid, errno);
188020a203aSopenharmony_ci            return false;
189020a203aSopenharmony_ci        }
190020a203aSopenharmony_ci        HIVIEW_LOGI("waitpid %{public}d success", childPid);
191020a203aSopenharmony_ci    }
192020a203aSopenharmony_ci    return true;
193020a203aSopenharmony_ci}
194020a203aSopenharmony_ci
195020a203aSopenharmony_ciint ShellCatcher::Catch(int fd, int jsonFd)
196020a203aSopenharmony_ci{
197020a203aSopenharmony_ci    auto originSize = GetFdSize(fd);
198020a203aSopenharmony_ci    if (catcherCmd_.empty()) {
199020a203aSopenharmony_ci        HIVIEW_LOGE("catcherCmd empty");
200020a203aSopenharmony_ci        return -1;
201020a203aSopenharmony_ci    }
202020a203aSopenharmony_ci
203020a203aSopenharmony_ci    ReadShellToFile(fd, catcherCmd_);
204020a203aSopenharmony_ci    logSize_ = GetFdSize(fd) - originSize;
205020a203aSopenharmony_ci    return logSize_;
206020a203aSopenharmony_ci}
207020a203aSopenharmony_ci} // namespace HiviewDFX
208020a203aSopenharmony_ci} // namespace OHOS
209