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