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