1 /*
2 * Copyright (c) 2025 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 "scene_monitor.h"
17 #include "jank_frame_monitor.h"
18 #include "perf_reporter.h"
19 #include "perf_trace.h"
20 #include "perf_utils.h"
21 #include "white_block_monitor.h"
22
23 #include "event_handler.h"
24 #include "hiview_logger.h"
25 #include "res_sched_client.h"
26 #include "render_service_client/core/transaction/rs_interfaces.h"
27
28 namespace OHOS {
29 namespace HiviewDFX {
30
31 DEFINE_LOG_LABEL(0xD002D66, "Hiview-PerfMonitor");
32
33 static constexpr uint32_t SENSITIVE_SCENE_RESTYPE = 72;
34 static constexpr const char* const SENSITIVE_SCENE_EXTTYPE = "10000";
35
OnSceneStart(const SceneType & type)36 void SceneManager::OnSceneStart(const SceneType& type)
37 {
38 std::lock_guard<std::mutex> Lock(mMutex);
39 auto it = sceneBoard.find(type);
40 if (it == sceneBoard.end()) {
41 SceneRecord* newRecord = GetRecordByType(type);
42 newRecord->StartRecord(type);
43 sceneBoard.insert(std::pair<SceneType, SceneRecord*> (type, newRecord));
44 } else {
45 sceneBoard[type]->StartRecord(type);
46 }
47 return;
48 }
49
OnSceneStop(const SceneType & type)50 void SceneManager::OnSceneStop(const SceneType& type)
51 {
52 std::lock_guard<std::mutex> Lock(mMutex);
53 if (sceneBoard.find(type) != sceneBoard.end()) {
54 sceneBoard[type]->StopRecord(type);
55 } else {
56 HIVIEW_LOGD("SceneManager::OnSceneStop scene has not started, scene type: %{public}d", static_cast<int>(type));
57 }
58 return;
59 }
60
OnSceneStart(const SceneType & type,const std::string & sceneId)61 void SceneManager::OnSceneStart(const SceneType& type, const std::string& sceneId)
62 {
63 std::lock_guard<std::mutex> Lock(mMutex);
64 auto it = sceneBoard.find(type);
65 if (it == sceneBoard.end()) {
66 SceneRecord* newRecord = GetRecordByType(type);
67 newRecord->StartRecord(type, sceneId);
68 sceneBoard.insert(std::pair<SceneType, SceneRecord*> (type, newRecord));
69 } else {
70 sceneBoard[type]->StartRecord(type, sceneId);
71 }
72 return;
73 }
74
OnSceneStop(const SceneType & type,const std::string & sceneId)75 void SceneManager::OnSceneStop(const SceneType& type, const std::string& sceneId)
76 {
77 std::lock_guard<std::mutex> Lock(mMutex);
78 if (sceneBoard.find(type) != sceneBoard.end()) {
79 sceneBoard[type]->StopRecord(type, sceneId);
80 } else {
81 HIVIEW_LOGD("SceneManager::OnSceneStop scene has not started, scene type: %{public}d, scene id: %{public}s",
82 static_cast<int>(type), sceneId.c_str());
83 }
84 return;
85 }
86
GetRecordByType(const SceneType & type)87 SceneRecord* SceneManager::GetRecordByType(const SceneType& type)
88 {
89 switch (type) {
90 case NON_EXPERIENCE_ANIMATOR:
91 return new NonExperienceAnimator();
92 case NON_EXPERIENCE_WINDOW:
93 return new NonExperienceWindow();
94 case APP_START:
95 return new NonExperienceAppStart();
96 case PAGE_LOADING:
97 return new NonExperiencePageLoading();
98 default:
99 return new SceneRecord();
100 }
101 }
102
GetSceneTag()103 uint64_t SceneManager::GetSceneTag()
104 {
105 std::lock_guard<std::mutex> Lock(mMutex);
106 uint64_t res = 0;
107 for (const auto& it : sceneBoard) {
108 if (it.second->status) {
109 res += 1 << (static_cast<uint64_t>(it.first) - 1);
110 }
111 }
112 return res;
113 }
114
GetSceneTagByType(const SceneType & type)115 uint64_t SceneManager::GetSceneTagByType(const SceneType& type)
116 {
117 std::lock_guard<std::mutex> Lock(mMutex);
118 uint64_t res = 0;
119 auto it = sceneBoard.find(type);
120 if (it != sceneBoard.end()) {
121 if (it->second->status) {
122 res += 1 << (static_cast<uint64_t>(it->first) - 1);
123 }
124 }
125 return res;
126 }
127
GetInstance()128 SceneMonitor& SceneMonitor::GetInstance()
129 {
130 static SceneMonitor instance;
131 return instance;
132 }
133
SceneMonitor()134 SceneMonitor::SceneMonitor()
135 {
136 RegisterSceneCallback(this);
137 AnimatorMonitor::GetInstance().RegisterAnimatorCallback(this);
138 }
139
~SceneMonitor()140 SceneMonitor::~SceneMonitor()
141 {
142 UnregisterSceneCallback(this);
143 AnimatorMonitor::GetInstance().UnregisterAnimatorCallback(this);
144 }
145
RegisterSceneCallback(ISceneCallback * cb)146 void SceneMonitor::RegisterSceneCallback(ISceneCallback* cb)
147 {
148 std::lock_guard<std::mutex> Lock(mMutex);
149 if (std::find(sceneCallbacks.begin(), sceneCallbacks.end(), cb) == sceneCallbacks.end()) {
150 sceneCallbacks.push_back(cb);
151 }
152 }
153
UnregisterSceneCallback(ISceneCallback * cb)154 void SceneMonitor::UnregisterSceneCallback(ISceneCallback* cb)
155 {
156 std::lock_guard<std::mutex> Lock(mMutex);
157 auto it = std::find(sceneCallbacks.begin(), sceneCallbacks.end(), cb);
158 if (it != sceneCallbacks.end()) {
159 sceneCallbacks.erase(it);
160 }
161 }
162
OnSceneEvent(const SceneType & type,bool status)163 void SceneMonitor::OnSceneEvent(const SceneType& type, bool status)
164 {
165 if (status) {
166 mNonexpManager.OnSceneStart(type);
167 } else {
168 mNonexpManager.OnSceneStop(type);
169 }
170 SetVsyncLazyMode(mNonexpManager.GetSceneTag());
171 }
172
OnSceneEvent(const SceneType & type,bool status,const std::string & sceneId)173 void SceneMonitor::OnSceneEvent(const SceneType& type, bool status, const std::string& sceneId)
174 {
175 if (status) {
176 mNonexpManager.OnSceneStart(type, sceneId);
177 } else {
178 mNonexpManager.OnSceneStop(type, sceneId);
179 }
180 SetVsyncLazyMode(mNonexpManager.GetSceneTag());
181 }
182
OnSceneChanged(const SceneType & type,bool status)183 void SceneMonitor::OnSceneChanged(const SceneType& type, bool status)
184 {
185 std::lock_guard<std::mutex> Lock(mMutex);
186 for (auto* cb: sceneCallbacks) {
187 cb->OnSceneEvent(type, status);
188 }
189 }
190
OnSceneChanged(const SceneType & type,bool status,const std::string & sceneId)191 void SceneMonitor::OnSceneChanged(const SceneType& type, bool status, const std::string& sceneId)
192 {
193 std::lock_guard<std::mutex> Lock(mMutex);
194 for (auto* cb: sceneCallbacks) {
195 cb->OnSceneEvent(type, status, sceneId);
196 }
197 }
198
OnAnimatorStart(const std::string & sceneId,PerfActionType type,const std::string & note)199 void SceneMonitor::OnAnimatorStart(const std::string& sceneId, PerfActionType type, const std::string& note)
200 {
201 SceneMonitor::GetInstance().OnSceneChanged(SceneType::NON_EXPERIENCE_ANIMATOR, true, sceneId);
202 SceneMonitor::GetInstance().SetCurrentSceneId(sceneId);
203 if (IsScrollJank(sceneId)) {
204 WhiteBlockMonitor::GetInstance().StartScroll();
205 }
206 SetAppGCStatus(sceneId, 0);
207 NotifyScbJankStatsEnd(sceneId);
208 }
209
OnAnimatorStop(const std::string & sceneId,bool isRsRender)210 void SceneMonitor::OnAnimatorStop(const std::string& sceneId, bool isRsRender)
211 {
212 SceneMonitor::GetInstance().OnSceneChanged(SceneType::NON_EXPERIENCE_ANIMATOR, false, sceneId);
213 SceneMonitor::GetInstance().OnSceneChanged(SceneType::PAGE_LOADING, true, sceneId);
214 if (IsScrollJank(sceneId)) {
215 WhiteBlockMonitor::GetInstance().EndScroll();
216 }
217 SetAppGCStatus(sceneId, 1);
218 NotifyScbJankStatsBegin(sceneId);
219 }
220
SingleFrameSceneStop(const std::string & sceneId)221 void SceneMonitor::SingleFrameSceneStop(const std::string& sceneId)
222 {
223 OnSceneChanged(SceneType::NON_EXPERIENCE_WINDOW, false, sceneId);
224 OnSceneChanged(SceneType::APP_START, false);
225 OnSceneChanged(SceneType::APP_RESPONSE, false);
226 OnSceneChanged(SceneType::PAGE_LOADING, false);
227 OnSceneChanged(SceneType::ACCESSIBLE_FEATURE, false);
228 }
229
NotifyAppJankStatsBegin()230 void SceneMonitor::NotifyAppJankStatsBegin()
231 {
232 XPERF_TRACE_SCOPED("NotifyAppJankStatsBegin");
233 if (!GetIsStats()) {
234 JankFrameMonitor::GetInstance().SetJankFrameRecordBeginTime(GetCurrentSystimeMs());
235 NotifyRsJankStatsBegin();
236 SetStats(true);
237 return;
238 }
239 int64_t endTime = GetCurrentSystimeMs();
240 int64_t duration = endTime - JankFrameMonitor::GetInstance().GetJankFrameRecordBeginTime();
241 if (duration >= DEFAULT_VSYNC) {
242 NotifyAppJankStatsReport(duration);
243 NotifyRsJankStatsEnd(endTime);
244 NotifyRsJankStatsBegin();
245 }
246 }
247
NotifyAppJankStatsEnd()248 void SceneMonitor::NotifyAppJankStatsEnd()
249 {
250 if (!GetIsStats()) {
251 return;
252 }
253 XPERF_TRACE_SCOPED("NotifyAppJankStatsEnd");
254 int64_t endTime = GetCurrentSystimeMs();
255 NotifyRsJankStatsEnd(endTime);
256 SetStats(false);
257 int64_t duration = endTime - JankFrameMonitor::GetInstance().GetJankFrameRecordBeginTime();
258 NotifyAppJankStatsReport(duration);
259 }
260
NotifyAppJankStatsReport(int64_t duration)261 void SceneMonitor::NotifyAppJankStatsReport(int64_t duration)
262 {
263 int32_t jankFrameTotalCount = JankFrameMonitor::GetInstance().GetJankFrameTotalCount();
264 int64_t jankFrameRecordBeginTime = JankFrameMonitor::GetInstance().GetJankFrameRecordBeginTime();
265 const auto& baseInfo = GetBaseInfo();
266 const auto& jankFrameRecord = JankFrameMonitor::GetInstance().GetJankFrameRecord();
267 PerfReporter::GetInstance().ReportStatsJankFrame(jankFrameRecordBeginTime, duration, jankFrameRecord,
268 jankFrameTotalCount, baseInfo);
269 JankFrameMonitor::GetInstance().ClearJankFrameRecord();
270 }
271
SetPageUrl(const std::string & pageUrl)272 void SceneMonitor::SetPageUrl(const std::string& pageUrl)
273 {
274 std::lock_guard<std::mutex> Lock(mMutex);
275 baseInfo.pageUrl = pageUrl;
276 }
277
GetPageUrl()278 std::string SceneMonitor::GetPageUrl()
279 {
280 std::lock_guard<std::mutex> Lock(mMutex);
281 return baseInfo.pageUrl;
282 }
283
SetPageName(const std::string & pageName)284 void SceneMonitor::SetPageName(const std::string& pageName)
285 {
286 std::lock_guard<std::mutex> Lock(mMutex);
287 baseInfo.pageName = pageName;
288 }
289
GetPageName()290 std::string SceneMonitor::GetPageName()
291 {
292 std::lock_guard<std::mutex> Lock(mMutex);
293 return baseInfo.pageName;
294 }
295
GetPid()296 int32_t SceneMonitor::GetPid()
297 {
298 std::lock_guard<std::mutex> Lock(mMutex);
299 return baseInfo.pid;
300 }
301
SetAppForeground(bool isShow)302 void SceneMonitor::SetAppForeground(bool isShow)
303 {
304 OnSceneChanged(SceneType::APP_BACKGROUND, !isShow);
305 }
306
SetAppStartStatus()307 void SceneMonitor::SetAppStartStatus()
308 {
309 OnSceneChanged(SceneType::APP_START, true);
310 }
311
SetStats(bool status)312 void SceneMonitor::SetStats(bool status)
313 {
314 std::lock_guard<std::mutex> Lock(mMutex);
315 isStats = status;
316 }
317
GetIsStats()318 bool SceneMonitor::GetIsStats()
319 {
320 std::lock_guard<std::mutex> Lock(mMutex);
321 return isStats;
322 }
323
SetCurrentSceneId(const std::string & sceneId)324 void SceneMonitor::SetCurrentSceneId(const std::string& sceneId)
325 {
326 std::lock_guard<std::mutex> Lock(mMutex);
327 currentSceneId = sceneId;
328 return;
329 }
330
GetCurrentSceneId()331 std::string SceneMonitor::GetCurrentSceneId()
332 {
333 std::lock_guard<std::mutex> Lock(mMutex);
334 return currentSceneId;
335 }
336
SetAppInfo(AceAppInfo & aceAppInfo)337 void SceneMonitor::SetAppInfo(AceAppInfo& aceAppInfo)
338 {
339 std::lock_guard<std::mutex> Lock(mMutex);
340 baseInfo.pid = aceAppInfo.pid;
341 baseInfo.bundleName = aceAppInfo.bundleName;
342 baseInfo.versionCode = aceAppInfo.versionCode;
343 baseInfo.versionName = aceAppInfo.versionName;
344 baseInfo.processName = aceAppInfo.processName;
345 baseInfo.abilityName = aceAppInfo.abilityName;
346 return;
347 }
348
GetBaseInfo()349 BaseInfo SceneMonitor::GetBaseInfo()
350 {
351 std::lock_guard<std::mutex> Lock(mMutex);
352 return baseInfo;
353 }
354
NotifyScbJankStatsBegin(const std::string & sceneId)355 void SceneMonitor::NotifyScbJankStatsBegin(const std::string& sceneId)
356 {
357 static std::set<std::string> backToHomeScene = {
358 PerfConstants::LAUNCHER_APP_BACK_TO_HOME,
359 PerfConstants::LAUNCHER_APP_SWIPE_TO_HOME,
360 PerfConstants::INTO_HOME_ANI,
361 PerfConstants::PASSWORD_UNLOCK_ANI,
362 PerfConstants::FACIAL_FLING_UNLOCK_ANI,
363 PerfConstants::FACIAL_UNLOCK_ANI,
364 PerfConstants::FINGERPRINT_UNLOCK_ANI
365 };
366 if (backToHomeScene.find(sceneId) != backToHomeScene.end()) {
367 XPERF_TRACE_SCOPED("NotifyScbJankStatsBegin");
368 NotifyAppJankStatsBegin();
369 }
370 }
371
NotifyScbJankStatsEnd(const std::string & sceneId)372 void SceneMonitor::NotifyScbJankStatsEnd(const std::string& sceneId)
373 {
374 static std::set<std::string> appLaunch = {
375 PerfConstants::LAUNCHER_APP_LAUNCH_FROM_DOCK,
376 PerfConstants::LAUNCHER_APP_LAUNCH_FROM_ICON,
377 PerfConstants::LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR,
378 PerfConstants::LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN,
379 PerfConstants::LAUNCHER_APP_LAUNCH_FROM_RECENT,
380 PerfConstants::START_APP_ANI_FORM,
381 PerfConstants::SCREENLOCK_SCREEN_OFF_ANIM
382 };
383 if (appLaunch.find(sceneId) != appLaunch.end()) {
384 XPERF_TRACE_SCOPED("NotifyScbJankStatsEnd");
385 NotifyAppJankStatsEnd();
386 }
387 }
388
NotifyRsJankStatsBegin()389 void SceneMonitor::NotifyRsJankStatsBegin()
390 {
391 XPERF_TRACE_SCOPED("NotifyRsJankStatsBegin");
392 OHOS::Rosen::AppInfo appInfo;
393 SetJankFrameRecord(appInfo, JankFrameMonitor::GetInstance().GetJankFrameRecordBeginTime(), 0);
394 Rosen::RSInterfaces::GetInstance().ReportRsSceneJankStart(appInfo);
395 }
396
NotifyRsJankStatsEnd(int64_t endTime)397 void SceneMonitor::NotifyRsJankStatsEnd(int64_t endTime)
398 {
399 XPERF_TRACE_SCOPED("NotifyRsJankStatsEnd");
400 OHOS::Rosen::AppInfo appInfo;
401 SetJankFrameRecord(appInfo, JankFrameMonitor::GetInstance().GetJankFrameRecordBeginTime(), endTime);
402 Rosen::RSInterfaces::GetInstance().ReportRsSceneJankEnd(appInfo);
403 }
404
IsScrollJank(const std::string & sceneId)405 bool SceneMonitor::IsScrollJank(const std::string& sceneId)
406 {
407 if (sceneId == PerfConstants::APP_LIST_FLING ||
408 sceneId == PerfConstants::APP_SWIPER_SCROLL ||
409 sceneId == PerfConstants::APP_SWIPER_FLING) {
410 return true;
411 }
412 return false;
413 }
414
SetJankFrameRecord(OHOS::Rosen::AppInfo & appInfo,int64_t startTime,int64_t endTime)415 void SceneMonitor::SetJankFrameRecord(OHOS::Rosen::AppInfo &appInfo, int64_t startTime, int64_t endTime)
416 {
417 std::lock_guard<std::mutex> Lock(mMutex);
418 appInfo.pid = baseInfo.pid;
419 appInfo.bundleName = baseInfo.bundleName;
420 appInfo.versionCode = baseInfo.versionCode;
421 appInfo.versionName = baseInfo.versionName;
422 appInfo.processName = baseInfo.processName;
423 appInfo.startTime = startTime;
424 appInfo.endTime = endTime;
425 }
426
IsExceptResponseTime(int64_t time,const std::string & sceneId)427 bool SceneMonitor::IsExceptResponseTime(int64_t time, const std::string& sceneId)
428 {
429 int64_t currentRealTimeNs = GetCurrentRealTimeNs();
430 static std::set<std::string> exceptSceneSet = {
431 PerfConstants::APP_LIST_FLING, PerfConstants::SCREEN_ROTATION_ANI,
432 PerfConstants::SHOW_INPUT_METHOD_ANIMATION, PerfConstants::HIDE_INPUT_METHOD_ANIMATION,
433 PerfConstants::APP_TRANSITION_FROM_OTHER_APP, PerfConstants::APP_TRANSITION_TO_OTHER_APP,
434 PerfConstants::VOLUME_BAR_SHOW, PerfConstants::PC_APP_CENTER_GESTURE_OPERATION,
435 PerfConstants::PC_GESTURE_TO_RECENT, PerfConstants::PC_SHORTCUT_SHOW_DESKTOP,
436 PerfConstants::PC_ALT_TAB_TO_RECENT, PerfConstants::PC_SHOW_DESKTOP_GESTURE_OPERATION,
437 PerfConstants::PC_SHORTCUT_RESTORE_DESKTOP, PerfConstants::PC_SHORTCUT_TO_RECENT,
438 PerfConstants::PC_EXIT_RECENT, PerfConstants::PC_SHORTCUT_TO_APP_CENTER_ON_RECENT,
439 PerfConstants::PC_SHORTCUT_TO_APP_CENTER, PerfConstants::PC_SHORTCUT_EXIT_APP_CENTER,
440 PerfConstants::WINDOW_TITLE_BAR_MINIMIZED, PerfConstants::WINDOW_RECT_MOVE,
441 PerfConstants::APP_EXIT_FROM_WINDOW_TITLE_BAR_CLOSED, PerfConstants::WINDOW_TITLE_BAR_RECOVER,
442 PerfConstants::LAUNCHER_APP_LAUNCH_FROM_OTHER, PerfConstants::WINDOW_RECT_RESIZE,
443 PerfConstants::WINDOW_TITLE_BAR_MAXIMIZED, PerfConstants::LAUNCHER_APP_LAUNCH_FROM_TRANSITION
444 };
445 if (exceptSceneSet.find(sceneId) != exceptSceneSet.end()) {
446 return true;
447 }
448 if ((sceneId == PerfConstants::ABILITY_OR_PAGE_SWITCH && currentRealTimeNs - time > RESPONSE_TIMEOUT)
449 || (sceneId == PerfConstants::CLOSE_FOLDER_ANI && currentRealTimeNs - time > RESPONSE_TIMEOUT)) {
450 return true;
451 }
452 return false;
453 }
454
GetNonexpFilterTag()455 uint64_t SceneMonitor::GetNonexpFilterTag()
456 {
457 return mNonexpManager.GetSceneTag();
458 }
459
SetVsyncLazyMode(uint64_t sceneTag)460 void SceneMonitor::SetVsyncLazyMode(uint64_t sceneTag)
461 {
462 static bool lastExcusion = false;
463 bool needExcusion = static_cast<bool>(sceneTag);
464 if (lastExcusion == needExcusion) {
465 return;
466 }
467
468 lastExcusion = needExcusion;
469 XPERF_TRACE_SCOPED("SetVsyncLazyMode: sceneTag = %" PRIu64, sceneTag);
470 OHOS::AppExecFwk::EventHandler::SetVsyncLazyMode(needExcusion);
471 }
472
SetAppGCStatus(const std::string & sceneId,int64_t value)473 void SceneMonitor::SetAppGCStatus(const std::string& sceneId, int64_t value)
474 {
475 std::unordered_map<std::string, std::string> payload;
476 payload["extType"] = SENSITIVE_SCENE_EXTTYPE;
477 payload["srcPid"] = std::to_string(GetPid());
478 ResourceSchedule::ResSchedClient::GetInstance().ReportData(SENSITIVE_SCENE_RESTYPE, value, payload);
479 }
480
SetSubHealthInfo(const SubHealthInfo & info)481 void SceneMonitor::SetSubHealthInfo(const SubHealthInfo& info)
482 {
483 subHealthInfo = info;
484 isSubHealthScene = true;
485 }
486
FlushSubHealthInfo()487 void SceneMonitor::FlushSubHealthInfo()
488 {
489 if (isSubHealthScene) {
490 baseInfo.subHealthInfo = subHealthInfo;
491 isSubHealthScene = false;
492 }
493 }
494
495 }
496 }