1 /*
2 * Copyright (c) 2022 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 "perform_reporter.h"
17
18 #include <hisysevent.h>
19
20 #include "window_manager_hilog.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 namespace {
25 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "PerformReporter"};
26 }
27 WM_IMPLEMENT_SINGLE_INSTANCE(WindowInfoReporter)
28
29 constexpr char EVENT_KEY_BUNDLE_NAME[] = "BUNDLE_NAME";
30 constexpr char EVENT_KEY_WINDOW_NAME[] = "WINDOW_NAME";
31 constexpr char EVENT_KEY_MISSION_ID[] = "MISSION_ID";
32 constexpr char EVENT_KEY_TIMESTAMP[] = "TIMESTAMP";
33
34 /**
35 * @brief Construct a new Perform Reporter:: Perform Reporter object
36 *
37 * @param tag A tag that in report string
38 * @param timeSpiltsMs The time-interval that data statistic, details look up the comments in function body
39 * @param reportInterval Report data after reportInterval round start-end
40 */
PerformReporter(const std::string & tag,const std::vector<int64_t> & timeSpiltsMs,uint32_t reportInterval)41 PerformReporter::PerformReporter(const std::string& tag,
42 const std::vector<int64_t>& timeSpiltsMs, uint32_t reportInterval)
43 : tag_(tag), reportInterval_(reportInterval)
44 {
45 // re-organ data struct
46 // a, b, c, d -->
47 // (0, a] : cnt=0, (a, b] : cnt=0, (b, c] : cnt=0, (c, d] : cnt=0
48 for (auto split : timeSpiltsMs) {
49 timeSplitCount_[split] = 0;
50 }
51 // (d, +limit] : cnt=0
52 timeSplitCount_[BARRIER] = 0;
53 totalCount_ = 0;
54 }
55
start()56 void PerformReporter::start()
57 {
58 startTime_ = std::chrono::steady_clock::now();
59 }
60
end()61 void PerformReporter::end()
62 {
63 auto currentTime = std::chrono::steady_clock::now();
64 int64_t costTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime_).count();
65
66 count(costTime);
67
68 bool repSucc = report();
69 if (repSucc) {
70 clear();
71 }
72 }
73
report()74 bool PerformReporter::report()
75 {
76 if (totalCount_ < reportInterval_) {
77 return false;
78 }
79
80 std::ostringstream oss;
81 oss << tag_ << ": ";
82 auto maxSplit = 0;
83 for (const auto& iter: timeSplitCount_) {
84 if (iter.first != BARRIER) {
85 oss << "BELLOW" << iter.first << "(ms): " << iter.second << ", ";
86 maxSplit = iter.first;
87 }
88 }
89 oss << "ABOVE" << maxSplit << "(ms): " << timeSplitCount_[BARRIER];
90
91 int32_t ret = HiSysEventWrite(
92 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, tag_,
93 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "MSG", oss.str());
94 WLOGI("Write HiSysEvent ret:%{public}d", ret);
95 return ret == 0;
96 }
97
count(int64_t costTime)98 void PerformReporter::count(int64_t costTime)
99 {
100 totalCount_++;
101 for (auto& iter: timeSplitCount_) {
102 if (costTime <= iter.first) {
103 iter.second++;
104 break;
105 }
106 }
107
108 std::ostringstream oss;
109 oss << tag_ << " cost " << costTime << "ms, total count " << totalCount_;
110 WLOGI("%{public}s", oss.str().c_str());
111 }
112
clear()113 void PerformReporter::clear()
114 {
115 totalCount_ = 0;
116 for (auto& iter: timeSplitCount_) {
117 iter.second = 0;
118 }
119 }
120
GetMsgString(const FullInfoMap & infoMap)121 std::string WindowInfoReporter::GetMsgString(const FullInfoMap& infoMap)
122 {
123 if (infoMap.empty()) {
124 return "";
125 }
126 std::ostringstream oss;
127 oss << "{";
128 for (auto& bundleInfos : infoMap) {
129 if (bundleInfos.second.empty()) {
130 continue;
131 }
132 oss << "{";
133 for (auto& packageInfo : bundleInfos.second) {
134 oss << "BUNDLE_NAME:" << bundleInfos.first << ",";
135 oss << "ABILITY_NAME:" << packageInfo.first << ",";
136 oss << "COUNT:" << packageInfo.second;
137 }
138 oss << "},";
139 }
140 oss << "};";
141 return oss.str();
142 }
143
GetMsgString(const BundleNameMap & infoMap)144 std::string WindowInfoReporter::GetMsgString(const BundleNameMap& infoMap)
145 {
146 if (infoMap.empty()) {
147 return "";
148 }
149 std::ostringstream oss;
150 oss << "{";
151 for (auto& bundleInfo : infoMap) {
152 oss << "{";
153 oss << "BUNDLE_NAME:" << bundleInfo.first << ",";
154 oss << "COUNT:" << bundleInfo.second;
155 oss << "},";
156 }
157 oss << "};";
158 return oss.str();
159 }
160
InsertCreateReportInfo(const std::string & bundleName)161 void WindowInfoReporter::InsertCreateReportInfo(const std::string& bundleName)
162 {
163 UpdateReportInfo(windowCreateReportInfos_, bundleName);
164 }
165
InsertShowReportInfo(const std::string & bundleName)166 void WindowInfoReporter::InsertShowReportInfo(const std::string& bundleName)
167 {
168 UpdateReportInfo(windowShowReportInfos_, bundleName);
169 }
170
InsertHideReportInfo(const std::string & bundleName)171 void WindowInfoReporter::InsertHideReportInfo(const std::string& bundleName)
172 {
173 UpdateReportInfo(windowHideReportInfos_, bundleName);
174 }
175
InsertDestroyReportInfo(const std::string & bundleName)176 void WindowInfoReporter::InsertDestroyReportInfo(const std::string& bundleName)
177 {
178 UpdateReportInfo(windowDestoryReportInfos_, bundleName);
179 }
180
InsertNavigationBarReportInfo(const std::string & bundleName,const std::string & packageName)181 void WindowInfoReporter::InsertNavigationBarReportInfo(const std::string& bundleName, const std::string& packageName)
182 {
183 UpdateReportInfo(windowNavigationBarReportInfos_, bundleName, packageName);
184 }
185
UpdateReportInfo(FullInfoMap & infoMap,const std::string & bundleName,const std::string & packageName)186 void WindowInfoReporter::UpdateReportInfo(FullInfoMap& infoMap,
187 const std::string& bundleName, const std::string& packageName)
188 {
189 if (bundleName.empty() || packageName.empty()) {
190 return;
191 }
192 std::lock_guard<std::mutex> lock(mtx_);
193 auto iter = infoMap.find(bundleName);
194 if (iter == infoMap.end()) {
195 std::map<std::string, uint32_t> infos;
196 infos.insert(std::make_pair(packageName, 1));
197 infoMap.insert(std::make_pair(bundleName, infos));
198 return;
199 }
200
201 auto countPairIter = iter->second.find(packageName);
202 if (countPairIter == iter->second.end()) {
203 iter->second.insert(std::make_pair(packageName, 1));
204 return;
205 }
206 infoMap[bundleName][packageName]++;
207 }
208
UpdateReportInfo(BundleNameMap & infoMap,const std::string & bundleName)209 void WindowInfoReporter::UpdateReportInfo(BundleNameMap& infoMap, const std::string& bundleName)
210 {
211 if (bundleName.empty()) {
212 return;
213 }
214 std::lock_guard<std::mutex> lock(mtx_);
215 auto iter = infoMap.find(bundleName);
216 if (iter == infoMap.end()) {
217 infoMap.insert(std::make_pair(bundleName, 1));
218 return;
219 }
220 infoMap[bundleName]++;
221 }
222
ReportBackButtonInfoImmediately()223 void WindowInfoReporter::ReportBackButtonInfoImmediately()
224 {
225 Report("WM_REPORT_BACK_KEYEVENT", "Click Back Button");
226 }
227
ReportZeroOpacityInfoImmediately(const std::string & bundleName,const std::string & packageName)228 void WindowInfoReporter::ReportZeroOpacityInfoImmediately(const std::string& bundleName, const std::string& packageName)
229 {
230 if (bundleName.empty()) {
231 return;
232 }
233 std::ostringstream oss;
234 oss << "{ PROCESS_NAME:" << bundleName.c_str() << ", PACKAGE_NAME:" << "" << packageName.c_str() << " }";
235 Report("WM_REPORT_WINDOW_OPACITY_ZERO", oss.str());
236 }
237
ReportStartWindow(const std::string & bundleName,const std::string & windowName)238 void WindowInfoReporter::ReportStartWindow(const std::string& bundleName, const std::string& windowName)
239 {
240 std::string eventName = "START_WINDOW";
241 int32_t ret = HiSysEventWrite(
242 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, eventName,
243 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
244 EVENT_KEY_BUNDLE_NAME, bundleName,
245 EVENT_KEY_WINDOW_NAME, windowName);
246 if (ret != 0) {
247 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
248 }
249 }
250
ReportRecordedInfos()251 void WindowInfoReporter::ReportRecordedInfos()
252 {
253 std::lock_guard<std::mutex> lock(mtx_);
254 WLOGFD("----Report HiSysEvent write all-----");
255 Report("WM_REPORT_WINDOW_CREATE", GetMsgString(windowCreateReportInfos_));
256 Report("WM_REPORT_WINDOW_SHOW", GetMsgString(windowShowReportInfos_));
257 Report("WM_REPORT_WINDOW_HIDE", GetMsgString(windowHideReportInfos_));
258 Report("WM_REPORT_WINDOW_DESTORY", GetMsgString(windowDestoryReportInfos_));
259 Report("WM_REPORT_HIDE_NAVIGATIONBAR", GetMsgString(windowNavigationBarReportInfos_));
260 ClearRecordedInfos();
261 }
262
ReportContainerStartBegin(int32_t missionId,const std::string & bundleName,int64_t timestamp)263 void WindowInfoReporter::ReportContainerStartBegin(int32_t missionId, const std::string& bundleName, int64_t timestamp)
264 {
265 std::string eventName = "CONTAINER_START_BEGIN";
266 int32_t ret = HiSysEventWrite(
267 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, eventName,
268 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
269 EVENT_KEY_MISSION_ID, missionId,
270 EVENT_KEY_BUNDLE_NAME, bundleName,
271 EVENT_KEY_TIMESTAMP, timestamp);
272 if (ret != 0) {
273 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
274 }
275 }
276
Report(const std::string & reportTag,const std::string & msg)277 void WindowInfoReporter::Report(const std::string& reportTag, const std::string& msg)
278 {
279 if (msg.empty()) {
280 return;
281 }
282 WLOGFD("Report Tag : [%{public}s], Msg: %{public}s", reportTag.c_str(), msg.c_str());
283 int32_t ret = HiSysEventWrite(
284 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, reportTag,
285 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "MSG", msg);
286 if (ret != 0) {
287 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
288 }
289 }
290
ClearRecordedInfos()291 void WindowInfoReporter::ClearRecordedInfos()
292 {
293 WLOGFD("Clear all hiSysEvent write information");
294 windowCreateReportInfos_.clear();
295 windowShowReportInfos_.clear();
296 windowHideReportInfos_.clear();
297 windowDestoryReportInfos_.clear();
298 windowNavigationBarReportInfos_.clear();
299 }
300
ReportWindowProfileInfo(const WindowProfileInfo & windowProfileInfo)301 int32_t WindowInfoReporter::ReportWindowProfileInfo(const WindowProfileInfo& windowProfileInfo)
302 {
303 std::string eventName = "WINDOW_PROFILE_INFORMATION";
304 int32_t ret = HiSysEventWrite(
305 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, eventName,
306 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
307 "BUNDLE_NAME", windowProfileInfo.bundleName,
308 "WINDOW_VISIBLE_STATE", windowProfileInfo.windowVisibleState,
309 "WINDOW_LOCATED_SCREEN", windowProfileInfo.windowLocatedScreen,
310 "WINDOW_SCENE_MODE", windowProfileInfo.windowSceneMode);
311 if (ret != 0) {
312 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
313 }
314 return ret;
315 }
316
ReportWindowException(int32_t detectionType,int32_t pid,const std::string & windowInfo)317 void WindowInfoReporter::ReportWindowException(int32_t detectionType, int32_t pid, const std::string& windowInfo)
318 {
319 std::string eventName = "WINDOW_EXCEPTION_DETECTION";
320 int32_t ret = HiSysEventWrite(
321 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, eventName,
322 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
323 "DETECTION_TYPE", detectionType,
324 "PID", pid,
325 "MSG", windowInfo);
326 if (ret != 0) {
327 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
328 }
329 }
330 }
331 }