• 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 <set>
17 
18 #include "jank_frame_monitor.h"
19 #include "perf_reporter.h"
20 #include "perf_trace.h"
21 #include "perf_utils.h"
22 #include "scene_monitor.h"
23 #include "hiview_logger.h"
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 DEFINE_LOG_LABEL(0xD002D66, "Hiview-PerfMonitor");
28 
GetInstance()29 JankFrameMonitor& JankFrameMonitor::GetInstance()
30 {
31     static JankFrameMonitor instance;
32     return instance;
33 }
34 
JankFrameMonitor()35 JankFrameMonitor::JankFrameMonitor()
36 {
37     InitJankFrameRecord();
38     RegisterFrameCallback(this);
39 }
40 
~JankFrameMonitor()41 JankFrameMonitor::~JankFrameMonitor()
42 {
43     UnregisterFrameCallback(this);
44 }
45 
RegisterFrameCallback(IFrameCallback * cb)46 void JankFrameMonitor::RegisterFrameCallback(IFrameCallback* cb)
47 {
48     std::lock_guard<std::mutex> Lock(mMutex);
49     if (std::find(frameCallbacks.begin(), frameCallbacks.end(), cb) == frameCallbacks.end()) {
50         frameCallbacks.push_back(cb);
51     }
52 }
53 
UnregisterFrameCallback(IFrameCallback * cb)54 void JankFrameMonitor::UnregisterFrameCallback(IFrameCallback* cb)
55 {
56     std::lock_guard<std::mutex> Lock(mMutex);
57     auto it = std::find(frameCallbacks.begin(), frameCallbacks.end(), cb);
58     if (it != frameCallbacks.end()) {
59         frameCallbacks.erase(it);
60     }
61 }
62 
OnFrameEnd(int64_t vsyncTime,int64_t duration,double jank,const std::string & windowName)63 void JankFrameMonitor::OnFrameEnd(int64_t vsyncTime, int64_t duration, double jank, const std::string& windowName)
64 {
65     AnimatorMonitor::GetInstance().OnVsyncEvent(vsyncTime, duration, jank, windowName);
66     for (auto* cb: frameCallbacks) {
67         cb->OnVsyncEvent(vsyncTime, duration, jank, windowName);
68     }
69 }
70 
OnVsyncEvent(int64_t vsyncTime,int64_t duration,double jank,const std::string & windowName)71 void JankFrameMonitor::OnVsyncEvent(int64_t vsyncTime, int64_t duration, double jank, const std::string& windowName)
72 {
73     SceneMonitor::GetInstance().OnSceneChanged(SceneType::NON_EXPERIENCE_WINDOW, true, windowName);
74     if (AnimatorMonitor::GetInstance().IsSubHealthScene()) {
75         SceneMonitor::GetInstance().FlushSubHealthInfo();
76     }
77     ProcessJank(vsyncTime, jank, windowName);
78     JankFrameStatsRecord(jank);
79     SceneMonitor::GetInstance().SingleFrameSceneStop(windowName);
80 }
81 
ProcessJank(int64_t vsyncTime,double jank,const std::string & windowName)82 void JankFrameMonitor::ProcessJank(int64_t vsyncTime, double jank, const std::string& windowName)
83 {
84     // single frame behavior report
85     if (jank >= static_cast<double>(DEFAULT_JANK_REPORT_THRESHOLD)) {
86         HIVIEW_LOGI("JankFrameMonitor::ProcessJank jank >= threshold");
87         JankInfo jankInfo;
88         jankInfo.skippedFrameTime = static_cast<int64_t>(jank * SINGLE_FRAME_TIME);
89         jankInfo.windowName = windowName;
90         jankInfo.baseInfo = SceneMonitor::GetInstance().GetBaseInfo();
91         jankInfo.sceneTag = SceneMonitor::GetInstance().GetNonexpFilterTag();
92         jankInfo.vsyncTime = vsyncTime;
93         if (!AnimatorMonitor::GetInstance().RecordsIsEmpty()) {
94             jankInfo.sceneId = SceneMonitor::GetInstance().GetCurrentSceneId();
95         } else {
96             jankInfo.sceneId = DEFAULT_SCENE_ID;
97         }
98         jankInfo.realSkippedFrameTime = jankInfo.sceneTag == 0 ? jankInfo.skippedFrameTime : 0;
99         PerfReporter::GetInstance().ReportSingleJankFrame(jankInfo);
100     }
101 }
102 
JankFrameStatsRecord(double jank)103 void JankFrameMonitor::JankFrameStatsRecord(double jank)
104 {
105     std::lock_guard<std::mutex> Lock(mMutex);
106     if (SceneMonitor::GetInstance().GetIsStats() && jank > 1.0f && !jankFrameRecord.empty()) {
107         jankFrameRecord[GetJankLimit(jank)]++;
108         jankFrameTotalCount++;
109     }
110 }
111 
InitJankFrameRecord()112 void JankFrameMonitor::InitJankFrameRecord()
113 {
114     jankFrameRecord = std::vector<uint16_t>(JANK_STATS_SIZE, 0);
115 }
116 
ClearJankFrameRecord()117 void JankFrameMonitor::ClearJankFrameRecord()
118 {
119     std::lock_guard<std::mutex> Lock(mMutex);
120     std::fill(jankFrameRecord.begin(), jankFrameRecord.end(), 0);
121     jankFrameTotalCount = 0;
122     jankFrameRecordBeginTime = 0;
123 }
124 
SetJankFrameRecordBeginTime(int64_t val)125 void JankFrameMonitor::SetJankFrameRecordBeginTime(int64_t val)
126 {
127     std::lock_guard<std::mutex> Lock(mMutex);
128     jankFrameRecordBeginTime = val;
129     return;
130 }
131 
GetJankFrameRecordBeginTime()132 int64_t JankFrameMonitor::GetJankFrameRecordBeginTime()
133 {
134     std::lock_guard<std::mutex> Lock(mMutex);
135     return jankFrameRecordBeginTime;
136 }
137 
GetJankFrameTotalCount()138 int32_t JankFrameMonitor::GetJankFrameTotalCount()
139 {
140     std::lock_guard<std::mutex> Lock(mMutex);
141     return jankFrameTotalCount;
142 }
143 
GetJankFrameRecord()144 const std::vector<uint16_t>& JankFrameMonitor::GetJankFrameRecord()
145 {
146     std::lock_guard<std::mutex> Lock(mMutex);
147     return jankFrameRecord;
148 }
149 
GetJankLimit(double jank)150 uint32_t JankFrameMonitor::GetJankLimit(double jank)
151 {
152     if (jank < 6.0f) {
153         return JANK_FRAME_6_LIMIT;
154     }
155     if (jank < 15.0f) {
156         return JANK_FRAME_15_LIMIT;
157     }
158     if (jank < 20.0f) {
159         return JANK_FRAME_20_LIMIT;
160     }
161     if (jank < 36.0f) {
162         return JANK_FRAME_36_LIMIT;
163     }
164     if (jank < 48.0f) {
165         return JANK_FRAME_48_LIMIT;
166     }
167     if (jank < 60.0f) {
168         return JANK_FRAME_60_LIMIT;
169     }
170     if (jank < 120.0f) {
171         return JANK_FRAME_120_LIMIT;
172     }
173     return JANK_FRAME_180_LIMIT;
174 }
175 }
176 }