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 22namespace OHOS { 23namespace Rosen { 24namespace { 25constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "PerformReporter"}; 26} 27WM_IMPLEMENT_SINGLE_INSTANCE(WindowInfoReporter) 28 29constexpr char EVENT_KEY_BUNDLE_NAME[] = "BUNDLE_NAME"; 30constexpr char EVENT_KEY_WINDOW_NAME[] = "WINDOW_NAME"; 31constexpr char EVENT_KEY_MISSION_ID[] = "MISSION_ID"; 32constexpr 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 */ 41PerformReporter::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 56void PerformReporter::start() 57{ 58 startTime_ = std::chrono::steady_clock::now(); 59} 60 61void 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 74bool 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 98void 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 113void PerformReporter::clear() 114{ 115 totalCount_ = 0; 116 for (auto& iter: timeSplitCount_) { 117 iter.second = 0; 118 } 119} 120 121std::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 144std::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 161void WindowInfoReporter::InsertCreateReportInfo(const std::string& bundleName) 162{ 163 UpdateReportInfo(windowCreateReportInfos_, bundleName); 164} 165 166void WindowInfoReporter::InsertShowReportInfo(const std::string& bundleName) 167{ 168 UpdateReportInfo(windowShowReportInfos_, bundleName); 169} 170 171void WindowInfoReporter::InsertHideReportInfo(const std::string& bundleName) 172{ 173 UpdateReportInfo(windowHideReportInfos_, bundleName); 174} 175 176void WindowInfoReporter::InsertDestroyReportInfo(const std::string& bundleName) 177{ 178 UpdateReportInfo(windowDestoryReportInfos_, bundleName); 179} 180 181void WindowInfoReporter::InsertNavigationBarReportInfo(const std::string& bundleName, const std::string& packageName) 182{ 183 UpdateReportInfo(windowNavigationBarReportInfos_, bundleName, packageName); 184} 185 186void 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 209void 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 223void WindowInfoReporter::ReportBackButtonInfoImmediately() 224{ 225 Report("WM_REPORT_BACK_KEYEVENT", "Click Back Button"); 226} 227 228void 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 238void 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 251void 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 263void 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 277void 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 291void 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 301int32_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 317void 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}