• 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 <thread>
20 #include "include/sp_utils.h"
21 #include "include/ByTrace.h"
22 #include "include/Capture.h"
23 #include "include/FPS.h"
24 namespace OHOS {
25 namespace SmartPerf {
ItemData()26 std::map<std::string, std::string> FPS::ItemData()
27 {
28     std::map<std::string, std::string> result;
29     FpsInfo fpsInfo = GetFpsInfo();
30     result["fps"] = std::to_string(fpsInfo.fps);
31     std::string jitterStr = "";
32     std::string split = "";
33     for (size_t i = 0; i < fpsInfo.jitters.size(); i++) {
34         if (i > 0) {
35             split = ";;";
36         }
37         jitterStr += split + std::to_string(fpsInfo.jitters[i]);
38     }
39     result["fpsJitters"] = jitterStr;
40     if (isCatchTrace > 0) {
41         ByTrace::GetInstance().CheckFpsJitters(fpsInfo.jitters);
42     }
43     if (isCapture > 0) {
44         Capture::GetInstance().TriggerGetCatch(SPUtils::GetCurTime());
45     }
46     return result;
47 }
48 
SetTraceCatch()49 void FPS::SetTraceCatch()
50 {
51     isCatchTrace = 1;
52 }
53 
SetCaptureOn()54 void FPS::SetCaptureOn()
55 {
56     isCapture = 1;
57 }
58 
SetPackageName(std::string pName)59 void FPS::SetPackageName(std::string pName)
60 {
61     pkgName = std::move(pName);
62 }
63 
GetFpsInfo()64 FpsInfo FPS::GetFpsInfo()
65 {
66     FpsInfo fpsInfoMax;
67     fpsInfoMax.fps = 0;
68     int fpsValue = 0;
69 
70     if (pkgName.empty()) {
71         return fpsInfoMax;
72     }
73 
74     std::string layerName;
75     std::vector<std::string> sps;
76     SPUtils::StrSplit(this->pkgName, ".", sps);
77     std::string addEndChar = "0";
78     const uint64_t pNameLastPos = sps.size();
79     std::string pkgSuffix = sps[pNameLastPos - 1];
80     layerName = std::string(pkgSuffix.c_str() + addEndChar);
81     std::string uniteLayer = "DisplayNode";
82     std::string spSurfacePrefix = "sp_";
83     std::string line = GetLayer(layerName);
84     std::vector<std::string> params;
85     SPUtils::StrSplit(line, ":", params);
86     std::string pkgZOrd = params[1];
87     std::string zOrd = "-1";
88     std::string focusSurface = params[0];
89     FpsInfo uniteFpsInfo;
90     if (focusSurface.find(layerName) != std::string::npos) {
91         uniteFpsInfo = GetSurfaceFrame(uniteLayer);
92     }
93     if ((focusSurface.find(spSurfacePrefix) != std::string::npos) && (strcmp(pkgZOrd.c_str(), zOrd.c_str()) != 0)) {
94         if (uniteFpsInfo.fps <= fpsValue) {
95            uniteFpsInfo = GetSurfaceFrame(uniteLayer);
96         }
97     }
98     FpsInfo fpsInfo = GetSurfaceFrame(layerName);
99     if (fpsInfo.fps > uniteFpsInfo.fps) {
100         fpsInfoMax = fpsInfo;
101     } else {
102         fpsInfoMax = uniteFpsInfo;
103     }
104     if (fpsInfoMax.fps < fpsValue) {
105         fpsInfoMax.fps = fpsValue;
106     }
107     return fpsInfoMax;
108 }
109 
GetSurfaceFrame(std::string name)110 FpsInfo FPS::GetSurfaceFrame(std::string name)
111 {
112     if (name == "") {
113         return FpsInfo();
114     }
115     static std::map<std::string, FpsInfo> fpsMap;
116     if (fpsMap.count(name) == 0) {
117         FpsInfo tmp;
118         tmp.fps = 0;
119         tmp.preFps = 0;
120         fpsMap[name] = tmp;
121     }
122     FpsInfo &fpsInfo = fpsMap[name];
123     fpsInfo.fps = 0;
124     FILE *fp;
125     static char tmp[1024];
126     std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
127     fp = popen(cmd.c_str(), "r");
128     if (fp == nullptr) {
129         return fpsInfo;
130     }
131     long long mod = 1e9;
132     long long lastReadyTime = -1;
133     int fpsGb = 0;
134     static long long lastLineTime;
135     if (!(fpsInfo.timeStampQ).empty()) {
136         lastReadyTime = (fpsInfo.timeStampQ).back();
137         lastLineTime = (fpsInfo.timeStampQ).back();
138     }
139     bool jump = false;
140     bool refresh = false;
141 
142     int cnt = 0;
143     int zeroNum = 0;
144     while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
145         long long frameReadyTime = 0;
146         std::stringstream sstream;
147         sstream << tmp;
148         sstream >> frameReadyTime;
149         cnt++;
150         if (frameReadyTime == 0) {
151             zeroNum++;
152             continue;
153         }
154         if (lastReadyTime >= frameReadyTime) {
155             lastReadyTime = -1;
156             continue;
157         }
158         refresh = true;
159         long long tFrameReadyTime = frameReadyTime / mod;
160         long long tLastReadyTime = lastReadyTime / mod;
161         long long lastFrame = -1;
162         if (tFrameReadyTime == tLastReadyTime) {
163             (fpsInfo.timeStampQ).push(frameReadyTime);
164         } else if (tFrameReadyTime == tLastReadyTime + 1) {
165             jump = true;
166             lastFrame = fpsInfo.lastFrameReadyTime;
167             lastReadyTime = frameReadyTime;
168             int fpsTmp = 0;
169             fpsInfo.jitters.clear();
170             while (!(fpsInfo.timeStampQ).empty()) {
171                 fpsTmp++;
172                 long long currFrame = (fpsInfo.timeStampQ.front());
173                 if (lastFrame != -1) {
174                     long long jitter = currFrame - lastFrame;
175                     fpsInfo.jitters.push_back(jitter);
176                 }
177                 lastFrame = currFrame;
178                 (fpsInfo.timeStampQ).pop();
179             }
180 
181             fpsGb = fpsTmp;
182 
183             (fpsInfo.timeStampQ).push(frameReadyTime);
184 
185             fpsInfo.lastFrameReadyTime = lastFrame;
186         } else if (tFrameReadyTime > tLastReadyTime + 1) {
187             jump = true;
188             lastReadyTime = frameReadyTime;
189 
190             while (!(fpsInfo.timeStampQ).empty()) {
191                 (fpsInfo.timeStampQ).pop();
192             }
193 
194             (fpsInfo.timeStampQ).push(frameReadyTime);
195         }
196     }
197 
198     pclose(fp);
199     const int maxZeroNum = 120;
200     if (zeroNum >= maxZeroNum) {
201         while (!(fpsInfo.timeStampQ.empty())) {
202             fpsInfo.timeStampQ.pop();
203         }
204         fpsInfo.fps = 0;
205         return fpsInfo;
206     }
207     const int minPrintLine = 5;
208     if (cnt < minPrintLine) {
209         fpsInfo.fps = fpsInfo.preFps;
210         return fpsInfo;
211     }
212     if (!fpsInfo.timeStampQ.empty() && fpsInfo.timeStampQ.back() == lastLineTime) {
213         fpsInfo.fps = 0;
214         return fpsInfo;
215     }
216     if (fpsGb > 0) {
217         fpsInfo.fps = fpsGb;
218         fpsInfo.preFps = fpsGb;
219         return fpsInfo;
220     } else if (refresh && !jump) {
221         fpsInfo.fps = fpsInfo.preFps;
222         return fpsInfo;
223     } else {
224         fpsInfo.fps = 0;
225         return fpsInfo;
226     }
227 }
228 
GetLayer(std::string pkgSurface)229 std::string FPS::GetLayer(std::string pkgSurface)
230 {
231     std::vector<DumpEntity> dumpEntityList;
232     std::string curFocusId = "-1";
233     const std::string cmd = "hidumper -s WindowManagerService -a -a";
234     FILE *fd = popen(cmd.c_str(), "r");
235     if (fd != nullptr) {
236         int lineNum = 0;
237         char buf[1024] = {'\0'};
238 
239         const int paramFifteen = 15;
240         const int paramThree = 3;
241         const int windowNameIndex = 0;
242         const int windowIdIndex = 3;
243         const int focusNameIndex = 2;
244 
245         while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
246             std::string line = buf;
247             if (line[0] == '-' || line[0] == ' ') {
248                 continue;
249             }
250             std::vector<std::string> params;
251             SPUtils::StrSplit(line, " ", params);
252             if (params[windowNameIndex].find("WindowName") != std::string::npos &&
253                 params[windowIdIndex].find("WinId") != std::string::npos) {
254                 continue;
255             }
256             if (params.size() == paramFifteen) {
257                 DumpEntity dumpEntity { params[0], params[1], params[2], params[3], params[7]};
258                 dumpEntityList.push_back(dumpEntity);
259             }
260             if (params.size() == paramThree) {
261                 curFocusId = params[focusNameIndex];
262                 break;
263             }
264             lineNum++;
265         }
266         pclose(fd);
267     }
268 
269     std::string focusWindowName = "NA";
270     std::string pkgZOrd = "-1";
271     int curId = std::stoi(curFocusId);
272     for (size_t i = 0; i < dumpEntityList.size(); i++) {
273         DumpEntity dumpItem = dumpEntityList[i];
274         int curWinId = std::stoi(dumpItem.windId);
275         if (curId == curWinId) {
276             focusWindowName = dumpItem.windowName;
277         }
278         if (dumpItem.windowName.find(pkgSurface) != std::string::npos)
279         {
280             pkgZOrd = dumpItem.zOrd;
281         }
282     }
283     return focusWindowName + ":" + pkgZOrd;
284 }
285 }
286 }
287