1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 <fstream>
16 #include <string>
17 #include <iostream>
18 #include <regex>
19 #include <cmath>
20 #include "include/stalling_rate_trace.h"
21 #include "include/sp_log.h"
22 
23 namespace OHOS {
24 namespace SmartPerf {
StallingRateResult(std::string file)25 double StallingRateTrace::StallingRateResult(std::string file)
26 {
27     double stalligRate = 0;
28     char realPath[PATH_MAX] = {0x00};
29     if ((realpath(file.c_str(), realPath) == nullptr)) {
30         std::cout << "" << std::endl;
31     }
32     infile.open(realPath);
33     if (infile.fail()) {
34         LOGI("StallingRateTrace open file(%s) fialed ", file.c_str());
35         return stalligRate;
36     }
37     stalligRate = SmartPerf::StallingRateTrace::CalculateTime();
38     infile.close();
39     return stalligRate;
40 }
41 
CalculateTime()42 double StallingRateTrace::CalculateTime()
43 {
44     frameLossRate = 0;
45     frameLossTime = 0;
46     swiperFrameLossRate = 0;
47     appFrameLossRate = 0;
48     tabsFrameLossRate = 0;
49     frameLossSwiperTime = 0;
50     frameLossTabsTime = 0;
51     std::string signS = "S|";
52     std::string signF = "F|";
53     std::string line;
54     while (getline(infile, line)) {
55         AppList(line, signS, signF);
56         AppSwiperScroll(line, signS, signF);
57         APPTabs(line, signS, signF);
58     }
59     CalcFrameRate();
60     JudgFrameRate();
61     MultiLaneFrameRate();
62     return frameLossRate;
63 }
64 
CalcFrameRate()65 void StallingRateTrace::CalcFrameRate()
66 {
67     if (appListDynamicStartTime != 0 && appListDynamicFinishTime != 0) {
68         appFrameLossRate = (frameLossTime / (appListDynamicFinishTime - appListDynamicStartTime) * oneThousand);
69     } else {
70         appFrameLossRate = -1;
71     }
72     LOGI("result.appFrameLossRate: (%s)", std::to_string(appFrameLossRate).c_str());
73 
74     if (swiperDynamicFinishTime != 0 && swiperDynamicStartTime != 0) {
75         swiperFrameLossRate = (frameLossSwiperTime / (swiperDynamicFinishTime - swiperDynamicStartTime) * oneThousand);
76     } else {
77         swiperFrameLossRate = -1;
78     }
79     LOGI("result.swiperFrameLossRate: (%s)", std::to_string(swiperFrameLossRate).c_str());
80 
81     if (appTabsDynamicStartTime != 0 && appTabsDynamicFinishTime != 0) {
82         tabsFrameLossRate = (frameLossTabsTime / (appTabsDynamicFinishTime - appTabsDynamicStartTime) * oneThousand);
83     } else {
84         tabsFrameLossRate = -1;
85     }
86     LOGI("result.tabsFrameLossRate: (%s)", std::to_string(tabsFrameLossRate).c_str());
87 }
88 
JudgFrameRate()89 void StallingRateTrace::JudgFrameRate()
90 {
91     auto hasDynamic = [](bool finishTime, bool startTime) {
92         return finishTime != 0 || startTime != 0;
93     };
94 
95     bool appListDynamicExists = hasDynamic(appListDynamicFinishTime, appListDynamicStartTime);
96     bool swiperDynamicExists = hasDynamic(swiperDynamicFinishTime, swiperDynamicStartTime);
97     bool tabsDynamicExists = hasDynamic(appTabsDynamicFinishTime, appTabsDynamicStartTime);
98 
99     if (!appListDynamicExists) {
100         LOGI("no app list Dynamic");
101         frameLossRate = swiperDynamicExists ? swiperFrameLossRate :
102                         tabsDynamicExists ? tabsFrameLossRate : -1;
103     } else if (!swiperDynamicExists) {
104         LOGI("no swiper Dynamic");
105         frameLossRate = appListDynamicExists ? appFrameLossRate :
106                         tabsDynamicExists ? tabsFrameLossRate : -1;
107     } else if (!tabsDynamicExists) {
108         LOGI("no tabs Dynamic");
109         frameLossRate = appListDynamicExists ? appFrameLossRate :
110                         swiperDynamicExists ? swiperFrameLossRate : -1;
111     } else {
112         frameLossRate = -1;
113     }
114 }
115 
MultiLaneFrameRate()116 void StallingRateTrace::MultiLaneFrameRate()
117 {
118     if (appFrameLossRate == 0) {
119         LOGI("no app list hitchTime");
120         if (swiperFrameLossRate > 0) {
121             frameLossRate = swiperFrameLossRate;
122         } else if (tabsFrameLossRate > 0) {
123             frameLossRate = tabsFrameLossRate;
124         } else {
125             frameLossRate = 0;
126         }
127     } else if (swiperFrameLossRate == 0) {
128         LOGI("no swiper list hitchTime");
129         if (appFrameLossRate > 0) {
130             frameLossRate = appFrameLossRate;
131         } else if (tabsFrameLossRate > 0) {
132             frameLossRate = tabsFrameLossRate;
133         } else {
134             frameLossRate = 0;
135         }
136     } else if (tabsFrameLossRate == 0) {
137         LOGI("no tabs list hitchTime");
138         if (appFrameLossRate > 0) {
139             frameLossRate = appFrameLossRate;
140         } else if (swiperFrameLossRate > 0) {
141             frameLossRate = swiperFrameLossRate;
142         }
143     }
144     AddMultiLaneFrameRate();
145 }
146 
AddMultiLaneFrameRate()147 void StallingRateTrace::AddMultiLaneFrameRate()
148 {
149     if (appFrameLossRate > 0 && swiperFrameLossRate > 0) {
150         //app and swiper hitchTime 1
151         if (appListDynamicStartTime < swiperDynamicStartTime) {
152             frameLossRate = appFrameLossRate;
153         } else {
154             frameLossRate = swiperFrameLossRate;
155         }
156     } else if (appFrameLossRate > 0 && tabsFrameLossRate > 0) {
157         //app and tabs hitchTime 2
158         if (appListDynamicStartTime < appTabsDynamicStartTime) {
159             frameLossRate = appFrameLossRate;
160         } else {
161             frameLossRate = appTabsDynamicStartTime;
162         }
163     } else if (tabsFrameLossRate > 0 && swiperFrameLossRate > 0) {
164         //tabs and swiper hitchTime 3
165         if (appTabsDynamicStartTime < swiperDynamicStartTime) {
166             frameLossRate = tabsFrameLossRate;
167         } else {
168             frameLossRate = swiperFrameLossRate;
169         }
170     }
171 }
172 
173 
AppList(const std::string &line, const std::string &signS, const std::string &signF)174 void StallingRateTrace::AppList(const std::string &line, const std::string &signS, const std::string &signF)
175 {
176     if (line.find("H:LAUNCHER_APP_LAUNCH_FROM_ICON,") != std::string::npos ||
177         line.find("H:APP_LIST_FLING,") != std::string::npos ||
178         line.find("H:WEB_LIST_FLING") != std::string::npos ||
179         line.find("H:ABILITY_OR_PAGE_SWITCH,") != std::string::npos ||
180         line.find("H:APP_TRANSITION_TO_OTHER_APP,") != std::string::npos ||
181         line.find("H:LAUNCHER_APP_LAUNCH_FROM_DOCK,") != std::string::npos ||
182         line.find("H:LAUNCHER_APP_LAUNCH_FROM_APPCENTER,") != std::string::npos) {
183         if (listFlag) {
184             LOGI("AppList line start: (%s)", line.c_str());
185             appListDynamicFinishTime = GetTimes(line, signF);
186             LOGI("appListDynamicFinishTime: (%s)", std::to_string(appListDynamicFinishTime).c_str());
187             listFlag = false;
188         } else {
189             LOGI("AppList line finish: (%s)", line.c_str());
190             appListDynamicStartTime = GetTimes(line, signS);
191             LOGI("appListDynamicStartTime: (%s)", std::to_string(appListDynamicStartTime).c_str());
192             listFlag = true;
193             frameLossTime = 0;
194         }
195     }
196     if (listFlag) {
197         GetRsHardWareRate(nowFrameRate, line, SWIM_APPLIST);
198         if (upperScreenFlag) {
199             if (line.find("|H:Present Fence ") != std::string::npos) {
200                 fenceId = GetFenceId(line);
201                 LOGI("fenceId: (%d)", fenceId);
202             }
203             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceId);
204             if (line.find(waitFenceId) != std::string::npos) {
205                 nowTime = std::stod(SmartPerf::StallingRateTrace::GetOnScreenTimeStart(line));
206                 GetFrameLossTime(nowTime, lastTime, roundTime, frameLossTime);
207                 LOGI("frameLossTime: (%s)", std::to_string(frameLossTime).c_str());
208                 lastTime = nowTime;
209                 upperScreenFlag = false;
210             }
211         }
212     }
213 }
214 
GetFrameLossTime(double curTime, double prevTime, double drawTime, double &totalFrameLossTime)215 void StallingRateTrace::GetFrameLossTime(double curTime, double prevTime, double drawTime, double &totalFrameLossTime)
216 {
217     if ((curTime - prevTime) > drawTime && prevTime != 0) {
218         double diffTime = (curTime - prevTime) - drawTime;
219         LOGI("diffTime: (%s)", std::to_string(diffTime).c_str());
220         totalFrameLossTime += diffTime;
221         LOGI("totalFrameLossTime: (%s)", std::to_string(totalFrameLossTime).c_str());
222     }
223 }
224 
GetRsHardWareRate(double curFrameRate, const std::string &line, SWIM_TYPE type)225 void StallingRateTrace::GetRsHardWareRate(double curFrameRate, const std::string &line, SWIM_TYPE type)
226 {
227     if (line.find("H:RSHardwareThread::CommitAndReleaseLayers") != std::string::npos) {
228         switch (type) {
229             case SWIM_APPLIST:
230                 upperScreenFlag = true;
231                 break;
232             case SWIM_APPSWIPER:
233                 upperScreenSwiperFlag = true;
234                 break;
235             case SWIM_APPTABS:
236                 upperScreenTabsFlag = true;
237                 break;
238             default:
239                 break;
240         }
241         curFrameRate = GetFrameRate(line);
242         LOGI("curFrameRate1: (%s)", std::to_string(curFrameRate).c_str());
243         if (curFrameRate != 0) {
244             UpdateRoundTime(curFrameRate, type);
245         }
246     } else if (line.find("H:RSHardwareThread::PerformSetActiveMode setting active mode") != std::string::npos) {
247         switch (type) {
248             case SWIM_APPLIST:
249                 upperScreenFlag = true;
250                 break;
251             case SWIM_APPSWIPER:
252                 upperScreenSwiperFlag = true;
253                 break;
254             case SWIM_APPTABS:
255                 upperScreenTabsFlag = true;
256                 break;
257             default:
258                 break;
259         }
260         curFrameRate = GetFrameRate(line);
261         LOGI("curFrameRate2: (%s)", std::to_string(curFrameRate).c_str());
262         if (curFrameRate != 0) {
263             UpdateRoundTime(curFrameRate, type);
264         }
265     }
266 }
267 
UpdateRoundTime(double curFrameRate, SWIM_TYPE type)268 void StallingRateTrace::UpdateRoundTime(double curFrameRate, SWIM_TYPE type)
269 {
270     const double kadunNum = 1.5;
271     const double num = 1;
272     if (curFrameRate != 0) {
273         switch (type) {
274             case SWIM_APPLIST:
275                 roundTime = (num / curFrameRate) * kadunNum;
276                 break;
277             case SWIM_APPSWIPER:
278                 roundSwiperTime = (num / curFrameRate) * kadunNum;
279                 break;
280             case SWIM_APPTABS:
281                 roundTabsTime = (num / curFrameRate) * kadunNum;
282                 break;
283             default:
284                 break;
285         }
286     }
287 }
288 
AppSwiperScroll(const std::string &line, const std::string &signS, const std::string &signF)289 void StallingRateTrace::AppSwiperScroll(const std::string &line, const std::string &signS, const std::string &signF)
290 {
291     if (line.find("H:APP_SWIPER_NO_ANIMATION_SWITCH") != std::string::npos ||
292         line.find("H:APP_SWITCH_FRAME_ANIMATION") != std::string::npos ||
293         line.find("H:APP_SWIPER_SCROLL,") != std::string::npos) {
294         if (swiperScrollFlag == 0) {
295             LOGI("AppSwiperScroll line start: (%s)", line.c_str());
296             swiperDynamicStartTime = GetTimes(line, signS);
297             LOGI("swiperDynamicStartTime: (%s)", std::to_string(swiperDynamicStartTime).c_str());
298             frameLossSwiperTime = 0;
299             swiperScrollFlag = 1;
300             swiperFlag = true;
301         }
302     }
303     if (line.find("H:APP_SWIPER_FLING,") != std::string::npos ||
304         line.find("H:APP_SWIPER_NO_ANIMATION_SWITCH") != std::string::npos ||
305         line.find("H:APP_SWITCH_FRAME_ANIMATION") != std::string::npos) {
306         if (swiperFlingFlag == 1) {
307             LOGI("AppSwiper FinishTime line: (%s)", line.c_str());
308             swiperDynamicFinishTime = GetTimes(line, signF);
309             LOGI("swiperDynamicFinishTime: (%s)", std::to_string(swiperDynamicFinishTime).c_str());
310             swiperFlag = false;
311         }
312         if (swiperDynamicFinishTime == 0) {
313             swiperFlingFlag = 0;
314         }
315         swiperFlingFlag++;
316     }
317     if (swiperFlag) {
318         GetRsHardWareRate(nowSwiperFrameRate, line, SWIM_APPSWIPER);
319         if (upperScreenSwiperFlag) {
320             if (line.find("|H:Present Fence ") != std::string::npos) {
321                 fenceIdSwiper = GetFenceId(line);
322                 LOGI("fenceIdSwiper: (%d)", fenceIdSwiper);
323             }
324             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceIdSwiper);
325             if (line.find(waitFenceId) != std::string::npos) {
326                 nowSwiperTime = std::stod(SmartPerf::StallingRateTrace::GetOnScreenTimeStart(line));
327                 LOGI("nowSwiperTime: (%s)", std::to_string(nowSwiperTime).c_str());
328                 GetFrameLossTime(nowSwiperTime, lastSwiperTime, roundSwiperTime, frameLossSwiperTime);
329                 LOGI("frameLossSwiperTime: (%s)", std::to_string(frameLossSwiperTime).c_str());
330                 lastSwiperTime = nowSwiperTime;
331                 upperScreenSwiperFlag = false;
332             }
333         }
334     }
335 }
336 
APPTabs(const std::string &line, const std::string &signS, const std::string &signF)337 void StallingRateTrace::APPTabs(const std::string &line, const std::string &signS, const std::string &signF)
338 {
339     static const std::string appTabsNoAnimation = "H:APP_TABS_NO_ANIMATION_SWITCH";
340     static const std::string appTabsFrameAnimation = "H:APP_TABS_FRAME_ANIMATION";
341     static const std::string appTabsScroll = "H:APP_TABS_SCROLL,";
342 
343     if (line.find(appTabsNoAnimation) != std::string::npos ||
344         line.find(appTabsFrameAnimation) != std::string::npos ||
345         line.find(appTabsScroll) != std::string::npos) {
346         if (tabsFlag) {
347             LOGI("APPTabs line start: (%s)", line.c_str());
348             appTabsDynamicFinishTime = GetTimes(line, signF);
349             LOGI("appTabsDynamicFinishTime: (%s)", std::to_string(appTabsDynamicFinishTime).c_str());
350             tabsFlag = false;
351         } else {
352             LOGI("APPTabs line finish: (%s)", line.c_str());
353             appTabsDynamicStartTime = GetTimes(line, signS);
354             LOGI("appTabsDynamicStartTime: (%s)", std::to_string(appTabsDynamicStartTime).c_str());
355             tabsFlag = true;
356             frameLossTabsTime = 0;
357         }
358     }
359     if (tabsFlag) {
360         GetRsHardWareRate(nowTabsFrameRate, line, SWIM_APPTABS);
361         if (upperScreenTabsFlag) {
362             if (line.find("|H:Present Fence ") != std::string::npos) {
363                 fenceIdTabs = GetFenceId(line);
364                 LOGI("fenceIdTabs: (%s)", std::to_string(fenceIdTabs).c_str());
365             }
366             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceIdTabs);
367             if (line.find(waitFenceId) != std::string::npos) {
368                 nowTabsTime = std::stod(SmartPerf::StallingRateTrace::GetOnScreenTimeStart(line));
369                 LOGI("nowTabsTime: (%s)", std::to_string(nowTabsTime).c_str());
370                 LOGI("lastTabsTime: (%s)", std::to_string(lastTabsTime).c_str());
371                 LOGI("roundTabsTime: (%s)", std::to_string(roundTabsTime).c_str());
372                 GetFrameLossTime(nowTabsTime, lastTabsTime, roundTabsTime, frameLossTabsTime);
373                 LOGI("app tabs frameLossTabsTime: (%s)", std::to_string(frameLossTabsTime).c_str());
374                 lastTabsTime = nowTabsTime;
375                 upperScreenTabsFlag = false;
376             }
377         }
378     }
379 }
380 
GetFrameRate(const std::string &line) const381 double StallingRateTrace::GetFrameRate(const std::string &line) const
382 {
383     double rate = 0;
384     std::string delimiter = "rate: ";
385     if (line.find("now:") != std::string::npos && line.find("rate:") != std::string::npos) {
386         std::string delimiter1 = ", now:";
387         size_t pos1 = line.find(delimiter);
388         std::string result1 = line.substr(pos1 + delimiter.length());
389         size_t pos2 = line.find(delimiter1);
390         std::string result2 = result1.substr(0, pos2);
391         rate = std::stod(result2.c_str());
392     }
393     if (line.find("rate:") != std::string::npos) {
394         size_t pos = line.find(delimiter);
395         std::string result = line.substr(pos + delimiter.length());
396         rate = std::stod(result.c_str());
397     }
398     return rate;
399 }
400 
GetFenceId(const std::string &line) const401 int StallingRateTrace::GetFenceId(const std::string &line) const
402 {
403     std::string delimiter = "H:Present Fence ";
404     size_t pos = line.find(delimiter);
405     std::string result = line.substr(pos + delimiter.length());
406     int presentFenceId = std::atoi(result.c_str());
407     return presentFenceId;
408 }
409 
GetOnScreenTimeStart(const std::string &line) const410 std::string StallingRateTrace::GetOnScreenTimeStart(const std::string &line) const
411 {
412     std::string startTime = "0";
413     size_t subNum = 7;
414     size_t positionFirst = line.find("....");
415     size_t positionSecond = line.find(":");
416     startTime = line.substr(positionFirst + subNum, positionSecond - positionFirst - subNum);
417     return startTime;
418 }
419 
GetTimes(const std::string &line, const std::string &sign) const420 double StallingRateTrace::GetTimes(const std::string &line, const std::string &sign) const
421 {
422     size_t positionFirst = line.find("....");
423     size_t positionSecond = line.find(":");
424     if (positionFirst != std::string::npos && positionSecond != std::string::npos) {
425         if (line.find(sign) != std::string::npos) {
426             size_t subNum = 7;
427             return std::stod(line.substr(positionFirst + subNum, positionSecond - positionFirst - subNum));
428         }
429     }
430     return 0.0;
431 }
432 }
433 }
434