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 ×tamp : 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