1/*
2 * Copyright (C) 2021 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 <thread>
16#include <cstdio>
17#include <ios>
18#include <vector>
19#include <iostream>
20#include <fstream>
21#include <sstream>
22#include <regex>
23#include <sys/wait.h>
24#include <sys/types.h>
25#include <unistd.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include "include/startup_delay.h"
29#include "include/sp_utils.h"
30#include "include/sp_log.h"
31#include "include/common.h"
32
33namespace OHOS {
34namespace SmartPerf {
35StartUpDelay::StartUpDelay() {}
36StartUpDelay::~StartUpDelay() {}
37void StartUpDelay::GetTrace(const std::string &traceName) const
38{
39    std::string result;
40    std::string cmdString;
41    if (SPUtils::IsHmKernel()) {
42        cmdString = CMD_COMMAND_MAP.at(CmdCommand::HITRACE_1024);
43    } else {
44        cmdString = CMD_COMMAND_MAP.at(CmdCommand::HITRACE_2048);
45    }
46    SPUtils::LoadCmd(cmdString + traceName, result);
47    if (result.find("OpenRecording failed") != std::string::npos) {
48        std::string str;
49        std::string traceFinishStr = "hitrace --trace_finish";
50        SPUtils::LoadCmd(traceFinishStr, str);
51        SPUtils::LoadCmd(cmdString + traceName, result);
52    }
53}
54
55void StartUpDelay::GetHisysId() const
56{
57    int time = 10;
58    sleep(time);
59    std::string str = "";
60    std::string cmd = HISYSEVENT_CMD_MAP.at(HisyseventCmd::HISYSEVENT);
61    SPUtils::LoadCmd(cmd, str);
62    std::stringstream ss(str);
63    std::string line = "";
64    getline(ss, line);
65    std::stringstream ssLine(line);
66    std::string word = "";
67    std::string secondStr;
68    int count = 0;
69    int num = 2;
70    while (ssLine >> word) {
71        count++;
72        if (count == num) {
73            secondStr = word;
74            break;
75        }
76    }
77    std::string killCmd = CMD_COMMAND_MAP.at(CmdCommand::KILL_CMD);
78    SPUtils::LoadCmd(killCmd + secondStr, str);
79}
80
81void StartUpDelay::GetHisysIdAndKill() const
82{
83    int time = 10;
84    sleep(time);
85    std::string str = "";
86    std::string cmd = HISYSEVENT_CMD_MAP.at(HisyseventCmd::HISYS_PID);
87    SPUtils::LoadCmd(cmd, str);
88    std::stringstream ss(str);
89    std::vector<std::string> hisysIdVec;
90    std::string singleId;
91    while (ss >> singleId) {
92        hisysIdVec.push_back(singleId);
93    }
94    std::string killCmd = CMD_COMMAND_MAP.at(CmdCommand::KILL_CMD);
95    for (size_t i = 0; i < hisysIdVec.size(); i++) {
96        SPUtils::LoadCmd(killCmd + hisysIdVec[i], str);
97    }
98}
99bool StartUpDelay::GetSpTcp()
100{
101    std::string resultPid;
102    std::string str;
103    std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::PIDOF_SP);
104    SPUtils::LoadCmd(cmd, resultPid);
105    std::vector<std::string> vec;
106    std::string token;
107    size_t pos = 0;
108    while ((pos = resultPid.find(' ')) != std::string::npos) {
109        token = resultPid.substr(0, pos);
110        vec.push_back(token);
111        resultPid.erase(0, pos + 1);
112    }
113    if (vec.size() > 0) {
114        std::string killCmd = CMD_COMMAND_MAP.at(CmdCommand::KILL_CMD);
115        for (size_t i = 0; i < vec.size(); i++) {
116            SPUtils::LoadCmd(killCmd + vec[i], str);
117        }
118    }
119    return false;
120}
121
122bool StartUpDelay::GetSpClear() const
123{
124    std::string resultPid;
125    std::string str;
126    std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::PIDOF_SP);
127    SPUtils::LoadCmd("pidof SP_daemon", resultPid);
128    std::string token;
129    std::string curPid = std::to_string(getpid());
130    std::stringstream ss(resultPid);
131    std::string killCmd = CMD_COMMAND_MAP.at(CmdCommand::KILL_CMD);
132    while (ss >> token) {
133        if (token != curPid) {
134            SPUtils::LoadCmd("kill " + token, str);
135        }
136    }
137
138    return false;
139}
140
141void StartUpDelay::ClearOldServer() const
142{
143    std::string curPid = std::to_string(getpid());
144    std::string commandServer = CMD_COMMAND_MAP.at(CmdCommand::SERVER_GREP);
145    std::string resultPidServer;
146    std::string commandEditorServer = CMD_COMMAND_MAP.at(CmdCommand::EDITOR_SERVER_GREP);
147    std::string resultPidEditorServer;
148
149    SPUtils::LoadCmdWithLinkBreak(commandServer, false, resultPidServer);
150    SPUtils::LoadCmdWithLinkBreak(commandEditorServer, false, resultPidEditorServer);
151
152    std::istringstream iss(resultPidServer + '\n' + resultPidEditorServer);
153    std::string resultLine;
154    std::string killResult;
155    std::string killCmd = CMD_COMMAND_MAP.at(CmdCommand::KILL_CMD);
156    while (std::getline(iss, resultLine)) {
157        if (resultLine.empty() || resultLine.find("sh -c") != std::string::npos) {
158            continue;
159        }
160
161        std::istringstream lineStream(resultLine);
162        std::string token;
163
164        int count = 0;
165        while (lineStream >> token) {
166            if (count == 1) {
167                break;
168            }
169            count++;
170        }
171
172        if (token != curPid) {
173            SPUtils::LoadCmd(killCmd + token, killResult);
174            LOGI("Find old server: %s, killed.", token.c_str());
175        }
176    }
177}
178std::string StartUpDelay::ExecuteCommand(const std::string &command, const std::vector<std::string> &args)
179{
180    std::string output = "";
181    int pipefd[2];
182    if (pipe(pipefd) == -1) {
183        LOGE("startup_delay::Failed to create pipe: %s", strerror(errno));
184        return output;
185    }
186    pid_t pid = fork();
187    if (pid == -1) {
188        LOGE("startup_delay::Failed to fork: %s", strerror(errno));
189        close(pipefd[0]);
190        close(pipefd[1]);
191        return output;
192    }
193    if (pid == 0) {
194        close(pipefd[0]);
195        dup2(pipefd[1], STDOUT_FILENO);
196        close(pipefd[1]);
197        std::vector<char*> argv(args.size() + 1);
198        for (size_t i = 0; i < args.size(); ++i) {
199            argv[i] = const_cast<char*>(args[i].c_str());
200        }
201        argv[args.size()] = nullptr;
202        execvp(command.c_str(), argv.data());
203        LOGE("startup_delay::Failed to execute pid: %s", strerror(errno));
204        _exit(EXIT_FAILURE);
205    }
206    close(pipefd[1]);
207    char buf[1024];
208    ssize_t nread;
209    while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
210        if (nread == sizeof(buf) - 1) {
211            LOGE("startup_delay::Buffer overflow: %s", strerror(errno));
212            break;
213        }
214        buf[nread] = '\0';
215        output.append(buf);
216    }
217    if (nread == -1) {
218        LOGE("startup_delay::Failed to read from pipe: %s", strerror(errno));
219    }
220    close(pipefd[0]);
221    int status;
222    if (waitpid(pid, &status, 0) == -1) {
223        LOGE("startup_delay::Failed to wait for child process: %s", strerror(errno));
224        return output;
225    }
226    return output;
227}
228
229std::string StartUpDelay::GetPidByPkg(const std::string &curPkgName)
230{
231    const std::string pidof = "pidof";
232    const std::vector<std::string> args = {pidof, curPkgName};
233    std::string resultProcId = ExecuteCommand(pidof, args);
234    if (!resultProcId.empty() && resultProcId.back() == '\n') {
235        resultProcId.pop_back();
236        LOGI("startup_delay::output: (%s)", resultProcId.c_str());
237    }
238    return resultProcId;
239}
240}
241}
242