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