1 /*
2  * Copyright (c) 2023 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 
16 #include "base/perfmonitor/perf_monitor.h"
17 
18 #include "base/log/ace_trace.h"
19 #include "base/log/event_report.h"
20 #include "base/perfmonitor/perf_constants.h"
21 #include "core/common/ace_application_info.h"
22 #include "render_service_client/core/transaction/rs_interfaces.h"
23 
24 namespace OHOS::Ace {
25 using namespace std;
26 PerfMonitor* PerfMonitor::pMonitor = nullptr;
27 constexpr int64_t SCENE_TIMEOUT = 10000000000;
28 constexpr int64_t RESPONSE_TIMEOUT = 600000000;
29 constexpr int64_t STARTAPP_FRAME_TIMEOUT = 1000000000;
30 constexpr float SINGLE_FRAME_TIME = 16600000;
31 const int32_t JANK_SKIPPED_THRESHOLD = SystemProperties::GetJankFrameThreshold();
32 const int32_t DEFAULT_JANK_REPORT_THRESHOLD = 3;
33 // Obtain the last three digits of the full path
34 constexpr uint32_t PATH_DEPTH = 3;
35 
ParsePageUrl(const std::string & pagePath)36 std::string ParsePageUrl(const std::string& pagePath)
37 {
38     std::string res;
39     std::vector<std::string> paths;
40     StringUtils::StringSplitter(pagePath, '/', paths);
41     uint32_t pathSize = paths.size();
42     if (pathSize < PATH_DEPTH) {
43         return pagePath;
44     }
45     for (uint32_t i = pathSize - PATH_DEPTH; i < pathSize; i++) {
46         res = res + "/" + paths[i];
47     }
48     return res;
49 }
50 
GetCurrentRealTimeNs()51 static int64_t GetCurrentRealTimeNs()
52 {
53     struct timespec ts = { 0, 0 };
54     if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
55         return 0;
56     }
57     return (ts.tv_sec * NS_TO_S + ts.tv_nsec);
58 }
59 
GetCurrentSystimeMs()60 static int64_t GetCurrentSystimeMs()
61 {
62     auto timeNow = std::chrono::system_clock::now();
63     auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
64     int64_t curSystime = tmp.count();
65     return curSystime;
66 }
67 
ConvertRealtimeToSystime(int64_t realTime,int64_t & sysTime)68 void ConvertRealtimeToSystime(int64_t realTime, int64_t& sysTime)
69 {
70     int64_t curRealTime = GetCurrentRealTimeNs();
71     if (curRealTime == 0) {
72         sysTime = 0;
73         return;
74     }
75     int64_t curSysTime = GetCurrentSystimeMs();
76     sysTime = curSysTime - (curRealTime - realTime) / NS_TO_MS;
77 }
78 
GetSourceTypeName(PerfSourceType sourceType)79 std::string GetSourceTypeName(PerfSourceType sourceType)
80 {
81     std::string type = "";
82     switch (sourceType) {
83         case PERF_TOUCH_EVENT:
84             type = "TOUCHSCREEN";
85             break;
86         case PERF_MOUSE_EVENT:
87             type = "MOUSE";
88             break;
89         case PERF_TOUCH_PAD:
90             type = "TOUCHPAD";
91             break;
92         case PERF_JOY_STICK:
93             type = "JOYSTICK";
94             break;
95         case PERF_KEY_EVENT:
96             type = "KEY_EVENT";
97             break;
98         default :
99             type = "UNKNOWN_SOURCE";
100             break;
101     }
102     return type;
103 }
104 
ConvertToRsData(OHOS::Rosen::DataBaseRs & dataRs,DataBase & data)105 void ConvertToRsData(OHOS::Rosen::DataBaseRs &dataRs, DataBase& data)
106 {
107     dataRs.eventType = static_cast<int32_t>(data.eventType);
108     dataRs.sceneId = data.sceneId;
109     dataRs.appPid = data.baseInfo.pid;
110     dataRs.uniqueId = data.beginVsyncTime / NS_TO_MS;
111     dataRs.inputTime = data.inputTime;
112     dataRs.beginVsyncTime = data.beginVsyncTime;
113     dataRs.endVsyncTime = data.endVsyncTime;
114     dataRs.versionCode = data.baseInfo.versionCode;
115     dataRs.versionName = data.baseInfo.versionName;
116     dataRs.bundleName = data.baseInfo.bundleName;
117     dataRs.processName = data.baseInfo.processName;
118     dataRs.abilityName = data.baseInfo.abilityName;
119     dataRs.pageUrl = data.baseInfo.pageUrl;
120     dataRs.sourceType = GetSourceTypeName(data.sourceType);
121     dataRs.note = data.baseInfo.note;
122     dataRs.isDisplayAnimator = data.isDisplayAnimator;
123 }
124 
ReportPerfEventToRS(DataBase & data)125 void ReportPerfEventToRS(DataBase& data)
126 {
127     OHOS::Rosen::DataBaseRs dataRs;
128     ConvertToRsData(dataRs, data);
129     switch (dataRs.eventType) {
130         case EVENT_RESPONSE:
131             {
132                 ACE_SCOPED_TRACE("EVENT_REPORT_RESPONSE_RS sceneId = %s, uniqueId = %lld",
133                     dataRs.sceneId.c_str(), static_cast<long long> (dataRs.uniqueId));
134                 Rosen::RSInterfaces::GetInstance().ReportEventResponse(dataRs);
135                 break;
136             }
137         case EVENT_COMPLETE:
138             {
139                 if (data.needReportRs) {
140                     ACE_SCOPED_TRACE("EVENT_REPORT_COMPLETE_RS sceneId = %s, uniqueId = %lld",
141                         dataRs.sceneId.c_str(), static_cast<long long> (dataRs.uniqueId));
142                     Rosen::RSInterfaces::GetInstance().ReportEventComplete(dataRs);
143                 }
144                 break;
145             }
146         case EVENT_JANK_FRAME:
147             {
148                 ACE_SCOPED_TRACE("EVENT_REPORT_JANK_RS sceneId = %s, uniqueId = %lld",
149                     dataRs.sceneId.c_str(), static_cast<long long> (dataRs.uniqueId));
150                 Rosen::RSInterfaces::GetInstance().ReportEventJankFrame(dataRs);
151                 break;
152             }
153         default :
154             break;
155     }
156 }
157 
ReportPerfEventToUI(DataBase data)158 void ReportPerfEventToUI(DataBase data)
159 {
160     switch (data.eventType) {
161         case EVENT_COMPLETE:
162             if (!data.needReportRs) {
163                 EventReport::ReportEventComplete(data);
164             }
165             break;
166         case EVENT_JANK_FRAME:
167             if (data.totalFrames > 0) {
168                 EventReport::ReportEventJankFrame(data);
169             }
170             break;
171         default :
172             break;
173     }
174 }
175 
InitRecord(const std::string & sId,PerfActionType aType,PerfSourceType sType,const std::string & nt,int64_t time)176 void SceneRecord::InitRecord(const std::string& sId, PerfActionType aType, PerfSourceType sType, const std::string& nt,
177     int64_t time)
178 {
179     sceneId = sId;
180     actionType = aType;
181     sourceType = sType;
182     note = nt;
183     inputTime = time;
184     beginVsyncTime = GetCurrentRealTimeNs();
185     isDisplayAnimator = IsDisplayAnimator(sceneId);
186 }
187 
IsTimeOut(int64_t nowTime)188 bool SceneRecord::IsTimeOut(int64_t nowTime)
189 {
190     if (nowTime - beginVsyncTime > SCENE_TIMEOUT) {
191         return true;
192     }
193     return false;
194 }
195 
RecordFrame(int64_t vsyncTime,int64_t duration,int32_t skippedFrames)196 void SceneRecord::RecordFrame(int64_t vsyncTime, int64_t duration, int32_t skippedFrames)
197 {
198     int64_t currentTimeNs = GetCurrentRealTimeNs();
199     if (totalFrames == 0) {
200         beginVsyncTime = currentTimeNs;
201         isFirstFrame = true;
202     } else {
203         isFirstFrame = false;
204     }
205     skippedFrames = static_cast<int32_t>(duration / SINGLE_FRAME_TIME);
206     if (!isFirstFrame && skippedFrames >= 1) {
207         if (isSuccessive) {
208             seqMissFrames = seqMissFrames + skippedFrames;
209         } else {
210             seqMissFrames = skippedFrames;
211             isSuccessive = true;
212         }
213         if (maxSuccessiveFrames < seqMissFrames) {
214             maxSuccessiveFrames = seqMissFrames;
215         }
216         totalMissed += skippedFrames;
217     } else {
218         isSuccessive = false;
219         seqMissFrames = 0;
220     }
221     if (!isFirstFrame && duration > maxFrameTime) {
222         maxFrameTime = duration;
223         maxFrameTimeSinceStart = (currentTimeNs - beginVsyncTime) / NS_TO_MS;
224     }
225     totalFrames++;
226 }
227 
Report(const std::string & sceneId,int64_t vsyncTime,bool isRsRender)228 void SceneRecord::Report(const std::string& sceneId, int64_t vsyncTime, bool isRsRender)
229 {
230     if (isRsRender || vsyncTime <= beginVsyncTime) {
231         endVsyncTime = GetCurrentRealTimeNs();
232     } else {
233         endVsyncTime = vsyncTime;
234     }
235     needReportRs = !isRsRender;
236 }
237 
IsFirstFrame()238 bool SceneRecord::IsFirstFrame()
239 {
240     return isFirstFrame;
241 }
242 
IsDisplayAnimator(const std::string & sceneId)243 bool SceneRecord::IsDisplayAnimator(const std::string& sceneId)
244 {
245     if (sceneId == PerfConstants::APP_LIST_FLING || sceneId == PerfConstants::APP_SWIPER_SCROLL
246         || sceneId == PerfConstants::SNAP_RECENT_ANI
247         || sceneId == PerfConstants::WINDOW_RECT_RESIZE
248         || sceneId == PerfConstants::WINDOW_RECT_MOVE
249         || sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE
250         || sceneId == PerfConstants::LAUNCHER_SPRINGBACK_SCROLL) {
251         return true;
252     }
253     return false;
254 }
255 
Reset()256 void SceneRecord::Reset()
257 {
258     beginVsyncTime = 0;
259     endVsyncTime = 0;
260     maxFrameTime = 0;
261     maxFrameTimeSinceStart = 0;
262     maxHitchTime = 0;
263     maxHitchTimeSinceStart = 0;
264     maxSuccessiveFrames = 0;
265     seqMissFrames = 0;
266     totalMissed = 0;
267     totalFrames = 0;
268     isSuccessive = false;
269     isFirstFrame = false;
270     sceneId = "";
271     actionType = UNKNOWN_ACTION;
272     sourceType = UNKNOWN_SOURCE;
273     note = "";
274 }
275 
GetPerfMonitor()276 PerfMonitor* PerfMonitor::GetPerfMonitor()
277 {
278     if (pMonitor == nullptr) {
279         pMonitor = new PerfMonitor();
280     }
281     return pMonitor;
282 }
283 
Start(const std::string & sceneId,PerfActionType type,const std::string & note)284 void PerfMonitor::Start(const std::string& sceneId, PerfActionType type, const std::string& note)
285 {
286     std::lock_guard<std::mutex> Lock(mMutex);
287     if (apsMonitor_ != nullptr) {
288         apsMonitor_->SetApsScene(sceneId, true);
289     }
290 
291     int64_t inputTime = GetInputTime(sceneId, type, note);
292     SceneRecord* record = GetRecord(sceneId);
293     if (IsSceneIdInSceneWhiteList(sceneId)) {
294         isExceptAnimator = true;
295     }
296     ACE_SCOPED_TRACE("Animation start and current sceneId=%s", sceneId.c_str());
297     if (record == nullptr) {
298         currentSceneId = sceneId;
299         record = new SceneRecord();
300         record->InitRecord(sceneId, type, mSourceType, note, inputTime);
301         mRecords.insert(std::pair<std::string, SceneRecord*> (sceneId, record));
302         RecordBaseInfo(record);
303         AceAsyncTraceBegin(0, sceneId.c_str());
304     }
305 }
306 
End(const std::string & sceneId,bool isRsRender)307 void PerfMonitor::End(const std::string& sceneId, bool isRsRender)
308 {
309     std::lock_guard<std::mutex> Lock(mMutex);
310     if (apsMonitor_ != nullptr) {
311         apsMonitor_->SetApsScene(sceneId, false);
312     }
313 
314     SceneRecord* record = GetRecord(sceneId);
315     ACE_SCOPED_TRACE("Animation end and current sceneId=%s", sceneId.c_str());
316     if (record != nullptr) {
317         if (IsSceneIdInSceneWhiteList(sceneId)) {
318             isExceptAnimator = false;
319         }
320         RecordBaseInfo(record);
321         record->Report(sceneId, mVsyncTime, isRsRender);
322         ReportAnimateEnd(sceneId, record);
323         RemoveRecord(sceneId);
324         AceAsyncTraceEnd(0, sceneId.c_str());
325     }
326 }
327 
RecordInputEvent(PerfActionType type,PerfSourceType sourceType,int64_t time)328 void PerfMonitor::RecordInputEvent(PerfActionType type, PerfSourceType sourceType, int64_t time)
329 {
330     mSourceType = sourceType;
331     if (time <= 0) {
332         time = GetCurrentRealTimeNs();
333     }
334     switch (type) {
335         case LAST_DOWN:
336             {
337                 ACE_SCOPED_TRACE("RecordInputEvent: last_down=%lld(ns)", static_cast<long long>(time));
338                 mInputTime[LAST_DOWN] = time;
339                 break;
340             }
341         case LAST_UP:
342             {
343                 ACE_SCOPED_TRACE("RecordInputEvent: last_up=%lld(ns)", static_cast<long long>(time));
344                 mInputTime[LAST_UP] = time;
345                 isResponseExclusion = true;
346                 break;
347             }
348         case FIRST_MOVE:
349             {
350                 ACE_SCOPED_TRACE("RecordInputEvent: first_move=%lld(ns)", static_cast<long long>(time));
351                 mInputTime[FIRST_MOVE] = time;
352                 break;
353             }
354         default:
355             break;
356     }
357 }
358 
SetFrameTime(int64_t vsyncTime,int64_t duration,double jank,const std::string & windowName)359 void PerfMonitor::SetFrameTime(int64_t vsyncTime, int64_t duration, double jank, const std::string& windowName)
360 {
361     std::lock_guard<std::mutex> Lock(mMutex);
362     mVsyncTime = vsyncTime;
363     int32_t skippedFrames = static_cast<int32_t> (jank);
364     for (auto it = mRecords.begin(); it != mRecords.end();) {
365         if (it->second != nullptr) {
366             (it->second)->RecordFrame(vsyncTime, duration, skippedFrames);
367             if ((it->second)->IsTimeOut(vsyncTime + duration)) {
368                 CheckTimeOutOfExceptAnimatorStatus(it->second->sceneId);
369                 delete it->second;
370                 it = mRecords.erase(it);
371                 continue;
372             }
373             if ((it->second)->IsFirstFrame()) {
374                 ReportAnimateStart(it->first, it->second);
375             }
376         }
377         it++;
378     }
379     ProcessJank(jank, windowName);
380 }
381 
ReportJankFrameApp(double jank)382 void PerfMonitor::ReportJankFrameApp(double jank)
383 {
384     if (jank >= static_cast<double>(JANK_SKIPPED_THRESHOLD) && !isBackgroundApp) {
385         JankInfo jankInfo;
386         jankInfo.skippedFrameTime = static_cast<int64_t>(jank * SINGLE_FRAME_TIME);
387         RecordBaseInfo(nullptr);
388         jankInfo.baseInfo = baseInfo;
389         EventReport::ReportJankFrameApp(jankInfo);
390     }
391 }
392 
SetPageUrl(const std::string & pageUrl)393 void PerfMonitor::SetPageUrl(const std::string& pageUrl)
394 {
395     baseInfo.pageUrl = ParsePageUrl(pageUrl);
396 }
397 
GetPageUrl()398 std::string PerfMonitor::GetPageUrl()
399 {
400     return baseInfo.pageUrl;
401 }
402 
SetPageName(const std::string & pageName)403 void PerfMonitor::SetPageName(const std::string& pageName)
404 {
405     baseInfo.pageName = pageName;
406 }
407 
GetPageName()408 std::string PerfMonitor::GetPageName()
409 {
410     return baseInfo.pageName;
411 }
412 
ReportPageShowMsg(const std::string & pageUrl,const std::string & bundleName,const std::string & pageName)413 void PerfMonitor::ReportPageShowMsg(const std::string& pageUrl, const std::string& bundleName,
414                                     const std::string& pageName)
415 {
416     std::string parsePageUrl = ParsePageUrl(pageUrl);
417     EventReport::ReportPageShowMsg(parsePageUrl, bundleName, pageName);
418 }
419 
RecordBaseInfo(SceneRecord * record)420 void PerfMonitor::RecordBaseInfo(SceneRecord* record)
421 {
422     baseInfo.pid = AceApplicationInfo::GetInstance().GetPid();
423     baseInfo.bundleName = AceApplicationInfo::GetInstance().GetPackageName();
424     baseInfo.versionCode = static_cast<int32_t>(AceApplicationInfo::GetInstance().GetAppVersionCode());
425     baseInfo.versionName = AceApplicationInfo::GetInstance().GetAppVersionName();
426     baseInfo.processName = AceApplicationInfo::GetInstance().GetProcessName();
427     baseInfo.abilityName = AceApplicationInfo::GetInstance().GetAbilityName();
428     if (record != nullptr) {
429         baseInfo.note = record->note;
430     }
431 }
432 
GetRecord(const std::string & sceneId)433 SceneRecord* PerfMonitor::GetRecord(const std::string& sceneId)
434 {
435     auto iter = mRecords.find(sceneId);
436     if (iter != mRecords.end()) {
437         return iter->second;
438     }
439     return nullptr;
440 }
441 
RemoveRecord(const std::string & sceneId)442 void PerfMonitor::RemoveRecord(const std::string& sceneId)
443 {
444     std::map <std::string, SceneRecord*>::iterator iter = mRecords.find(sceneId);
445     if (iter != mRecords.end()) {
446         if (iter->second != nullptr) {
447             delete iter->second;
448         }
449         mRecords.erase(iter);
450     }
451 }
452 
GetInputTime(const std::string & sceneId,PerfActionType type,const std::string & note)453 int64_t PerfMonitor::GetInputTime(const std::string& sceneId, PerfActionType type, const std::string& note)
454 {
455     int64_t inputTime = 0;
456     switch (type) {
457         case LAST_DOWN:
458             inputTime = mInputTime[LAST_DOWN];
459             break;
460         case LAST_UP:
461             inputTime = mInputTime[LAST_UP];
462             break;
463         case FIRST_MOVE:
464             inputTime = mInputTime[FIRST_MOVE];
465             break;
466         default:
467             break;
468     }
469     if (inputTime <= 0 || IsExceptResponseTime(inputTime, sceneId)) {
470         ACE_SCOPED_TRACE("GetInputTime: now time");
471         inputTime = GetCurrentRealTimeNs();
472     }
473     return inputTime;
474 }
475 
ReportAnimateStart(const std::string & sceneId,SceneRecord * record)476 void PerfMonitor::ReportAnimateStart(const std::string& sceneId, SceneRecord* record)
477 {
478     if (record == nullptr) {
479         return;
480     }
481     DataBase data;
482     FlushDataBase(record, data);
483     ReportPerfEvent(EVENT_RESPONSE, data);
484 }
485 
ReportAnimateEnd(const std::string & sceneId,SceneRecord * record)486 void PerfMonitor::ReportAnimateEnd(const std::string& sceneId, SceneRecord* record)
487 {
488     if (record == nullptr) {
489         return;
490     }
491     DataBase data;
492     FlushDataBase(record, data);
493     ReportPerfEvent(EVENT_JANK_FRAME, data);
494     ReportPerfEvent(EVENT_COMPLETE, data);
495 }
496 
FlushDataBase(SceneRecord * record,DataBase & data)497 void PerfMonitor::FlushDataBase(SceneRecord* record, DataBase& data)
498 {
499     if (record == nullptr) {
500         return;
501     }
502     data.sceneId = record->sceneId;
503     data.inputTime = record->inputTime;
504     data.beginVsyncTime = record->beginVsyncTime;
505     if (data.beginVsyncTime < data.inputTime) {
506         data.inputTime = data.beginVsyncTime;
507     }
508     data.endVsyncTime = record->endVsyncTime;
509     if (data.beginVsyncTime > data.endVsyncTime) {
510         data.endVsyncTime = data.beginVsyncTime;
511     }
512     data.maxFrameTime = record->maxFrameTime;
513     data.maxFrameTimeSinceStart = record->maxFrameTimeSinceStart;
514     data.maxHitchTime = record->maxHitchTime;
515     data.maxHitchTimeSinceStart = record->maxHitchTimeSinceStart;
516     data.maxSuccessiveFrames = record->maxSuccessiveFrames;
517     data.totalMissed = record->totalMissed;
518     data.totalFrames = record->totalFrames;
519     data.needReportRs = record->needReportRs;
520     data.isDisplayAnimator = record->isDisplayAnimator;
521     data.sourceType = record->sourceType;
522     data.actionType = record->actionType;
523     data.baseInfo = baseInfo;
524 }
525 
ReportPerfEvent(PerfEventType type,DataBase & data)526 void PerfMonitor::ReportPerfEvent(PerfEventType type, DataBase& data)
527 {
528     switch (type) {
529         case EVENT_RESPONSE:
530             data.eventType = EVENT_RESPONSE;
531             break;
532         case EVENT_COMPLETE:
533             data.eventType = EVENT_COMPLETE;
534             break;
535         case EVENT_JANK_FRAME:
536             data.eventType = EVENT_JANK_FRAME;
537             break;
538         default :
539             break;
540     }
541     ReportPerfEventToUI(data);
542     ReportPerfEventToRS(data);
543 }
544 
IsExceptResponseTime(int64_t time,const std::string & sceneId)545 bool PerfMonitor::IsExceptResponseTime(int64_t time, const std::string& sceneId)
546 {
547     int64_t currentRealTimeNs = GetCurrentRealTimeNs();
548     static set<std::string> exceptSceneSet = {
549         PerfConstants::APP_LIST_FLING, PerfConstants::SCREEN_ROTATION_ANI,
550         PerfConstants::SHOW_INPUT_METHOD_ANIMATION, PerfConstants::HIDE_INPUT_METHOD_ANIMATION,
551         PerfConstants::APP_TRANSITION_FROM_OTHER_APP, PerfConstants::APP_TRANSITION_TO_OTHER_APP,
552         PerfConstants::VOLUME_BAR_SHOW, PerfConstants::PC_APP_CENTER_GESTURE_OPERATION,
553         PerfConstants::PC_GESTURE_TO_RECENT, PerfConstants::PC_SHORTCUT_SHOW_DESKTOP,
554         PerfConstants::PC_ALT_TAB_TO_RECENT, PerfConstants::PC_SHOW_DESKTOP_GESTURE_OPERATION,
555         PerfConstants::PC_SHORTCUT_RESTORE_DESKTOP, PerfConstants::PC_SHORTCUT_TO_RECENT,
556         PerfConstants::PC_EXIT_RECENT, PerfConstants::PC_SHORTCUT_TO_APP_CENTER_ON_RECENT,
557         PerfConstants::PC_SHORTCUT_TO_APP_CENTER, PerfConstants::PC_SHORTCUT_EXIT_APP_CENTER,
558         PerfConstants::WINDOW_TITLE_BAR_MINIMIZED, PerfConstants::WINDOW_RECT_MOVE,
559         PerfConstants::APP_EXIT_FROM_WINDOW_TITLE_BAR_CLOSED, PerfConstants::WINDOW_TITLE_BAR_RECOVER,
560         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_OTHER, PerfConstants::WINDOW_RECT_RESIZE,
561         PerfConstants::WINDOW_TITLE_BAR_MAXIMIZED, PerfConstants::LAUNCHER_APP_LAUNCH_FROM_TRANSITION
562     };
563     if (exceptSceneSet.find(sceneId) != exceptSceneSet.end()) {
564         return true;
565     }
566     if ((sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH && currentRealTimeNs - time > RESPONSE_TIMEOUT)
567         || (sceneId == PerfConstants::CLOSE_FOLDER_ANI && currentRealTimeNs - time > RESPONSE_TIMEOUT)) {
568         return true;
569     }
570     return false;
571 }
572 
573 // for jank frame app
IsExclusionFrame()574 bool PerfMonitor::IsExclusionFrame()
575 {
576     ACE_SCOPED_TRACE("IsExclusionFrame: isResponse(%d) isStartApp(%d) isBg(%d) isExcluWindow(%d) isExcAni(%d)",
577         isResponseExclusion, isStartAppFrame, isBackgroundApp, isExclusionWindow, isExceptAnimator);
578     return isResponseExclusion || isStartAppFrame || isBackgroundApp || isExclusionWindow || isExceptAnimator;
579 }
580 
SetAppStartStatus()581 void PerfMonitor::SetAppStartStatus()
582 {
583     ACE_FUNCTION_TRACE();
584     isStartAppFrame = true;
585     startAppTime = GetCurrentRealTimeNs();
586 }
587 
CheckInStartAppStatus()588 void PerfMonitor::CheckInStartAppStatus()
589 {
590     if (isStartAppFrame) {
591         int64_t curTime = GetCurrentRealTimeNs();
592         if (curTime - startAppTime >= STARTAPP_FRAME_TIMEOUT) {
593             isStartAppFrame = false;
594             startAppTime = curTime;
595         }
596     }
597 }
598 
SetAppForeground(bool isShow)599 void PerfMonitor::SetAppForeground(bool isShow)
600 {
601     isBackgroundApp = !isShow;
602 }
603 
CheckExclusionWindow(const std::string & windowName)604 void PerfMonitor::CheckExclusionWindow(const std::string& windowName)
605 {
606     isExclusionWindow = false;
607     if (windowName == "softKeyboard1" ||
608         windowName == "SCBWallpaper1" ||
609         windowName == "SCBStatusBar15") {
610         isExclusionWindow = true;
611     }
612 }
613 
CheckResponseStatus()614 void PerfMonitor::CheckResponseStatus()
615 {
616     if (isResponseExclusion) {
617         isResponseExclusion = false;
618     }
619 }
620 
ProcessJank(double jank,const std::string & windowName)621 void PerfMonitor::ProcessJank(double jank, const std::string& windowName)
622 {
623     // single frame behavior report
624     CheckExclusionWindow(windowName);
625     ReportJankFrame(jank, windowName);
626     CheckInStartAppStatus();
627     CheckResponseStatus();
628 }
629 
ReportJankFrame(double jank,const std::string & windowName)630 void PerfMonitor::ReportJankFrame(double jank, const std::string& windowName)
631 {
632     if (jank >= static_cast<double>(DEFAULT_JANK_REPORT_THRESHOLD)) {
633         JankInfo jankInfo;
634         jankInfo.skippedFrameTime = static_cast<int64_t>(jank * SINGLE_FRAME_TIME);
635         jankInfo.windowName = windowName;
636         RecordBaseInfo(nullptr);
637         jankInfo.baseInfo = baseInfo;
638         jankInfo.filterType = GetFilterType();
639         if (!mRecords.empty()) {
640             jankInfo.sceneId = currentSceneId;
641         } else {
642             jankInfo.sceneId = DEFAULT_SCENE_ID;
643         }
644         EventReport::ReportJankFrameUnFiltered(jankInfo);
645         if (!IsExclusionFrame()) {
646             EventReport::ReportJankFrameFiltered(jankInfo);
647         }
648     }
649 }
650 
IsSceneIdInSceneWhiteList(const std::string & sceneId)651 bool PerfMonitor::IsSceneIdInSceneWhiteList(const std::string& sceneId)
652 {
653     if (sceneId == PerfConstants::LAUNCHER_APP_LAUNCH_FROM_ICON ||
654         sceneId == PerfConstants::LAUNCHER_APP_LAUNCH_FROM_DOCK ||
655         sceneId == PerfConstants::LAUNCHER_APP_LAUNCH_FROM_MISSON ||
656         sceneId == PerfConstants::LAUNCHER_APP_SWIPE_TO_HOME ||
657         sceneId == PerfConstants::LAUNCHER_APP_BACK_TO_HOME ||
658         sceneId == PerfConstants::EXIT_RECENT_2_HOME_ANI ||
659         sceneId == PerfConstants::APP_SWIPER_FLING ||
660         sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH) {
661         return true;
662     }
663     return false;
664 }
665 
CheckTimeOutOfExceptAnimatorStatus(const std::string & sceneId)666 void PerfMonitor::CheckTimeOutOfExceptAnimatorStatus(const std::string& sceneId)
667 {
668     if (IsSceneIdInSceneWhiteList(sceneId)) {
669         isExceptAnimator = false;
670     }
671 }
672 
GetFilterType() const673 int32_t PerfMonitor::GetFilterType() const
674 {
675     int32_t filterType = (isBackgroundApp << 4) | (isResponseExclusion << 3) | (isStartAppFrame << 2)
676         | (isExclusionWindow << 1) | isExceptAnimator;
677     return filterType;
678 }
679 
SetApsMonitor(const std::shared_ptr<ApsMonitor> & apsMonitor)680 void PerfMonitor::SetApsMonitor(const std::shared_ptr<ApsMonitor>& apsMonitor)
681 {
682     apsMonitor_ = apsMonitor;
683 }
684 
685 } // namespace OHOS::Ace
686