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