• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <iostream>
16 #include <thread>
17 #include <string>
18 #include <climits>
19 #include "include/sp_profiler_factory.h"
20 #include "include/sp_utils.h"
21 #include "include/FPS.h"
22 #include "include/FileDescriptor.h"
23 #include "include/RAM.h"
24 #include "include/CPU.h"
25 #include "include/Capture.h"
26 #include "include/startup_delay.h"
27 #include "include/sp_log.h"
28 #include "ByTrace.h"
29 #include <cstdio>
30 #include <ios>
31 #include <vector>
32 #include <fstream>
33 #include <sstream>
34 #include <regex>
35 #include "unistd.h"
36 #include <future>
37 #include "include/common.h"
38 #include "include/sp_csv_util.h"
39 namespace OHOS {
40 namespace SmartPerf {
41 const long long RM_0 = 0;
42 const long long RM_5000 = 5000;
43 const long long RM_1000 = 1000;
44 const long long RM_1000000 = 1000000;
45 const long long END_WAITING_TIME = 8; // End waiting time,unit seconds
ParseCommandArgs(std::string & command)46 std::vector<std::string> ParseCommandArgs(std::string &command)
47 {
48     std::vector<std::string> args;
49     size_t pos = 0;
50     while ((pos = command.find(" ")) != std::string::npos) {
51         args.push_back(command.substr(0, pos));
52         command.erase(0, pos + 1);
53     }
54     args.push_back(command);
55     return args;
56 }
57 
58 // init::-SESSIONID 12345678 -INTERVAL 1000 -PKG ohos.samples.ecg -c -g -t -p -f -r -fl 30
ParseToTask(std::string command,TaskInfo & taskInfo)59 static ExceptionMsg ParseToTask(std::string command, TaskInfo &taskInfo)
60 {
61     StuckNotification snf;
62     snf.isEffective = false;
63     std::string sessionId;
64     long long interval = 1000;
65     std::string pkg;
66     std::string pid;
67     bool isFPS = false;
68     bool isPrint = false;
69     std::vector<std::string> configs;
70     std::vector<std::string> args = ParseCommandArgs(command);
71     for (size_t i = 0; i < args.size(); i++) {
72         if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_SESSIONID)) {
73             sessionId = args[++i];
74         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_INTERVAL)) {
75             interval = SPUtilesTye::StringToSometype<long long>(args[++i]);
76         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_PKG)) {
77             pkg = args[++i];
78         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_PID)) {
79             pid = args[++i];
80         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_PRINT)) {
81             isPrint = true;
82         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_FL)) { // 获取用户fps的值,并赋给snf.   CT_FL
83             snf.fps = SPUtilesTye::StringToSometype<int>(args[++i]);
84             snf.isEffective = true;
85         } else if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_FTL)) { // 获取frameTime的值      CT_FTL
86             snf.frameTime = SPUtilesTye::StringToSometype<int>(args[++i]);
87             snf.isEffective = true;
88         } else {
89             if (args[i] == COMMAND_MAP_REVERSE.at(CommandType::CT_F)) { // 判断用户设置是否有-f
90                 isFPS = true;
91             }
92             if (COMMAND_MAP.end() != COMMAND_MAP.find(args[i])) {
93                 configs.push_back(args[i]);
94             }
95         }
96     }
97     if (snf.isEffective && (!isFPS)) {
98         return ExceptionMsg::TASK_CONFIG_NULL;
99     }
100     if (sessionId.empty()) {
101         LOGE("ExceptionMsg ParseToTask sessoin id is null");
102         return ExceptionMsg::SESSION_ID_NULL;
103     } else if (configs.size() == 0) {
104         LOGE("ExceptionMsg ParseToTask configs size is 0");
105         return ExceptionMsg::TASK_CONFIG_NULL;
106     }
107     taskInfo = { sessionId, pkg, pid, configs, interval, snf, isPrint };
108     return ExceptionMsg::NO_ERR;
109 }
110 
MapToString(std::map<std::string,std::string> myMap)111 static std::string MapToString(std::map<std::string, std::string> myMap)
112 {
113     // 将Map转换为字符串
114     std::string str = "{ ";
115     for (auto it = myMap.begin(); it != myMap.end(); ++it) {
116         str += "\"" + it->first + "\": " + it->second + ", ";
117     }
118     const int subLen = 2;
119     str.erase(str.end() - subLen, str.end());
120     str += " }";
121     return str;
122 }
123 
PrintMap(std::map<std::string,std::string> & dataMap)124 void SPTask::PrintMap(std::map<std::string, std::string> &dataMap)
125 {
126     if (curTaskInfo.isPrint) {
127         int i = 0;
128         for (auto iter = dataMap.cbegin() ; iter != dataMap.cend(); ++iter) {
129             fprintf(stderr, "\norder:%d %s=%s", i++, iter->first.c_str(), iter->second.c_str());
130         }
131         std::cerr << std::endl << std::flush;
132     }
133 }
134 
InitTask(const std::string & recvStr)135 ErrCode SPTask::InitTask(const std::string &recvStr)
136 {
137     std::string result = "";
138     std::string hiprofiler = CMD_COMMAND_MAP.at(CmdCommand::HIPROFILER);
139     SPUtils::LoadCmd(hiprofiler, result);
140     result.clear();
141     std::string perf = CMD_COMMAND_MAP.at(CmdCommand::PERF);
142     SPUtils::LoadCmd(perf, result);
143     std::cout << recvStr.substr(recvStr.find("-SESSIONID")) << std::endl;
144     WLOGI("Received init task string: %s", recvStr.substr(recvStr.find("-SESSIONID")).c_str());
145     ExceptionMsg exMsg = ParseToTask(recvStr, curTaskInfo);
146     if (exMsg == ExceptionMsg::NO_ERR) {
147         FPS &fps = FPS::GetInstance();
148         fps.isGameApp = SPUtils::GetIsGameApp(curTaskInfo.packageName);
149         fps.firstDump = true;
150         isInit = true;
151         LOGD("InitTask success, task initialized.");
152         return ErrCode::OK;
153     }
154 
155     std::string errInfo = EXCEPTION_MSG_MAP.at(exMsg);
156     LOGE("InitTask error(%s)", errInfo.c_str());
157     return ErrCode::FAILED;
158 }
159 
AsyncCollectRam()160 std::future<std::map<std::string, std::string>> SPTask::AsyncCollectRam()
161 {
162     std::promise<std::map<std::string, std::string>> p;
163     std::future<std::map<std::string, std::string>> futureResult;
164     for (std::string ramConfig : curTaskInfo.taskConfig) {
165         if (ramConfig.find("-r") != std::string::npos) {
166             futureResult = p.get_future();
167             std::thread([p = std::move(p)]() mutable {
168                 LOGD("Starting RAM collection in new thread");
169                 p.set_value(RAM::GetInstance().ItemData());
170             }).detach();
171         }
172     }
173     return futureResult;
174 }
175 
AsyncCollectCpu()176 std::future<std::map<std::string, std::string>> SPTask::AsyncCollectCpu()
177 {
178     std::promise<std::map<std::string, std::string>> p;
179     std::future<std::map<std::string, std::string>> futureResult;
180     for (std::string cpuConfig : curTaskInfo.taskConfig) {
181         if (cpuConfig.find("-c") != std::string::npos) {
182             futureResult = p.get_future();
183             std::thread([p = std::move(p)]() mutable {
184                 LOGD("Starting CPU collection in new thread");
185                 p.set_value(CPU::GetInstance().ItemData());
186             }).detach();
187         }
188     }
189     return futureResult;
190 }
191 
AsyncCollectFps()192 std::future<std::map<std::string, std::string>> SPTask::AsyncCollectFps()
193 {
194     std::promise<std::map<std::string, std::string>> p;
195     std::future<std::map<std::string, std::string>> futureResult;
196     for (std::string fpsConfig : curTaskInfo.taskConfig) {
197         if (fpsConfig == "-f") {
198             futureResult = p.get_future();
199             std::thread([p = std::move(p)]() mutable {
200                 LOGD("Starting FPS collection in new thread");
201                 p.set_value(FPS::GetInstance().ItemData());
202             }).detach();
203         }
204     }
205     return futureResult;
206 }
207 
AsyncCollectFds()208 std::future<std::map<std::string, std::string>> SPTask::AsyncCollectFds()
209 {
210     std::promise<std::map<std::string, std::string>> p;
211     std::future<std::map<std::string, std::string>> futureResult;
212     for (std::string fdsConfig : curTaskInfo.taskConfig) {
213         if (fdsConfig.find("-fds") != std::string::npos) {
214             futureResult = p.get_future();
215             std::thread([p = std::move(p)]() mutable {
216                 p.set_value(FileDescriptor::GetInstance().ItemData());
217             }).detach();
218         }
219     }
220     return futureResult;
221 }
222 
CheckFutureRam(std::future<std::map<std::string,std::string>> & ramResult,std::map<std::string,std::string> & dataMap)223 void SPTask::CheckFutureRam(std::future<std::map<std::string, std::string>> &ramResult,
224     std::map<std::string, std::string> &dataMap)
225 {
226     if (ramResult.valid()) {
227         std::map<std::string, std::string> result = ramResult.get();
228         dataMap.insert(result.begin(), result.end());
229     }
230 }
231 
CheckFutureCpu(std::future<std::map<std::string,std::string>> & cpuResult,std::map<std::string,std::string> & dataMap)232 void SPTask::CheckFutureCpu(std::future<std::map<std::string, std::string>> &cpuResult,
233     std::map<std::string, std::string> &dataMap)
234 {
235     if (cpuResult.valid()) {
236         std::map<std::string, std::string> result = cpuResult.get();
237         dataMap.insert(result.begin(), result.end());
238     }
239 }
240 
CheckFutureFps(std::future<std::map<std::string,std::string>> & fpsResult,std::map<std::string,std::string> & dataMap)241 void SPTask::CheckFutureFps(std::future<std::map<std::string, std::string>> &fpsResult,
242     std::map<std::string, std::string> &dataMap)
243 {
244     if (fpsResult.valid()) {
245         std::map<std::string, std::string> result = fpsResult.get();
246         dataMap.insert(result.begin(), result.end());
247     }
248 }
249 
CheckFutureFds(std::future<std::map<std::string,std::string>> & fdsResult,std::map<std::string,std::string> & dataMap)250 void SPTask::CheckFutureFds(std::future<std::map<std::string, std::string>> &fdsResult,
251     std::map<std::string, std::string> &dataMap)
252 {
253     if (fdsResult.valid()) {
254         std::map<std::string, std::string> result = fdsResult.get();
255         dataMap.insert(result.begin(), result.end());
256     }
257 }
258 
GetItemData(std::map<std::string,std::string> & dataMap)259 void SPTask::GetItemData(std::map<std::string, std::string> &dataMap)
260 {
261     for (std::string itConfig : curTaskInfo.taskConfig) {
262         if (itConfig.find("-snapshot") != std::string::npos && screenshotFlag) {
263             Capture::GetInstance().SocketMessage();
264             std::map<std::string, std::string> captureMap = Capture::GetInstance().ItemData();
265             dataMap.insert(captureMap.begin(), captureMap.end());
266         }
267 
268         if (itConfig.find("-gc") != std::string::npos ||
269             itConfig.find("-o") != std::string::npos ||
270             itConfig.find("-lockfreq") != std::string::npos) {
271             continue;
272         }
273 
274         SpProfiler *profiler = SpProfilerFactory::GetCmdProfilerItem(COMMAND_MAP.at(itConfig), false);
275         if (profiler != nullptr) {
276             std::map<std::string, std::string> itemMap = profiler->ItemData();
277             dataMap.insert(itemMap.begin(), itemMap.end());
278         }
279     }
280 }
281 
ConfigDataThread()282 void SPTask::ConfigDataThread()
283 {
284     for (std::string itConfig : curTaskInfo.taskConfig) {
285         if (!sdkData) {
286             ConfigureSdkData(itConfig);
287         }
288 
289         if (itConfig.find("-gc") != std::string::npos) {
290             WLOGI("Starting GpuCounter collection in new thread");
291             gpuCounter.StartCollect(GpuCounter::GC_START);
292         }
293 
294         if (itConfig.find("-lockfreq") != std::string::npos) {
295             lockFreq.SetIsCollecting(true);
296             lockFreqThread = std::thread([this]() {
297                 WLOGI("Starting lock frequency locking thread");
298                 this->lockFreq.LockingThread();
299             });
300         }
301     }
302 }
303 
ConfigureSdkData(std::string itConfig)304 void SPTask::ConfigureSdkData(std::string itConfig)
305 {
306     if (itConfig.find("-o") != std::string::npos) {
307         sdkData = true;
308         OHOS::system::SetParameter("debug.smartperf.sdkdataenable", "1");
309         SdkDataRecv &sdkDataRecv = SdkDataRecv::GetInstance();
310         sdkDataRecv.SetRunningState(true);
311         WLOGI("Starting sdkdata collection in new thread");
312         sdk = std::thread([&sdkDataRecv, this]() { this->RunSdkServer(sdkDataRecv); });
313     }
314 }
315 
RunSdkServer(SdkDataRecv & sdkDataRecv)316 void SPTask::RunSdkServer(SdkDataRecv &sdkDataRecv)
317 {
318     sdkDataRecv.ServerThread(sdkvec);
319 }
320 
ResetSdkParam()321 void SPTask::ResetSdkParam()
322 {
323     WLOGI("Disabling sdk data collection and resetting parameters");
324     OHOS::system::SetParameter("debug.smartperf.sdkdataenable", "0");
325     sdkData = false;
326     SdkDataRecv &sdkDataRecv = SdkDataRecv::GetInstance();
327     sdkDataRecv.SetRunningState(false);
328     int listenFd = sdkDataRecv.GetListenFd();
329     if (listenFd != -1) {
330         LOGD("Closing sdk data listenFd: %d", listenFd);
331         close(listenFd);
332         sdkDataRecv.SetListenFd(-1);
333     }
334     if (sdk.joinable()) {
335         LOGD("Joining sdk data server thread");
336         sdk.join();
337     }
338 }
339 
StopSdkRecv()340 void SPTask::StopSdkRecv()
341 {
342     if (!sdkData || sdkvec.size() <= 0) {
343         WLOGI("SDK data is not enabled or sdkvec is empty");
344         return;
345     }
346     LOGD("SDK data stop");
347     std::string outSdkDataDir = baseOutPath + "/" + curTaskInfo.sessionId;
348     char outSdkDataDirChar[PATH_MAX] = {0x00};
349     if (realpath(outSdkDataDir.c_str(), outSdkDataDirChar) == nullptr) {
350         WLOGE("data dir %s is nullptr", outSdkDataDir.c_str());
351         return;
352     }
353     std::string outSdkDataPath = std::string(outSdkDataDirChar) + "/sdk_data.csv";
354     sdkDataMtx.lock();
355     std::ofstream outFile;
356     outFile.open(outSdkDataPath.c_str(), std::ios::out | std::ios::trunc);
357     if (!outFile.is_open()) {
358         WLOGE("data %s open failed", outSdkDataPath.c_str());
359         sdkDataMtx.unlock();
360         return;
361     }
362     std::string title = "source,timestamp,eventName,enable,value\r";
363     outFile << title << std::endl;
364     for (const auto &item : sdkvec) {
365         outFile << item << std::endl;
366     }
367     outFile.close();
368     sdkDataMtx.unlock();
369     WLOGI("SDK data written successfully to %s", outSdkDataPath.c_str());
370     return;
371 }
372 
InitDataFile()373 void SPTask::InitDataFile()
374 {
375     vmap.clear();
376     sdkvec.clear();
377     gpuCounter.GetGpuCounterSaveReportData().clear();
378     SdkDataRecv::GetInstance().SetStartRecordTime();
379     startTime = SPUtils::GetCurTime();
380     std::vector<std::string> files = {
381         "sdk_data.csv",
382         "gpu_counter.csv",
383         "t_general_info.csv",
384         "t_index_info.csv",
385     };
386     std::string fileDir = baseOutPath + "/" + curTaskInfo.sessionId;
387 
388     for (const auto &file: files) {
389         std::string filePath = fileDir + "/" + file;
390         char filePathChar[PATH_MAX] = {0x00};
391         if (realpath(filePath.c_str(), filePathChar) == nullptr) {
392             LOGE("%s is not exist, init finish.", filePath.c_str());
393             continue;
394         }
395         std::remove(filePathChar);
396     }
397 
398     LOGD("Data file initialization completed.");
399     return;
400 }
401 
SetProfilerPid()402 void SPTask::SetProfilerPid()
403 {
404     SpProfilerFactory::editorFlag = true;
405     std::string processId = "";
406     std::string processIds = "";
407     OHOS::SmartPerf::StartUpDelay sp;
408     processId = sp.GetPidByPkg(curTaskInfo.packageName, &processIds);
409     SpProfilerFactory::SetProfilerPidByPkg(processId, processIds);
410 }
411 
AsyncGetDataMap(std::function<void (std::string data)> msgTask)412 void SPTask::AsyncGetDataMap(std::function<void(std::string data)> msgTask)
413 {
414     long long lastTime = SPUtils::GetCurTime();
415     asyncDataMtx.lock();
416     std::map<std::string, std::string> dataMap;
417     if (!curTaskInfo.packageName.empty()) {
418         SetProfilerPid();
419     }
420     dataMap.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(lastTime)));
421     std::future<std::map<std::string, std::string>> fpsResult = AsyncCollectFps();
422     std::future<std::map<std::string, std::string>> cpuResult = AsyncCollectCpu();
423     std::future<std::map<std::string, std::string>> ramResult = AsyncCollectRam();
424     std::future<std::map<std::string, std::string>> fdsResult = AsyncCollectFds();
425     GetItemData(dataMap);
426     CheckFutureFps(fpsResult, dataMap);
427     CheckFutureCpu(cpuResult, dataMap);
428     CheckFutureRam(ramResult, dataMap);
429     CheckFutureFds(fdsResult, dataMap);
430     if (curTaskInfo.stuckInfo.isEffective && recordTrace) {
431         std::map<std::string, std::string> timeUsedMap = DetectionAndGrab();
432         if (!timeUsedMap.empty()) {
433             dataMap.insert(timeUsedMap.begin(), timeUsedMap.end());
434         }
435     }
436     SPData spdata;
437     spdata.values.insert(dataMap.begin(), dataMap.end());
438     if (GetRecordState()) {
439         ProcessErrorData(spdata);
440     }
441     gpuCounter.GetGpuRealtimeData(dataMap);
442     SdkDataRecv::GetInstance().GetSdkDataRealtimeData(dataMap);
443     if (GetRecordState()) {
444         PrintMap(dataMap);
445     }
446     msgTask(MapToString(dataMap));
447     nextTime = SPUtils::GetCurTime();
448     long long costTime = nextTime - lastTime;
449     long long pTime = 998;
450     if (costTime < curTaskInfo.freq) {
451         std::this_thread::sleep_for(std::chrono::milliseconds(pTime - costTime));
452     }
453     asyncDataMtx.unlock();
454 }
455 
StartTask(std::function<void (std::string data)> msgTask)456 ErrCode SPTask::StartTask(std::function<void(std::string data)> msgTask)
457 {
458     LOGD("Task starting...");
459     RAM &ram = RAM::GetInstance();
460     ram.SetFirstFlag();
461     LOGD("RAM first flag set.");
462     if (!isInit) {
463         WLOGE("Initialization failed.");
464         return ErrCode::FAILED;
465     }
466     isRunning = true;
467     realTimeStart = SPUtils::GetCurTime();
468     LOGD("Task initialized, realTimeStart = %lld", realTimeStart);
469     if (!curTaskInfo.packageName.empty()) {
470         SpProfilerFactory::SetProfilerPkg(curTaskInfo.packageName);
471         LOGD("Profiler package name set to: %s", curTaskInfo.packageName.c_str());
472     } else {
473         LOGW("No package name provided for profiler.");
474     }
475     if (!curTaskInfo.pid.empty()) {
476         SpProfilerFactory::SetProfilerPidByPkg(curTaskInfo.pid);
477     }
478     InitDataFile();
479     LOGD("Data files initialized.");
480     ConfigDataThread();
481     LOGD("Data collection thread configuration completed.");
482     thread = std::thread([this, msgTask]() {
483         WLOGI("Starting data collection thread.");
484         while (isRunning) {
485             AsyncGetDataMap(msgTask);
486         }
487         WLOGI("Data collection thread exiting.");
488         if (curTaskInfo.isPrint) {
489             std::cerr << "End please press the enter key..." << std::endl << std::flush;
490         }
491     });
492     EnablePrint();
493     return ErrCode::OK;
494 }
495 
CreatPath(std::string path)496 void SPTask::CreatPath(std::string path)
497 {
498     if (!SPUtils::FileAccess(path)) {
499         LOGD("CreatPath does not exist, attempting to create: %s", path.c_str());
500         std::string cmdResult;
501         std::string creatPath = CMD_COMMAND_MAP.at(CmdCommand::CREAT_DIR) + path;
502         bool cmdSuccess = SPUtils::LoadCmd(creatPath, cmdResult);
503         if (cmdSuccess) {
504             LOGD("CreatPath created successfully: %s", path.c_str());
505         } else {
506             LOGE("Failed to create path: %s. Command result: %s", path.c_str(), cmdResult.c_str());
507         }
508     } else {
509         LOGD("CreatPath already exists: %s", path.c_str());
510     }
511 }
512 
SetTaskInfo()513 std::map<std::string, std::string> SPTask::SetTaskInfo()
514 {
515     long long endTime = SPUtils::GetCurTime();
516     long long testDuration = (endTime - startTime) / 1000;
517     std::string refreshrate;
518     LOGD("Test duration: %lld seconds", testDuration);
519     const std::string gpuDataVersion = "1.1";
520     std::string screenStr = SPUtils::GetScreen();
521     size_t pos3 = screenStr.find("=");
522     if (pos3 != std::string::npos) {
523         refreshrate = screenStr.substr(pos3 + 1);
524         LOGD("Screen refresh rate: %s", refreshrate.c_str());
525     } else {
526         LOGW("Failed to extract refresh rate from screen string: %s", screenStr.c_str());
527     }
528 
529     std::map<std::string, std::string> taskInfoMap = {
530         { "sessionId", curTaskInfo.sessionId },
531         { "taskId", curTaskInfo.sessionId },
532         { "appName", curTaskInfo.packageName },
533         { "packageName", curTaskInfo.packageName },
534         { "pid", curTaskInfo.pid },
535         { "startTime", std::to_string(startTime) },
536         { "endTime", std::to_string(endTime) },
537         { "testDuration", std::to_string(testDuration) },
538         { "taskName", "testtask" },
539         { "board", "hw" },
540         { "target_fps", refreshrate },
541         { "gpuDataVersion", gpuDataVersion },
542         { "battery_change", std::to_string(battaryEnd - battaryStart) },
543     };
544     return taskInfoMap;
545 }
546 
StopGetInfo()547 void SPTask::StopGetInfo()
548 {
549     bool isTcpMessage = true;
550     CreatPath(baseOutPath);
551     std::string thisBasePath = baseOutPath + "/" + curTaskInfo.sessionId;
552     CreatPath(thisBasePath);
553     std::string outIndexpath = thisBasePath + "/t_index_info.csv";
554 
555     std::map<std::string, std::string> taskInfoMap = SetTaskInfo();
556     std::map<std::string, std::string> deviceInfo = SPUtils::GetDeviceInfo();
557     if (deviceInfo.empty()) {
558         LOGW("Failed to get device info when stop.");
559     }
560     std::map<std::string, std::string> cpuInfo = SPUtils::GetCpuInfo(isTcpMessage);
561     if (cpuInfo.empty()) {
562         LOGW("Failed to get CPU info when stop.");
563     }
564     std::map<std::string, std::string> gpuInfo = SPUtils::GetGpuInfo(isTcpMessage);
565     if (gpuInfo.empty()) {
566         LOGW("Failed to get GPU info when stop.");
567     }
568     std::map<std::string, std::string> destMap;
569     destMap.insert(taskInfoMap.begin(), taskInfoMap.end());
570     destMap.insert(deviceInfo.begin(), deviceInfo.end());
571     destMap.insert(cpuInfo.begin(), cpuInfo.end());
572     destMap.insert(gpuInfo.begin(), gpuInfo.end());
573     OHOS::SmartPerf::SpCsvUtil::WriteCsvH(destMap);
574     OHOS::SmartPerf::SpCsvUtil::WriteCsv(outIndexpath, vmap);
575     WLOGI("Write CSV header done.");
576 }
StopGpuCounterRecv()577 void SPTask::StopGpuCounterRecv()
578 {
579     std::string outGpuCounterDataPath = baseOutPath + "/" + curTaskInfo.sessionId;
580 
581     if (GetRecordState()) {
582         WLOGI("Record state is valid. Saving GPU counter data.");
583         gpuCounter.GetInstance().SaveData(outGpuCounterDataPath);
584     } else {
585         WLOGW("Record state is invalid. GPU counter data will not be saved.");
586     }
587 }
StopTask()588 ErrCode SPTask::StopTask()
589 {
590     if (GetRecordState()) {
591         WLOGI("Record state is valid. Stopping task and cleaning up.");
592         StopGetInfo();
593         StopSdkRecv();
594         StopGpuCounterRecv();
595 
596         vmap.clear();
597         sdkvec.clear();
598         gpuCounter.GetGpuCounterData().clear();
599         recordState = false;
600         screenshotFlag = false;
601     } else {
602         WLOGW("Record state is invalid. Skipping task stop operations.");
603     }
604 
605     ResetSdkParam();
606     gpuCounter.StopCollect();
607     lockFreq.SetIsCollecting(false);
608     if (lockFreqThread.joinable()) {
609         LOGD("Joining lockFreqThread.");
610         lockFreqThread.join();
611     }
612 
613     WLOGI("Stopping task. isRunning: %d, isInit: %d", isRunning, isInit);
614     isRunning = false;
615     isInit = false;
616     realTimeStart = 0;
617     if (stdOutLog >= 0) {
618         close(stdOutLog);
619         stdOutLog = -1;
620     }
621     if (thread.joinable()) {
622         LOGD("Joining thread.");
623         thread.join();
624     }
625     LOGD("Killing Hiperf command.");
626     SpProfilerFactory::editorFlag = false;
627     WLOGI("Task successfully stopped.");
628     return ErrCode::OK;
629 }
630 
DetectionAndGrab()631 std::map<std::string, std::string> SPTask::DetectionAndGrab()
632 {
633     std::map<std::string, std::string> templateMap;
634     if (!curTaskInfo.stuckInfo.isEffective) {
635         LOGE("StuckInfo is not effective. Returning empty map.");
636         return templateMap;
637     }
638 
639     FpsCurrentFpsTime fcf = FPS::GetInstance().GetFpsCurrentFpsTime();
640     long long nowTime = SPUtils::GetCurTime();
641     long long curframeTime = fcf.currentFpsTime / RM_1000000; // Convert to milliseconds
642     LOGD("Start capture time: %lld", startCaptuerTime);
643 
644     if (startCaptuerTime > 0) {
645         long long diff =
646             startCaptuerTime > nowTime ? (LLONG_MAX - startCaptuerTime + nowTime) : (nowTime - startCaptuerTime);
647         LOGD("Time difference: %lld ms", diff);
648 
649         if (diff > RM_5000 && (!CheckCounterId())) {
650             LOGW("Time difference exceeded threshold, resetting start capture time.");
651             startCaptuerTime = RM_0;
652         }
653     }
654 
655     if (curTaskInfo.stuckInfo.fps > fcf.fps || curTaskInfo.stuckInfo.frameTime < curframeTime) {
656         if (startCaptuerTime == 0) {
657             startCaptuerTime = nowTime;
658             LOGD("ThreadGetHiperf::%ld", startCaptuerTime);
659             ThreadGetHiperf(startCaptuerTime);
660         }
661     }
662     templateMap["fpsWarn"] = std::to_string(fcf.fps);
663     templateMap["FrameTimeWarn"] = std::to_string(fcf.currentFpsTime);
664     templateMap["TraceTime"] = std::to_string(startCaptuerTime);
665 
666     return templateMap;
667 }
668 
CheckCounterId()669 bool SPTask::CheckCounterId()
670 {
671     std::string result;
672     std::string hiprofilerCmd = CMD_COMMAND_MAP.at(CmdCommand::HIPROFILER_CMD);
673     LOGD("Loading hiprofiler command");
674     SPUtils::LoadCmd(hiprofilerCmd, result);
675     if (result.empty()) {
676         LOGW("Failed to load hiprofiler command or received empty result.");
677         return false;
678     }
679 
680     if (result.find("-k") != std::string::npos) {
681         LOGD("Command contains '-k'.");
682         return true;
683     }
684 
685     LOGD("Command does not contain '-k'.");
686     return false;
687 }
ThreadGetHiperf(long long timeStamp)688 std::thread SPTask::ThreadGetHiperf(long long timeStamp)
689 {
690     auto thGetTrace = [this, timeStamp]() { this->GetHiperf(std::to_string(timeStamp)); };
691     std::thread spThread(thGetTrace);
692     spThread.detach();
693     return spThread;
694 }
695 
GetHiperf(const std::string & traceName)696 void SPTask::GetHiperf(const std::string &traceName)
697 {
698     std::string result;
699     std::string tmp = SetHiperf(traceName);
700     std::cout << tmp << std::endl;
701     SPUtils::LoadCmd(tmp, result);
702     LOGD("hiprofiler exec (%s), hiprofiler exec trace name(%s), hiprofiler exec end (%s)",
703         tmp.c_str(), traceName.c_str(), result.c_str());
704 }
705 
706 
CheckTcpParam(std::string str,std::string & errorInfo)707 bool SPTask::CheckTcpParam(std::string str, std::string &errorInfo)
708 {
709     std::set<std::string> keys;
710     std::string params;
711     if (str.find("-SESSIONID") != std::string::npos) {
712         params = str.substr(str.find("-SESSIONID"));
713     } else {
714         LOGE("Init parameter error not contain '-SESSIONID'");
715         return false;
716     }
717     LOGD("Start validating Init parameter: %s", params.c_str());
718 
719     for (auto a : COMMAND_MAP) {
720         keys.insert(a.first.substr(1)); // 不需要前面的'-'
721     }
722     bool isValid = SPUtils::VeriyParameter(keys, params, errorInfo);
723     if (isValid) {
724         LOGD("Init parameter validation successful");
725     } else {
726         LOGE("Init parameter validation failed, Error: %s", errorInfo.c_str());
727     }
728     return isValid;
729 }
730 
KillHiperfCmd()731 void SPTask::KillHiperfCmd()
732 {
733     long long now = 0;
734     long long runTime = 0;
735     std::string killCmd = CMD_COMMAND_MAP.at(CmdCommand::KILL_CMD) + "-9 ";
736     std::string result;
737     std::vector<std::string> out;
738 
739     if (startCaptuerTime <= 0) {
740         return;
741     }
742 
743     now = SPUtils::GetCurTime();
744     runTime = now > startCaptuerTime ? now - startCaptuerTime : LLONG_MAX - startCaptuerTime + now;
745     runTime = runTime / RM_1000; // Convert to seconds
746 
747     LOGD("Preparing to exit run time(%lld)", runTime);
748     do {
749         out.clear();
750         std::string hiprofilerPid = CMD_COMMAND_MAP.at(CmdCommand::HIPROFILER_PID);
751         SPUtils::LoadCmd(hiprofilerPid, result);
752         SPUtils::StrSplit(result, " ", out);
753         if (out.empty()) {
754             break;
755         }
756 
757         sleep(1);
758     } while (END_WAITING_TIME - runTime++ > 0);
759 
760     out.clear();
761     std::string hiprofilerPid = CMD_COMMAND_MAP.at(CmdCommand::HIPROFILER_PID);
762     SPUtils::LoadCmd(hiprofilerPid, result);
763     SPUtils::StrSplit(result, " ", out);
764     LOGD("pidof hiprofiker_cmd size(%d)", out.size());
765     for (auto it = out.begin(); out.end() != it; ++it) {
766         result.clear();
767         SPUtils::LoadCmd(killCmd + (*it), result);
768     }
769 
770     return;
771 }
772 
SetHiperf(const std::string & traceName)773 std::string SPTask::SetHiperf(const std::string &traceName)
774 {
775     std::string hiPrefix = "hiprofiler_";
776     std::string dataPrefix = "perf_";
777     requestId++;
778     std::string trtmp = strOne + hiPrefix + traceName + strTwo + "\n" + strThree + std::to_string(requestId) + "\n" +
779         strFour + "\n" + strFive + hiPrefix + traceName + strSix + "\n" + strNine + strEleven + "\n" + strSeven +
780         dataPrefix + traceName + strEight + strTen + "\n" + conFig;
781     return trtmp;
782 }
783 
GetRecordState()784 bool SPTask::GetRecordState()
785 {
786     return recordState;
787 }
GetCurrentBattary()788 int SPTask::GetCurrentBattary()
789 {
790     std::string content;
791     const std::string cmd = "hidumper -s 3302 -a -i | grep capacity";
792     SPUtils::LoadCmd(cmd, content);
793     content = content.substr(content.find(':') + 1);
794     if (content == "") {
795         WLOGE("Battery capacity is empty.");
796         return 0;
797     }
798     return SPUtilesTye::StringToSometype<int>(content);
799 }
800 
StartRecord()801 ErrCode SPTask::StartRecord()
802 {
803     battaryStart = GetCurrentBattary();
804     startTime = SPUtils::GetCurTime();
805     WLOGI("StartRecord initiated: Battery %d, Start time %lld.", battaryStart, startTime);
806     while (startTime > nextTime) {
807         std::this_thread::sleep_for(std::chrono::milliseconds(1));
808     }
809     InitDataFile();
810     screenshotFlag = true;
811     recordState = true;
812     recordTrace = true;
813     return ErrCode::OK;
814 }
815 
StopRecord()816 ErrCode SPTask::StopRecord()
817 {
818     battaryEnd = GetCurrentBattary();
819     long long stopRecordTime = SPUtils::GetCurTime();
820     WLOGI("StopRecord initiated: Battery %d, Stop time %lld.", battaryEnd, stopRecordTime);
821     while (stopRecordTime > nextTime) {
822         std::this_thread::sleep_for(std::chrono::milliseconds(1));
823     }
824     screenshotFlag = false;
825     recordState = false;
826     recordTrace = false;
827     std::string outGpuCounterDataPath = baseOutPath + "/" + curTaskInfo.sessionId;
828 
829     if (isInit) {
830         StopGetInfo();
831         if (sdkData) {
832             StopSdkRecv();
833         }
834         gpuCounter.GetInstance().SaveData(outGpuCounterDataPath);
835     }
836 
837     vmap.clear();
838     sdkvec.clear();
839     gpuCounter.GetGpuCounterData().clear();
840     Capture::GetInstance().SetCollectionNum();
841     KillHiperfCmd();
842 
843     return ErrCode::OK;
844 }
GetRealStartTime() const845 time_t SPTask::GetRealStartTime() const
846 {
847     return realTimeStart;
848 }
SetTcpToken(std::string token)849 void SPTask::SetTcpToken(std::string token)
850 {
851     tcpToken = token;
852 }
GetTcpToken()853 std::string SPTask::GetTcpToken()
854 {
855     return tcpToken;
856 }
ProcessErrorData(SPData & spdata)857 void SPTask::ProcessErrorData(SPData &spdata)
858 {
859     unsigned int newDataSize = spdata.values.size();
860     if (newDataSize > dataSize) {
861         for (auto iter = spdata.values.cbegin(); iter != spdata.values.cend(); ++iter) {
862             csvTitle += iter->first + ",";
863         }
864         if (!vmap.empty()) {
865             vmap.pop_back();
866         }
867     }
868     dataSize = newDataSize;
869     vmap.push_back(spdata);
870 }
GetCsvTitle()871 std::string SPTask::GetCsvTitle()
872 {
873     return csvTitle;
874 }
SetRecordState(bool status)875 void SPTask::SetRecordState(bool status)
876 {
877     recordState = status;
878 }
EnablePrint()879 void SPTask::EnablePrint()
880 {
881     if (curTaskInfo.isPrint) {
882         stdOutLog = SPUtils::GetTtyDeviceFd();
883         if (dup2(stdOutLog, STDERR_FILENO) < 0) {
884             LOGE("Dup2 fail");
885         } else {
886             close(stdOutLog);
887             stdOutLog = -1;
888         }
889     } else {
890         int &fd = SPUtils::GetTtyDeviceFd();
891         if (fd >= 0) {
892             close(fd);
893             fd = -1;
894         }
895     }
896 }
897 }
898 }
899