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