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 }
WM_IMPLEMENT_SINGLE_INSTANCE(WindowInfoReporter)27 WM_IMPLEMENT_SINGLE_INSTANCE(WindowInfoReporter)
28
29 /**
30 * @brief Construct a new Perform Reporter:: Perform Reporter object
31 *
32 * @param tag A tag that in report string
33 * @param timeSpiltsMs The time-interval that data statistic, details look up the comments in function body
34 * @param reportInterval Report data after reportInterval round start-end
35 */
36 PerformReporter::PerformReporter(const std::string& tag,
37 const std::vector<int64_t>& timeSpiltsMs, uint32_t reportInterval)
38 : tag_(tag), reportInterval_(reportInterval)
39 {
40 // re-organ data struct
41 // a, b, c, d -->
42 // (0, a] : cnt=0, (a, b] : cnt=0, (b, c] : cnt=0, (c, d] : cnt=0
43 for (auto split : timeSpiltsMs) {
44 timeSplitCount_[split] = 0;
45 }
46 // (d, +limit] : cnt=0
47 timeSplitCount_[BARRIER] = 0;
48 totalCount_ = 0;
49 }
50
start()51 void PerformReporter::start()
52 {
53 startTime_ = std::chrono::steady_clock::now();
54 }
55
end()56 void PerformReporter::end()
57 {
58 auto currentTime = std::chrono::steady_clock::now();
59 int64_t costTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime_).count();
60
61 count(costTime);
62
63 bool repSucc = report();
64 if (repSucc) {
65 clear();
66 }
67 }
68
report()69 bool PerformReporter::report()
70 {
71 if (totalCount_ < reportInterval_) {
72 return false;
73 }
74
75 std::ostringstream oss;
76 oss << tag_ << ": ";
77 auto maxSplit = 0;
78 for (const auto& iter: timeSplitCount_) {
79 if (iter.first != BARRIER) {
80 oss << "BELLOW" << iter.first << "(ms): " << iter.second << ", ";
81 maxSplit = iter.first;
82 }
83 }
84 oss << "ABOVE" << maxSplit << "(ms): " << timeSplitCount_[BARRIER];
85
86 int32_t ret = HiSysEventWrite(
87 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, tag_,
88 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "MSG", oss.str());
89 WLOGI("Write HiSysEvent ret:%{public}d", ret);
90 return ret == 0;
91 }
92
count(int64_t costTime)93 void PerformReporter::count(int64_t costTime)
94 {
95 totalCount_++;
96 for (auto& iter: timeSplitCount_) {
97 if (costTime <= iter.first) {
98 iter.second++;
99 break;
100 }
101 }
102
103 std::ostringstream oss;
104 oss << tag_ << " cost " << costTime << "ms, total count " << totalCount_;
105 WLOGI("%{public}s", oss.str().c_str());
106 }
107
clear()108 void PerformReporter::clear()
109 {
110 totalCount_ = 0;
111 for (auto& iter: timeSplitCount_) {
112 iter.second = 0;
113 }
114 }
115
GetMsgString(const FullInfoMap & infoMap)116 std::string WindowInfoReporter::GetMsgString(const FullInfoMap& infoMap)
117 {
118 if (infoMap.empty()) {
119 return "";
120 }
121 std::ostringstream oss;
122 oss << "{";
123 for (auto& bundleInfos : infoMap) {
124 if (bundleInfos.second.empty()) {
125 continue;
126 }
127 oss << "{";
128 for (auto& packageInfo : bundleInfos.second) {
129 oss << "BUNDLE_NAME:" << bundleInfos.first << ",";
130 oss << "ABILITY_NAME:" << packageInfo.first << ",";
131 oss << "COUNT:" << packageInfo.second;
132 }
133 oss << "},";
134 }
135 oss << "};";
136 return oss.str();
137 }
138
GetMsgString(const BundleNameMap & infoMap)139 std::string WindowInfoReporter::GetMsgString(const BundleNameMap& infoMap)
140 {
141 if (infoMap.empty()) {
142 return "";
143 }
144 std::ostringstream oss;
145 oss << "{";
146 for (auto& bundleInfo : infoMap) {
147 oss << "{";
148 oss << "BUNDLE_NAME:" << bundleInfo.first << ",";
149 oss << "COUNT:" << bundleInfo.second;
150 oss << "},";
151 }
152 oss << "};";
153 return oss.str();
154 }
155
InsertCreateReportInfo(const std::string & bundleName)156 void WindowInfoReporter::InsertCreateReportInfo(const std::string& bundleName)
157 {
158 UpdateReportInfo(windowCreateReportInfos_, bundleName);
159 }
160
InsertShowReportInfo(const std::string & bundleName)161 void WindowInfoReporter::InsertShowReportInfo(const std::string& bundleName)
162 {
163 UpdateReportInfo(windowShowReportInfos_, bundleName);
164 }
165
InsertHideReportInfo(const std::string & bundleName)166 void WindowInfoReporter::InsertHideReportInfo(const std::string& bundleName)
167 {
168 UpdateReportInfo(windowHideReportInfos_, bundleName);
169 }
170
InsertDestroyReportInfo(const std::string & bundleName)171 void WindowInfoReporter::InsertDestroyReportInfo(const std::string& bundleName)
172 {
173 UpdateReportInfo(windowDestoryReportInfos_, bundleName);
174 }
175
InsertNavigationBarReportInfo(const std::string & bundleName,const std::string & packageName)176 void WindowInfoReporter::InsertNavigationBarReportInfo(const std::string& bundleName, const std::string& packageName)
177 {
178 UpdateReportInfo(windowNavigationBarReportInfos_, bundleName, packageName);
179 }
180
UpdateReportInfo(FullInfoMap & infoMap,const std::string & bundleName,const std::string & packageName)181 void WindowInfoReporter::UpdateReportInfo(FullInfoMap& infoMap,
182 const std::string& bundleName, const std::string& packageName)
183 {
184 if (bundleName.empty() || packageName.empty()) {
185 return;
186 }
187 std::lock_guard<std::mutex> lock(mtx_);
188 auto iter = infoMap.find(bundleName);
189 if (iter == infoMap.end()) {
190 std::map<std::string, uint32_t> infos;
191 infos.insert(std::make_pair(packageName, 1));
192 infoMap.insert(std::make_pair(bundleName, infos));
193 return;
194 }
195
196 auto countPairIter = iter->second.find(packageName);
197 if (countPairIter == iter->second.end()) {
198 iter->second.insert(std::make_pair(packageName, 1));
199 return;
200 }
201 infoMap[bundleName][packageName]++;
202 }
203
UpdateReportInfo(BundleNameMap & infoMap,const std::string & bundleName)204 void WindowInfoReporter::UpdateReportInfo(BundleNameMap& infoMap, const std::string& bundleName)
205 {
206 if (bundleName.empty()) {
207 return;
208 }
209 std::lock_guard<std::mutex> lock(mtx_);
210 auto iter = infoMap.find(bundleName);
211 if (iter == infoMap.end()) {
212 infoMap.insert(std::make_pair(bundleName, 1));
213 return;
214 }
215 infoMap[bundleName]++;
216 }
217
ReportBackButtonInfoImmediately()218 void WindowInfoReporter::ReportBackButtonInfoImmediately()
219 {
220 Report("WM_REPORT_BACK_KEYEVENT", "Click Back Button");
221 }
222
ReportZeroOpacityInfoImmediately(const std::string & bundleName,const std::string & packageName)223 void WindowInfoReporter::ReportZeroOpacityInfoImmediately(const std::string& bundleName, const std::string& packageName)
224 {
225 if (bundleName.empty()) {
226 return;
227 }
228 std::ostringstream oss;
229 oss << "{ PROCESS_NAME:" << bundleName.c_str() << ", PACKAGE_NAME:" << "" << packageName.c_str() << " }";
230 Report("WM_REPORT_WINDOW_OPACITY_ZERO", oss.str());
231 }
232
ReportRecordedInfos()233 void WindowInfoReporter::ReportRecordedInfos()
234 {
235 std::lock_guard<std::mutex> lock(mtx_);
236 WLOGFD("----Report HiSysEvent write all-----");
237 Report("WM_REPORT_WINDOW_CREATE", GetMsgString(windowCreateReportInfos_));
238 Report("WM_REPORT_WINDOW_SHOW", GetMsgString(windowShowReportInfos_));
239 Report("WM_REPORT_WINDOW_HIDE", GetMsgString(windowHideReportInfos_));
240 Report("WM_REPORT_WINDOW_DESTORY", GetMsgString(windowDestoryReportInfos_));
241 Report("WM_REPORT_HIDE_NAVIGATIONBAR", GetMsgString(windowNavigationBarReportInfos_));
242 ClearRecordedInfos();
243 }
244
Report(const std::string & reportTag,const std::string & msg)245 void WindowInfoReporter::Report(const std::string& reportTag, const std::string& msg)
246 {
247 if (msg.empty()) {
248 return;
249 }
250 WLOGFD("Report Tag : [%{public}s], Msg: %{public}s", reportTag.c_str(), msg.c_str());
251 int32_t ret = HiSysEventWrite(
252 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, reportTag,
253 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "MSG", msg);
254 if (ret != 0) {
255 WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
256 }
257 }
258
ClearRecordedInfos()259 void WindowInfoReporter::ClearRecordedInfos()
260 {
261 WLOGFD("Clear all hiSysEvent write information");
262 windowCreateReportInfos_.clear();
263 windowShowReportInfos_.clear();
264 windowHideReportInfos_.clear();
265 windowDestoryReportInfos_.clear();
266 windowNavigationBarReportInfos_.clear();
267 }
268 }
269 }