• 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 "animator_monitor.h"
17 #include "input_monitor.h"
18 #include "jank_frame_monitor.h"
19 #include "perf_reporter.h"
20 #include "perf_trace.h"
21 #include "perf_utils.h"
22 #include "res_sched_client.h"
23 #include "hiview_logger.h"
24 #include "white_block_monitor.h"
25 
26 namespace OHOS {
27 namespace HiviewDFX {
28 
29 DEFINE_LOG_LABEL(0xD002D66, "Hiview-PerfMonitor");
30 
GetInstance()31 AnimatorMonitor& AnimatorMonitor::GetInstance()
32 {
33     static AnimatorMonitor instance;
34     return instance;
35 }
36 
AnimatorMonitor()37 AnimatorMonitor::AnimatorMonitor()
38 {
39     RegisterAnimatorCallback(this);
40 }
41 
~AnimatorMonitor()42 AnimatorMonitor::~AnimatorMonitor()
43 {
44     UnregisterAnimatorCallback(this);
45 }
46 
RegisterAnimatorCallback(IAnimatorCallback * cb)47 void AnimatorMonitor::RegisterAnimatorCallback(IAnimatorCallback* cb)
48 {
49     std::lock_guard<std::mutex> Lock(mMutex);
50     if (std::find(animatorCallbacks.begin(), animatorCallbacks.end(), cb) == animatorCallbacks.end()) {
51         animatorCallbacks.push_back(cb);
52     }
53 }
54 
UnregisterAnimatorCallback(IAnimatorCallback * cb)55 void AnimatorMonitor::UnregisterAnimatorCallback(IAnimatorCallback* cb)
56 {
57     std::lock_guard<std::mutex> Lock(mMutex);
58     auto it = std::find(animatorCallbacks.begin(), animatorCallbacks.end(), cb);
59     if (it != animatorCallbacks.end()) {
60         animatorCallbacks.erase(it);
61     }
62 }
63 
Start(const std::string & sceneId,PerfActionType type,const std::string & note)64 void AnimatorMonitor::Start(const std::string& sceneId, PerfActionType type, const std::string& note)
65 {
66     std::lock_guard<std::mutex> Lock(mMutex);
67     for (auto* cb: animatorCallbacks) {
68         cb->OnAnimatorStart(sceneId, type, note);
69     }
70 }
71 
End(const std::string & sceneId,bool isRsRender)72 void AnimatorMonitor::End(const std::string& sceneId, bool isRsRender)
73 {
74     std::lock_guard<std::mutex> Lock(mMutex);
75     for (auto* cb: animatorCallbacks) {
76         cb->OnAnimatorStop(sceneId, isRsRender);
77     }
78 }
79 
OnAnimatorStart(const std::string & sceneId,PerfActionType type,const std::string & note)80 void AnimatorMonitor::OnAnimatorStart(const std::string& sceneId, PerfActionType type, const std::string& note)
81 {
82     if (!isValidSceneId(sceneId)) {
83         HIVIEW_LOGW("invalid sceneId: %{public}s", sceneId.c_str());
84         return;
85     }
86     AnimatorRecord* record = GetRecord(sceneId);
87     XPERF_TRACE_SCOPED("Animation start and current sceneId=%s", sceneId.c_str());
88     HIVIEW_LOGD("Animation start and current sceneId: %{public}s", sceneId.c_str());
89     if (record == nullptr) {
90         record = new AnimatorRecord();
91         int64_t inputTime = InputMonitor::GetInstance().GetInputTime(sceneId, type, note);
92         PerfSourceType sourceType = InputMonitor::GetInstance().GetSourceType();
93         record->InitRecord(sceneId, type, sourceType, note, inputTime);
94         mRecords.insert(std::pair<std::string, AnimatorRecord*> (sceneId, record));
95         XperfAsyncTraceBegin(0, sceneId.c_str());
96     } else {
97         HIVIEW_LOGW("Animation has already started, sceneId: %{public}s", sceneId.c_str());
98     }
99 }
100 
OnAnimatorStop(const std::string & sceneId,bool isRsRender)101 void AnimatorMonitor::OnAnimatorStop(const std::string& sceneId, bool isRsRender)
102 {
103     AnimatorRecord* record = GetRecord(sceneId);
104     XPERF_TRACE_SCOPED("Animation end and current sceneId=%s", sceneId.c_str());
105     HIVIEW_LOGD("Animation stop and current sceneId: %{public}s", sceneId.c_str());
106     if (record != nullptr) {
107         SceneMonitor::GetInstance().FlushSubHealthInfo();
108         int64_t mVsyncTime = InputMonitor::GetInstance().GetVsyncTime();
109         record->Report(sceneId, mVsyncTime, isRsRender);
110         ReportAnimateEnd(sceneId, record);
111         RemoveRecord(sceneId);
112         XperfAsyncTraceEnd(0, sceneId.c_str());
113     } else {
114         HIVIEW_LOGW("Animation has not started, sceneId: %{public}s", sceneId.c_str());
115     }
116 }
117 
OnVsyncEvent(int64_t vsyncTime,int64_t duration,double jank,const std::string & windowName)118 void AnimatorMonitor::OnVsyncEvent(int64_t vsyncTime, int64_t duration, double jank, const std::string& windowName)
119 {
120     std::lock_guard<std::mutex> Lock(mMutex);
121     InputMonitor::GetInstance().SetVsyncTime(vsyncTime);
122     int32_t skippedFrames = static_cast<int32_t> (jank);
123     for (auto it = mRecords.begin(); it != mRecords.end();) {
124         if (it->second != nullptr) {
125             (it->second)->RecordFrame(vsyncTime, duration, skippedFrames);
126             if ((it->second)->IsTimeOut(vsyncTime + duration)) {
127                 SceneMonitor::GetInstance().OnSceneChanged(SceneType::NON_EXPERIENCE_ANIMATOR,
128                     false, it->second->sceneId);
129                 delete it->second;
130                 it = mRecords.erase(it);
131                 continue;
132             }
133             if ((it->second)->IsFirstFrame()) {
134                 ReportAnimateStart(it->first, it->second);
135             }
136         }
137         it++;
138     }
139 }
140 
RecordsIsEmpty()141 bool AnimatorMonitor::RecordsIsEmpty()
142 {
143     std::lock_guard<std::mutex> Lock(mMutex);
144     return mRecords.empty();
145 }
146 
GetRecord(const std::string & sceneId)147 AnimatorRecord* AnimatorMonitor::GetRecord(const std::string& sceneId)
148 {
149     auto iter = mRecords.find(sceneId);
150     if (iter != mRecords.end()) {
151         return iter->second;
152     }
153     return nullptr;
154 }
155 
SetSubHealthInfo(const SubHealthInfo & info)156 void AnimatorMonitor::SetSubHealthInfo(const SubHealthInfo& info)
157 {
158     subHealthRecordTime = GetCurrentSystimeMs();
159     SceneMonitor::GetInstance().SetSubHealthInfo(info);
160 }
161 
IsSubHealthScene()162 bool AnimatorMonitor::IsSubHealthScene()
163 {
164     return (GetCurrentSystimeMs() - subHealthRecordTime < VAILD_JANK_SUB_HEALTH_INTERVAL);
165 }
166 
RemoveRecord(const std::string & sceneId)167 void AnimatorMonitor::RemoveRecord(const std::string& sceneId)
168 {
169     std::map <std::string, AnimatorRecord*>::iterator iter = mRecords.find(sceneId);
170     if (iter != mRecords.end()) {
171         if (iter->second != nullptr) {
172             delete iter->second;
173         }
174         mRecords.erase(iter);
175     }
176 }
177 
isValidSceneId(const std::string & sceneId)178 bool AnimatorMonitor::isValidSceneId(const std::string& sceneId)
179 {
180     if (sceneId.empty()) {
181         return false;
182     }
183     return validSceneIds.count(sceneId);
184 }
185 
FlushDataBase(AnimatorRecord * record,DataBase & data)186 void AnimatorMonitor::FlushDataBase(AnimatorRecord* record, DataBase& data)
187 {
188     if (record == nullptr) {
189         return;
190     }
191     data.sceneId = record->sceneId;
192     data.inputTime = record->inputTime;
193     data.beginVsyncTime = record->beginVsyncTime;
194     if (data.beginVsyncTime < data.inputTime) {
195         data.inputTime = data.beginVsyncTime;
196     }
197     data.endVsyncTime = record->endVsyncTime;
198     if (data.beginVsyncTime > data.endVsyncTime) {
199         data.endVsyncTime = data.beginVsyncTime;
200     }
201     data.maxFrameTime = record->maxFrameTime;
202     data.maxFrameTimeSinceStart = record->maxFrameTimeSinceStart;
203     data.maxHitchTime = record->maxHitchTime;
204     data.maxHitchTimeSinceStart = record->maxHitchTimeSinceStart;
205     data.maxSuccessiveFrames = record->maxSuccessiveFrames;
206     data.totalMissed = record->totalMissed;
207     data.totalFrames = record->totalFrames;
208     data.needReportRs = record->needReportRs;
209     data.isDisplayAnimator = record->isDisplayAnimator;
210     data.sourceType = record->sourceType;
211     data.actionType = record->actionType;
212     data.baseInfo = SceneMonitor::GetInstance().GetBaseInfo();
213     data.baseInfo.note = record->note;
214 }
215 
ReportAnimateStart(const std::string & sceneId,AnimatorRecord * record)216 void AnimatorMonitor::ReportAnimateStart(const std::string& sceneId, AnimatorRecord* record)
217 {
218     if (record == nullptr) {
219         return;
220     }
221     DataBase data;
222     FlushDataBase(record, data);
223     PerfReporter::GetInstance().ReportAnimatorEvent(EVENT_RESPONSE, data);
224 }
225 
ReportAnimateEnd(const std::string & sceneId,AnimatorRecord * record)226 void AnimatorMonitor::ReportAnimateEnd(const std::string& sceneId, AnimatorRecord* record)
227 {
228     if (record == nullptr) {
229         return;
230     }
231     DataBase data;
232     FlushDataBase(record, data);
233     PerfReporter::GetInstance().ReportAnimatorEvent(EVENT_JANK_FRAME, data);
234     PerfReporter::GetInstance().ReportAnimatorEvent(EVENT_COMPLETE, data);
235 }
236 
237 }
238 }