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 <vector>
21 #include <map>
22 #include <string>
23 #include <unistd.h>
24 #include <sys/time.h>
25
26 namespace {
27 struct DumpEntity {
28 const std::string windowName;
29 const std::string displayId;
30 const std::string pid;
31 const std::string windId;
32 };
33 struct FpsInfo {
34 int fps;
35 int preFps;
36 std::vector<long long> jitters;
37 std::queue<long long> timeStampQ;
38 long long lastFrameReadyTime;
39 long long currentFpsTime;
FpsInfo__anon60f48c330111::FpsInfo40 FpsInfo()
41 {
42 fps = 0;
43 preFps = 0;
44 lastFrameReadyTime = 0;
45 currentFpsTime = 0;
46 }
47 };
48 struct FpsConfig {
49 const long long mod = 1e9;
50 long long lastReadyTime;
51 int fpsGb;
52 bool jump;
53 bool refresh;
54 int cnt;
55 int zeroNum;
FpsConfig__anon60f48c330111::FpsConfig56 FpsConfig()
57 {
58 lastReadyTime = -1;
59 fpsGb = 0;
60 jump = false;
61 refresh = false;
62 cnt = 0;
63 zeroNum = 0;
64 }
65 };
66 }
StrSplit(const std::string & content,const std::string & sp,std::vector<std::string> & out)67 static void StrSplit(const std::string &content, const std::string &sp, std::vector<std::string> &out)
68 {
69 size_t index = 0;
70 while (index != std::string::npos) {
71 size_t tEnd = content.find_first_of(sp, index);
72 std::string tmp = content.substr(index, tEnd - index);
73 if (tmp != "" && tmp != " ") {
74 out.push_back(tmp);
75 }
76 if (tEnd == std::string::npos) {
77 break;
78 }
79 index = tEnd + 1;
80 }
81 }
82
GetLayer()83 static std::string GetLayer()
84 {
85 std::vector<DumpEntity> dumpEntityList;
86 std::string curFocusId = "-1";
87 const std::string cmd = "hidumper -s WindowManagerService -a -a";
88 std::string cmdExc = cmd;
89 FILE *fd = popen(cmdExc.c_str(), "r");
90 if (fd != nullptr) {
91 int lineNum = 0;
92 std::string line;
93 char buf[1024] = {'\0'};
94 const int paramFifteen = 15;
95 const int paramThree = 3;
96 const int windowNameIndex = 0;
97 const int windowIdIndex = 3;
98 const int focusNameIndex = 2;
99 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
100 line = buf;
101 if (line[0] == '-' || line[0] == ' ') {
102 continue;
103 }
104 std::vector<std::string> params;
105 StrSplit(line, " ", params);
106 if (params[windowNameIndex].find("WindowName")!= std::string::npos &&
107 params[windowIdIndex].find("WinId")!= std::string::npos) {
108 continue;
109 }
110 if (params.size() == paramFifteen) {
111 DumpEntity dumpEntity { params[0], params[1], params[2], params[3] };
112 dumpEntityList.push_back(dumpEntity);
113 }
114 if (params.size() == paramThree) {
115 curFocusId = params[focusNameIndex];
116 break;
117 }
118 lineNum++;
119 }
120 pclose(fd);
121 }
122 std::string resultWindowName = "NA";
123 int curId = std::stoi(curFocusId);
124 for (size_t i = 0; i < dumpEntityList.size(); i++) {
125 DumpEntity dumpItem = dumpEntityList[i];
126 int curWinId = std::stoi(dumpItem.windId);
127 if (curId == curWinId) {
128 resultWindowName = dumpItem.windowName;
129 }
130 }
131 return resultWindowName;
132 }
ProcessResult(FILE * fp,FpsConfig & fpsConfig,FpsInfo & fpsInfo)133 static void ProcessResult(FILE *fp, FpsConfig &fpsConfig, FpsInfo &fpsInfo)
134 {
135 char tmp[1024];
136 while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
137 long long frameReadyTime = 0;
138 std::stringstream sstream;
139 sstream << tmp;
140 sstream >> frameReadyTime;
141 fpsConfig.cnt++;
142 if (frameReadyTime == 0) {
143 fpsConfig.zeroNum++;
144 continue;
145 }
146 if (fpsConfig.lastReadyTime >= frameReadyTime) {
147 fpsConfig.lastReadyTime = -1;
148 continue;
149 }
150 fpsConfig.refresh = true;
151 long long tFrameReadyTime = frameReadyTime / fpsConfig.mod;
152 long long tLastReadyTime = fpsConfig.lastReadyTime / fpsConfig.mod;
153 long long lastFrame = -1;
154 if (tFrameReadyTime == tLastReadyTime) {
155 (fpsInfo.timeStampQ).push(frameReadyTime);
156 } else if (tFrameReadyTime == tLastReadyTime + 1) {
157 fpsConfig.jump = true;
158 lastFrame = fpsInfo.lastFrameReadyTime;
159 fpsConfig.lastReadyTime = frameReadyTime;
160 int fpsTmp = 0;
161 fpsInfo.jitters.clear();
162 while (!(fpsInfo.timeStampQ).empty()) {
163 fpsTmp++;
164 long long currFrame = (fpsInfo.timeStampQ.front());
165 if (lastFrame != -1) {
166 long long jitter = currFrame - lastFrame;
167 fpsInfo.jitters.push_back(jitter);
168 }
169 lastFrame = currFrame;
170 (fpsInfo.timeStampQ).pop();
171 }
172 fpsConfig.fpsGb = fpsTmp;
173 (fpsInfo.timeStampQ).push(frameReadyTime);
174 fpsInfo.lastFrameReadyTime = lastFrame;
175 } else if (tFrameReadyTime > tLastReadyTime + 1) {
176 fpsConfig.jump = true;
177 fpsConfig.lastReadyTime = frameReadyTime;
178 while (!(fpsInfo.timeStampQ).empty()) {
179 (fpsInfo.timeStampQ).pop();
180 }
181 (fpsInfo.timeStampQ).push(frameReadyTime);
182 }
183 }
184 }
185
GetSurfaceFrame(std::string name,FpsConfig & fpsConfig)186 static FpsInfo GetSurfaceFrame(std::string name, FpsConfig &fpsConfig)
187 {
188 static std::map<std::string, FpsInfo> fpsMap;
189 if (fpsMap.count(name) == 0) {
190 FpsInfo tmp;
191 tmp.fps = 0;
192 tmp.preFps = 0;
193 fpsMap[name] = tmp;
194 }
195 FpsInfo &fpsInfo = fpsMap[name];
196 fpsInfo.fps = 0;
197 struct timeval tv;
198 gettimeofday(&tv, nullptr);
199 fpsInfo.currentFpsTime = tv.tv_sec * 1e3 + tv.tv_usec / 1e3;
200 std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
201 std::string cmdExc = cmd;
202 FILE *fp = popen(cmdExc.c_str(), "r");
203 if (fp == nullptr) {
204 return fpsInfo;
205 }
206 static long long lastLineTime;
207 if (!(fpsInfo.timeStampQ).empty()) {
208 fpsConfig.lastReadyTime = (fpsInfo.timeStampQ).back();
209 lastLineTime = (fpsInfo.timeStampQ).back();
210 }
211 ProcessResult(fp, fpsConfig, fpsInfo);
212 pclose(fp);
213 const int maxZeroNum = 120;
214 const int minPrintLine = 5;
215 if (fpsConfig.zeroNum >= maxZeroNum) {
216 while (!(fpsInfo.timeStampQ.empty())) {
217 fpsInfo.timeStampQ.pop();
218 }
219 fpsInfo.fps = 0;
220 return fpsInfo;
221 }
222
223 if (fpsConfig.cnt < minPrintLine) {
224 fpsInfo.fps = fpsInfo.preFps;
225 return fpsInfo;
226 }
227
228 if (!fpsInfo.timeStampQ.empty() && fpsInfo.timeStampQ.back() == lastLineTime) {
229 fpsInfo.fps = 0;
230 return fpsInfo;
231 }
232
233 if (fpsConfig.fpsGb > 0) {
234 fpsInfo.fps = fpsConfig.fpsGb;
235 fpsInfo.preFps = fpsConfig.fpsGb;
236 return fpsInfo;
237 } else if (fpsConfig.refresh && !fpsConfig.jump) {
238 fpsInfo.fps = fpsInfo.preFps;
239 return fpsInfo;
240 } else {
241 fpsInfo.fps = 0;
242 return fpsInfo;
243 }
244 }
245
ReplaceString(std::string & res)246 static void ReplaceString(std::string &res)
247 {
248 std::string flagOne = "\r";
249 std::string flagTwo = "\n";
250 std::string::size_type ret = res.find(flagOne);
251 while (ret != res.npos) {
252 res.replace(ret, 1, "");
253 ret = res.find(flagOne);
254 }
255 ret = res.find(flagTwo);
256 while (ret != res.npos) {
257 res.replace(ret, 1, "");
258 ret = res.find(flagTwo);
259 }
260 }
261
LoadCmd(const std::string & cmd,std::string & result)262 static bool LoadCmd(const std::string &cmd, std::string &result)
263 {
264 std::string cmdExc = cmd;
265 FILE *fd = popen(cmdExc.c_str(), "r");
266 if (fd == nullptr) {
267 return false;
268 }
269 char buf[1024] = {'\0'};
270 int ret = fread(buf, sizeof(buf), 1, fd);
271 if (ret >= 0) {
272 result = buf;
273 }
274 if (pclose(fd) == -1) {
275 std::cout << "" << std::endl;
276 }
277 ReplaceString(result);
278 return ret >= 0 ? true : false;
279 }
GetSurFace()280 static std::string GetSurFace()
281 {
282 std::string cmdResult;
283 std::string cmdString1 = "hidumper -s 10 -a sur";
284 std::string cmdString2 = "face | grep sur";
285 std::string cmdString3 = "face";
286 LoadCmd(cmdString1 + cmdString2 + cmdString3, cmdResult);
287 size_t position1 = cmdResult.find("[");
288 size_t position2 = cmdResult.find("]");
289 return cmdResult.substr(position1 + 1, position2 - position1 - 1);
290 }
main(int argc,char * argv[])291 int main(int argc, char *argv[])
292 {
293 if (argc < 2) {
294 printf("exec failed, require one param | example: GP_daemon_fps 10");
295 return 0;
296 }
297 int num = 1;
298 if (!strcmp(argv[1], "")) {
299 printf("the args of num must be not-null!\n");
300 } else {
301 num = atoi(argv[1]);
302 if (num < 0) {
303 printf("set num:%d not valid arg\n", num);
304 }
305 printf("set num:%d success\n", num);
306 FpsInfo gfpsInfo;
307 FpsInfo gfpsUniteInfo;
308 std::string layerName;
309 std::string tempLayerName;
310 struct timeval start;
311 struct timeval end;
312 std::string uniteLayer = "DisplayNode";
313 uniteLayer = GetSurFace();
314 unsigned long oneSec = 1000000;
315 std::string cmdResult;
316 for (int i = 0; i < num; i++) {
317 unsigned long runTime;
318 gettimeofday(&start, nullptr);
319 tempLayerName = GetLayer();
320 if (i == 0) {
321 layerName = tempLayerName;
322 LoadCmd("hidumper -s 10 -a \"fpsClear DisplayNode\"", cmdResult);
323 LoadCmd("hidumper -s 10 -a \"fpsClear" + layerName + "\"", cmdResult);
324 } else {
325 if (layerName.compare(tempLayerName) != 0) {
326 layerName = tempLayerName;
327 LoadCmd("hidumper -s 10 -a \"fpsClear" + layerName + "\"", cmdResult);
328 }
329 }
330 FpsConfig fpsConfig;
331 FpsConfig fpsUniteConfig;
332 gfpsInfo = GetSurfaceFrame(layerName, fpsConfig);
333 gfpsUniteInfo = GetSurfaceFrame(uniteLayer, fpsUniteConfig);
334 if (gfpsUniteInfo.fps > gfpsInfo.fps)
335 {
336 printf("fps:%d|%lld\n", gfpsUniteInfo.fps, gfpsUniteInfo.currentFpsTime);
337 } else {
338 printf("fps:%d|%lld\n", gfpsInfo.fps, gfpsInfo.currentFpsTime);
339 }
340 fflush(stdout);
341 gettimeofday(&end, nullptr);
342 runTime = end.tv_sec * 1e6 - start.tv_sec * 1e6 + end.tv_usec - start.tv_usec;
343 if (runTime < oneSec) {
344 usleep(oneSec - runTime);
345 }
346 }
347 }
348 printf("GP_daemon_fps exec finished!\n");
349 return 0;
350 }
351