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 }