• 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 <cstdio>
16 #include <algorithm>
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include <unistd.h>
21 #include <ctime>
22 #include <sys/time.h>
23 #include "include/sp_utils.h"
24 #include "include/FPS.h"
25 #include "include/startup_delay.h"
26 #include "include/sp_log.h"
27 #include "include/common.h"
28 #include <sys/wait.h>
29 #include <sys/types.h>
30 #include "include/GameEvent.h"
31 #include "transaction/rs_interfaces.h"
32 #include "include/ByTrace.h"
33 #include "include/sp_profiler_factory.h"
34 namespace OHOS {
35 namespace SmartPerf {
36 bool HAVE_CATON = false;
ItemData()37 std::map<std::string, std::string> FPS::ItemData()
38 {
39     std::map<std::string, std::string> result;
40     FpsInfo fpsInfoResult;
41     if (surfaceViewName.length() > 0) {
42         fpsInfoResult = GetDiffLayersFpsInfo(surfaceViewName);
43     } else {
44         fpsInfo.currDumpTimeStamps.clear();
45         fpsInfoResult = GetFpsInfo();
46     }
47     prevResultFpsInfo = fpsInfoResult;
48     std::string value = FindFpsRefreshrate();
49     result["refreshrate"] = value;
50     if (processFlag) {
51         result["fps"] = "NA";
52         result["fpsJitters"] = "NA";
53     } else {
54         GetFpsAndJitters(fpsInfoResult, result);
55     }
56     LOGI("FPS:ItemData map size(%u)", result.size());
57     return result;
58 }
59 
GetFpsAndJitters(FpsInfo & fpsInfoResult,std::map<std::string,std::string> & result)60 std::map<std::string, std::string> FPS::GetFpsAndJitters(FpsInfo &fpsInfoResult,
61     std::map<std::string, std::string> &result)
62 {
63     const int fullFrame = 120;
64     const int maxFullFrame = 123;
65     if (fpsInfoResult.fps > fullFrame && fpsInfoResult.fps < maxFullFrame) {
66         fpsInfoResult.fps = fullFrame;
67     }
68     result["fps"] = std::to_string(fpsInfoResult.fps);
69     std::string jitterStr = "";
70     std::string split = "";
71     for (size_t i = 0; i < fpsInfoResult.jitters.size(); i++) {
72         if (i > 0) {
73             split = ";;";
74         }
75         jitterStr += split + std::to_string(fpsInfoResult.jitters[i]);
76     }
77     if (hapNeedCatonInfo && inGameSceneNum > eleven) {
78         CalcFatalCaton(fpsInfoResult.jitters);
79     }
80     result["fpsJitters"] = jitterStr;
81     LOGD("result.fps: %s, result.curTime: %s, result.jitters: %s",
82         std::to_string(fpsInfoResult.fps).c_str(),
83         std::to_string(fpsInfoResult.curTime).c_str(),
84         jitterStr.c_str());
85     SetFpsCurrentFpsTime(fpsInfoResult);
86     if (isCatchTrace > 0) {
87         long long maxJitters = 0;
88         if (!fpsInfoResult.jitters.empty()) {
89             auto maxElement = std::max_element(fpsInfoResult.jitters.begin(), fpsInfoResult.jitters.end());
90             maxJitters = static_cast<long long>(*maxElement / oneSec);
91         }
92         ByTrace::GetInstance().CheckFpsJitters(maxJitters, fpsInfoResult.fps);
93     }
94     return result;
95 }
96 
CalcFatalCaton(std::vector<long long> & jitters)97 void FPS::CalcFatalCaton(std::vector<long long>& jitters)
98 {
99     if (!HAVE_CATON && catonNum == 0) {
100         for (long long &timestamp : jitters) {
101             if ((timestamp / 1e6) > hundred) {
102                 HAVE_CATON = true;
103                 catonNum = 1;
104                 ipcCallback_("haveCaton");
105                 break;
106             }
107         }
108     }
109 }
110 
GetGameScenStatus()111 void FPS::GetGameScenStatus()
112 {
113     if (!hapNeedCatonInfo || catonNum > 0) {
114         return;
115     }
116     std::map<std::string, std::string> gameEvent = GameEvent::GetInstance().GetGameEventItemData();
117     for (const auto& item : gameEvent) {
118         if (item.first == "sceneId") {
119             if (item.second == "4") {
120                 inGameSceneNum++;
121             } else {
122                 inGameSceneNum = 0;
123             }
124         }
125     }
126     LOGD("IN GAME SCENE inGameSceneNum (%d)", inGameSceneNum);
127 }
128 
StartExecutionOnce(bool isPause)129 void FPS::StartExecutionOnce(bool isPause)
130 {
131     if (isPause) {
132         return;
133     }
134     isGameApp = SPUtils::GetIsGameApp(pkgName);
135     catonNum = 0;
136 }
137 
SetFpsCurrentFpsTime(FpsInfo fpsInfoResult)138 void FPS::SetFpsCurrentFpsTime(FpsInfo fpsInfoResult)
139 {
140     ffTime.fps = fpsInfoResult.fps;
141     if (!fpsInfoResult.jitters.empty()) {
142         auto maxElement = std::max_element(fpsInfoResult.jitters.begin(), fpsInfoResult.jitters.end());
143         ffTime.currentFpsTime = *maxElement;
144     }
145 }
146 
GetFpsCurrentFpsTime()147 FpsCurrentFpsTime FPS::GetFpsCurrentFpsTime()
148 {
149     return ffTime;
150 }
151 
SetPackageName(const std::string & pName)152 void FPS::SetPackageName(const std::string& pName)
153 {
154     pkgName = pName;
155 }
156 
SetProcessId(const std::string & pid)157 void FPS::SetProcessId(const std::string &pid)
158 {
159     processId = pid;
160 }
161 
SetLayerName(const std::string & sName)162 void FPS::SetLayerName(const std::string& sName)
163 {
164     surfaceViewName = sName;
165     isNeedDump = true;
166 }
GetDiffLayersFpsInfo(const std::string & sName)167 FpsInfo FPS::GetDiffLayersFpsInfo(const std::string &sName)
168 {
169     OHOS::SmartPerf::SPUtils::GetCurrentTime(prevResultFpsInfo.curTime);
170     fpsInfoData = GetSurfaceFrame(sName);
171     return fpsInfoData;
172 }
173 
GetFpsInfo()174 FpsInfo FPS::GetFpsInfo()
175 {
176     processFlag = false;
177     fpsInfoData.fps = 0;
178     if (isGameApp) {
179         if (gameLayerName.empty()) {
180             std::string processIds = "";
181             OHOS::SmartPerf::StartUpDelay sp;
182             processId = sp.GetPidByPkg(pkgName, &processIds);
183             SpProfilerFactory::SetProfilerPidByPkg(processId, processIds);
184             gameLayerName = GetGameLayer();
185             if (gameLayerName.empty()) {
186                 fpsInfoData.fps = 0;
187                 fpsInfoData.jitters.clear();
188                 return fpsInfoData;
189             }
190         }
191         GetGameScenStatus();
192         OHOS::SmartPerf::SPUtils::GetCurrentTime(prevResultFpsInfo.curTime);
193         fpsInfoData = GetSurfaceFrame(gameLayerName);
194         if (fpsInfoData.fps == 0) {
195             return GetChangedLayerFps();
196         } else {
197             return fpsInfoData;
198         }
199     } else {
200         std::string uniteLayer;
201         if (ohFlag) {
202             uniteLayer = OHOS::SmartPerf::SPUtils::GetSurface();
203         } else if (!rkFlag && !isOtherDevice) {
204             uniteLayer = "UniRender";
205         } else {
206             uniteLayer = OHOS::SmartPerf::SPUtils::GetSurface();
207             isNeedDump = true;
208         }
209         if (isSections || pkgName.find("sceneboard") != std::string::npos) {
210             OHOS::SmartPerf::SPUtils::GetCurrentTime(prevResultFpsInfo.curTime);
211             fpsInfoData = GetSurfaceFrame(uniteLayer);
212         } else {
213             fpsInfoData = GetAppFps(uniteLayer);
214         }
215     }
216     return fpsInfoData;
217 }
218 
GetAppFps(std::string & uniteLayer)219 FpsInfo FPS::GetAppFps(std::string &uniteLayer)
220 {
221     bool onTop = OHOS::SmartPerf::SPUtils::IsForeGround(pkgName);
222     if (onTop) {
223         OHOS::SmartPerf::SPUtils::GetCurrentTime(prevResultFpsInfo.curTime);
224         fpsInfoData = GetSurfaceFrame(uniteLayer);
225     } else {
226         LOGD("FPS::app is in the background");
227         if (processId.empty()) {
228             processFlag = true;
229         }
230         fpsInfoData.fps = 0;
231         fpsInfoData.jitters.clear();
232     }
233     return fpsInfoData;
234 }
235 
SetOtherDeviceFlag()236 bool FPS::SetOtherDeviceFlag()
237 {
238     isOtherDevice = true;
239     return isOtherDevice;
240 }
241 
GetChangedLayerFps()242 FpsInfo FPS::GetChangedLayerFps()
243 {
244     gameLayerName = GetGameLayer();
245     if (gameLayerName.empty()) {
246         //start-stop -VIEW -profilerfps ohtest rk3568 historyHap
247         if (processId.empty()) {
248             processFlag = true;
249         }
250         fpsInfoData.fps = 0;
251         fpsInfoData.jitters.clear();
252     } else {
253         fpsInfoData = GetSurfaceFrame(gameLayerName);
254     }
255     return fpsInfoData;
256 }
257 
GetSurfaceFrame(const std::string & name)258 FpsInfo FPS::GetSurfaceFrame(const std::string& name)
259 {
260     if (name == "") {
261         return FpsInfo();
262     }
263     FpsInfo tmpFps;
264     tmpFps.fps = 0;
265     tmpFps.jitters.clear();
266     fpsInfo = tmpFps;
267     fpsNum = 0;
268     prevScreenTimestamp = -1;
269     struct timespec time1 = { 0 };
270     clock_gettime(CLOCK_MONOTONIC, &time1);
271     fpsInfo.curTime = static_cast<int>(time1.tv_sec - 1);
272     fpsInfo.currTimeDump = (time1.tv_sec - 1) * mod + time1.tv_nsec;
273     LOGD("FPS:fpsInfo.curTime: %d, FPS:psInfo.currTimeDump: %lld", fpsInfo.curTime, fpsInfo.currTimeDump);
274     if (name == "UniRender" || isNeedDump || isHistoryHap) {
275         fpsInfo = GetFpsInfoByDump(name);
276     } else {
277         fpsInfo = GetFpsInfoByRs(name);
278     }
279     return fpsInfo;
280 }
281 
GetFpsInfoByDump(const std::string & name)282 FpsInfo FPS::GetFpsInfoByDump(const std::string& name)
283 {
284     std::string command = "";
285     if (isNeedDump && isGameApp) {
286         command = "fps -id " + name;
287     } else {
288         command = "fps " + name;
289     }
290     const std::vector<const char*> args = { "hidumper", "-s", "10", "-a", command.c_str(), nullptr };
291     int pipefd[2];
292     pid_t pid;
293     if (pipe(pipefd) == -1) {
294         LOGE("FPS::Failed to create pipe");
295         return fpsInfo;
296     }
297     pid = fork();
298     if (pid == -1) {
299         LOGE("FPS::Failed to fork");
300         return fpsInfo;
301     }
302     if (pid == 0) {
303         close(pipefd[0]);
304         dup2(pipefd[1], STDOUT_FILENO);
305         close(pipefd[1]);
306         execvp(args[0], const_cast<char *const*>(args.data()));
307         LOGE("FPS::Failed to execute hidumper");
308         _exit(EXIT_FAILURE);
309     }
310     close(pipefd[1]);
311     ReadDataFromPipe(pipefd[0]);
312     waitpid(pid, nullptr, 0);
313     return fpsInfo;
314 }
315 
316 
ReadDataFromPipe(int fd)317 void FPS::ReadDataFromPipe(int fd)
318 {
319     char tmp[1024];
320     bool isBreak = false;
321     if (isSections) {
322         GetTimeDiff();
323     }
324     FILE *fp = fdopen(fd, "r");
325     if (!fp) {
326         LOGE("FPS::Failed to open file descriptor");
327         close(fd);
328         return;
329     }
330     std::stringstream sstream;
331     while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
332         LOGD("FPS::ReadDataFromPipe::dump time: %s", tmp);
333         std::string tmpStr(tmp);
334         curScreenTimestamp = 0;
335         sstream.clear();
336         sstream.str(tmpStr);
337         sstream >> curScreenTimestamp;
338         if (curScreenTimestamp == 0) {
339             continue;
340         }
341         if (CalcFpsAndJitters(isBreak)) {
342             break;
343         }
344     }
345     (void)fclose(fp);
346     if (!hapLowFpsFlag || !isLowCurFps) {
347         CalcJitters();
348     }
349 }
350 
GetFpsInfoByRs(const std::string & name)351 FpsInfo FPS::GetFpsInfoByRs(const std::string& name)
352 {
353     bool isBreak = false;
354     uint64_t nodeId;
355     std::istringstream s(name);
356     s >> nodeId;
357     LOGD("FPS::GetFpsInfoByRs nodeId: (%lld)", nodeId);
358     std::string fpsInfoResult = OHOS::Rosen::RSInterfaces::GetInstance().GetRefreshInfoToSP(nodeId);
359     LOGD("FPS fpsInfoResult: %s", fpsInfoResult.c_str());
360     std::stringstream iss;
361     iss << fpsInfoResult;
362     std::string timeStampLine;
363     while (getline(iss, timeStampLine, '\n')) {
364         timeStampLine.erase(0, timeStampLine.find_first_not_of(' '));
365         curScreenTimestamp = 0;
366         if (timeStampLine.empty()) {
367             continue;
368         }
369         std::stringstream ss;
370         ss.clear();
371         ss << timeStampLine;
372         ss >> curScreenTimestamp;
373         if (curScreenTimestamp == 0) {
374             continue;
375         }
376         if (CalcFpsAndJitters(isBreak)) {
377             break;
378         }
379     }
380     CalcJitters();
381     return fpsInfo;
382 }
383 
CalcFpsAndJitters(bool isBreak)384 bool FPS::CalcFpsAndJitters(bool isBreak)
385 {
386     long long onScreenTime = curScreenTimestamp / mod;
387     bool findFpsCurTime = (onScreenTime == fpsInfo.curTime);
388     if (findFpsCurTime) {
389         isBreak = true;
390         fpsNum++;
391         fpsInfo.fps = fpsNum;
392         fpsInfo.currDumpTimeStamps.push_back(curScreenTimestamp);
393     } else {
394         findFpsCurTime = false;
395     }
396     return isBreak && !findFpsCurTime;
397 }
398 
CalcJitters()399 void FPS::CalcJitters()
400 {
401     bool isOrder = true;
402     if (fpsInfo.currDumpTimeStamps.size() > 1) {
403         isOrder = fpsInfo.currDumpTimeStamps[1] - fpsInfo.currDumpTimeStamps[0] > 0;
404     }
405     if (isOrder) {
406         for (size_t i = 0; i < fpsInfo.currDumpTimeStamps.size(); i++) {
407             curScreenTimestamp = fpsInfo.currDumpTimeStamps[i];
408             fpsInfo.currTimeStamps.push_back(curScreenTimestamp);
409             long long jitter = CalculateJitter();
410             fpsInfo.jitters.push_back(jitter);
411             prevlastScreenTimestamp = curScreenTimestamp;
412             prevScreenTimestamp = curScreenTimestamp;
413         }
414     } else {
415         for (size_t i = fpsInfo.currDumpTimeStamps.size(); i > 0 ; i--) {
416             curScreenTimestamp = fpsInfo.currDumpTimeStamps[i - 1];
417             fpsInfo.currTimeStamps.push_back(curScreenTimestamp);
418             long long jitter = CalculateJitter();
419             fpsInfo.jitters.push_back(jitter);
420             prevlastScreenTimestamp = curScreenTimestamp;
421             prevScreenTimestamp = curScreenTimestamp;
422         }
423     }
424     if (!fpsInfo.jitters.empty()) {
425         fpsInfo.jitters.erase(fpsInfo.jitters.begin());
426     }
427 }
428 
CalculateJitter() const429 long long FPS::CalculateJitter() const
430 {
431     long long jitter;
432     if (prevScreenTimestamp == -1) {
433         if (prevlastScreenTimestamp != 0 && (curScreenTimestamp - prevlastScreenTimestamp) < mod) {
434             jitter = curScreenTimestamp - prevlastScreenTimestamp;
435         } else {
436             jitter = curScreenTimestamp % mod;
437         }
438     } else {
439         jitter = curScreenTimestamp - prevScreenTimestamp;
440     }
441     return jitter;
442 }
443 
SetRkFlag()444 void FPS::SetRkFlag()
445 {
446     rkFlag = true;
447 }
448 
FindFpsRefreshrate()449 std::string FPS::FindFpsRefreshrate()
450 {
451     std::string value;
452     std::string screenInfo;
453     SPUtils::LoadFile(screenPath, screenInfo);
454     value = GetHardenRefreshrate(screenInfo);
455     size_t pos = 0;
456     std::string token;
457     if (!rkFlag) {
458         while ((pos = screenInfo.find(";")) != std::string::npos) {
459             token = screenInfo.substr(0, pos);
460             screenInfo.erase(0, pos + 1);
461             if (token.find("current_fps:") != std::string::npos || token.find("lcd_fps:") != std::string::npos) {
462                 value = token.substr(token.find(":") + 1);
463                 break;
464             }
465         }
466     } else {
467         std::string screen = OHOS::SmartPerf::SPUtils::GetScreen();
468         pos = screen.find("=");
469         if (pos != std::string::npos) {
470             value = screen.substr(pos + 1);
471             if (!value.empty() && value.back() == '\n') {
472                 value.pop_back();
473             }
474         }
475     }
476     return value;
477 }
478 
GetHardenRefreshrate(std::string & screenInfo) const479 std::string FPS::GetHardenRefreshrate(std::string &screenInfo) const
480 {
481     if (screenInfo.empty()) {
482         SPUtils::LoadCmd(HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_SCREEN), screenInfo);
483     }
484     std::string value = "";
485     std::string refreshrate = "refreshrate=";
486     size_t activeModePos = screenInfo.find("activeMode:");
487     if (activeModePos != std::string::npos) {
488         size_t refreshRatePos = screenInfo.find(refreshrate, activeModePos);
489         if (refreshRatePos != std::string::npos) {
490             size_t endPos = screenInfo.find(" ", refreshRatePos);
491             if (endPos != std::string::npos) {
492                 value = screenInfo.substr(refreshRatePos + refreshrate.length(),
493                 endPos - refreshRatePos - refreshrate.length());
494             }
495         }
496     }
497     return value;
498 }
499 
GetGameLayer()500 std::string FPS::GetGameLayer()
501 {
502     std::string gameLayer = "";
503     if (processId.empty()) {
504         LOGE("FPS::processId is empty");
505         return gameLayer;
506     }
507     const std::string dumperSurface = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_RS_TREE);
508     uint64_t nodeId;
509     std::string start = "SURFACE_NODE[";
510     std::string end = "],";
511     char buf[1024] = {'\0'};
512     FILE *fd = popen(dumperSurface.c_str(), "r");
513     if (fd == nullptr) {
514         LOGE("FPS::fd is nullptr");
515         return gameLayer;
516     }
517     while (fgets(buf, sizeof(buf), fd) != nullptr) {
518         std::string line = buf;
519         size_t startPos = line.find(start);
520         size_t endPos = line.find_first_of(end);
521         if (startPos != std::string::npos && endPos != std::string::npos) {
522             nodeIdStr = line.substr(startPos + start.length(), endPos - startPos - start.length());
523         }
524         if (line.find(pkgName) != std::string::npos ||
525             (line.find("ShellAssistantAnco") != std::string::npos && line.find("Surface") != std::string::npos)) {
526             pclose(fd);
527             return nodeIdStr;
528         }
529         const int kShiftAmount = 32;
530         if (!nodeIdStr.empty()) {
531             std::stringstream ss(nodeIdStr);
532             ss >> nodeId;
533             if (ss.fail() || !ss.eof()) {
534                 pclose(fd);
535                 return gameLayer;
536             }
537             nodeId = nodeId >> kShiftAmount;
538             gameLayer = GetLayerName(gameLayer, nodeId, line, endPos);
539             if (!gameLayer.empty()) {
540                 break;
541             }
542         }
543     }
544     if (pclose(fd) == -1) {
545         LOGE("FPS Error: Failed to close file");
546         return gameLayer;
547     }
548     LOGD("FPS::gameLayer: (%s)", gameLayer.c_str());
549     return gameLayer;
550 }
551 
GetLayerName(std::string & gameLayer,uint64_t & nodeId,const std::string & line,size_t & endPos)552 std::string FPS::GetLayerName(std::string &gameLayer, uint64_t &nodeId, const std::string& line, size_t &endPos)
553 {
554     if (isPreset) {
555         gameLayer = GetSurfaceId(gameLayer, nodeId, processId, line, endPos);
556         LOGD("FPS::GetLayerName::processId: (%s)", processId.c_str());
557     } else {
558         StartUpDelay startUpDelay;
559         if (startUpDelay.GetPidParams().empty()) {
560             gameLayer = GetSurfaceId(gameLayer, nodeId, processId, line, endPos);
561         }
562         for (const auto& pid : startUpDelay.GetPidParams()) {
563             gameLayer = GetSurfaceId(gameLayer, nodeId, pid, line, endPos);
564             if (!gameLayer.empty()) {
565                 break;
566             }
567         }
568     }
569     return gameLayer;
570 }
571 
GetSurfaceId(std::string & gameLayer,uint64_t & nodeId,const std::string & surfaceId,const std::string & line,size_t & endPos)572 std::string FPS::GetSurfaceId(std::string &gameLayer, uint64_t &nodeId, const std::string &surfaceId,
573     const std::string& line, size_t &endPos)
574 {
575     if (std::to_string(nodeId) == surfaceId &&
576         line.find("VisibleRegion [Empty], OpaqueRegion [Empty]") != std::string::npos) {
577         if (isHistoryHap) {
578             size_t startSixPos = 6;
579             size_t layerStartPos = line.find("Name [");
580             size_t layerEndPos = line.find("], hasConsumer");
581             if (layerEndPos - layerStartPos <= 1 && layerEndPos > endPos) {
582                 return gameLayer;
583             }
584             layerStartPos += startSixPos;
585             gameLayer = line.substr(layerStartPos, layerEndPos - layerStartPos);
586         } else {
587             gameLayer = nodeIdStr;
588         }
589     }
590     LOGD("FPS::GetSurfaceId::gameLayer: (%s)", gameLayer.c_str());
591     return gameLayer;
592 }
593 
SetTraceCatch()594 void FPS::SetTraceCatch()
595 {
596     isCatchTrace = 1;
597 }
598 
GetOhFps(std::vector<std::string> & v)599 void FPS::GetOhFps(std::vector<std::string>& v)
600 {
601     if (v[number] == "") {
602         printf("the args of num must be not-null!\n");
603     } else {
604         this->num = SPUtilesTye::StringToSometype<int>(v[number].c_str());
605         if (this->num < 0) {
606             printf("set num:%d not vaild arg\n", this->num);
607         }
608         printf("set num:%d success\n", this->num);
609         ohFlag = true;
610         int sectionsNum;
611         if (static_cast<int>(v.size()) < four) {
612             sectionsNum = 0;
613         } else {
614             sectionsNum = SPUtilesTye::StringToSometype<int>(v[four].c_str());
615         }
616         for (int i = 0; i < this->num; i++) {
617             GetResultFPS(sectionsNum);
618         }
619     }
620     printf("SP_daemon exec finished!\n");
621 }
622 
GetTimeDiff()623 void FPS::GetTimeDiff()
624 {
625     long long clockRealTime = 0;
626     long long clockMonotonicRaw = 0;
627     const int two = 2;
628     std::string strRealTime;
629     const std::string cmd = CMD_COMMAND_MAP.at(CmdCommand::TIMESTAMPS);
630     FILE *fd = popen(cmd.c_str(), "r");
631     if (fd == nullptr) {
632         return;
633     }
634     char buf[1024] = {'\0'};
635     while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
636         std::string line(buf);
637         std::vector<std::string> params;
638         SPUtils::StrSplit(line, " ", params);
639         if (params[0].find("CLOCK_REALTIME") != std::string::npos && clockRealTime == 0) {
640             strRealTime = params[two];
641             strRealTime.erase(strRealTime.find('.'), 1);
642             clockRealTime = SPUtilesTye::StringToSometype<long long>(strRealTime);
643             currRealTime = clockRealTime;
644         } else if (params[0].find("CLOCK_MONOTONIC_RAW") != std::string::npos && clockMonotonicRaw == 0) {
645             strRealTime = params[two];
646             strRealTime.erase(strRealTime.find('.'), 1);
647             clockMonotonicRaw = SPUtilesTye::StringToSometype<long long>(strRealTime);
648         }
649     }
650     if (pclose(fd) == -1) {
651         LOGE("Error: Failed to close file");
652         return;
653     }
654     fpsInfo.currTimeDiff = clockRealTime - clockMonotonicRaw;
655 }
656 
GetResultFPS(int sectionsNum)657 void FPS::GetResultFPS(int sectionsNum)
658 {
659     isNeedDump = true;
660     isSections = true;
661     struct timeval start;
662     struct timeval end;
663     gettimeofday(&start, nullptr);
664     FpsInfo fpsInfoResult = GetFpsInfo();
665     unsigned long runTime;
666     if (fpsInfoResult.fps == 0) {
667         if (lastCurrTime == 0) {
668             long long currTime = (fpsInfoResult.currTimeDump / msClear) * msClear + fpsInfoResult.currTimeDiff;
669             lastCurrTime = currTime / oneSec;
670             printf("fps:%d|%lld\n", fpsInfoResult.fps, currTime / oneSec);
671         } else {
672             printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime + oneThousand);
673             lastCurrTime = lastCurrTime + oneThousand;
674         }
675     } else {
676         long long currTime = (fpsInfoResult.currTimeStamps[0] / msClear) * msClear + fpsInfoResult.currTimeDiff;
677         lastCurrTime = currTime / oneSec;
678         printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime);
679     }
680     prevResultFpsInfo = fpsInfoResult;
681     if (sectionsNum != 0 && fpsInfoResult.fps != 0) {
682         GetSectionsFps(fpsInfoResult, sectionsNum);
683     }
684     time_t now = time(nullptr);
685     if (now == -1) {
686         LOGE("Failed to get current time.");
687         return;
688     }
689     char *dt = ctime(&now);
690     LOGD("printf time is: %s", dt);
691     fflush(stdout);
692     gettimeofday(&end, nullptr);
693     runTime = end.tv_sec * 1e6 - start.tv_sec * 1e6 + end.tv_usec - start.tv_usec;
694     LOGD("printf time is runTime: %s", std::to_string(runTime).c_str());
695     if (runTime < sleepTime) {
696         usleep(sleepTime - runTime);
697     }
698     OHOS::SmartPerf::SPUtils::GetCurrentTime(prevResultFpsInfo.curTime);
699 }
700 
GetSectionsFps(FpsInfo & fpsInfoResult,int nums) const701 void FPS::GetSectionsFps(FpsInfo &fpsInfoResult, int nums) const
702 {
703     int msCount = 0;
704     long long msJiange = 0;
705     if (nums != 0) {
706         msJiange = msClear / nums;
707     }
708     long long msStartTime = (fpsInfoResult.currTimeStamps[0] / msClear) * msClear + msJiange;
709     long long currLastTime = lastCurrTime;
710     long long harTime = msJiange / 1000000;
711     int printCount = 0;
712     long long currTimeStart = 0;
713     long long currTimeLast = 0;
714     for (size_t i = 0; i < fpsInfoResult.currTimeStamps.size(); i++) {
715         long long currTime = fpsInfoResult.currTimeStamps[i];
716         if (currTime <= msStartTime) {
717             if (msCount == 0) {
718                 currTimeStart = currTime;
719             }
720             currTimeLast = currTime;
721             msCount++;
722         } else {
723             while (currTime > msStartTime) {
724                 PrintSections(msCount, currTimeLast, currTimeStart, currLastTime);
725                 printCount++;
726                 msCount = 1;
727                 msStartTime += msJiange;
728                 currLastTime += harTime;
729                 currTimeLast = currTime;
730                 currTimeStart = currTime;
731             }
732         }
733         if (i == (static_cast<size_t>(fpsInfoResult.currTimeStamps.size()) - 1)) {
734             PrintSections(msCount, currTimeLast, currTimeStart, currLastTime);
735             currTimeLast = currTime;
736             printCount++;
737             GetSectionsPrint(printCount, currLastTime, nums, harTime);
738         }
739     }
740 }
741 
PrintSections(int msCount,long long currTimeLast,long long currTimeStart,long long currLastTime) const742 void FPS::PrintSections(int msCount, long long currTimeLast, long long currTimeStart, long long currLastTime) const
743 {
744     int conversionFps = 1000000;
745     int conversionTime = 1000;
746     long long times = 120;
747     int fpsNums = 0;
748     if (msCount == 0) {
749         fpsNums = 0;
750     } else {
751         fpsNums = msCount - 1;
752     }
753     double timeN = (currTimeLast - currTimeStart) * 1.0 / conversionTime;
754     if (timeN == 0) {
755         printf("sectionsFps:%d|%lld\n", 0, currLastTime);
756         return;
757     }
758     double fpsSections = (fpsNums * conversionFps) / timeN;
759     int fpsSectionsInt = round(fpsSections);
760     if (fpsSectionsInt > static_cast<int>(times)) {
761         fpsSectionsInt = static_cast<int>(times);
762     }
763     printf("sectionsFps:%d|%lld\n", fpsSectionsInt, currLastTime);
764 }
765 
GetSectionsPrint(int printCount,long long msStartTime,int numb,long long harTime) const766 void FPS::GetSectionsPrint(int printCount, long long msStartTime, int numb, long long harTime) const
767 {
768     if (printCount < numb) {
769         for (int i = 0; i < numb - printCount; i++) {
770             msStartTime += harTime;
771             printf("sectionsFps:%d|%lld\n", 0, msStartTime);
772         }
773     }
774 }
775 
GetFPS(std::vector<std::string> & v)776 void FPS::GetFPS(std::vector<std::string>& v)
777 {
778     if (v[number] == "") {
779         printf("the args of num must be not-null!\n");
780     } else {
781         this->num = SPUtilesTye::StringToSometype<int>(v[number].c_str());
782         if (this->num < 0) {
783             printf("set num:%d not valid arg\n", this->num);
784         }
785         printf("set num:%d success\n", this->num);
786         int sectionsNum = (static_cast<int>(v.size()) >= four) ?
787                             SPUtilesTye::StringToSometype<int>(v[four].c_str()) : 0;
788         if (sectionsNum > ten) {
789             printf("set sectionsNum:%d not valid arg \n", sectionsNum);
790         } else {
791             for (int i = 0; i < this->num; i++) {
792                 GetResultFPS(sectionsNum);
793             }
794         }
795     }
796     printf("SP_daemon exec finished!\n");
797 }
798 }
799 }
800 
801