• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }