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