106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include <cstdio> 1606f6ba60Sopenharmony_ci#include <algorithm> 1706f6ba60Sopenharmony_ci#include <iostream> 1806f6ba60Sopenharmony_ci#include <sstream> 1906f6ba60Sopenharmony_ci#include <queue> 2006f6ba60Sopenharmony_ci#include <string> 2106f6ba60Sopenharmony_ci#include <thread> 2206f6ba60Sopenharmony_ci#include <unistd.h> 2306f6ba60Sopenharmony_ci#include <ctime> 2406f6ba60Sopenharmony_ci#include <sys/time.h> 2506f6ba60Sopenharmony_ci#include "include/sp_utils.h" 2606f6ba60Sopenharmony_ci#include "include/ByTrace.h" 2706f6ba60Sopenharmony_ci#include "include/Capture.h" 2806f6ba60Sopenharmony_ci#include "include/FPS.h" 2906f6ba60Sopenharmony_ci#include "include/startup_delay.h" 3006f6ba60Sopenharmony_ci#include "include/profiler_fps.h" 3106f6ba60Sopenharmony_ci#include "include/sp_log.h" 3206f6ba60Sopenharmony_ci#include "include/common.h" 3306f6ba60Sopenharmony_ci#include <sys/wait.h> 3406f6ba60Sopenharmony_ci#include <sys/types.h> 3506f6ba60Sopenharmony_cinamespace OHOS { 3606f6ba60Sopenharmony_cinamespace SmartPerf { 3706f6ba60Sopenharmony_cistd::map<std::string, std::string> FPS::ItemData() 3806f6ba60Sopenharmony_ci{ 3906f6ba60Sopenharmony_ci std::map<std::string, std::string> result; 4006f6ba60Sopenharmony_ci FpsInfo fpsInfoResult; 4106f6ba60Sopenharmony_ci if (surfaceViewName.length() > 0) { 4206f6ba60Sopenharmony_ci fpsInfoResult = GetDiffLayersFpsInfo(surfaceViewName); 4306f6ba60Sopenharmony_ci } else { 4406f6ba60Sopenharmony_ci fpsInfoResult = GetFpsInfo(); 4506f6ba60Sopenharmony_ci } 4606f6ba60Sopenharmony_ci prevResultFpsInfo = fpsInfoResult; 4706f6ba60Sopenharmony_ci std::string value = FindFpsRefreshrate(); 4806f6ba60Sopenharmony_ci result["refreshrate"] = value; 4906f6ba60Sopenharmony_ci if (processFlag) { 5006f6ba60Sopenharmony_ci result["fps"] = "NA"; 5106f6ba60Sopenharmony_ci result["fpsJitters"] = "NA"; 5206f6ba60Sopenharmony_ci } else { 5306f6ba60Sopenharmony_ci int fullFrame = 120; 5406f6ba60Sopenharmony_ci if (fpsInfoResult.fps > fullFrame) { 5506f6ba60Sopenharmony_ci fpsInfoResult.fps = fullFrame; 5606f6ba60Sopenharmony_ci } 5706f6ba60Sopenharmony_ci result["fps"] = std::to_string(fpsInfoResult.fps); 5806f6ba60Sopenharmony_ci LOGI("result.fps: %s", std::to_string(fpsInfoResult.fps).c_str()); 5906f6ba60Sopenharmony_ci LOGI("result.curTime: %s", std::to_string(fpsInfoResult.curTime).c_str()); 6006f6ba60Sopenharmony_ci std::string jitterStr = ""; 6106f6ba60Sopenharmony_ci std::string split = ""; 6206f6ba60Sopenharmony_ci for (size_t i = 0; i < fpsInfoResult.jitters.size(); i++) { 6306f6ba60Sopenharmony_ci if (i > 0) { 6406f6ba60Sopenharmony_ci split = ";;"; 6506f6ba60Sopenharmony_ci } 6606f6ba60Sopenharmony_ci jitterStr += split + std::to_string(fpsInfoResult.jitters[i]); 6706f6ba60Sopenharmony_ci } 6806f6ba60Sopenharmony_ci result["fpsJitters"] = jitterStr; 6906f6ba60Sopenharmony_ci LOGI("result.jitters: %s", jitterStr.c_str()); 7006f6ba60Sopenharmony_ci SetFpsCurrentFpsTime(fpsInfoResult); 7106f6ba60Sopenharmony_ci } 7206f6ba60Sopenharmony_ci return result; 7306f6ba60Sopenharmony_ci} 7406f6ba60Sopenharmony_ci 7506f6ba60Sopenharmony_civoid FPS::SetFpsCurrentFpsTime(FpsInfo fpsInfoResult) 7606f6ba60Sopenharmony_ci{ 7706f6ba60Sopenharmony_ci ffTime.fps = fpsInfoResult.fps; 7806f6ba60Sopenharmony_ci if (!fpsInfoResult.jitters.empty()) { 7906f6ba60Sopenharmony_ci auto maxElement = std::max_element(fpsInfoResult.jitters.begin(), fpsInfoResult.jitters.end()); 8006f6ba60Sopenharmony_ci ffTime.currentFpsTime = *maxElement; 8106f6ba60Sopenharmony_ci } 8206f6ba60Sopenharmony_ci} 8306f6ba60Sopenharmony_ci 8406f6ba60Sopenharmony_ciFpsCurrentFpsTime FPS::GetFpsCurrentFpsTime() 8506f6ba60Sopenharmony_ci{ 8606f6ba60Sopenharmony_ci return ffTime; 8706f6ba60Sopenharmony_ci} 8806f6ba60Sopenharmony_ci 8906f6ba60Sopenharmony_civoid FPS::SetPackageName(std::string pName) 9006f6ba60Sopenharmony_ci{ 9106f6ba60Sopenharmony_ci pkgName = std::move(pName); 9206f6ba60Sopenharmony_ci} 9306f6ba60Sopenharmony_ci 9406f6ba60Sopenharmony_civoid FPS::SetProcessId(const std::string &pid) 9506f6ba60Sopenharmony_ci{ 9606f6ba60Sopenharmony_ci processId = pid; 9706f6ba60Sopenharmony_ci} 9806f6ba60Sopenharmony_ci 9906f6ba60Sopenharmony_civoid FPS::SetLayerName(std::string sName) 10006f6ba60Sopenharmony_ci{ 10106f6ba60Sopenharmony_ci surfaceViewName = std::move(sName); 10206f6ba60Sopenharmony_ci} 10306f6ba60Sopenharmony_ciFpsInfo FPS::GetDiffLayersFpsInfo(const std::string &sName) 10406f6ba60Sopenharmony_ci{ 10506f6ba60Sopenharmony_ci OHOS::SmartPerf::SPUtils::GetCurrentTime(fifty, prevResultFpsInfo.curTime); 10606f6ba60Sopenharmony_ci fpsInfoMax = GetSurfaceFrame(sName); 10706f6ba60Sopenharmony_ci return fpsInfoMax; 10806f6ba60Sopenharmony_ci} 10906f6ba60Sopenharmony_ci 11006f6ba60Sopenharmony_ciFpsInfo FPS::GetFpsInfo() 11106f6ba60Sopenharmony_ci{ 11206f6ba60Sopenharmony_ci processFlag = false; 11306f6ba60Sopenharmony_ci fpsInfoMax.fps = 0; 11406f6ba60Sopenharmony_ci if (pkgName.empty()) { 11506f6ba60Sopenharmony_ci return fpsInfoMax; 11606f6ba60Sopenharmony_ci } 11706f6ba60Sopenharmony_ci bool onTop = OHOS::SmartPerf::SPUtils::IsForeGround(pkgName); 11806f6ba60Sopenharmony_ci if (onTop) { 11906f6ba60Sopenharmony_ci std::string uniteLayer; 12006f6ba60Sopenharmony_ci if (!rkFlag) { 12106f6ba60Sopenharmony_ci uniteLayer = "UniRender"; 12206f6ba60Sopenharmony_ci } else { 12306f6ba60Sopenharmony_ci ProfilerFPS &profilerFps = ProfilerFPS::GetInstance(); 12406f6ba60Sopenharmony_ci uniteLayer = profilerFps.GetSurface(); 12506f6ba60Sopenharmony_ci } 12606f6ba60Sopenharmony_ci OHOS::SmartPerf::SPUtils::GetCurrentTime(fifty, prevResultFpsInfo.curTime); 12706f6ba60Sopenharmony_ci fpsInfoMax = GetSurfaceFrame(uniteLayer); 12806f6ba60Sopenharmony_ci } else { 12906f6ba60Sopenharmony_ci LOGI("FPS:app is in the background"); 13006f6ba60Sopenharmony_ci if (processId.empty()) { 13106f6ba60Sopenharmony_ci processFlag = true; 13206f6ba60Sopenharmony_ci fpsInfoMax.Clear(); 13306f6ba60Sopenharmony_ci } else { 13406f6ba60Sopenharmony_ci fpsInfoMax.Clear(); 13506f6ba60Sopenharmony_ci } 13606f6ba60Sopenharmony_ci } 13706f6ba60Sopenharmony_ci return fpsInfoMax; 13806f6ba60Sopenharmony_ci} 13906f6ba60Sopenharmony_ci 14006f6ba60Sopenharmony_ciFpsInfo FPS::GetSurfaceFrame(std::string name) 14106f6ba60Sopenharmony_ci{ 14206f6ba60Sopenharmony_ci if (name == "") { 14306f6ba60Sopenharmony_ci return FpsInfo(); 14406f6ba60Sopenharmony_ci } 14506f6ba60Sopenharmony_ci static std::map<std::string, FpsInfo> fpsMap; 14606f6ba60Sopenharmony_ci if (fpsMap.count(name) == 0) { 14706f6ba60Sopenharmony_ci FpsInfo tmp; 14806f6ba60Sopenharmony_ci tmp.fps = 0; 14906f6ba60Sopenharmony_ci fpsMap[name] = tmp; 15006f6ba60Sopenharmony_ci } 15106f6ba60Sopenharmony_ci fpsInfo = fpsMap[name]; 15206f6ba60Sopenharmony_ci fpsInfo.fps = 0; 15306f6ba60Sopenharmony_ci std::string command = "fps " + name; 15406f6ba60Sopenharmony_ci const char* args[] = { "hidumper", "-s", "10", "-a", command.c_str(), nullptr }; 15506f6ba60Sopenharmony_ci int pipefd[2]; 15606f6ba60Sopenharmony_ci pid_t pid; 15706f6ba60Sopenharmony_ci if (pipe(pipefd) == -1) { 15806f6ba60Sopenharmony_ci LOGE("FPS::Failed to create pipe"); 15906f6ba60Sopenharmony_ci return fpsInfo; 16006f6ba60Sopenharmony_ci } 16106f6ba60Sopenharmony_ci pid = fork(); 16206f6ba60Sopenharmony_ci if (pid == -1) { 16306f6ba60Sopenharmony_ci LOGE("FPS::Failed to fork"); 16406f6ba60Sopenharmony_ci return fpsInfo; 16506f6ba60Sopenharmony_ci } else if (pid == 0) { 16606f6ba60Sopenharmony_ci close(pipefd[0]); 16706f6ba60Sopenharmony_ci dup2(pipefd[1], STDOUT_FILENO); 16806f6ba60Sopenharmony_ci close(pipefd[1]); 16906f6ba60Sopenharmony_ci if (execvp(args[0], const_cast<char *const*>(args)) == -1) { 17006f6ba60Sopenharmony_ci LOGE("FPS::Failed to execute hidumper"); 17106f6ba60Sopenharmony_ci return fpsInfo; 17206f6ba60Sopenharmony_ci } 17306f6ba60Sopenharmony_ci } else { 17406f6ba60Sopenharmony_ci close(pipefd[1]); 17506f6ba60Sopenharmony_ci ReadDataFromPipe(pipefd[0]); 17606f6ba60Sopenharmony_ci close(pipefd[0]); 17706f6ba60Sopenharmony_ci waitpid(pid, nullptr, 0); 17806f6ba60Sopenharmony_ci } 17906f6ba60Sopenharmony_ci return fpsInfo; 18006f6ba60Sopenharmony_ci} 18106f6ba60Sopenharmony_ci 18206f6ba60Sopenharmony_civoid FPS::ReadDataFromPipe(int fd) 18306f6ba60Sopenharmony_ci{ 18406f6ba60Sopenharmony_ci char tmp[1024]; 18506f6ba60Sopenharmony_ci fpsNum = 0; 18606f6ba60Sopenharmony_ci prevScreenTimestamp = -1; 18706f6ba60Sopenharmony_ci LOGI("FPS::dump time: start!"); 18806f6ba60Sopenharmony_ci struct timespec time1 = { 0 }; 18906f6ba60Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &time1); 19006f6ba60Sopenharmony_ci fpsInfo.curTime = static_cast<int>(time1.tv_sec - 1); 19106f6ba60Sopenharmony_ci fpsInfo.currTimeDump = (time1.tv_sec - 1) * mod + time1.tv_nsec; 19206f6ba60Sopenharmony_ci LOGI("FPS:fpsInfo.curTime: %d", fpsInfo.curTime); 19306f6ba60Sopenharmony_ci LOGI("FPS:psInfo.currTimeDump: %lld", fpsInfo.currTimeDump); 19406f6ba60Sopenharmony_ci FILE *fp = fdopen(fd, "r"); 19506f6ba60Sopenharmony_ci if (!fp) { 19606f6ba60Sopenharmony_ci LOGE("FPS::Failed to open file descriptor"); 19706f6ba60Sopenharmony_ci return; 19806f6ba60Sopenharmony_ci } 19906f6ba60Sopenharmony_ci while (fgets(tmp, sizeof(tmp), fp) != nullptr) { 20006f6ba60Sopenharmony_ci std::string str(tmp); 20106f6ba60Sopenharmony_ci LOGD("FPS::dump time: %s", str.c_str()); 20206f6ba60Sopenharmony_ci curScreenTimestamp = 0; 20306f6ba60Sopenharmony_ci std::stringstream sstream; 20406f6ba60Sopenharmony_ci sstream << tmp; 20506f6ba60Sopenharmony_ci sstream >> curScreenTimestamp; 20606f6ba60Sopenharmony_ci if (curScreenTimestamp == 0) { 20706f6ba60Sopenharmony_ci continue; 20806f6ba60Sopenharmony_ci } 20906f6ba60Sopenharmony_ci CalcFpsAndJitters(); 21006f6ba60Sopenharmony_ci } 21106f6ba60Sopenharmony_ci if (fclose(fp) == EOF) { 21206f6ba60Sopenharmony_ci LOGE("FPS::Failed to close file descriptor"); 21306f6ba60Sopenharmony_ci } 21406f6ba60Sopenharmony_ci} 21506f6ba60Sopenharmony_ci 21606f6ba60Sopenharmony_civoid FPS::CalcFpsAndJitters() 21706f6ba60Sopenharmony_ci{ 21806f6ba60Sopenharmony_ci std::string onScreenTime = std::to_string(curScreenTimestamp / mod); 21906f6ba60Sopenharmony_ci std::string fpsCurTime = std::to_string(fpsInfo.curTime); 22006f6ba60Sopenharmony_ci if (onScreenTime.find(fpsCurTime) != std::string::npos) { 22106f6ba60Sopenharmony_ci fpsNum++; 22206f6ba60Sopenharmony_ci fpsInfo.currTimeStamps.push_back(curScreenTimestamp); 22306f6ba60Sopenharmony_ci } 22406f6ba60Sopenharmony_ci fpsInfo.fps = fpsNum; 22506f6ba60Sopenharmony_ci if (onScreenTime == fpsCurTime) { 22606f6ba60Sopenharmony_ci long long jitter; 22706f6ba60Sopenharmony_ci if (prevScreenTimestamp != -1) { 22806f6ba60Sopenharmony_ci jitter = curScreenTimestamp - prevScreenTimestamp; 22906f6ba60Sopenharmony_ci fpsInfo.jitters.push_back(jitter); 23006f6ba60Sopenharmony_ci } else { 23106f6ba60Sopenharmony_ci if (prevlastScreenTimestamp != 0 && (curScreenTimestamp - prevlastScreenTimestamp) < mod) { 23206f6ba60Sopenharmony_ci jitter = curScreenTimestamp - prevlastScreenTimestamp; 23306f6ba60Sopenharmony_ci fpsInfo.jitters.push_back(jitter); 23406f6ba60Sopenharmony_ci } else { 23506f6ba60Sopenharmony_ci jitter = curScreenTimestamp - curScreenTimestamp / mod * mod; 23606f6ba60Sopenharmony_ci fpsInfo.jitters.push_back(jitter); 23706f6ba60Sopenharmony_ci } 23806f6ba60Sopenharmony_ci } 23906f6ba60Sopenharmony_ci prevScreenTimestamp = curScreenTimestamp; 24006f6ba60Sopenharmony_ci prevlastScreenTimestamp = curScreenTimestamp; 24106f6ba60Sopenharmony_ci } 24206f6ba60Sopenharmony_ci} 24306f6ba60Sopenharmony_ci 24406f6ba60Sopenharmony_civoid FPS::SetRkFlag() 24506f6ba60Sopenharmony_ci{ 24606f6ba60Sopenharmony_ci rkFlag = true; 24706f6ba60Sopenharmony_ci} 24806f6ba60Sopenharmony_ci 24906f6ba60Sopenharmony_cistd::string FPS::FindFpsRefreshrate() 25006f6ba60Sopenharmony_ci{ 25106f6ba60Sopenharmony_ci std::string screenInfo; 25206f6ba60Sopenharmony_ci SPUtils::LoadFile(screenPath, screenInfo); 25306f6ba60Sopenharmony_ci size_t pos = 0; 25406f6ba60Sopenharmony_ci std::string token; 25506f6ba60Sopenharmony_ci std::string value; 25606f6ba60Sopenharmony_ci if (!rkFlag) { 25706f6ba60Sopenharmony_ci while ((pos = screenInfo.find(";")) != std::string::npos) { 25806f6ba60Sopenharmony_ci token = screenInfo.substr(0, pos); 25906f6ba60Sopenharmony_ci screenInfo.erase(0, pos + 1); 26006f6ba60Sopenharmony_ci if (token.find("current_fps:") != std::string::npos) { 26106f6ba60Sopenharmony_ci value = token.substr(token.find(":") + 1); 26206f6ba60Sopenharmony_ci break; 26306f6ba60Sopenharmony_ci } 26406f6ba60Sopenharmony_ci } 26506f6ba60Sopenharmony_ci } else { 26606f6ba60Sopenharmony_ci std::string screen = OHOS::SmartPerf::SPUtils::GetScreen(); 26706f6ba60Sopenharmony_ci std::string start = "refreshrate="; 26806f6ba60Sopenharmony_ci size_t startPos = screen.find(start) + start.length(); 26906f6ba60Sopenharmony_ci size_t endPos = screen.length(); 27006f6ba60Sopenharmony_ci value = screen.substr(startPos, endPos - startPos); 27106f6ba60Sopenharmony_ci } 27206f6ba60Sopenharmony_ci return value; 27306f6ba60Sopenharmony_ci} 27406f6ba60Sopenharmony_ci} 27506f6ba60Sopenharmony_ci} 27606f6ba60Sopenharmony_ci 277