1 /*
2  * Copyright (c) 2024 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 "AnimatorSceneDataProcessor.h"
17 #include "JlogId.h"
18 #include "hiview_logger.h"
19 
20 DEFINE_LOG_LABEL(0xD002D66, "Hiview-XPerformance");
21 
22 namespace {
23 const int32_t S_TO_MS = 1000;
24 const int64_t S_TO_US = 10000000;
25 // process animator point when timeout
26 const int32_t TIME_OUT = 5000;
27 
28 // define animator process point
29 enum ANIMATOR_POINT {
30     SUP_START_POINT = -1,
31     START_POINT = 0,
32     END_POINT = 1
33 };
34 }
GetCurrentRealtimeMs()35 static int64_t GetCurrentRealtimeMs()
36 {
37     struct timespec t;
38     t.tv_sec = t.tv_nsec = 0;
39     clock_gettime(CLOCK_REALTIME, &t);
40     return (t.tv_sec * S_TO_MS + t.tv_nsec / S_TO_US);
41 }
42 
SetCb(IAnimatorSceneDataProcessor::MetricReporter * cb)43 void AnimatorSceneDataProcessor::SetCb(IAnimatorSceneDataProcessor::MetricReporter* cb)
44 {
45     this->cb = cb;
46 }
47 
CacheFocusWindowPid(std::shared_ptr<XperfEvt> evt)48 void AnimatorSceneDataProcessor::CacheFocusWindowPid(std::shared_ptr<XperfEvt> evt)
49 {
50     if (evt == nullptr) {
51         return;
52     }
53     focusWindowPid = evt->pid;
54     focusBundleName = evt->bundleName;
55 }
56 
ProcessSceneData(std::shared_ptr<XperfEvt> evt)57 void AnimatorSceneDataProcessor::ProcessSceneData(std::shared_ptr<XperfEvt> evt)
58 {
59     HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData]");
60     if (evt == nullptr) {
61         HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData] evt == nullptr");
62         return;
63     }
64     switch (evt->logId) {
65         case JLID_ACE_INTERACTION_APP_JANK:
66             HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData] JLID_ACE_INTERACTION_APP_JANK");
67             CreateRecord(evt, START_POINT);
68             break;
69         case JLID_GRAPHIC_INTERACTION_RENDER_JANK:
70             HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData] JLID_GRAPHIC_INTERACTION_RENDER_JANK");
71             if (!HasStartPoint(evt)) {
72                 CreateRecord(evt, SUP_START_POINT);
73             }
74             SaveAnimatorPoint(evt, END_POINT);
75             break;
76         case JLID_WINDOWMANAGER_FOCUS_WINDOW:
77             HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData] JLID_WINDOWMANAGER_FOCUS_WINDOW");
78             CacheFocusWindowPid(evt);
79             break;
80         default:
81             return;
82     }
83     if (AllPointsReceived(evt)) {
84         HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData] AllPointsReceived");
85         AnimatorRecord* record = GetRecord(evt->animatorInfo.basicInfo.uniqueId);
86         if (record == nullptr) {
87             HIVIEW_LOGD("[AnimatorSceneDataProcessor::ProcessSceneData] record == nullptr");
88             return;
89         }
90         AnimatorMetrics metrics = CalcMetrics(*record);
91         Report(metrics);
92         DeleteRecord(evt->animatorInfo.basicInfo.uniqueId);
93     }
94     HandleTimeOutPoints();
95 }
96 
CreateRecord(std::shared_ptr<XperfEvt> evt,int32_t indexPoint)97 void AnimatorSceneDataProcessor::CreateRecord(std::shared_ptr<XperfEvt> evt, int32_t indexPoint)
98 {
99     HIVIEW_LOGD("[AnimatorSceneDataProcessor::CreateRecord]");
100     if (evt == nullptr) {
101         return;
102     }
103     AnimatorRecord* animatorRecord = new AnimatorRecord();
104     db.insert(std::map<int32_t, AnimatorRecord*>::value_type(evt->animatorInfo.basicInfo.uniqueId, animatorRecord));
105     SaveAnimatorPoint(evt, indexPoint);
106 }
107 
HasStartPoint(std::shared_ptr<XperfEvt> evt)108 bool AnimatorSceneDataProcessor::HasStartPoint(std::shared_ptr<XperfEvt> evt)
109 {
110     if (evt == nullptr) {
111         return false;
112     }
113     AnimatorRecord* record = GetRecord(evt->animatorInfo.basicInfo.uniqueId);
114     if (record != nullptr && record->hasStartPoint) {
115         return true;
116     }
117     return false;
118 }
119 
AllPointsReceived(std::shared_ptr<XperfEvt> evt)120 bool AnimatorSceneDataProcessor::AllPointsReceived(std::shared_ptr<XperfEvt> evt)
121 {
122     if (evt == nullptr) {
123         return false;
124     }
125     AnimatorRecord* record = GetRecord(evt->animatorInfo.basicInfo.uniqueId);
126     if (record != nullptr) {
127         if (record->hasStartPoint &&
128             record->receviedPoint >= record->allReceviedPoint) {
129             return true;
130         }
131     }
132     return false;
133 }
134 
SaveAnimatorPoint(std::shared_ptr<XperfEvt> evt,int32_t indexPoint)135 void AnimatorSceneDataProcessor::SaveAnimatorPoint(std::shared_ptr<XperfEvt> evt, int32_t indexPoint)
136 {
137     HIVIEW_LOGD("[AnimatorSceneDataProcessor::SaveAnimatorPoint]");
138     if (evt == nullptr) {
139         return;
140     }
141     AnimatorRecord* record = GetRecord(evt->animatorInfo.basicInfo.uniqueId);
142     if (record == nullptr) {
143         return;
144     }
145     if (indexPoint == START_POINT || indexPoint == SUP_START_POINT) {
146         record->hasStartPoint = true;
147         record->startTime = GetCurrentRealtimeMs();
148     }
149     record->receviedPoint++;
150     if (indexPoint == SUP_START_POINT) {
151         record->animatorPoints[START_POINT].basicInfo = evt->animatorInfo.basicInfo;
152         return;
153     }
154     record->animatorPoints[indexPoint].basicInfo = evt->animatorInfo.basicInfo;
155     record->animatorPoints[indexPoint].commonInfo = evt->animatorInfo.commonInfo;
156 }
157 
CalcMetrics(const AnimatorRecord & record)158 AnimatorMetrics AnimatorSceneDataProcessor::CalcMetrics(const AnimatorRecord& record)
159 {
160     AnimatorMetrics animatorMetrics;
161     animatorMetrics.basicInfo = record.animatorPoints[START_POINT].basicInfo;
162     animatorMetrics.appInfo = record.animatorPoints[START_POINT].commonInfo;
163     animatorMetrics.rsInfo = record.animatorPoints[END_POINT].commonInfo;
164     if (animatorMetrics.basicInfo.bundleNameEx.empty()) {
165         animatorMetrics.basicInfo.bundleNameEx = animatorMetrics.basicInfo.moduleName;
166     }
167     if (animatorMetrics.basicInfo.bundleNameEx == focusBundleName ||
168         (animatorMetrics.basicInfo.bundleNameEx.empty() && animatorMetrics.basicInfo.moduleName == focusBundleName)) {
169         animatorMetrics.focus = true;
170     } else {
171         animatorMetrics.focus = false;
172     }
173     return animatorMetrics;
174 }
175 
Report(const AnimatorMetrics & metrics)176 void AnimatorSceneDataProcessor::Report(const AnimatorMetrics& metrics)
177 {
178     HIVIEW_LOGD("[AnimatorSceneDataProcessor::Report]");
179     cb->ReportMetrics(metrics);
180 }
181 
GetRecord(const int32_t uniqueId)182 AnimatorRecord* AnimatorSceneDataProcessor::GetRecord(const int32_t uniqueId)
183 {
184     AnimatorRecord* record = nullptr;
185     if (db.find(uniqueId) != db.end()) {
186         record = db[uniqueId];
187     }
188     return record;
189 }
190 
DeleteRecord(const int32_t uniqueId)191 void AnimatorSceneDataProcessor::DeleteRecord(const int32_t uniqueId)
192 {
193     auto iter = db.find(uniqueId);
194     if (iter != db.end()) {
195         delete iter->second;
196         db.erase(iter);
197     }
198 }
199 
HandleTimeOutPoints()200 void AnimatorSceneDataProcessor::HandleTimeOutPoints()
201 {
202     HIVIEW_LOGD("[AnimatorSceneDataProcessor::HandleTimeOutPoints] begin");
203     for (auto it = db.begin(); it != db.end();) {
204         if (it->second != nullptr && (GetCurrentRealtimeMs() - (it->second)->startTime) >= TIME_OUT) {
205             HIVIEW_LOGD("[AnimatorSceneDataProcessor::HandleTimeOutPoints] match if");
206             Report(CalcMetrics(*(it->second)));
207             delete it->second;
208             it = db.erase(it);
209             continue;
210         }
211         it++;
212     }
213     HIVIEW_LOGD("[AnimatorSceneDataProcessor::HandleTimeOutPoints] end");
214 }
215