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 <string>
20 #include <thread>
21 #include "include/sp_utils.h"
22 #include "include/ByTrace.h"
23 #include "include/Capture.h"
24 #include "include/FPS.h"
25 #include "include/sp_log.h"
26 namespace OHOS {
27 namespace SmartPerf {
ItemData()28 std::map<std::string, std::string> FPS::ItemData()
29 {
30 std::map<std::string, std::string> result;
31 FpsInfo fpsInfoResult;
32 if (surfaceViewName.length() > 0) {
33 fpsInfoResult = GetDiffLayersFpsInfo(surfaceViewName);
34 } else {
35 fpsInfoResult = GetFpsInfo();
36 }
37 result["fps"] = std::to_string(fpsInfoResult.fps);
38 LOGI("result.fps====: %s", std::to_string(fpsInfoResult.fps).c_str());
39 std::string jitterStr = "";
40 std::string split = "";
41 for (size_t i = 0; i < fpsInfoResult.jitters.size(); i++) {
42 if (i > 0) {
43 split = ";;";
44 }
45 jitterStr += split + std::to_string(fpsInfoResult.jitters[i]);
46 }
47 result["fpsJitters"] = jitterStr;
48 LOGI("result.jitters====: %s", jitterStr.c_str());
49 if (isCatchTrace > 0) {
50 ByTrace::GetInstance().CheckFpsJitters(fpsInfoResult.jitters, fpsInfoResult.fps);
51 }
52 if (isCapture > 0) {
53 Capture::GetInstance().TriggerGetCatch(SPUtils::GetCurTime());
54 }
55 return result;
56 }
57
SetTraceCatch()58 void FPS::SetTraceCatch()
59 {
60 isCatchTrace = 1;
61 }
62
SetCaptureOn()63 void FPS::SetCaptureOn()
64 {
65 isCapture = 1;
66 }
67
SetPackageName(std::string pName)68 void FPS::SetPackageName(std::string pName)
69 {
70 pkgName = std::move(pName);
71 }
SetLayerName(std::string sName)72 void FPS::SetLayerName(std::string sName)
73 {
74 surfaceViewName = std::move(sName);
75 }
GetDiffLayersFpsInfo(std::string sName)76 FpsInfo FPS::GetDiffLayersFpsInfo(std::string sName)
77 {
78 FpsInfo surfaceFramefpsInfo = GetSurfaceFrame(sName);
79 return surfaceFramefpsInfo;
80 }
GetSurface()81 std::string FPS::GetSurface()
82 {
83 std::string cmdResult;
84 std::string cmdString1 = "hidumper -s 10 -a sur";
85 std::string cmdString2 = "face | grep sur";
86 std::string cmdString3 = "face";
87 SPUtils::LoadCmd(cmdString1 + cmdString2 + cmdString3, cmdResult);
88 size_t position1 = cmdResult.find("[");
89 size_t position2 = cmdResult.find("]");
90 LOGI("cmdResult==: %s", (cmdResult.substr(position1 + 1, position2 - position1 - 1)).c_str());
91 return cmdResult.substr(position1 + 1, position2 - position1 - 1);
92 }
PrintFpsInfo(FpsInfo & fpsInfo,const std::string tag,const std::string type)93 static void PrintFpsInfo(FpsInfo &fpsInfo, const std::string tag, const std::string type)
94 {
95 LOGI("Print fps: %s", std::to_string(fpsInfo.fps).c_str());
96 LOGI("Print tag: %s", tag.c_str());
97 LOGI("Print type: %s", type.c_str());
98 std::string jitterStr = "";
99 std::string split = "";
100 for (size_t i = 0; i < fpsInfo.jitters.size(); i++) {
101 if (i > 0) {
102 split = ";;";
103 }
104 jitterStr += split + std::to_string(fpsInfo.jitters[i]);
105 }
106 LOGI("Print jitterStr: %s", jitterStr.c_str());
107 }
CutLayerName(std::string layerName)108 std::string FPS::CutLayerName(std::string layerName)
109 {
110 std::string subLayerName;
111 size_t twenty = 20;
112 if (layerName.size() > twenty) {
113 subLayerName = layerName.substr(0, twenty);
114 } else {
115 subLayerName = layerName;
116 }
117 return subLayerName;
118 }
119
GetFpsInfoMax()120 FpsInfo FPS::GetFpsInfoMax()
121 {
122 int fpsValue = 0;
123 if (fpsInfo.fps > uniteFpsInfo.fps) {
124 fpsInfoMax = fpsInfo;
125 } else {
126 fpsInfoMax = uniteFpsInfo;
127 }
128 if (fpsInfoMax.fps < fpsValue) {
129 fpsInfoMax.fps = fpsValue;
130 }
131 if (fpsInfoMax == prevFlagFpsInfo) {
132 LOGI("fpsInfoMax == prevFlagFpsInfo");
133 if (cntFpsInfo == lastFlagFpsInfo) {
134 LOGI("cntFpsInfo == lastFlagFpsInfo");
135 fpsInfoMax.fps = 0;
136 fpsInfoMax.Clear();
137 return fpsInfoMax;
138 } else {
139 LOGI("cntFpsInfo != lastFlagFpsInfo");
140 if ((cntFpsInfo.jitters.size() > 0 && lastFlagFpsInfo.jitters.size() > 0) &&
141 cntFpsInfo.jitters[0] == lastFlagFpsInfo.jitters[0]) {
142 LOGI("cntFpsInfo.jitters.size: %s", std::to_string(cntFpsInfo.jitters.size()).c_str());
143 LOGI("lastFlagFpsInfo.jitters.size: %s", std::to_string(lastFlagFpsInfo.jitters.size()).c_str());
144 LOGI("cntFpsInfo.jitters[0]: %s", std::to_string(cntFpsInfo.jitters[0]).c_str());
145 LOGI("lastFlagFpsInfo.jitters[0]: %s", std::to_string(lastFlagFpsInfo.jitters[0]).c_str());
146 cntFpsInfo.fps = 0;
147 cntFpsInfo.Clear();
148 } else {
149 LOGI("6666666666666666666");
150 lastFlagFpsInfo = cntFpsInfo;
151 }
152 return cntFpsInfo;
153 }
154 } else {
155 LOGI("fpsInfoMax != prevFlagFpsInfo");
156 if ((fpsInfoMax.jitters.size() > 0 && lastFlagFpsInfo.jitters.size() > 0) &&
157 fpsInfoMax.jitters[0] == lastFlagFpsInfo.jitters[0]) {
158 LOGI("fpsInfoMax == lastFlagFpsInfo");
159 lastFlagFpsInfo = cntFpsInfo;
160 return cntFpsInfo;
161 } else {
162 LOGI("fpsInfoMax != lastFlagFpsInfo");
163 prevFlagFpsInfo = fpsInfoMax;
164 return fpsInfoMax;
165 }
166 }
167 }
168
GetFpsInfo()169 FpsInfo FPS::GetFpsInfo()
170 {
171 fpsInfoMax.fps = 0;
172 if (pkgName.empty()) {
173 return fpsInfoMax;
174 }
175 std::vector<std::string> sps;
176 SPUtils::StrSplit(this->pkgName, ".", sps);
177 std::string layerName = std::string(sps[sps.size() - 1].c_str());
178 LOGI("layerName===: %s", layerName.c_str());
179 std::string uniteLayer = "DisplayNode";
180 uniteLayer = GetSurface();
181 LOGI("uniteLayer===: %s", uniteLayer.c_str());
182 std::string line = GetLayer(layerName);
183 LOGI("line===: %s", line.c_str());
184 std::vector<std::string> params;
185 SPUtils::StrSplit(line, ":", params);
186 std::string pkgZOrd = params[1];
187 LOGI("pkgZOrd===: %s", pkgZOrd.c_str());
188 std::string zOrd = "-1";
189 std::string focusSurface = params[0];
190 LOGI("focusSurface===: %s", focusSurface.c_str());
191 std::string subStrLayerName = CutLayerName(layerName);
192 LOGI("subStrLayerName===: %s", subStrLayerName.c_str());
193 if ((focusSurface.find(subStrLayerName) != std::string::npos) && (strcmp(pkgZOrd.c_str(), zOrd.c_str()) != 0)) {
194 uniteFpsInfo = GetSurfaceFrame(uniteLayer);
195 PrintFpsInfo(uniteFpsInfo, uniteLayer, "one");
196 }
197 fpsInfo = GetSurfaceFrame(focusSurface);
198 PrintFpsInfo(fpsInfo, focusSurface, "two");
199 return GetFpsInfoMax();
200 }
GetFpsInfoResult(FpsInfo & fpsInfo,long long & lastLineTime)201 FpsInfo FPS::GetFpsInfoResult(FpsInfo &fpsInfo, long long &lastLineTime)
202 {
203 const int maxZeroNum = 266;
204 if (zeroNum >= maxZeroNum) {
205 LOGI("zeroNum====: %s", std::to_string(zeroNum).c_str());
206 while (!(fpsInfo.timeStampQ.empty())) {
207 fpsInfo.timeStampQ.pop();
208 }
209 fpsInfo.fps = 0;
210 fpsInfo.jitters.clear();
211 LOGI("fpsInfo.fps0: %s", std::to_string(fpsInfo.fps).c_str());
212 return fpsInfo;
213 }
214 const int minPrintLine = 5;
215 if (cnt < minPrintLine) {
216 fpsInfo.fps = fpsInfo.preFps;
217 LOGI("fpsInfo.fps1: %s", std::to_string(fpsInfo.fps).c_str());
218 return fpsInfo;
219 }
220 if (!fpsInfo.timeStampQ.empty() && fpsInfo.timeStampQ.back() == lastLineTime) {
221 fpsInfo.fps = fpsGb;
222 if (fpsGb == 0) {
223 fpsInfo.jitters.clear();
224 }
225 LOGI("fpsInfo.fps2: %s", std::to_string(fpsInfo.fps).c_str());
226 LOGI("lastLineTime: %s", std::to_string(lastLineTime).c_str());
227 return fpsInfo;
228 }
229 if (fpsGb > 0) {
230 fpsInfo.fps = fpsGb;
231 fpsInfo.preFps = fpsGb;
232 LOGI("fpsInfo.fps3: %s", std::to_string(fpsInfo.fps).c_str());
233 LOGI("fpsInfo.preFps3: %s", std::to_string(fpsInfo.preFps).c_str());
234 return fpsInfo;
235 } else if (refresh && !jump) {
236 fpsInfo.fps = fpsInfo.preFps;
237 LOGI("fpsInfo.fps4: %s", std::to_string(fpsInfo.fps).c_str());
238 return fpsInfo;
239 } else {
240 fpsInfo.fps = 0;
241 fpsInfo.jitters.clear();
242 LOGI("fpsInfo.fps5: %s", std::to_string(fpsInfo.fps).c_str());
243 return fpsInfo;
244 }
245 }
246
GetLastFpsInfo(FpsInfo & fpsInfo)247 void FPS::GetLastFpsInfo(FpsInfo &fpsInfo)
248 {
249 int total = 266;
250 if (cnt == total && fpsGb != 0) {
251 LOGI("cnt == total && fpsGb != 0");
252 lastReadyTime = frameReadyTime;
253 int fpsTmp = 0;
254 cntFpsInfo.jitters.clear();
255 while (!(fpsInfo.timeStampQ).empty()) {
256 fpsTmp++;
257 long long currFrame = (fpsInfo.timeStampQ.front());
258 if (lastFrame != -1) {
259 long long jitter = currFrame - lastFrame;
260 cntFpsInfo.jitters.push_back(jitter);
261 } else {
262 long long jitter = currFrame - currFrame / mod * mod;
263 cntFpsInfo.jitters.push_back(jitter);
264 }
265 lastFrame = currFrame;
266 (fpsInfo.timeStampQ).pop();
267 }
268 cntFpsInfo.fps = fpsTmp;
269 LOGI("cntFpsInfo.fps====: %s", std::to_string(cntFpsInfo.fps).c_str());
270 }
271 }
272
GetPrevFpsInfo(FpsInfo & fpsInfo)273 void FPS::GetPrevFpsInfo(FpsInfo &fpsInfo)
274 {
275 refresh = true;
276 long long tFrameReadyTime = frameReadyTime / mod;
277 long long tLastReadyTime = lastReadyTime / mod;
278 lastFrame = -1;
279 if (tFrameReadyTime == tLastReadyTime) {
280 (fpsInfo.timeStampQ).push(frameReadyTime);
281 } else if (tFrameReadyTime == tLastReadyTime + 1) {
282 jump = true;
283 lastReadyTime = frameReadyTime;
284 int fpsTmp = 0;
285 fpsInfo.jitters.clear();
286 while (!(fpsInfo.timeStampQ).empty()) {
287 fpsTmp++;
288 long long currFrame = (fpsInfo.timeStampQ.front());
289 if (lastFrame != -1) {
290 long long jitter = currFrame - lastFrame;
291 fpsInfo.jitters.push_back(jitter);
292 } else {
293 long long jitter = currFrame - currFrame / mod * mod;
294 fpsInfo.jitters.push_back(jitter);
295 }
296 lastFrame = currFrame;
297 (fpsInfo.timeStampQ).pop();
298 }
299 fpsGb = fpsTmp;
300 LOGI("fpsGb====: %s", std::to_string(fpsGb).c_str());
301 (fpsInfo.timeStampQ).push(frameReadyTime);
302 fpsInfo.lastFrameReadyTime = lastFrame;
303 } else if (tFrameReadyTime > tLastReadyTime + 1) {
304 jump = true;
305 lastReadyTime = frameReadyTime;
306 while (!(fpsInfo.timeStampQ).empty()) {
307 (fpsInfo.timeStampQ).pop();
308 }
309 (fpsInfo.timeStampQ).push(frameReadyTime);
310 }
311 }
InitParams(FpsInfo & fpsInfo,long long & lastLineTime)312 void FPS::InitParams(FpsInfo &fpsInfo, long long &lastLineTime)
313 {
314 lastReadyTime = -1;
315 fpsGb = 0;
316 if (!(fpsInfo.timeStampQ).empty()) {
317 lastReadyTime = (fpsInfo.timeStampQ).back();
318 lastLineTime = (fpsInfo.timeStampQ).back();
319 }
320 jump = false;
321 refresh = false;
322 cnt = 0;
323 zeroNum = 0;
324 }
325
GetSurfaceFrame(std::string name)326 FpsInfo FPS::GetSurfaceFrame(std::string name)
327 {
328 if (name == "") {
329 return FpsInfo();
330 }
331 static std::map<std::string, FpsInfo> fpsMap;
332 if (fpsMap.count(name) == 0) {
333 FpsInfo tmp;
334 tmp.fps = 0;
335 tmp.preFps = 0;
336 fpsMap[name] = tmp;
337 }
338 fpsInfo = fpsMap[name];
339 fpsInfo.fps = 0;
340 FILE *fp;
341 static char tmp[1024];
342 std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
343 LOGI("cmd=====: %s", cmd.c_str());
344 fp = popen(cmd.c_str(), "r");
345 if (fp == nullptr) {
346 return fpsInfo;
347 }
348 static long long lastLineTime;
349 InitParams(fpsInfo, lastLineTime);
350 LOGI("dump time: start!");
351 while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
352 std::string str(tmp);
353 LOGD("dump time: %s", str.c_str());
354 frameReadyTime = 0;
355 std::stringstream sstream;
356 sstream << tmp;
357 sstream >> frameReadyTime;
358 cnt++;
359 if (frameReadyTime == 0) {
360 zeroNum++;
361 continue;
362 }
363 if (lastReadyTime >= frameReadyTime) {
364 lastReadyTime = -1;
365 continue;
366 }
367 GetPrevFpsInfo(fpsInfo);
368 GetLastFpsInfo(fpsInfo);
369 }
370 pclose(fp);
371 return GetFpsInfoResult(fpsInfo, lastLineTime);
372 }
373
GetLayer(std::string pkgSurface)374 std::string FPS::GetLayer(std::string pkgSurface)
375 {
376 std::vector<DumpEntity> dumpEntityList;
377 std::string curFocusId = "-1";
378 const std::string cmd = "hidumper -s WindowManagerService -a -a";
379 FILE *fd = popen(cmd.c_str(), "r");
380 if (fd != nullptr) {
381 int lineNum = 0;
382 char buf[1024] = {'\0'};
383 const int paramFourteen = 14;
384 const int paramTwentyFour = 24;
385 const int paramThree = 3;
386 const int windowNameIndex = 0;
387 const int windowIdIndex = 3;
388 const int focusNameIndex = 2;
389 while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
390 std::string line = buf;
391 LOGE("hidumperline: %s", line.c_str());
392 if (line[0] == '-' || line[0] == ' ') {
393 continue;
394 }
395 std::vector<std::string> params;
396 SPUtils::StrSplit(line, " ", params);
397 if (params[windowNameIndex].find("WindowName") != std::string::npos &&
398 params[windowIdIndex].find("WinId") != std::string::npos) {
399 continue;
400 }
401 if (params.size() > paramFourteen) {
402 DumpEntity dumpEntity { params[0], params[1], params[2], params[3], params[7]};
403 dumpEntityList.push_back(dumpEntity);
404 }
405 if (params.size() == paramFourteen || params.size() == paramTwentyFour) {
406 DumpEntity dumpEntity { params[0], params[2], params[2], params[3], params[6]};
407 dumpEntityList.push_back(dumpEntity);
408 }
409 if (params.size() == paramThree) {
410 curFocusId = params[focusNameIndex];
411 break;
412 }
413 lineNum++;
414 }
415 pclose(fd);
416 }
417
418 std::string focusWindowName = "NA";
419 std::string pkgZOrd = "-1";
420 std::string spSurfacePrefix = "sp_";
421 std::string floatWindow = "floatWindow";
422 int curId = std::stoi(curFocusId);
423 LOGE("getLayerCurId====: %s", std::to_string(curId).c_str());
424 for (size_t i = 0; i < dumpEntityList.size(); i++) {
425 DumpEntity dumpItem = dumpEntityList[i];
426 int curWinId = std::stoi(dumpItem.windId);
427 if (curId == curWinId) {
428 LOGE("curId == curWinId");
429 if ((dumpItem.windowName.find(spSurfacePrefix) != std::string::npos ||
430 dumpItem.windowName.find(floatWindow) != std::string::npos) && dumpItem.zOrd != "-1") {
431 continue;
432 }
433 focusWindowName = dumpItem.windowName;
434 LOGE("focusWindowName: %s", focusWindowName.c_str());
435 LOGE("dumpItem.windowName: %s", dumpItem.windowName.c_str());
436 }
437 if (dumpItem.windowName.find(pkgSurface) != std::string::npos && dumpItem.zOrd != "-1") {
438 focusWindowName = dumpItem.windowName;
439 pkgZOrd = dumpItem.zOrd;
440 LOGE("pkgZOrd: %s", pkgZOrd.c_str());
441 LOGE("dumpItem.zOrd: %s", dumpItem.zOrd.c_str());
442 LOGE("focusWindowName2: %s", focusWindowName.c_str());
443 LOGE("dumpItem.windowName2: %s", dumpItem.windowName.c_str());
444 }
445 }
446 return focusWindowName + ":" + pkgZOrd;
447 }
448 }
449 }
450