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 <queue>
20 #include <string>
21 #include <thread>
22 #include <unistd.h>
23 #include <ctime>
24 #include <sys/time.h>
25 #include "include/sp_utils.h"
26 #include "include/ByTrace.h"
27 #include "include/Capture.h"
28 #include "include/FPS.h"
29 #include "include/startup_delay.h"
30 #include "include/sp_log.h"
31 namespace OHOS {
32 namespace SmartPerf {
ItemData()33 std::map<std::string, std::string> FPS::ItemData()
34 {
35 std::map<std::string, std::string> result;
36 FpsInfo fpsInfoResult;
37 if (surfaceViewName.length() > 0) {
38 fpsInfoResult = GetDiffLayersFpsInfo(surfaceViewName);
39 prevResultFpsInfo = fpsInfoResult;
40 } else {
41 fpsInfoResult = GetFpsInfo();
42 prevResultFpsInfo = fpsInfoResult;
43 }
44 result["refreshrate"] = GetScreenInfo();
45 result["fps"] = std::to_string(fpsInfoResult.fps);
46 LOGI("result.fps====: %s", std::to_string(fpsInfoResult.fps).c_str());
47 LOGI("result.curTime====: %s", std::to_string(fpsInfoResult.curTime).c_str());
48 std::string jitterStr = "";
49 std::string split = "";
50 for (size_t i = 0; i < fpsInfoResult.jitters.size(); i++) {
51 if (i > 0) {
52 split = ";;";
53 }
54 jitterStr += split + std::to_string(fpsInfoResult.jitters[i]);
55 }
56 result["fpsJitters"] = jitterStr;
57 LOGI("result.jitters====: %s", jitterStr.c_str());
58 if (pkgName.length() > 0) {
59 std::string processId = "";
60 OHOS::SmartPerf::StartUpDelay sp;
61 processId = sp.GetPidByPkg(pkgName);
62 LOGI("FPS::processId -- %s", processId.c_str());
63 if (processId.empty()) {
64 result["fps"] = "NA";
65 result["fpsJitters"] = "NA";
66 }
67 }
68
69 SetFpsCurrentFpsTime(fpsInfoResult);
70
71 LOGI("FPS::ItemData map size(%u)", result.size());
72 return result;
73 }
74
GetScreenInfo() const75 std::string FPS::GetScreenInfo() const
76 {
77 std::string resultScreen = SPUtils::GetScreen();
78 unsigned int pos = resultScreen.find("=");
79 std::string numStr = resultScreen.substr(pos + 1);
80 LOGI("numStr====: %s", numStr.c_str());
81 return numStr;
82 }
83
SetFpsCurrentFpsTime(FpsInfo fpsInfoResult)84 void FPS::SetFpsCurrentFpsTime(FpsInfo fpsInfoResult)
85 {
86 ffTime.fps = fpsInfoResult.fps;
87 if (!fpsInfoResult.jitters.empty()) {
88 auto maxElement = std::max_element(fpsInfoResult.jitters.begin(), fpsInfoResult.jitters.end());
89 ffTime.currentFpsTime = *maxElement;
90 }
91 }
92
GetFpsCurrentFpsTime()93 FpsCurrentFpsTime FPS::GetFpsCurrentFpsTime()
94 {
95 return ffTime;
96 }
97
SetPackageName(std::string pName)98 void FPS::SetPackageName(std::string pName)
99 {
100 pkgName = std::move(pName);
101 }
SetLayerName(std::string sName)102 void FPS::SetLayerName(std::string sName)
103 {
104 surfaceViewName = std::move(sName);
105 }
GetDiffLayersFpsInfo(const std::string & sName)106 FpsInfo FPS::GetDiffLayersFpsInfo(const std::string &sName)
107 {
108 GetCurrentTime();
109 fpsInfoMax = GetSurfaceFrame(sName);
110 return fpsInfoMax;
111 }
112
GetCurrentTime()113 void FPS::GetCurrentTime()
114 {
115 for (int i = 0; i < fifty; i++) {
116 struct timespec time1 = { 0 };
117 clock_gettime(CLOCK_MONOTONIC, &time1);
118 int curTimeNow = static_cast<int>(time1.tv_sec - 1);
119 if (curTimeNow == prevResultFpsInfo.curTime) {
120 usleep(sleepNowTime);
121 } else {
122 break;
123 }
124 }
125 }
126
GetFpsInfo()127 FpsInfo FPS::GetFpsInfo()
128 {
129 fpsInfoMax.fps = 0;
130 if (pkgName.empty()) {
131 return fpsInfoMax;
132 }
133 bool onTop = IsForeGround();
134 if (onTop) {
135 LOGI("onTop===========");
136 std::string uniteLayer = "UniRender";
137 GetCurrentTime();
138 fpsInfoMax = GetSurfaceFrame(uniteLayer);
139 } else {
140 fpsInfoMax.Clear();
141 }
142 return fpsInfoMax;
143 }
144
GetSurfaceFrame(std::string name)145 FpsInfo FPS::GetSurfaceFrame(std::string name)
146 {
147 if (name == "") {
148 return FpsInfo();
149 }
150 static std::map<std::string, FpsInfo> fpsMap;
151 if (fpsMap.count(name) == 0) {
152 FpsInfo tmp;
153 tmp.fps = 0;
154 fpsMap[name] = tmp;
155 }
156 fpsInfo = fpsMap[name];
157 fpsInfo.fps = 0;
158 FILE *fp;
159 static char tmp[1024];
160 std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
161 fp = popen(cmd.c_str(), "r");
162 if (fp == nullptr) {
163 return fpsInfo;
164 }
165 fpsNum = 0;
166 refresh = true;
167 lastTime = -1;
168 LOGI("dump time: start!");
169 struct timespec time1 = { 0 };
170 clock_gettime(CLOCK_MONOTONIC, &time1);
171 fpsInfo.curTime = static_cast<int>(time1.tv_sec - 1);
172 fpsInfo.currTimeDump = (time1.tv_sec - 1) * mod + time1.tv_nsec;
173 LOGI("Time-------time1.tv_sec: %s", std::to_string(time1.tv_sec).c_str());
174 LOGI("Time-------time1.tv_nsec: %s", std::to_string(time1.tv_nsec).c_str());
175 LOGI("Time-------fpsInfo.curTime: %s", std::to_string(fpsInfo.curTime).c_str());
176 LOGI("Time-------fpsInfo.currTimeDump: %s", std::to_string(fpsInfo.currTimeDump).c_str());
177 while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
178 std::string str(tmp);
179 LOGD("dump time: %s", str.c_str());
180 frameReadyTime = 0;
181 std::stringstream sstream;
182 sstream << tmp;
183 sstream >> frameReadyTime;
184 if (frameReadyTime == 0) {
185 continue;
186 }
187 if (lastReadyTime >= frameReadyTime) {
188 lastReadyTime = -1;
189 continue;
190 }
191 GetSameTimeNums();
192 }
193 pclose(fp);
194 LOGI("Time-------fpsNum: %s", std::to_string(fpsNum).c_str());
195 return fpsInfo;
196 }
197
GetSameTimeNums()198 void FPS::GetSameTimeNums()
199 {
200 std::string onScreenTime = std::to_string(frameReadyTime / mod);
201 std::string fpsCurTime = std::to_string(fpsInfo.curTime);
202 if (onScreenTime.find(fpsCurTime) != std::string::npos) {
203 fpsNum++;
204 fpsInfo.currTimeStamps.push_back(frameReadyTime);
205 }
206 fpsInfo.fps = fpsNum;
207 if (onScreenTime == fpsCurTime) {
208 long long jitter;
209 if (lastTime != -1) {
210 jitter = frameReadyTime - lastTime;
211 fpsInfo.jitters.push_back(jitter);
212 } else {
213 if (lastFrameReadyTime != 0) {
214 jitter = frameReadyTime - lastFrameReadyTime;
215 fpsInfo.jitters.push_back(jitter);
216 }
217 }
218 lastTime = frameReadyTime;
219 lastFrameReadyTime = frameReadyTime;
220 }
221 }
222
IsForeGround()223 bool FPS::IsForeGround()
224 {
225 const std::string cmd = "hidumper -s WindowManagerService -a -a";
226 char buf[1024] = {'\0'};
227 std::string appLine = "app name [" + pkgName;
228 std::string bundleLine = "bundle name [" + pkgName;
229 isFoundAppName = false;
230 isFoundBundleName = false;
231 FILE *fd = popen(cmd.c_str(), "r");
232 if (fd == nullptr) {
233 return false;
234 }
235 while (fgets(buf, sizeof(buf), fd) != nullptr) {
236 std::string line = buf;
237 if (line.find(appLine) != std::string::npos) {
238 isFoundAppName = true;
239 }
240 if (line.find(bundleLine) != std::string::npos) {
241 isFoundBundleName = true;
242 }
243 if (isFoundAppName || isFoundBundleName) {
244 if (line.find("app state") != std::string::npos) {
245 bool tag = IsFindForeGround(line);
246 pclose(fd);
247 return tag;
248 }
249 }
250 }
251 pclose(fd);
252 return false;
253 }
254
IsFindForeGround(std::string line) const255 bool FPS::IsFindForeGround(std::string line) const
256 {
257 std::string foreGroundTag = line.substr(line.find("#") + 1);
258 if (foreGroundTag.find("FOREGROUND") != std::string::npos) {
259 return true;
260 } else {
261 return false;
262 }
263 }
264 }
265 }
266