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 
33 namespace OHOS {
34 namespace SmartPerf {
StartUpDelay()35 StartUpDelay::StartUpDelay() {}
~StartUpDelay()36 StartUpDelay::~StartUpDelay() {}
GetTrace(const std::string &traceName) const37 void 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 
GetHisysId() const55 void 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 
GetHisysIdAndKill() const81 void 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 }
GetSpTcp()99 bool 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 
GetSpClear() const122 bool 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 
ClearOldServer() const141 void 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 }
ExecuteCommand(const std::string &command, const std::vector<std::string> &args)178 std::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 
GetPidByPkg(const std::string &curPkgName)229 std::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