• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/perfmonitor/perf_interfaces.h"
22 #include "base/utils/system_properties.h"
23 #include "core/common/ace_application_info.h"
24 #include "render_service_client/core/transaction/rs_interfaces.h"
25 #ifdef OHOS_STANDARD_SYSTEM
26 #include "event_handler.h"
27 #endif
28 
29 namespace OHOS::Ace {
30 using namespace std;
31 PerfMonitor* PerfMonitor::pMonitor = nullptr;
32 constexpr int64_t SCENE_TIMEOUT = 10000000000;
33 constexpr int64_t RESPONSE_TIMEOUT = 600000000;
34 constexpr int64_t STARTAPP_FRAME_TIMEOUT = 1000000000;
35 constexpr float SINGLE_FRAME_TIME = 16600000;
36 const int32_t JANK_SKIPPED_THRESHOLD = SystemProperties::GetJankFrameThreshold();
37 const int32_t DEFAULT_JANK_REPORT_THRESHOLD = 3;
38 constexpr uint32_t DEFAULT_VSYNC = 16;
39 // Obtain the last three digits of the full path
40 constexpr uint32_t PATH_DEPTH = 3;
41 
42 constexpr uint32_t JANK_FRAME_6_LIMIT = 0;
43 constexpr uint32_t JANK_FRAME_15_LIMIT = 1;
44 constexpr uint32_t JANK_FRAME_20_LIMIT = 2;
45 constexpr uint32_t JANK_FRAME_36_LIMIT = 3;
46 constexpr uint32_t JANK_FRAME_48_LIMIT = 4;
47 constexpr uint32_t JANK_FRAME_60_LIMIT = 5;
48 constexpr uint32_t JANK_FRAME_120_LIMIT = 6;
49 constexpr uint32_t JANK_FRAME_180_LIMIT = 7;
50 constexpr uint32_t JANK_STATS_SIZE = 8;
51 
GetJankLimit(double jank)52 uint32_t GetJankLimit(double jank)
53 {
54     if (jank < 6.0f) {
55         return JANK_FRAME_6_LIMIT;
56     }
57     if (jank < 15.0f) {
58         return JANK_FRAME_15_LIMIT;
59     }
60     if (jank < 20.0f) {
61         return JANK_FRAME_20_LIMIT;
62     }
63     if (jank < 36.0f) {
64         return JANK_FRAME_36_LIMIT;
65     }
66     if (jank < 48.0f) {
67         return JANK_FRAME_48_LIMIT;
68     }
69     if (jank < 60.0f) {
70         return JANK_FRAME_60_LIMIT;
71     }
72     if (jank < 120.0f) {
73         return JANK_FRAME_120_LIMIT;
74     }
75     return JANK_FRAME_180_LIMIT;
76 }
77 
ParsePageUrl(const std::string & pagePath)78 std::string ParsePageUrl(const std::string& pagePath)
79 {
80     std::string res;
81     std::vector<std::string> paths;
82     StringUtils::StringSplitter(pagePath, '/', paths);
83     uint32_t pathSize = paths.size();
84     if (pathSize < PATH_DEPTH) {
85         return pagePath;
86     }
87     for (uint32_t i = pathSize - PATH_DEPTH; i < pathSize; i++) {
88         res = res + "/" + paths[i];
89     }
90     return res;
91 }
92 
GetCurrentRealTimeNs()93 static int64_t GetCurrentRealTimeNs()
94 {
95     struct timespec ts = { 0, 0 };
96     if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
97         return 0;
98     }
99     return (ts.tv_sec * NS_TO_S + ts.tv_nsec);
100 }
101 
GetCurrentSystimeMs()102 static int64_t GetCurrentSystimeMs()
103 {
104     auto timeNow = std::chrono::system_clock::now();
105     auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
106     int64_t curSystime = tmp.count();
107     return curSystime;
108 }
109 
ConvertRealtimeToSystime(int64_t realTime,int64_t & sysTime)110 void ConvertRealtimeToSystime(int64_t realTime, int64_t& sysTime)
111 {
112     int64_t curRealTime = GetCurrentRealTimeNs();
113     if (curRealTime == 0) {
114         sysTime = 0;
115         return;
116     }
117     int64_t curSysTime = GetCurrentSystimeMs();
118     sysTime = curSysTime - (curRealTime - realTime) / NS_TO_MS;
119 }
120 
GetSourceTypeName(PerfSourceType sourceType)121 std::string GetSourceTypeName(PerfSourceType sourceType)
122 {
123     std::string type = "";
124     switch (sourceType) {
125         case PERF_TOUCH_EVENT:
126             type = "TOUCHSCREEN";
127             break;
128         case PERF_MOUSE_EVENT:
129             type = "MOUSE";
130             break;
131         case PERF_TOUCH_PAD:
132             type = "TOUCHPAD";
133             break;
134         case PERF_JOY_STICK:
135             type = "JOYSTICK";
136             break;
137         case PERF_KEY_EVENT:
138             type = "KEY_EVENT";
139             break;
140         default :
141             type = "UNKNOWN_SOURCE";
142             break;
143     }
144     return type;
145 }
146 
ConvertToRsData(OHOS::Rosen::DataBaseRs & dataRs,DataBase & data)147 void ConvertToRsData(OHOS::Rosen::DataBaseRs &dataRs, DataBase& data)
148 {
149     dataRs.eventType = static_cast<int32_t>(data.eventType);
150     dataRs.sceneId = data.sceneId;
151     dataRs.appPid = data.baseInfo.pid;
152     dataRs.uniqueId = data.beginVsyncTime / NS_TO_MS;
153     dataRs.inputTime = data.inputTime;
154     dataRs.beginVsyncTime = data.beginVsyncTime;
155     dataRs.endVsyncTime = data.endVsyncTime;
156     dataRs.versionCode = data.baseInfo.versionCode;
157     dataRs.versionName = data.baseInfo.versionName;
158     dataRs.bundleName = data.baseInfo.bundleName;
159     dataRs.processName = data.baseInfo.processName;
160     dataRs.abilityName = data.baseInfo.abilityName;
161     dataRs.pageUrl = data.baseInfo.pageUrl;
162     dataRs.sourceType = GetSourceTypeName(data.sourceType);
163     dataRs.note = data.baseInfo.note;
164     dataRs.isDisplayAnimator = data.isDisplayAnimator;
165 }
166 
ReportPerfEventToRS(DataBase & data)167 void ReportPerfEventToRS(DataBase& data)
168 {
169     OHOS::Rosen::DataBaseRs dataRs;
170     ConvertToRsData(dataRs, data);
171     switch (dataRs.eventType) {
172         case EVENT_RESPONSE:
173             {
174                 ACE_SCOPED_TRACE("EVENT_REPORT_RESPONSE_RS sceneId = %s, uniqueId = %lld",
175                     dataRs.sceneId.c_str(), static_cast<long long> (dataRs.uniqueId));
176                 Rosen::RSInterfaces::GetInstance().ReportEventResponse(dataRs);
177                 break;
178             }
179         case EVENT_COMPLETE:
180             {
181                 if (data.needReportRs) {
182                     ACE_SCOPED_TRACE("EVENT_REPORT_COMPLETE_RS sceneId = %s, uniqueId = %lld",
183                         dataRs.sceneId.c_str(), static_cast<long long> (dataRs.uniqueId));
184                     Rosen::RSInterfaces::GetInstance().ReportEventComplete(dataRs);
185                 }
186                 break;
187             }
188         case EVENT_JANK_FRAME:
189             {
190                 ACE_SCOPED_TRACE("EVENT_REPORT_JANK_RS sceneId = %s, uniqueId = %lld",
191                     dataRs.sceneId.c_str(), static_cast<long long> (dataRs.uniqueId));
192                 Rosen::RSInterfaces::GetInstance().ReportEventJankFrame(dataRs);
193                 break;
194             }
195         default :
196             break;
197     }
198 }
199 
ReportPerfEventToUI(DataBase data)200 void ReportPerfEventToUI(DataBase data)
201 {
202     switch (data.eventType) {
203         case EVENT_COMPLETE:
204             if (!data.needReportRs) {
205                 EventReport::ReportEventComplete(data);
206             }
207             break;
208         case EVENT_JANK_FRAME:
209             if (data.totalFrames > 0) {
210                 EventReport::ReportEventJankFrame(data);
211             }
212             break;
213         default :
214             break;
215     }
216 }
217 
InitRecord(const std::string & sId,PerfActionType aType,PerfSourceType sType,const std::string & nt,int64_t time)218 void SceneRecord::InitRecord(const std::string& sId, PerfActionType aType, PerfSourceType sType, const std::string& nt,
219     int64_t time)
220 {
221     sceneId = sId;
222     actionType = aType;
223     sourceType = sType;
224     note = nt;
225     inputTime = time;
226     beginVsyncTime = GetCurrentRealTimeNs();
227     isDisplayAnimator = IsDisplayAnimator(sceneId);
228 }
229 
IsTimeOut(int64_t nowTime)230 bool SceneRecord::IsTimeOut(int64_t nowTime)
231 {
232     if (nowTime - beginVsyncTime > SCENE_TIMEOUT) {
233         return true;
234     }
235     return false;
236 }
237 
RecordFrame(int64_t vsyncTime,int64_t duration,int32_t skippedFrames)238 void SceneRecord::RecordFrame(int64_t vsyncTime, int64_t duration, int32_t skippedFrames)
239 {
240     int64_t currentTimeNs = GetCurrentRealTimeNs();
241     if (totalFrames == 0) {
242         beginVsyncTime = currentTimeNs;
243         isFirstFrame = true;
244     } else {
245         isFirstFrame = false;
246     }
247     skippedFrames = static_cast<int32_t>(duration / SINGLE_FRAME_TIME);
248     if (!isFirstFrame && skippedFrames >= 1) {
249         if (isSuccessive) {
250             seqMissFrames = seqMissFrames + skippedFrames;
251         } else {
252             seqMissFrames = skippedFrames;
253             isSuccessive = true;
254         }
255         if (maxSuccessiveFrames < seqMissFrames) {
256             maxSuccessiveFrames = seqMissFrames;
257         }
258         totalMissed += skippedFrames;
259     } else {
260         isSuccessive = false;
261         seqMissFrames = 0;
262     }
263     if (!isFirstFrame && duration > maxFrameTime) {
264         maxFrameTime = duration;
265         maxFrameTimeSinceStart = (currentTimeNs - beginVsyncTime) / NS_TO_MS;
266     }
267     totalFrames++;
268 }
269 
Report(const std::string & sceneId,int64_t vsyncTime,bool isRsRender)270 void SceneRecord::Report(const std::string& sceneId, int64_t vsyncTime, bool isRsRender)
271 {
272     if (isRsRender || vsyncTime <= beginVsyncTime) {
273         endVsyncTime = GetCurrentRealTimeNs();
274     } else {
275         endVsyncTime = vsyncTime;
276     }
277     needReportRs = !isRsRender;
278 }
279 
IsFirstFrame()280 bool SceneRecord::IsFirstFrame()
281 {
282     return isFirstFrame;
283 }
284 
IsDisplayAnimator(const std::string & sceneId)285 bool SceneRecord::IsDisplayAnimator(const std::string& sceneId)
286 {
287     if (sceneId == PerfConstants::APP_LIST_FLING || sceneId == PerfConstants::APP_SWIPER_SCROLL
288         || sceneId == PerfConstants::SNAP_RECENT_ANI
289         || sceneId == PerfConstants::WINDOW_RECT_RESIZE
290         || sceneId == PerfConstants::WINDOW_RECT_MOVE
291         || sceneId == PerfConstants::META_BALLS_TURBO_CHARGING_ANIMATION
292         || sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH_INTERACTIVE
293         || sceneId == PerfConstants::LAUNCHER_SPRINGBACK_SCROLL) {
294         return true;
295     }
296     return false;
297 }
298 
Reset()299 void SceneRecord::Reset()
300 {
301     beginVsyncTime = 0;
302     endVsyncTime = 0;
303     maxFrameTime = 0;
304     maxFrameTimeSinceStart = 0;
305     maxHitchTime = 0;
306     maxHitchTimeSinceStart = 0;
307     maxSuccessiveFrames = 0;
308     seqMissFrames = 0;
309     totalMissed = 0;
310     totalFrames = 0;
311     isSuccessive = false;
312     isFirstFrame = false;
313     sceneId = "";
314     actionType = UNKNOWN_ACTION;
315     sourceType = UNKNOWN_SOURCE;
316     note = "";
317 }
318 
GetPerfMonitor()319 PerfMonitor* PerfMonitor::GetPerfMonitor()
320 {
321     if (pMonitor == nullptr) {
322         pMonitor = new PerfMonitor();
323     }
324     return pMonitor;
325 }
326 
Start(const std::string & sceneId,PerfActionType type,const std::string & note)327 void PerfMonitor::Start(const std::string& sceneId, PerfActionType type, const std::string& note)
328 {
329     std::lock_guard<std::mutex> Lock(mMutex);
330     if (IsScrollJank(sceneId)) {
331         PerfInterfaces::SetScrollState(true);
332     }
333     NotifySdbJankStatsEnd(sceneId);
334     if (apsMonitor_ != nullptr) {
335         apsMonitor_->SetApsScene(sceneId, true);
336     }
337 
338     int64_t inputTime = GetInputTime(sceneId, type, note);
339     SceneRecord* record = GetRecord(sceneId);
340     if (IsSceneIdInSceneWhiteList(sceneId)) {
341         isExceptAnimator = true;
342         SetVsyncLazyMode();
343     }
344     ACE_SCOPED_TRACE("Animation start and current sceneId=%s", sceneId.c_str());
345     if (record == nullptr) {
346         currentSceneId = sceneId;
347         record = new SceneRecord();
348         record->InitRecord(sceneId, type, mSourceType, note, inputTime);
349         mRecords.insert(std::pair<std::string, SceneRecord*> (sceneId, record));
350         RecordBaseInfo(record);
351         AceAsyncTraceBegin(0, sceneId.c_str());
352     }
353 }
354 
StartCommercial(const std::string & sceneId,PerfActionType type,const std::string & note)355 void PerfMonitor::StartCommercial(const std::string& sceneId, PerfActionType type, const std::string& note)
356 {
357     std::lock_guard<std::mutex> Lock(mMutex);
358     if (IsScrollJank(sceneId)) {
359         PerfInterfaces::SetScrollState(true);
360     }
361     if (apsMonitor_ != nullptr) {
362         apsMonitor_->SetApsScene(sceneId, true);
363     }
364 
365     int64_t inputTime = GetInputTime(sceneId, type, note);
366     SceneRecord* record = GetRecord(sceneId);
367     if (IsSceneIdInSceneWhiteList(sceneId)) {
368         isExceptAnimator = true;
369     }
370     ACE_SCOPED_TRACE_COMMERCIAL("Animation start and current sceneId=%s", sceneId.c_str());
371     if (record == nullptr) {
372         currentSceneId = sceneId;
373         record = new SceneRecord();
374         record->InitRecord(sceneId, type, mSourceType, note, inputTime);
375         mRecords.insert(std::pair<std::string, SceneRecord*> (sceneId, record));
376         RecordBaseInfo(record);
377         AceAsyncTraceBeginCommercial(0, sceneId.c_str());
378     }
379 }
380 
End(const std::string & sceneId,bool isRsRender)381 void PerfMonitor::End(const std::string& sceneId, bool isRsRender)
382 {
383     std::lock_guard<std::mutex> Lock(mMutex);
384     if (IsScrollJank(sceneId)) {
385         PerfInterfaces::SetScrollState(false);
386     }
387     NotifySbdJankStatsBegin(sceneId);
388     if (apsMonitor_ != nullptr) {
389         apsMonitor_->SetApsScene(sceneId, false);
390     }
391 
392     SceneRecord* record = GetRecord(sceneId);
393     ACE_SCOPED_TRACE("Animation end and current sceneId=%s", sceneId.c_str());
394     if (record != nullptr) {
395         if (IsSceneIdInSceneWhiteList(sceneId)) {
396             isExceptAnimator = false;
397             SetVsyncLazyMode();
398         }
399         RecordBaseInfo(record);
400         record->Report(sceneId, mVsyncTime, isRsRender);
401         ReportAnimateEnd(sceneId, record);
402         RemoveRecord(sceneId);
403         AceAsyncTraceEnd(0, sceneId.c_str());
404     }
405 }
406 
EndCommercial(const std::string & sceneId,bool isRsRender)407 void PerfMonitor::EndCommercial(const std::string& sceneId, bool isRsRender)
408 {
409     std::lock_guard<std::mutex> Lock(mMutex);
410     if (IsScrollJank(sceneId)) {
411         PerfInterfaces::SetScrollState(false);
412     }
413     if (apsMonitor_ != nullptr) {
414         apsMonitor_->SetApsScene(sceneId, false);
415     }
416 
417     SceneRecord* record = GetRecord(sceneId);
418     ACE_SCOPED_TRACE_COMMERCIAL("Animation end and current sceneId=%s", sceneId.c_str());
419     if (record != nullptr) {
420         if (IsSceneIdInSceneWhiteList(sceneId)) {
421             isExceptAnimator = false;
422         }
423         RecordBaseInfo(record);
424         record->Report(sceneId, mVsyncTime, isRsRender);
425         ReportAnimateEnd(sceneId, record);
426         RemoveRecord(sceneId);
427         AceAsyncTraceEndCommercial(0, sceneId.c_str());
428     }
429 }
430 
RecordInputEvent(PerfActionType type,PerfSourceType sourceType,int64_t time)431 void PerfMonitor::RecordInputEvent(PerfActionType type, PerfSourceType sourceType, int64_t time)
432 {
433     std::lock_guard<std::mutex> Lock(mMutex);
434     mSourceType = sourceType;
435     if (time <= 0) {
436         time = GetCurrentRealTimeNs();
437     }
438     switch (type) {
439         case LAST_DOWN:
440             {
441                 ACE_SCOPED_TRACE("RecordInputEvent: last_down=%lld(ns)", static_cast<long long>(time));
442                 mInputTime[LAST_DOWN] = time;
443                 break;
444             }
445         case LAST_UP:
446             {
447                 ACE_SCOPED_TRACE("RecordInputEvent: last_up=%lld(ns)", static_cast<long long>(time));
448                 mInputTime[LAST_UP] = time;
449                 isResponseExclusion = true;
450                 SetVsyncLazyMode();
451                 break;
452             }
453         case FIRST_MOVE:
454             {
455                 ACE_SCOPED_TRACE("RecordInputEvent: first_move=%lld(ns)", static_cast<long long>(time));
456                 mInputTime[FIRST_MOVE] = time;
457                 break;
458             }
459         default:
460             break;
461     }
462 }
463 
SetFrameTime(int64_t vsyncTime,int64_t duration,double jank,const std::string & windowName)464 void PerfMonitor::SetFrameTime(int64_t vsyncTime, int64_t duration, double jank, const std::string& windowName)
465 {
466     std::lock_guard<std::mutex> Lock(mMutex);
467     mVsyncTime = vsyncTime;
468     int32_t skippedFrames = static_cast<int32_t> (jank);
469     for (auto it = mRecords.begin(); it != mRecords.end();) {
470         if (it->second != nullptr) {
471             (it->second)->RecordFrame(vsyncTime, duration, skippedFrames);
472             if ((it->second)->IsTimeOut(vsyncTime + duration)) {
473                 CheckTimeOutOfExceptAnimatorStatus(it->second->sceneId);
474                 delete it->second;
475                 it = mRecords.erase(it);
476                 continue;
477             }
478             if ((it->second)->IsFirstFrame()) {
479                 ReportAnimateStart(it->first, it->second);
480             }
481         }
482         it++;
483     }
484     ProcessJank(jank, windowName);
485     JankFrameStatsRecord(jank);
486 }
487 
ReportJankFrameApp(double jank)488 void PerfMonitor::ReportJankFrameApp(double jank)
489 {
490     if (jank >= static_cast<double>(JANK_SKIPPED_THRESHOLD) && !isBackgroundApp) {
491         JankInfo jankInfo;
492         jankInfo.skippedFrameTime = static_cast<int64_t>(jank * SINGLE_FRAME_TIME);
493         RecordBaseInfo(nullptr);
494         jankInfo.baseInfo = baseInfo;
495         EventReport::ReportJankFrameApp(jankInfo);
496     }
497 }
498 
SetPageUrl(const std::string & pageUrl)499 void PerfMonitor::SetPageUrl(const std::string& pageUrl)
500 {
501     baseInfo.pageUrl = ParsePageUrl(pageUrl);
502 }
503 
GetPageUrl()504 std::string PerfMonitor::GetPageUrl()
505 {
506     return baseInfo.pageUrl;
507 }
508 
SetPageName(const std::string & pageName)509 void PerfMonitor::SetPageName(const std::string& pageName)
510 {
511     baseInfo.pageName = pageName;
512 }
513 
GetPageName()514 std::string PerfMonitor::GetPageName()
515 {
516     return baseInfo.pageName;
517 }
518 
ReportPageShowMsg(const std::string & pageUrl,const std::string & bundleName,const std::string & pageName)519 void PerfMonitor::ReportPageShowMsg(const std::string& pageUrl, const std::string& bundleName,
520                                     const std::string& pageName)
521 {
522     std::string parsePageUrl = ParsePageUrl(pageUrl);
523     EventReport::ReportPageShowMsg(parsePageUrl, bundleName, pageName);
524 }
525 
RecordBaseInfo(SceneRecord * record)526 void PerfMonitor::RecordBaseInfo(SceneRecord* record)
527 {
528     baseInfo.pid = AceApplicationInfo::GetInstance().GetPid();
529     baseInfo.bundleName = AceApplicationInfo::GetInstance().GetPackageName();
530     baseInfo.versionCode = static_cast<int32_t>(AceApplicationInfo::GetInstance().GetAppVersionCode());
531     baseInfo.versionName = AceApplicationInfo::GetInstance().GetAppVersionName();
532     baseInfo.processName = AceApplicationInfo::GetInstance().GetProcessName();
533     baseInfo.abilityName = AceApplicationInfo::GetInstance().GetAbilityName();
534     if (record != nullptr) {
535         baseInfo.note = record->note;
536     }
537 }
538 
GetRecord(const std::string & sceneId)539 SceneRecord* PerfMonitor::GetRecord(const std::string& sceneId)
540 {
541     auto iter = mRecords.find(sceneId);
542     if (iter != mRecords.end()) {
543         return iter->second;
544     }
545     return nullptr;
546 }
547 
RemoveRecord(const std::string & sceneId)548 void PerfMonitor::RemoveRecord(const std::string& sceneId)
549 {
550     std::map <std::string, SceneRecord*>::iterator iter = mRecords.find(sceneId);
551     if (iter != mRecords.end()) {
552         if (iter->second != nullptr) {
553             delete iter->second;
554         }
555         mRecords.erase(iter);
556     }
557 }
558 
GetInputTime(const std::string & sceneId,PerfActionType type,const std::string & note)559 int64_t PerfMonitor::GetInputTime(const std::string& sceneId, PerfActionType type, const std::string& note)
560 {
561     int64_t inputTime = 0;
562     switch (type) {
563         case LAST_DOWN:
564             inputTime = mInputTime[LAST_DOWN];
565             break;
566         case LAST_UP:
567             inputTime = mInputTime[LAST_UP];
568             break;
569         case FIRST_MOVE:
570             inputTime = mInputTime[FIRST_MOVE];
571             break;
572         default:
573             break;
574     }
575     if (inputTime <= 0 || IsExceptResponseTime(inputTime, sceneId)) {
576         ACE_SCOPED_TRACE("GetInputTime: now time");
577         inputTime = GetCurrentRealTimeNs();
578     }
579     return inputTime;
580 }
581 
ReportAnimateStart(const std::string & sceneId,SceneRecord * record)582 void PerfMonitor::ReportAnimateStart(const std::string& sceneId, SceneRecord* record)
583 {
584     if (record == nullptr) {
585         return;
586     }
587     DataBase data;
588     FlushDataBase(record, data);
589     ReportPerfEvent(EVENT_RESPONSE, data);
590 }
591 
ReportAnimateEnd(const std::string & sceneId,SceneRecord * record)592 void PerfMonitor::ReportAnimateEnd(const std::string& sceneId, SceneRecord* record)
593 {
594     if (record == nullptr) {
595         return;
596     }
597     DataBase data;
598     FlushDataBase(record, data);
599     ReportPerfEvent(EVENT_JANK_FRAME, data);
600     ReportPerfEvent(EVENT_COMPLETE, data);
601 }
602 
FlushDataBase(SceneRecord * record,DataBase & data)603 void PerfMonitor::FlushDataBase(SceneRecord* record, DataBase& data)
604 {
605     if (record == nullptr) {
606         return;
607     }
608     data.sceneId = record->sceneId;
609     data.inputTime = record->inputTime;
610     data.beginVsyncTime = record->beginVsyncTime;
611     if (data.beginVsyncTime < data.inputTime) {
612         data.inputTime = data.beginVsyncTime;
613     }
614     data.endVsyncTime = record->endVsyncTime;
615     if (data.beginVsyncTime > data.endVsyncTime) {
616         data.endVsyncTime = data.beginVsyncTime;
617     }
618     data.maxFrameTime = record->maxFrameTime;
619     data.maxFrameTimeSinceStart = record->maxFrameTimeSinceStart;
620     data.maxHitchTime = record->maxHitchTime;
621     data.maxHitchTimeSinceStart = record->maxHitchTimeSinceStart;
622     data.maxSuccessiveFrames = record->maxSuccessiveFrames;
623     data.totalMissed = record->totalMissed;
624     data.totalFrames = record->totalFrames;
625     data.needReportRs = record->needReportRs;
626     data.isDisplayAnimator = record->isDisplayAnimator;
627     data.sourceType = record->sourceType;
628     data.actionType = record->actionType;
629     data.baseInfo = baseInfo;
630 }
631 
ReportPerfEvent(PerfEventType type,DataBase & data)632 void PerfMonitor::ReportPerfEvent(PerfEventType type, DataBase& data)
633 {
634     switch (type) {
635         case EVENT_RESPONSE:
636             data.eventType = EVENT_RESPONSE;
637             break;
638         case EVENT_COMPLETE:
639             data.eventType = EVENT_COMPLETE;
640             break;
641         case EVENT_JANK_FRAME:
642             data.eventType = EVENT_JANK_FRAME;
643             break;
644         default :
645             break;
646     }
647     ReportPerfEventToUI(data);
648     ReportPerfEventToRS(data);
649 }
650 
IsExceptResponseTime(int64_t time,const std::string & sceneId)651 bool PerfMonitor::IsExceptResponseTime(int64_t time, const std::string& sceneId)
652 {
653     int64_t currentRealTimeNs = GetCurrentRealTimeNs();
654     static set<std::string> exceptSceneSet = {
655         PerfConstants::APP_LIST_FLING, PerfConstants::SCREEN_ROTATION_ANI,
656         PerfConstants::SHOW_INPUT_METHOD_ANIMATION, PerfConstants::HIDE_INPUT_METHOD_ANIMATION,
657         PerfConstants::APP_TRANSITION_FROM_OTHER_APP, PerfConstants::APP_TRANSITION_TO_OTHER_APP,
658         PerfConstants::VOLUME_BAR_SHOW, PerfConstants::PC_APP_CENTER_GESTURE_OPERATION,
659         PerfConstants::PC_GESTURE_TO_RECENT, PerfConstants::PC_SHORTCUT_SHOW_DESKTOP,
660         PerfConstants::PC_ALT_TAB_TO_RECENT, PerfConstants::PC_SHOW_DESKTOP_GESTURE_OPERATION,
661         PerfConstants::PC_SHORTCUT_RESTORE_DESKTOP, PerfConstants::PC_SHORTCUT_TO_RECENT,
662         PerfConstants::PC_EXIT_RECENT, PerfConstants::PC_SHORTCUT_TO_APP_CENTER_ON_RECENT,
663         PerfConstants::PC_SHORTCUT_TO_APP_CENTER, PerfConstants::PC_SHORTCUT_EXIT_APP_CENTER,
664         PerfConstants::WINDOW_TITLE_BAR_MINIMIZED, PerfConstants::WINDOW_RECT_MOVE,
665         PerfConstants::APP_EXIT_FROM_WINDOW_TITLE_BAR_CLOSED, PerfConstants::WINDOW_TITLE_BAR_RECOVER,
666         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_OTHER, PerfConstants::WINDOW_RECT_RESIZE,
667         PerfConstants::WINDOW_TITLE_BAR_MAXIMIZED, PerfConstants::LAUNCHER_APP_LAUNCH_FROM_TRANSITION
668     };
669     if (exceptSceneSet.find(sceneId) != exceptSceneSet.end()) {
670         return true;
671     }
672     if ((sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH && currentRealTimeNs - time > RESPONSE_TIMEOUT)
673         || (sceneId == PerfConstants::CLOSE_FOLDER_ANI && currentRealTimeNs - time > RESPONSE_TIMEOUT)) {
674         return true;
675     }
676     return false;
677 }
678 
679 // for jank frame app
IsExclusionFrame()680 bool PerfMonitor::IsExclusionFrame()
681 {
682     ACE_SCOPED_TRACE("IsExclusionFrame: isResponse(%d) isStartApp(%d) isBg(%d) isExcluWindow(%d) isExcAni(%d)",
683         isResponseExclusion, isStartAppFrame, isBackgroundApp, isExclusionWindow, isExceptAnimator);
684     return isResponseExclusion || isStartAppFrame || isBackgroundApp || isExclusionWindow || isExceptAnimator;
685 }
686 
SetVsyncLazyMode()687 void PerfMonitor::SetVsyncLazyMode()
688 {
689 #ifdef OHOS_STANDARD_SYSTEM
690     static bool lastExcusion = false;
691     bool needExcusion = isResponseExclusion || isStartAppFrame || isBackgroundApp ||
692                         isExclusionWindow || isExceptAnimator;
693     if (lastExcusion == needExcusion) {
694         return;
695     }
696 
697     lastExcusion = needExcusion;
698     ACE_VSYNC_MODE_SCOPED_TRACE("SetVsyncLazyMode: isResponse(%d) isStartApp(%d) isBg(%d) isExcluWindow(%d) "
699         "isExcAni(%d)",
700         isResponseExclusion, isStartAppFrame, isBackgroundApp, isExclusionWindow, isExceptAnimator);
701     OHOS::AppExecFwk::EventHandler::SetVsyncLazyMode(needExcusion);
702 #endif
703 }
704 
SetAppStartStatus()705 void PerfMonitor::SetAppStartStatus()
706 {
707     ACE_FUNCTION_TRACE();
708     isStartAppFrame = true;
709     SetVsyncLazyMode();
710     startAppTime = GetCurrentRealTimeNs();
711 }
712 
CheckInStartAppStatus()713 void PerfMonitor::CheckInStartAppStatus()
714 {
715     if (isStartAppFrame) {
716         int64_t curTime = GetCurrentRealTimeNs();
717         if (curTime - startAppTime >= STARTAPP_FRAME_TIMEOUT) {
718             isStartAppFrame = false;
719             startAppTime = curTime;
720             SetVsyncLazyMode();
721         }
722     }
723 }
724 
SetAppForeground(bool isShow)725 void PerfMonitor::SetAppForeground(bool isShow)
726 {
727     isBackgroundApp = !isShow;
728     SetVsyncLazyMode();
729 }
730 
CheckExclusionWindow(const std::string & windowName)731 void PerfMonitor::CheckExclusionWindow(const std::string& windowName)
732 {
733     isExclusionWindow = false;
734     if (windowName == "softKeyboard1" ||
735         windowName == "SCBWallpaper1" ||
736         windowName == "SCBStatusBar15") {
737         isExclusionWindow = true;
738     }
739     SetVsyncLazyMode();
740 }
741 
CheckResponseStatus()742 void PerfMonitor::CheckResponseStatus()
743 {
744     if (isResponseExclusion) {
745         isResponseExclusion = false;
746         SetVsyncLazyMode();
747     }
748 }
749 
ProcessJank(double jank,const std::string & windowName)750 void PerfMonitor::ProcessJank(double jank, const std::string& windowName)
751 {
752     // single frame behavior report
753     CheckExclusionWindow(windowName);
754     ReportJankFrame(jank, windowName);
755     CheckInStartAppStatus();
756     CheckResponseStatus();
757 }
758 
ReportJankFrame(double jank,const std::string & windowName)759 void PerfMonitor::ReportJankFrame(double jank, const std::string& windowName)
760 {
761     if (jank >= static_cast<double>(DEFAULT_JANK_REPORT_THRESHOLD)) {
762         JankInfo jankInfo;
763         jankInfo.skippedFrameTime = static_cast<int64_t>(jank * SINGLE_FRAME_TIME);
764         jankInfo.windowName = windowName;
765         RecordBaseInfo(nullptr);
766         jankInfo.baseInfo = baseInfo;
767         jankInfo.filterType = GetFilterType();
768         if (!mRecords.empty()) {
769             jankInfo.sceneId = currentSceneId;
770         } else {
771             jankInfo.sceneId = DEFAULT_SCENE_ID;
772         }
773         jankInfo.realSkippedFrameTime = jankInfo.filterType == 0 ? jankInfo.skippedFrameTime : 0;
774         EventReport::ReportJankFrameUnFiltered(jankInfo);
775         if (!IsExclusionFrame()) {
776             EventReport::ReportJankFrameFiltered(jankInfo);
777         }
778     }
779 }
780 
IsSceneIdInSceneWhiteList(const std::string & sceneId)781 bool PerfMonitor::IsSceneIdInSceneWhiteList(const std::string& sceneId)
782 {
783     if (sceneId == PerfConstants::LAUNCHER_APP_LAUNCH_FROM_ICON ||
784         sceneId == PerfConstants::LAUNCHER_APP_LAUNCH_FROM_DOCK ||
785         sceneId == PerfConstants::LAUNCHER_APP_LAUNCH_FROM_MISSON ||
786         sceneId == PerfConstants::LAUNCHER_APP_SWIPE_TO_HOME ||
787         sceneId == PerfConstants::LAUNCHER_APP_BACK_TO_HOME ||
788         sceneId == PerfConstants::EXIT_RECENT_2_HOME_ANI ||
789         sceneId == PerfConstants::APP_SWIPER_FLING ||
790         sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH ||
791         sceneId == PerfConstants::SCREENLOCK_SCREEN_OFF_ANIM) {
792             return true;
793         }
794     return false;
795 }
796 
IsScrollJank(const std::string & sceneId)797 bool PerfMonitor::IsScrollJank(const std::string& sceneId)
798 {
799     if (sceneId == PerfConstants::APP_LIST_FLING ||
800         sceneId == PerfConstants::APP_SWIPER_SCROLL ||
801         sceneId == PerfConstants::APP_SWIPER_FLING) {
802         return true;
803     }
804     return false;
805 }
806 
CheckTimeOutOfExceptAnimatorStatus(const std::string & sceneId)807 void PerfMonitor::CheckTimeOutOfExceptAnimatorStatus(const std::string& sceneId)
808 {
809     if (IsSceneIdInSceneWhiteList(sceneId)) {
810         isExceptAnimator = false;
811         SetVsyncLazyMode();
812     }
813 }
814 
GetFilterType() const815 int32_t PerfMonitor::GetFilterType() const
816 {
817     int32_t filterType = (isBackgroundApp << 4) | (isResponseExclusion << 3) | (isStartAppFrame << 2)
818         | (isExclusionWindow << 1) | isExceptAnimator;
819     return filterType;
820 }
821 
RecordWindowRectResize(OHOS::Ace::WindowSizeChangeReason reason,const std::string & bundleName)822 void PerfMonitor::RecordWindowRectResize(OHOS::Ace::WindowSizeChangeReason reason, const std::string& bundleName)
823 {
824     switch (reason) {
825         case OHOS::Ace::WindowSizeChangeReason::DRAG_START:
826             Start(PerfConstants::WINDOW_RECT_RESIZE, PerfActionType::LAST_DOWN, bundleName.c_str());
827             break;
828         case OHOS::Ace::WindowSizeChangeReason::DRAG_END:
829             End(PerfConstants::WINDOW_RECT_RESIZE, true);
830             break;
831         default:
832             break;
833     }
834 }
835 
ClearJankFrameRecord()836 void PerfMonitor::ClearJankFrameRecord()
837 {
838     std::fill(jankFrameRecord.begin(), jankFrameRecord.end(), 0);
839     jankFrameTotalCount = 0;
840     jankFrameRecordBeginTime = 0;
841 }
842 
SetJankFrameRecord(OHOS::Rosen::AppInfo & appInfo,int64_t startTime,int64_t endTime)843 void SetJankFrameRecord(OHOS::Rosen::AppInfo &appInfo, int64_t startTime, int64_t endTime)
844 {
845     appInfo.pid = AceApplicationInfo::GetInstance().GetPid();
846     appInfo.bundleName = AceApplicationInfo::GetInstance().GetPackageName();
847     appInfo.versionCode = static_cast<int32_t>(AceApplicationInfo::GetInstance().GetAppVersionCode());
848     appInfo.versionName = AceApplicationInfo::GetInstance().GetAppVersionName();
849     appInfo.processName = AceApplicationInfo::GetInstance().GetProcessName();
850     appInfo.startTime = startTime;
851     appInfo.endTime = endTime;
852 }
853 
JankFrameStatsRecord(double jank)854 void PerfMonitor::JankFrameStatsRecord(double jank)
855 {
856     if (isStats == true && jank > 1.0f && !jankFrameRecord.empty()) {
857         jankFrameRecord[GetJankLimit(jank)]++;
858         jankFrameTotalCount++;
859     }
860 }
861 
NotifySbdJankStatsBegin(const std::string & sceneId)862 void PerfMonitor::NotifySbdJankStatsBegin(const std::string& sceneId)
863 {
864     static set<std::string> backToHomeScene = {
865         PerfConstants::LAUNCHER_APP_BACK_TO_HOME,
866         PerfConstants::LAUNCHER_APP_SWIPE_TO_HOME,
867         PerfConstants::INTO_HOME_ANI,
868         PerfConstants::PASSWORD_UNLOCK_ANI,
869         PerfConstants::FACIAL_FLING_UNLOCK_ANI,
870         PerfConstants::FACIAL_UNLOCK_ANI,
871         PerfConstants::FINGERPRINT_UNLOCK_ANI
872     };
873     if (backToHomeScene.find(sceneId) != backToHomeScene.end()) {
874         ACE_SCOPED_TRACE("NotifySbdJankStatsBegin");
875         NotifyAppJankStatsBegin();
876     }
877 }
878 
NotifySdbJankStatsEnd(const std::string & sceneId)879 void PerfMonitor::NotifySdbJankStatsEnd(const std::string& sceneId)
880 {
881     static set<std::string> appLaunch = {
882         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_DOCK,
883         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_ICON,
884         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR,
885         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN,
886         PerfConstants::LAUNCHER_APP_LAUNCH_FROM_RECENT,
887         PerfConstants::START_APP_ANI_FORM,
888         PerfConstants::SCREENLOCK_SCREEN_OFF_ANIM
889     };
890     if (appLaunch.find(sceneId) != appLaunch.end()) {
891         ACE_SCOPED_TRACE("NotifySdbJankStatsEnd");
892         NotifyAppJankStatsEnd();
893     }
894 }
895 
896 
NotifyAppJankStatsBegin()897 void PerfMonitor::NotifyAppJankStatsBegin()
898 {
899     ACE_SCOPED_TRACE("NotifyAppJankStatsBegin");
900     int64_t duration = GetCurrentSystimeMs() - jankFrameRecordBeginTime;
901     if (!isStats) {
902         if (jankFrameRecord.empty()) {
903             jankFrameRecord = std::vector<uint16_t>(JANK_STATS_SIZE, 0);
904         }
905         isStats = true;
906         NotifyRsJankStatsBegin();
907         return;
908     }
909     if (duration >= DEFAULT_VSYNC) {
910         ReportJankStatsApp(duration);
911         NotifyRsJankStatsEnd(GetCurrentSystimeMs());
912         ClearJankFrameRecord();
913         NotifyRsJankStatsBegin();
914     }
915 }
916 
NotifyAppJankStatsEnd()917 void PerfMonitor::NotifyAppJankStatsEnd()
918 {
919     if (!isStats) {
920         return;
921     }
922     ACE_SCOPED_TRACE("NotifyAppJankStatsEnd");
923     int64_t endTime = GetCurrentSystimeMs();
924     NotifyRsJankStatsEnd(endTime);
925     isStats = false;
926     int64_t duration = endTime - jankFrameRecordBeginTime;
927     ReportJankStatsApp(duration);
928 }
929 
ReportJankStatsApp(int64_t duration)930 void PerfMonitor::ReportJankStatsApp(int64_t duration)
931 {
932     ACE_SCOPED_TRACE("ReportJankStatsApp count=%" PRId32 ";duration=%" PRId64 ";beginTime=%" PRId64 ";",
933         jankFrameTotalCount, duration, jankFrameRecordBeginTime);
934     if (duration > DEFAULT_VSYNC && jankFrameTotalCount > 0 && jankFrameRecordBeginTime > 0) {
935         EventReport::JankFrameReport(jankFrameRecordBeginTime, duration, jankFrameRecord,
936             baseInfo.pageUrl, JANK_STATS_VERSION);
937     }
938     ClearJankFrameRecord();
939 }
940 
NotifyRsJankStatsBegin()941 void PerfMonitor::NotifyRsJankStatsBegin()
942 {
943     ACE_SCOPED_TRACE("NotifyRsJankStatsBegin");
944     OHOS::Rosen::AppInfo appInfo;
945     jankFrameRecordBeginTime = GetCurrentSystimeMs();
946     SetJankFrameRecord(appInfo, jankFrameRecordBeginTime, 0);
947     Rosen::RSInterfaces::GetInstance().ReportRsSceneJankStart(appInfo);
948 }
949 
NotifyRsJankStatsEnd(int64_t endTime)950 void PerfMonitor::NotifyRsJankStatsEnd(int64_t endTime)
951 {
952     ACE_SCOPED_TRACE("NotifyRsJankStatsEnd");
953     OHOS::Rosen::AppInfo appInfo;
954     SetJankFrameRecord(appInfo, jankFrameRecordBeginTime, endTime);
955     Rosen::RSInterfaces::GetInstance().ReportRsSceneJankEnd(appInfo);
956 }
957 
SetApsMonitor(const std::shared_ptr<ApsMonitor> & apsMonitor)958 void PerfMonitor::SetApsMonitor(const std::shared_ptr<ApsMonitor>& apsMonitor)
959 {
960     apsMonitor_ = apsMonitor;
961 }
962 
963 } // namespace OHOS::Ace
964