* 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 <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <thread>
#include "include/sp_utils.h"
#include "include/ByTrace.h"
#include "include/Capture.h"
#include "include/FPS.h"
namespace OHOS {
namespace SmartPerf {
std::map<std::string, std::string> FPS::ItemData()
{
std::map<std::string, std::string> result;
FpsInfo fpsInfo = GetFpsInfo();
result["fps"] = std::to_string(fpsInfo.fps);
std::string jitterStr = "";
std::string split = "";
for (size_t i = 0; i < fpsInfo.jitters.size(); i++) {
if (i > 0) {
split = ";;";
}
jitterStr += split + std::to_string(fpsInfo.jitters[i]);
}
result["fpsJitters"] = jitterStr;
if (isCatchTrace > 0) {
ByTrace::GetInstance().CheckFpsJitters(fpsInfo.jitters);
}
if (isCapture > 0) {
Capture::GetInstance().TriggerGetCatch(SPUtils::GetCurTime());
}
return result;
}
void FPS::SetTraceCatch()
{
isCatchTrace = 1;
}
void FPS::SetCaptureOn()
{
isCapture = 1;
}
void FPS::SetPackageName(std::string pName)
{
pkgName = std::move(pName);
}
FpsInfo FPS::GetFpsInfo()
{
FpsInfo fpsInfoMax;
fpsInfoMax.fps = -1;
if (pkgName.empty()) {
return fpsInfoMax;
}
std::string layerName;
std::vector<std::string> sps;
SPUtils::StrSplit(this->pkgName, ".", sps);
std::string addEndChar = "0";
const int pNameLastPos = 2;
std::string pkgSuffix = sps[pNameLastPos];
layerName = std::string(pkgSuffix.c_str() + addEndChar);
if (pkgSuffix.find("camera") != std::string::npos) {
layerName = std::string("RosenRenderXComponent");
}
FpsInfo fpsInfo = GetSurfaceFrame(layerName);
if (fpsInfo.fps > fpsInfoMax.fps) {
fpsInfoMax = fpsInfo;
}
return fpsInfoMax;
}
FpsInfo FPS::GetSurfaceFrame(std::string name)
{
if (name == "") {
return FpsInfo();
}
static std::map<std::string, FpsInfo> fpsMap;
if (fpsMap.count(name) == 0) {
FpsInfo tmp;
tmp.fps = 0;
tmp.preFps = 0;
fpsMap[name] = tmp;
}
FpsInfo &fpsInfo = fpsMap[name];
fpsInfo.fps = 0;
FILE *fp;
static char tmp[1024];
std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
fp = popen(cmd.c_str(), "r");
if (fp == nullptr) {
return fpsInfo;
}
long long mod = 1e9;
long long lastReadyTime = -1;
int fpsGb = 0;
if (!(fpsInfo.timeStampQ).empty()) {
lastReadyTime = (fpsInfo.timeStampQ).back();
}
bool jump = false;
bool refresh = false;
int cnt = 0;
int zeroNum = 0;
while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
long long frameReadyTime = 0;
std::stringstream sstream;
sstream << tmp;
sstream >> frameReadyTime;
cnt++;
if (frameReadyTime == 0) {
zeroNum++;
continue;
}
if (lastReadyTime >= frameReadyTime) {
lastReadyTime = -1;
continue;
}
refresh = true;
long long tFrameReadyTime = frameReadyTime / mod;
long long tLastReadyTime = lastReadyTime / mod;
long long lastFrame = -1;
if (tFrameReadyTime == tLastReadyTime) {
(fpsInfo.timeStampQ).push(frameReadyTime);
} else if (tFrameReadyTime == tLastReadyTime + 1) {
jump = true;
lastFrame = fpsInfo.lastFrameReadyTime;
lastReadyTime = frameReadyTime;
int fpsTmp = 0;
fpsInfo.jitters.clear();
while (!(fpsInfo.timeStampQ).empty()) {
fpsTmp++;
long long currFrame = (fpsInfo.timeStampQ.front());
if (lastFrame != -1) {
long long jitter = currFrame - lastFrame;
fpsInfo.jitters.push_back(jitter);
}
lastFrame = currFrame;
(fpsInfo.timeStampQ).pop();
}
fpsGb = fpsTmp;
(fpsInfo.timeStampQ).push(frameReadyTime);
fpsInfo.lastFrameReadyTime = lastFrame;
} else if (tFrameReadyTime > tLastReadyTime + 1) {
jump = true;
lastReadyTime = frameReadyTime;
while (!(fpsInfo.timeStampQ).empty()) {
(fpsInfo.timeStampQ).pop();
}
(fpsInfo.timeStampQ).push(frameReadyTime);
}
}
pclose(fp);
const int maxZeroNum = 120;
if (zeroNum >= maxZeroNum) {
while (!(fpsInfo.timeStampQ.empty())) {
fpsInfo.timeStampQ.pop();
}
fpsInfo.fps = 0;
return fpsInfo;
}
const int minPrintLine = 5;
if (cnt < minPrintLine) {
fpsInfo.fps = fpsInfo.preFps;
return fpsInfo;
}
if (fpsGb > 0) {
fpsInfo.fps = fpsGb;
fpsInfo.preFps = fpsGb;
return fpsInfo;
} else if (refresh && !jump) {
fpsInfo.fps = fpsInfo.preFps;
return fpsInfo;
} else {
fpsInfo.fps = 0;
return fpsInfo;
}
}
}
}