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