1 /*
2 * Copyright (c) 2025 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 #include "imf_hisysevent_reporter.h"
16
17 #include <algorithm>
18 #include <chrono>
19
20 #include "common_timer_errors.h"
21 #include "ipc_skeleton.h"
22 namespace OHOS {
23 namespace MiscServices {
24 using namespace std::chrono;
~ImfHiSysEventReporter()25 ImfHiSysEventReporter::~ImfHiSysEventReporter()
26 {
27 StopTimer();
28 }
29
ReportEvent(ImfEventType eventType,const HiSysOriginalInfo & info)30 void ImfHiSysEventReporter::ReportEvent(ImfEventType eventType, const HiSysOriginalInfo &info)
31 {
32 auto it = EVENT_MAPPING.find(eventType);
33 if (it == EVENT_MAPPING.end()) {
34 return;
35 }
36 StartTimer();
37 ReportFaultEvent(it->second.first, info);
38 RecordStatisticsEvent(it->second.second, info);
39 }
40
ReportFaultEvent(ImfFaultEvent event,const HiSysOriginalInfo & info)41 void ImfHiSysEventReporter::ReportFaultEvent(ImfFaultEvent event, const HiSysOriginalInfo &info)
42 {
43 auto it = FAULT_EVENT_HANDLERS.find(event);
44 if (it == FAULT_EVENT_HANDLERS.end() || it->second == nullptr) {
45 return;
46 }
47 auto faultReportInfo = GenerateFaultReportInfo(event, info);
48 if (!faultReportInfo.first) {
49 return;
50 }
51 it->second(GetSelfName(), faultReportInfo.second, info);
52 }
53
StartTimer()54 void ImfHiSysEventReporter::StartTimer()
55 {
56 std::lock_guard<std::mutex> lock(timerLock_);
57 if (timerId_ != 0) {
58 return;
59 }
60 uint32_t ret = timer_.Setup();
61 if (ret != Utils::TIMER_ERR_OK) {
62 IMSA_HILOGE("failed to create timer!");
63 return;
64 }
65 auto callback = [this]() { TimerCallback(); };
66 timerId_ = timer_.Register(callback, HISYSEVENT_TIMER_TASK_INTERNAL, false);
67 timerStartTime_ = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
68 }
69
TimerCallback()70 void ImfHiSysEventReporter::TimerCallback()
71 {
72 ReportStatisticsEvent();
73 ClearFaultEventInfo();
74 }
75
StopTimer()76 void ImfHiSysEventReporter::StopTimer()
77 {
78 timer_.Unregister(timerId_);
79 timer_.Shutdown();
80 }
81
GetStatisticalIntervalIndex()82 uint32_t ImfHiSysEventReporter::GetStatisticalIntervalIndex()
83 {
84 auto time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
85 auto index = (time - timerStartTime_) / HISYSEVENT_STATISTICS_INTERNAL;
86 if (index < 0) {
87 return 0;
88 }
89 if (index >= COUNT_STATISTICS_INTERVAL_NUM) {
90 return COUNT_STATISTICS_INTERVAL_NUM - 1;
91 }
92 return index;
93 }
94
ResetTimerStartTime(int64_t time)95 void ImfHiSysEventReporter::ResetTimerStartTime(int64_t time)
96 {
97 timerStartTime_ = time;
98 }
99
GenerateFaultReportInfo(ImfFaultEvent event,const HiSysOriginalInfo & info)100 std::pair<bool, int64_t> ImfHiSysEventReporter::GenerateFaultReportInfo(
101 ImfFaultEvent event, const HiSysOriginalInfo &info)
102 {
103 std::pair<bool, int64_t> faultReportInfo{ false, 0 };
104 if (info.errCode == ErrorCode::NO_ERROR || !IsValidErrCode(info.errCode) || !IsFault(info.errCode)) {
105 IMSA_HILOGD("%{public}d not err or fault.", info.errCode);
106 return faultReportInfo;
107 }
108 auto key = GenerateFaultEventKey(event, info);
109 std::lock_guard<std::mutex> lock(faultEventRecordsLock_);
110 auto curTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
111 auto it = faultEventRecords_.find(key);
112 if (it != faultEventRecords_.end()) {
113 if (curTime - it->second.first < FAULT_REPORT_INTERVAL) {
114 it->second.second++;
115 IMSA_HILOGD("%{public}s fault report within five minutes:%{public}d.", key.c_str(), it->second.second);
116 return faultReportInfo;
117 }
118 }
119 faultReportInfo.second = it != faultEventRecords_.end() ? it->second.second : 1;
120 faultReportInfo.first = true;
121 faultEventRecords_.insert_or_assign(key, std::make_pair(curTime, 1));
122 return faultReportInfo;
123 }
124
GenerateFaultEventKey(ImfFaultEvent event,const HiSysOriginalInfo & info)125 std::string ImfHiSysEventReporter::GenerateFaultEventKey(ImfFaultEvent event, const HiSysOriginalInfo &info)
126 {
127 std::string key(std::to_string(event));
128 key.append("/")
129 .append(std::to_string(info.peerUserId))
130 .append("/")
131 .append(info.peerName)
132 .append("/")
133 .append(std::to_string(info.eventCode))
134 .append("/")
135 .append(std::to_string(info.errCode));
136 return key;
137 }
138
ClearFaultEventInfo()139 void ImfHiSysEventReporter::ClearFaultEventInfo()
140 {
141 std::lock_guard<std::mutex> lock(faultEventRecordsLock_);
142 auto curTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
143 auto it = std::find_if(faultEventRecords_.begin(), faultEventRecords_.end(),
144 [&curTime](const std::pair<std::string, std::pair<int64_t, uint32_t>> &record) {
145 return curTime - record.second.first > FAULT_RETENTION_PERIOD;
146 });
147 if (it == faultEventRecords_.end()) {
148 return;
149 }
150 faultEventRecords_.erase(it);
151 }
152
GetSelfName()153 std::string ImfHiSysEventReporter::GetSelfName()
154 {
155 std::lock_guard<std::mutex> lock(selfNameLock_);
156 if (!selfName_.empty()) {
157 return selfName_;
158 }
159 selfName_ = ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetSelfTokenID());
160 return selfName_;
161 }
162 } // namespace MiscServices
163 } // namespace OHOS