• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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