1 /*
2 * Copyright (c) 2023-2024 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 "app_event_observer.h"
16
17 #include <sstream>
18
19 #include "app_event.h"
20 #include "app_event_store.h"
21 #include "hiappevent_base.h"
22 #include "hiappevent_common.h"
23 #include "hilog/log.h"
24
25 #undef LOG_DOMAIN
26 #define LOG_DOMAIN 0xD002D07
27
28 #undef LOG_TAG
29 #define LOG_TAG "Observer"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace HiAppEvent {
34 namespace {
35 constexpr int MAX_SIZE_ON_EVENTS = 100;
36 constexpr uint64_t BIT_MASK = 1;
37 struct OsEventPosInfo {
38 std::string name;
39 EventType type;
40 uint8_t pos; // means position in binary
41 };
42 const std::vector<OsEventPosInfo> OS_EVENT_POS_INFOS = {
43 { EVENT_APP_CRASH, FAULT, 0 },
44 { EVENT_APP_FREEZE, FAULT, 1 },
45 { EVENT_APP_LAUNCH, BEHAVIOR, 2 },
46 { EVENT_SCROLL_JANK, FAULT, 3 },
47 { EVENT_CPU_USAGE_HIGH, FAULT, 4 },
48 { EVENT_BATTERY_USAGE, STATISTIC, 5 },
49 { EVENT_RESOURCE_OVERLIMIT, FAULT, 6 },
50 { EVENT_ADDRESS_SANITIZER, FAULT, 7 },
51 { EVENT_MAIN_THREAD_JANK, FAULT, 8 },
52 { EVENT_APP_START, BEHAVIOR, 9 },
53 };
54
MeetNumberCondition(int currNum,int maxNum)55 bool MeetNumberCondition(int currNum, int maxNum)
56 {
57 return maxNum > 0 && currNum >= maxNum;
58 }
59
GetStr(const std::unordered_set<std::string> & strSet)60 std::string GetStr(const std::unordered_set<std::string>& strSet)
61 {
62 if (strSet.empty()) {
63 return "[]";
64 }
65 std::stringstream strStream("[");
66 for (const auto& str : strSet) {
67 strStream << str << ",";
68 }
69 strStream.seekp(-1, std::ios_base::end); // -1 for delete ','
70 strStream << "]";
71 return strStream.str();
72 }
73
GetStr(const std::vector<EventConfig> & eventConfigs)74 std::string GetStr(const std::vector<EventConfig>& eventConfigs)
75 {
76 if (eventConfigs.empty()) {
77 return "[]";
78 }
79 std::stringstream strStream("[");
80 for (const auto& eventConfig : eventConfigs) {
81 strStream << eventConfig.ToString() << ",";
82 }
83 strStream.seekp(-1, std::ios_base::end); // -1 for delete ','
84 strStream << "]";
85 return strStream.str();
86 }
87 }
88
AppEventFilter(const std::string & domain,const std::unordered_set<std::string> & names,uint32_t types)89 AppEventFilter::AppEventFilter(const std::string& domain, const std::unordered_set<std::string>& names,
90 uint32_t types) : domain(domain), names(names), types(types)
91 {}
92
AppEventFilter(const std::string & domain,uint32_t types)93 AppEventFilter::AppEventFilter(const std::string& domain, uint32_t types) : domain(domain), types(types)
94 {}
95
IsValidEvent(std::shared_ptr<AppEventPack> event) const96 bool AppEventFilter::IsValidEvent(std::shared_ptr<AppEventPack> event) const
97 {
98 return IsValidEvent(event->GetDomain(), event->GetName(), event->GetType());
99 }
100
IsValidEvent(const std::string & eventDomain,const std::string & eventName,int eventType) const101 bool AppEventFilter::IsValidEvent(const std::string& eventDomain, const std::string& eventName, int eventType) const
102 {
103 if (domain.empty()) {
104 return false;
105 }
106 if (!domain.empty() && domain != eventDomain) {
107 return false;
108 }
109 if (!names.empty() && (names.find(eventName) == names.end())) {
110 return false;
111 }
112 if (types != 0 && !(types & (1 << eventType))) { // 1: bit mask
113 return false;
114 }
115 return true;
116 }
117
GetOsEventsMask() const118 uint64_t AppEventFilter::GetOsEventsMask() const
119 {
120 uint64_t mask = 0;
121 for (const auto& event : OS_EVENT_POS_INFOS) {
122 if (IsValidEvent(DOMAIN_OS, event.name, event.type)) {
123 mask |= (BIT_MASK << event.pos);
124 }
125 }
126 return mask;
127 }
128
IsValidEvent(std::shared_ptr<AppEventPack> event) const129 bool EventConfig::IsValidEvent(std::shared_ptr<AppEventPack> event) const
130 {
131 if (domain.empty() && name.empty()) {
132 return false;
133 }
134 if (!domain.empty() && (domain != event->GetDomain())) {
135 return false;
136 }
137 if (!name.empty() && (name != event->GetName())) {
138 return false;
139 }
140 return true;
141 }
142
IsRealTimeEvent(std::shared_ptr<AppEventPack> event) const143 bool EventConfig::IsRealTimeEvent(std::shared_ptr<AppEventPack> event) const
144 {
145 return IsValidEvent(event) && isRealTime;
146 }
147
ToString() const148 std::string EventConfig::ToString() const
149 {
150 std::stringstream strStream;
151 strStream << "{" << domain << "," << name << "," << isRealTime << "}";
152 return strStream.str();
153 }
154
ToString() const155 std::string TriggerCondition::ToString() const
156 {
157 std::stringstream strStream;
158 strStream << "{" << row << "," << size << "," << timeout << "," << onStartup << "," << onBackground << "}";
159 return strStream.str();
160 }
161
ToString() const162 std::string ReportConfig::ToString() const
163 {
164 std::stringstream strStream;
165 strStream << "{" << name << "," << debugMode << "," << routeInfo << "," << appId << "," << triggerCond.ToString()
166 << "," << GetStr(userIdNames) << "," << GetStr(userPropertyNames) << "," << GetStr(eventConfigs) << "}";
167 return strStream.str();
168 }
169
VerifyEvent(std::shared_ptr<AppEventPack> event)170 bool AppEventObserver::VerifyEvent(std::shared_ptr<AppEventPack> event)
171 {
172 if (filters_.empty()) {
173 return true;
174 }
175 auto it = std::find_if(filters_.begin(), filters_.end(), [event](const auto& filter) {
176 return filter.IsValidEvent(event);
177 });
178 return it != filters_.end();
179 }
180
IsRealTimeEvent(std::shared_ptr<AppEventPack> event)181 bool AppEventObserver::IsRealTimeEvent(std::shared_ptr<AppEventPack> event)
182 {
183 const auto& eventConfigs = reportConfig_.eventConfigs;
184 if (eventConfigs.empty()) {
185 return false;
186 }
187 auto it = std::find_if(eventConfigs.begin(), eventConfigs.end(), [event](const auto& config) {
188 return config.IsRealTimeEvent(event);
189 });
190 return it != eventConfigs.end();
191 }
192
ProcessEvent(std::shared_ptr<AppEventPack> event)193 void AppEventObserver::ProcessEvent(std::shared_ptr<AppEventPack> event)
194 {
195 HILOG_DEBUG(LOG_CORE, "observer=%{public}s start to process event", name_.c_str());
196 ++currCond_.row;
197 currCond_.size += static_cast<int>(event->GetEventStr().size());
198 if (MeetProcessCondition()) {
199 OnTrigger(currCond_);
200 ResetCurrCondition();
201 }
202 }
203
MeetProcessCondition()204 bool AppEventObserver::MeetProcessCondition()
205 {
206 return MeetNumberCondition(currCond_.row, reportConfig_.triggerCond.row)
207 || MeetNumberCondition(currCond_.size, reportConfig_.triggerCond.size);
208 }
209
ResetCurrCondition()210 void AppEventObserver::ResetCurrCondition()
211 {
212 currCond_.row = 0;
213 currCond_.size = 0;
214 currCond_.timeout = 0;
215 }
216
OnTrigger(const TriggerCondition & triggerCond)217 void AppEventObserver::OnTrigger(const TriggerCondition& triggerCond)
218 {
219 std::vector<std::shared_ptr<AppEventPack>> events;
220 QueryEventsFromDb(events);
221 if (!events.empty()) {
222 OnEvents(events);
223 }
224 }
225
QueryEventsFromDb(std::vector<std::shared_ptr<AppEventPack>> & events)226 void AppEventObserver::QueryEventsFromDb(std::vector<std::shared_ptr<AppEventPack>>& events)
227 {
228 if (AppEventStore::GetInstance().QueryEvents(events, seq_, MAX_SIZE_ON_EVENTS) != 0) {
229 HILOG_WARN(LOG_CORE, "failed to take data from observer=%{public}s, seq=%{public}" PRId64,
230 name_.c_str(), seq_);
231 return;
232 }
233 HILOG_INFO(LOG_CORE, "end to take data from observer=%{public}s, seq=%{public}" PRId64 ", size=%{public}zu",
234 name_.c_str(), seq_, events.size());
235 }
236
ProcessTimeout()237 void AppEventObserver::ProcessTimeout()
238 {
239 currCond_.timeout += TIMEOUT_STEP;
240 if (!MeetTimeoutCondition()) {
241 return;
242 }
243 OnTrigger(currCond_);
244 ResetCurrCondition();
245 }
246
MeetTimeoutCondition()247 bool AppEventObserver::MeetTimeoutCondition()
248 {
249 return MeetNumberCondition(currCond_.timeout, reportConfig_.triggerCond.timeout) && currCond_.row > 0;
250 }
251
HasTimeoutCondition()252 bool AppEventObserver::HasTimeoutCondition()
253 {
254 return reportConfig_.triggerCond.timeout > 0 && currCond_.row > 0;
255 }
256
ProcessStartup()257 void AppEventObserver::ProcessStartup()
258 {
259 if (!MeetStartupCondition()) {
260 return;
261 }
262 OnTrigger(currCond_);
263 ResetCurrCondition();
264 }
265
MeetStartupCondition()266 bool AppEventObserver::MeetStartupCondition()
267 {
268 return reportConfig_.triggerCond.onStartup && currCond_.row > 0;
269 }
270
ProcessBackground()271 void AppEventObserver::ProcessBackground()
272 {
273 if (!MeetBackgroundCondition()) {
274 return;
275 }
276 OnTrigger(currCond_);
277 ResetCurrCondition();
278 }
279
MeetBackgroundCondition()280 bool AppEventObserver::MeetBackgroundCondition()
281 {
282 return reportConfig_.triggerCond.onBackground && currCond_.row > 0;
283 }
284
GetName()285 std::string AppEventObserver::GetName()
286 {
287 return name_;
288 }
289
GetSeq()290 int64_t AppEventObserver::GetSeq()
291 {
292 return seq_;
293 }
294
GetReportConfig()295 ReportConfig AppEventObserver::GetReportConfig()
296 {
297 return reportConfig_;
298 }
299
SetSeq(int64_t seq)300 void AppEventObserver::SetSeq(int64_t seq)
301 {
302 seq_ = seq;
303 }
304
SetCurrCondition(const TriggerCondition & triggerCond)305 void AppEventObserver::SetCurrCondition(const TriggerCondition& triggerCond)
306 {
307 currCond_ = triggerCond;
308 }
309
SetReportConfig(const ReportConfig & reportConfig)310 void AppEventObserver::SetReportConfig(const ReportConfig& reportConfig)
311 {
312 reportConfig_ = reportConfig;
313
314 filters_.clear();
315 // if event configs is empty, do not report event
316 if (reportConfig.eventConfigs.empty()) {
317 filters_.emplace_back(AppEventFilter()); // invalid filter
318 return;
319 }
320
321 for (const auto& eventConfig : reportConfig.eventConfigs) {
322 if (eventConfig.domain.empty() && eventConfig.name.empty()) {
323 continue;
324 }
325 std::unordered_set<std::string> names;
326 if (!eventConfig.name.empty()) {
327 names.emplace(eventConfig.name);
328 }
329 filters_.emplace_back(AppEventFilter(eventConfig.domain, names));
330 }
331 }
332
GenerateHashCode()333 int64_t AppEventObserver::GenerateHashCode()
334 {
335 if (reportConfig_.name.empty()) {
336 // default hash code for watcher
337 return 0;
338 }
339 return (reportConfig_.configId > 0)
340 ? static_cast<int64_t>(reportConfig_.configId)
341 : static_cast<int64_t>(std::hash<std::string>{}(reportConfig_.ToString()));
342 }
343
GetOsEventsMask()344 uint64_t AppEventObserver::GetOsEventsMask()
345 {
346 uint64_t mask = 0;
347 std::for_each(filters_.begin(), filters_.end(), [&mask](const auto& filter) {
348 mask |= filter.GetOsEventsMask();
349 });
350 return mask;
351 }
352 } // namespace HiAppEvent
353 } // namespace HiviewDFX
354 } // namespace OHOS
355