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