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 <cstdio>
16 #include <thread>
17 #include <cstring>
18 #include <iterator>
19 #include "unistd.h"
20 #include "include/heartbeat.h"
21 #include "include/sp_utils.h"
22 #include "include/sp_csv_util.h"
23 #include "include/sp_profiler_factory.h"
24 #include "include/sp_thread_socket.h"
25 #include "include/startup_delay.h"
26 #include "include/ByTrace.h"
27 #include "include/smartperf_command.h"
28 #include "include/sp_log.h"
29 #include "include/RAM.h"
30 #include "include/common.h"
31 
32 namespace OHOS {
33 namespace SmartPerf {
SmartPerfCommand(std::vector<std::string> argv)34 SmartPerfCommand::SmartPerfCommand(std::vector<std::string> argv)
35 {
36     LOGI("SmartPerfCommand::SmartPerfCommand size(%u)", argv.size());
37     if (argv.size() == oneParam) {
38         OHOS::SmartPerf::StartUpDelay sd;
39         sd.GetSpTcp();
40         std::string pidStr = sd.GetPidByPkg("SP_daemon");
41         std::string cmdStr = CMD_COMMAND_MAP.at(CmdCommand::TASKSET);
42         std::string result = "";
43         SPUtils::LoadCmd(cmdStr + pidStr, result);
44         daemon(0, 0);
45         CreateSocketThread();
46     }
47     if (argv.size() == twoParam) {
48         auto iterator = COMMAND_HELP_MAP.begin();
49         while (iterator != COMMAND_HELP_MAP.end()) {
50             if (iterator->second.compare(argv[1]) == 0) {
51                 HelpCommand(iterator->first);
52                 break;
53             }
54             ++iterator;
55         }
56     }
57     if (argv.size() >= threeParamMore) {
58         for (int i = 1; i <= static_cast<int>(argv.size()) - 1; i++) {
59             std::string argStr = argv[i];
60             std::string argStr1;
61             if (i < static_cast<int>(argv.size()) - 1) {
62                 argStr1 = argv[i + 1];
63             }
64             if (COMMAND_MAP.count(argStr) > 0) {
65                 HandleCommand(argStr, argStr1);
66             }
67         }
68     }
69 
70     LOGI("SmartPerfCommand::SmartPerfCommand  complete");
71 }
HelpCommand(CommandHelp type) const72 void SmartPerfCommand::HelpCommand(CommandHelp type) const
73 {
74     LOGI("SmartPerfCommand::HelpCommand  type(%d)", type);
75     if (type == CommandHelp::HELP) {
76         std::cout << smartPerfMsg << std::endl;
77     }
78     if (type == CommandHelp::VERSION) {
79         std::cout << "Version: " << smartPerfVersion << std::endl;
80     }
81     if (type == CommandHelp::SCREEN) {
82         std::string result = SPUtils::GetScreen();
83         std::cout << result << std::endl;
84     }
85     OHOS::SmartPerf::StartUpDelay sd;
86     if (type == CommandHelp::CLEAR) {
87         sd.GetSpClear();
88     }
89     if (type == CommandHelp::SERVER || type == CommandHelp::EDITORSERVER) {
90         sd.ClearOldServer();
91         std::string pidStr = sd.GetPidByPkg("SP_daemon");
92         std::string cmdStr = CMD_COMMAND_MAP.at(CmdCommand::TASKSET);
93         std::string result = "";
94         SPUtils::LoadCmd(cmdStr + pidStr, result);
95         if (type == CommandHelp::SERVER) {
96             daemon(0, 0);
97         }
98         CreateSocketThread();
99     }
100 }
101 
CreateSocketThread() const102 void SmartPerfCommand::CreateSocketThread() const
103 {
104     InitSomething();
105     SpThreadSocket udpThreadSocket;
106     SpThreadSocket udpExThreadSocket;
107     SpThreadSocket tcpThreadSocket;
108     auto tcpSocket = std::thread([&tcpThreadSocket]() { tcpThreadSocket.Process(ProtoType::TCP); });
109     sleep(1);
110     auto udpSocket = std::thread([&udpThreadSocket]() { udpThreadSocket.Process(ProtoType::UDP); });
111     sleep(1);
112     auto udpexSocket = std::thread([&udpExThreadSocket]() { udpExThreadSocket.Process(ProtoType::UDPEX); });
113     Heartbeat &heartbeat = Heartbeat::GetInstance();
114     heartbeat.UpdatestartTime();
115     std::thread threadHeartbeat([&heartbeat]() {heartbeat.HeartbeatRule(); });
116     threadHeartbeat.detach();
117     tcpSocket.join();
118     udpSocket.join();
119     udpexSocket.join();
120 }
HandleCommand(std::string argStr, const std::string &argStr1)121 void SmartPerfCommand::HandleCommand(std::string argStr, const std::string &argStr1)
122 {
123     LOGI("SmartPerfCommand::HandleCommand  argStr(%s) argStr1(%s)", argStr.c_str(), argStr1.c_str());
124     switch (COMMAND_MAP.at(argStr)) {
125         case CommandType::CT_N:
126             num = atoi(argStr1.c_str());
127             break;
128         case CommandType::CT_PKG:
129             pkgName = argStr1;
130             if (pkgName.length() > 0) {
131                 SpProfilerFactory::SetProfilerPkg(pkgName);
132             }
133             break;
134         case CommandType::CT_VIEW:
135             layerName = argStr1;
136             if (layerName.length() > 0) {
137                 SpProfilerFactory::SetProfilerLayer(layerName);
138             }
139             break;
140         case CommandType::CT_OUT:
141             outPathParam = argStr1;
142             if (strcmp(outPathParam.c_str(), "") != 0) {
143                 outPath = outPathParam;
144             }
145             break;
146         case CommandType::CT_C:
147         case CommandType::CT_G:
148         case CommandType::CT_D:
149         case CommandType::CT_F:
150         case CommandType::CT_T:
151         case CommandType::CT_P:
152         case CommandType::CT_R:
153         case CommandType::CT_NET:
154         case CommandType::CT_TTRACE:
155         case CommandType::CT_SNAPSHOT:
156         case CommandType::CT_HW:
157         case CommandType::CT_GC:
158         case CommandType::CT_NAV:
159             configs.push_back(argStr);
160             break;
161         default:
162             std::cout << "other unknown args:" << argStr << std::endl;
163             break;
164     }
165 }
166 
GetItemInfo(std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> &spMap)167 int SmartPerfCommand::GetItemInfo(std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> &spMap)
168 {
169     int rc = 0;
170     std::string errInfo;
171     if (!pkgName.empty()) {
172         std::string processId = "";
173         OHOS::SmartPerf::StartUpDelay sp;
174         processId = sp.GetPidByPkg(pkgName);
175         SpProfilerFactory::SetProfilerPidByPkg(processId);
176     }
177     for (size_t j = 0; j < configs.size(); j++) {
178         std::string curParam = configs[j];
179 
180         if (curParam.find("-gc") != std::string::npos) {
181             continue;
182         }
183 
184         SpProfiler *profiler = SpProfilerFactory::GetCmdProfilerItem(COMMAND_MAP.at(curParam), true);
185         if (profiler != nullptr) {
186             std::map<std::string, std::string> data = profiler->ItemData();
187             spMap.insert(data.cbegin(), data.cend());
188         }
189     }
190 
191     if (!errInfo.empty()) { // GPU Counter init failed
192         printf("%s\n", errInfo.c_str());
193         LOGE("%s", errInfo.c_str());
194         return -1;
195     }
196 
197     return rc;
198 }
199 
SaveGpuCounter() const200 void SmartPerfCommand::SaveGpuCounter() const
201 {
202     std::string outGpuCounterDataPath = "/data/local/tmp";
203     gpuCounter.SaveData(outGpuCounterDataPath);
204     gpuCounter.StopCollect();
205 }
206 
ExecCommand()207 std::string SmartPerfCommand::ExecCommand()
208 {
209     RAM &ram = RAM::GetInstance();
210     ram.SetFirstFlag();
211     int rc = 0;
212     int index = 0;
213     std::vector<SPData> vmap;
214     const long long freq = 1000;
215     num = num + 1;
216     bool gcFlag = false;
217     for (std::string itConfig : configs) {
218         if (itConfig.find("-gc") != std::string::npos) {
219             gpuCounter.StartCollect(GpuCounter::GC_START);
220             gcFlag = true;
221         }
222     }
223     while (index < num) {
224         std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> spMap(SPUtils::Cmp);
225         long long lastTime = SPUtils::GetCurTime();
226         spMap.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(lastTime)));
227         rc = GetItemInfo(spMap);
228         if (rc == -1) {
229             break;
230         }
231         std::map<std::string, std::string> gpuCounterDataMap;
232         gpuCounter.GetGpuRealtimeData(gpuCounterDataMap);
233         spMap.insert(gpuCounterDataMap.begin(), gpuCounterDataMap.end());
234         std::cout << std::endl;
235         PrintMap(spMap, index);
236         std::cout << std::endl;
237         SPData spdata;
238         if (index != 0) {
239             spdata.values.insert(spMap.cbegin(), spMap.cend());
240             vmap.push_back(spdata);
241         }
242         long long nextTime = SPUtils::GetCurTime();
243         long long costTime = nextTime - lastTime;
244         if (costTime < freq) {
245             std::this_thread::sleep_for(std::chrono::milliseconds(freq - costTime));
246         }
247         index++;
248     }
249     if (gcFlag) {
250         SaveGpuCounter();
251     }
252     std::this_thread::sleep_for(std::chrono::milliseconds(freq));
253     LOGI("SmartPerfCommand::WriteCsv start");
254     SpCsvUtil::WriteCsv(std::string(outPath.c_str()), vmap);
255     LOGI("SmartPerfCommand::WriteCsv finish");
256     return std::string("command exec finished!");
257 }
PrintfExecCommand(const std::map<std::string, std::string> data) const258 void SmartPerfCommand::PrintfExecCommand(const std::map<std::string, std::string> data) const
259 {
260     int i = 0;
261     for (auto a = data.cbegin(); a != data.cend(); ++a) {
262         printf("order:%d %s=%s\n", i++, a->first.c_str(), a->second.c_str());
263     }
264 }
265 
PrintMap(std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> &spMap, int index) const266 void SmartPerfCommand::PrintMap(std::multimap<std::string, std::string,
267     decltype(SPUtils::Cmp) *> &spMap, int index) const
268 {
269     int i = 0;
270     for (auto iter = spMap.cbegin(); iter != spMap.cend(); ++iter) {
271         if (index != 0) {
272             printf("order:%d %s=%s\n", i++, iter->first.c_str(), iter->second.c_str());
273         }
274     }
275 }
276 
InitSomething()277 void SmartPerfCommand::InitSomething()
278 {
279     std::string cmdResult;
280     std::string stat = CMD_COMMAND_MAP.at(CmdCommand::PROC_STAT);
281     if (SPUtils::LoadCmd(stat, cmdResult)) {
282         LOGI("SmartPerfCommand::InitSomething Privilege escalation!");
283     };
284 }
285 }
286 }
287