/* * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include "include/sp_utils.h" #include "include/ByTrace.h" #include "include/Capture.h" #include "include/FPS.h" #include "include/startup_delay.h" #include "include/profiler_fps.h" #include "include/sp_log.h" #include "include/common.h" #include #include namespace OHOS { namespace SmartPerf { std::map FPS::ItemData() { std::map result; FpsInfo fpsInfoResult; if (surfaceViewName.length() > 0) { fpsInfoResult = GetDiffLayersFpsInfo(surfaceViewName); } else { fpsInfoResult = GetFpsInfo(); } prevResultFpsInfo = fpsInfoResult; std::string value = FindFpsRefreshrate(); result["refreshrate"] = value; if (processFlag) { result["fps"] = "NA"; result["fpsJitters"] = "NA"; } else { int fullFrame = 120; if (fpsInfoResult.fps > fullFrame) { fpsInfoResult.fps = fullFrame; } result["fps"] = std::to_string(fpsInfoResult.fps); LOGI("result.fps: %s", std::to_string(fpsInfoResult.fps).c_str()); LOGI("result.curTime: %s", std::to_string(fpsInfoResult.curTime).c_str()); std::string jitterStr = ""; std::string split = ""; for (size_t i = 0; i < fpsInfoResult.jitters.size(); i++) { if (i > 0) { split = ";;"; } jitterStr += split + std::to_string(fpsInfoResult.jitters[i]); } result["fpsJitters"] = jitterStr; LOGI("result.jitters: %s", jitterStr.c_str()); SetFpsCurrentFpsTime(fpsInfoResult); } return result; } void FPS::SetFpsCurrentFpsTime(FpsInfo fpsInfoResult) { ffTime.fps = fpsInfoResult.fps; if (!fpsInfoResult.jitters.empty()) { auto maxElement = std::max_element(fpsInfoResult.jitters.begin(), fpsInfoResult.jitters.end()); ffTime.currentFpsTime = *maxElement; } } FpsCurrentFpsTime FPS::GetFpsCurrentFpsTime() { return ffTime; } void FPS::SetPackageName(std::string pName) { pkgName = std::move(pName); } void FPS::SetProcessId(const std::string &pid) { processId = pid; } void FPS::SetLayerName(std::string sName) { surfaceViewName = std::move(sName); } FpsInfo FPS::GetDiffLayersFpsInfo(const std::string &sName) { OHOS::SmartPerf::SPUtils::GetCurrentTime(fifty, prevResultFpsInfo.curTime); fpsInfoMax = GetSurfaceFrame(sName); return fpsInfoMax; } FpsInfo FPS::GetFpsInfo() { processFlag = false; fpsInfoMax.fps = 0; if (pkgName.empty()) { return fpsInfoMax; } bool onTop = OHOS::SmartPerf::SPUtils::IsForeGround(pkgName); if (onTop) { std::string uniteLayer; if (!rkFlag) { uniteLayer = "UniRender"; } else { ProfilerFPS &profilerFps = ProfilerFPS::GetInstance(); uniteLayer = profilerFps.GetSurface(); } OHOS::SmartPerf::SPUtils::GetCurrentTime(fifty, prevResultFpsInfo.curTime); fpsInfoMax = GetSurfaceFrame(uniteLayer); } else { LOGI("FPS:app is in the background"); if (processId.empty()) { processFlag = true; fpsInfoMax.Clear(); } else { fpsInfoMax.Clear(); } } return fpsInfoMax; } FpsInfo FPS::GetSurfaceFrame(std::string name) { if (name == "") { return FpsInfo(); } static std::map fpsMap; if (fpsMap.count(name) == 0) { FpsInfo tmp; tmp.fps = 0; fpsMap[name] = tmp; } fpsInfo = fpsMap[name]; fpsInfo.fps = 0; std::string command = "fps " + name; const char* args[] = { "hidumper", "-s", "10", "-a", command.c_str(), nullptr }; int pipefd[2]; pid_t pid; if (pipe(pipefd) == -1) { LOGE("FPS::Failed to create pipe"); return fpsInfo; } pid = fork(); if (pid == -1) { LOGE("FPS::Failed to fork"); return fpsInfo; } else if (pid == 0) { close(pipefd[0]); dup2(pipefd[1], STDOUT_FILENO); close(pipefd[1]); if (execvp(args[0], const_cast(args)) == -1) { LOGE("FPS::Failed to execute hidumper"); return fpsInfo; } } else { close(pipefd[1]); ReadDataFromPipe(pipefd[0]); close(pipefd[0]); waitpid(pid, nullptr, 0); } return fpsInfo; } void FPS::ReadDataFromPipe(int fd) { char tmp[1024]; fpsNum = 0; prevScreenTimestamp = -1; LOGI("FPS::dump time: start!"); struct timespec time1 = { 0 }; clock_gettime(CLOCK_MONOTONIC, &time1); fpsInfo.curTime = static_cast(time1.tv_sec - 1); fpsInfo.currTimeDump = (time1.tv_sec - 1) * mod + time1.tv_nsec; LOGI("FPS:fpsInfo.curTime: %d", fpsInfo.curTime); LOGI("FPS:psInfo.currTimeDump: %lld", fpsInfo.currTimeDump); FILE *fp = fdopen(fd, "r"); if (!fp) { LOGE("FPS::Failed to open file descriptor"); return; } while (fgets(tmp, sizeof(tmp), fp) != nullptr) { std::string str(tmp); LOGD("FPS::dump time: %s", str.c_str()); curScreenTimestamp = 0; std::stringstream sstream; sstream << tmp; sstream >> curScreenTimestamp; if (curScreenTimestamp == 0) { continue; } CalcFpsAndJitters(); } if (fclose(fp) == EOF) { LOGE("FPS::Failed to close file descriptor"); } } void FPS::CalcFpsAndJitters() { std::string onScreenTime = std::to_string(curScreenTimestamp / mod); std::string fpsCurTime = std::to_string(fpsInfo.curTime); if (onScreenTime.find(fpsCurTime) != std::string::npos) { fpsNum++; fpsInfo.currTimeStamps.push_back(curScreenTimestamp); } fpsInfo.fps = fpsNum; if (onScreenTime == fpsCurTime) { long long jitter; if (prevScreenTimestamp != -1) { jitter = curScreenTimestamp - prevScreenTimestamp; fpsInfo.jitters.push_back(jitter); } else { if (prevlastScreenTimestamp != 0 && (curScreenTimestamp - prevlastScreenTimestamp) < mod) { jitter = curScreenTimestamp - prevlastScreenTimestamp; fpsInfo.jitters.push_back(jitter); } else { jitter = curScreenTimestamp - curScreenTimestamp / mod * mod; fpsInfo.jitters.push_back(jitter); } } prevScreenTimestamp = curScreenTimestamp; prevlastScreenTimestamp = curScreenTimestamp; } } void FPS::SetRkFlag() { rkFlag = true; } std::string FPS::FindFpsRefreshrate() { std::string screenInfo; SPUtils::LoadFile(screenPath, screenInfo); size_t pos = 0; std::string token; std::string value; if (!rkFlag) { while ((pos = screenInfo.find(";")) != std::string::npos) { token = screenInfo.substr(0, pos); screenInfo.erase(0, pos + 1); if (token.find("current_fps:") != std::string::npos) { value = token.substr(token.find(":") + 1); break; } } } else { std::string screen = OHOS::SmartPerf::SPUtils::GetScreen(); std::string start = "refreshrate="; size_t startPos = screen.find(start) + start.length(); size_t endPos = screen.length(); value = screen.substr(startPos, endPos - startPos); } return value; } } }