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 "event_json_util.h"
22 #include "hiappevent_base.h"
23 #include "hiappevent_common.h"
24 #include "hilog/log.h"
25
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN 0xD002D07
28
29 #undef LOG_TAG
30 #define LOG_TAG "Observer"
31
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace HiAppEvent {
35 namespace {
36 constexpr int MAX_SIZE_ON_EVENTS = 100;
37 constexpr uint64_t BIT_MASK = 1;
38 const std::string DOMAIN_PROPERTY = "domain";
39 const std::string NAMES_PROPERTY = "names";
40 const std::string TYPES_PROPERTY = "types";
41 struct OsEventPosInfo {
42 std::string name;
43 EventType type;
44 uint8_t pos; // means position in binary
45 };
46 const std::vector<OsEventPosInfo> OS_EVENT_POS_INFOS = {
47 { EVENT_APP_CRASH, FAULT, 0 },
48 { EVENT_APP_FREEZE, FAULT, 1 },
49 { EVENT_APP_LAUNCH, BEHAVIOR, 2 },
50 { EVENT_SCROLL_JANK, FAULT, 3 },
51 { EVENT_CPU_USAGE_HIGH, FAULT, 4 },
52 { EVENT_BATTERY_USAGE, STATISTIC, 5 },
53 { EVENT_RESOURCE_OVERLIMIT, FAULT, 6 },
54 { EVENT_ADDRESS_SANITIZER, FAULT, 7 },
55 { EVENT_MAIN_THREAD_JANK, FAULT, 8 },
56 { EVENT_APP_START, BEHAVIOR, 9 },
57 { EVENT_APP_HICOLLIE, FAULT, 10 },
58 };
59
MeetNumberCondition(int currNum,int maxNum)60 bool MeetNumberCondition(int currNum, int maxNum)
61 {
62 return maxNum > 0 && currNum >= maxNum;
63 }
64
GetStr(const std::unordered_set<std::string> & strSet)65 std::string GetStr(const std::unordered_set<std::string>& strSet)
66 {
67 if (strSet.empty()) {
68 return "[]";
69 }
70 std::stringstream strStream("[");
71 for (const auto& str : strSet) {
72 strStream << str << ",";
73 }
74 strStream.seekp(-1, std::ios_base::end); // -1 for delete ','
75 strStream << "]";
76 return strStream.str();
77 }
78
GetStr(const std::vector<EventConfig> & eventConfigs)79 std::string GetStr(const std::vector<EventConfig>& eventConfigs)
80 {
81 if (eventConfigs.empty()) {
82 return "[]";
83 }
84 std::stringstream strStream("[");
85 for (const auto& eventConfig : eventConfigs) {
86 strStream << eventConfig.ToString() << ",";
87 }
88 strStream.seekp(-1, std::ios_base::end); // -1 for delete ','
89 strStream << "]";
90 return strStream.str();
91 }
92 }
93
AppEventFilter(const std::string & domain,const std::unordered_set<std::string> & names,uint32_t types)94 AppEventFilter::AppEventFilter(const std::string& domain, const std::unordered_set<std::string>& names,
95 uint32_t types) : domain(domain), names(names), types(types)
96 {}
97
AppEventFilter(const std::string & domain,uint32_t types)98 AppEventFilter::AppEventFilter(const std::string& domain, uint32_t types) : domain(domain), types(types)
99 {}
100
IsValidEvent(std::shared_ptr<AppEventPack> event) const101 bool AppEventFilter::IsValidEvent(std::shared_ptr<AppEventPack> event) const
102 {
103 return IsValidEvent(event->GetDomain(), event->GetName(), event->GetType());
104 }
105
IsValidEvent(const std::string & eventDomain,const std::string & eventName,int eventType) const106 bool AppEventFilter::IsValidEvent(const std::string& eventDomain, const std::string& eventName, int eventType) const
107 {
108 if (domain.empty()) {
109 return false;
110 }
111 if (!domain.empty() && domain != eventDomain) {
112 return false;
113 }
114 if (!names.empty() && (names.find(eventName) == names.end())) {
115 return false;
116 }
117 if (types != 0 && !(types & (1 << eventType))) { // 1: bit mask
118 return false;
119 }
120 return true;
121 }
122
GetOsEventsMask() const123 uint64_t AppEventFilter::GetOsEventsMask() const
124 {
125 uint64_t mask = 0;
126 for (const auto& event : OS_EVENT_POS_INFOS) {
127 if (IsValidEvent(DOMAIN_OS, event.name, event.type)) {
128 mask |= (BIT_MASK << event.pos);
129 }
130 }
131 return mask;
132 }
133
ToJsonValue() const134 Json::Value AppEventFilter::ToJsonValue() const
135 {
136 Json::Value filterJson;
137 filterJson[DOMAIN_PROPERTY] = domain;
138 Json::Value namesJson(Json::arrayValue);
139 for (const auto& name : names) {
140 namesJson.append(name);
141 }
142 filterJson[NAMES_PROPERTY] = namesJson;
143 filterJson[TYPES_PROPERTY] = types;
144 return filterJson;
145 }
146
IsValidEvent(std::shared_ptr<AppEventPack> event) const147 bool EventConfig::IsValidEvent(std::shared_ptr<AppEventPack> event) const
148 {
149 if (domain.empty() && name.empty()) {
150 return false;
151 }
152 if (!domain.empty() && (domain != event->GetDomain())) {
153 return false;
154 }
155 if (!name.empty() && (name != event->GetName())) {
156 return false;
157 }
158 return true;
159 }
160
IsRealTimeEvent(std::shared_ptr<AppEventPack> event) const161 bool EventConfig::IsRealTimeEvent(std::shared_ptr<AppEventPack> event) const
162 {
163 return IsValidEvent(event) && isRealTime;
164 }
165
ToString() const166 std::string EventConfig::ToString() const
167 {
168 std::stringstream strStream;
169 strStream << "{" << domain << "," << name << "," << isRealTime << "}";
170 return strStream.str();
171 }
172
ToString() const173 std::string TriggerCondition::ToString() const
174 {
175 std::stringstream strStream;
176 strStream << "{" << row << "," << size << "," << timeout << "," << onStartup << "," << onBackground << "}";
177 return strStream.str();
178 }
179
ToString() const180 std::string ReportConfig::ToString() const
181 {
182 std::stringstream strStream;
183 strStream << "{" << name << "," << debugMode << "," << routeInfo << "," << appId << "," << triggerCond.ToString()
184 << "," << GetStr(userIdNames) << "," << GetStr(userPropertyNames) << "," << GetStr(eventConfigs) << "}";
185 return strStream.str();
186 }
187
VerifyEvent(std::shared_ptr<AppEventPack> event)188 bool AppEventObserver::VerifyEvent(std::shared_ptr<AppEventPack> event)
189 {
190 if (filters_.empty()) {
191 return true;
192 }
193 auto it = std::find_if(filters_.begin(), filters_.end(), [event](const auto& filter) {
194 return filter.IsValidEvent(event);
195 });
196 return it != filters_.end();
197 }
198
IsRealTimeEvent(std::shared_ptr<AppEventPack> event)199 bool AppEventObserver::IsRealTimeEvent(std::shared_ptr<AppEventPack> event)
200 {
201 const auto& eventConfigs = reportConfig_.eventConfigs;
202 if (eventConfigs.empty()) {
203 return false;
204 }
205 auto it = std::find_if(eventConfigs.begin(), eventConfigs.end(), [event](const auto& config) {
206 return config.IsRealTimeEvent(event);
207 });
208 return it != eventConfigs.end();
209 }
210
ProcessEvent(std::shared_ptr<AppEventPack> event)211 void AppEventObserver::ProcessEvent(std::shared_ptr<AppEventPack> event)
212 {
213 HILOG_DEBUG(LOG_CORE, "observer=%{public}s start to process event", name_.c_str());
214 ++currCond_.row;
215 currCond_.size += static_cast<int>(event->GetEventStr().size());
216 if (MeetProcessCondition()) {
217 OnTrigger(currCond_);
218 ResetCurrCondition();
219 }
220 }
221
MeetProcessCondition()222 bool AppEventObserver::MeetProcessCondition()
223 {
224 return MeetNumberCondition(currCond_.row, reportConfig_.triggerCond.row)
225 || MeetNumberCondition(currCond_.size, reportConfig_.triggerCond.size);
226 }
227
ResetCurrCondition()228 void AppEventObserver::ResetCurrCondition()
229 {
230 currCond_.row = 0;
231 currCond_.size = 0;
232 currCond_.timeout = 0;
233 }
234
OnTrigger(const TriggerCondition & triggerCond)235 void AppEventObserver::OnTrigger(const TriggerCondition& triggerCond)
236 {
237 std::vector<std::shared_ptr<AppEventPack>> events;
238 QueryEventsFromDb(events);
239 if (!events.empty()) {
240 OnEvents(events);
241 }
242 }
243
QueryEventsFromDb(std::vector<std::shared_ptr<AppEventPack>> & events)244 void AppEventObserver::QueryEventsFromDb(std::vector<std::shared_ptr<AppEventPack>>& events)
245 {
246 if (AppEventStore::GetInstance().QueryEvents(events, seq_, MAX_SIZE_ON_EVENTS) != 0) {
247 HILOG_WARN(LOG_CORE, "failed to take data from observer=%{public}s, seq=%{public}" PRId64,
248 name_.c_str(), seq_);
249 return;
250 }
251 HILOG_INFO(LOG_CORE, "end to take data from observer=%{public}s, seq=%{public}" PRId64 ", size=%{public}zu",
252 name_.c_str(), seq_, events.size());
253 }
254
ProcessTimeout()255 void AppEventObserver::ProcessTimeout()
256 {
257 currCond_.timeout += TIMEOUT_STEP;
258 if (!MeetTimeoutCondition()) {
259 return;
260 }
261 OnTrigger(currCond_);
262 ResetCurrCondition();
263 }
264
MeetTimeoutCondition()265 bool AppEventObserver::MeetTimeoutCondition()
266 {
267 return MeetNumberCondition(currCond_.timeout, reportConfig_.triggerCond.timeout) && currCond_.row > 0;
268 }
269
HasTimeoutCondition()270 bool AppEventObserver::HasTimeoutCondition()
271 {
272 return reportConfig_.triggerCond.timeout > 0 && currCond_.row > 0;
273 }
274
ProcessStartup()275 void AppEventObserver::ProcessStartup()
276 {
277 if (!MeetStartupCondition()) {
278 return;
279 }
280 OnTrigger(currCond_);
281 ResetCurrCondition();
282 }
283
MeetStartupCondition()284 bool AppEventObserver::MeetStartupCondition()
285 {
286 return reportConfig_.triggerCond.onStartup && currCond_.row > 0;
287 }
288
ProcessBackground()289 void AppEventObserver::ProcessBackground()
290 {
291 if (!MeetBackgroundCondition()) {
292 return;
293 }
294 OnTrigger(currCond_);
295 ResetCurrCondition();
296 }
297
MeetBackgroundCondition()298 bool AppEventObserver::MeetBackgroundCondition()
299 {
300 return reportConfig_.triggerCond.onBackground && currCond_.row > 0;
301 }
302
GetName()303 std::string AppEventObserver::GetName()
304 {
305 return name_;
306 }
307
GetSeq()308 int64_t AppEventObserver::GetSeq()
309 {
310 return seq_;
311 }
312
GetReportConfig()313 ReportConfig AppEventObserver::GetReportConfig()
314 {
315 return reportConfig_;
316 }
317
SetSeq(int64_t seq)318 void AppEventObserver::SetSeq(int64_t seq)
319 {
320 seq_ = seq;
321 }
322
SetCurrCondition(const TriggerCondition & triggerCond)323 void AppEventObserver::SetCurrCondition(const TriggerCondition& triggerCond)
324 {
325 currCond_ = triggerCond;
326 }
327
SetReportConfig(const ReportConfig & reportConfig)328 void AppEventObserver::SetReportConfig(const ReportConfig& reportConfig)
329 {
330 reportConfig_ = reportConfig;
331
332 filters_.clear();
333 // if event configs is empty, do not report event
334 if (reportConfig.eventConfigs.empty()) {
335 filters_.emplace_back(AppEventFilter()); // invalid filter
336 return;
337 }
338
339 for (const auto& eventConfig : reportConfig.eventConfigs) {
340 if (eventConfig.domain.empty() && eventConfig.name.empty()) {
341 continue;
342 }
343 std::unordered_set<std::string> names;
344 if (!eventConfig.name.empty()) {
345 names.emplace(eventConfig.name);
346 }
347 filters_.emplace_back(AppEventFilter(eventConfig.domain, names));
348 }
349 }
350
GenerateHashCode()351 int64_t AppEventObserver::GenerateHashCode()
352 {
353 if (reportConfig_.name.empty()) {
354 // default hash code for watcher
355 return 0;
356 }
357 return (reportConfig_.configId > 0)
358 ? static_cast<int64_t>(reportConfig_.configId)
359 : static_cast<int64_t>(std::hash<std::string>{}(reportConfig_.ToString()));
360 }
361
GetOsEventsMask()362 uint64_t AppEventObserver::GetOsEventsMask()
363 {
364 uint64_t mask = 0;
365 std::for_each(filters_.begin(), filters_.end(), [&mask](const auto& filter) {
366 mask |= filter.GetOsEventsMask();
367 });
368 return mask;
369 }
370
GetFiltersStr()371 std::string AppEventObserver::GetFiltersStr()
372 {
373 if (!reportConfig_.name.empty()) {
374 // default hash code for processor
375 return "";
376 }
377 Json::Value filtersJson(Json::arrayValue);
378 std::for_each(filters_.begin(), filters_.end(), [&filtersJson](const auto& filter) {
379 filtersJson.append(filter.ToJsonValue());
380 });
381 return Json::FastWriter().write(filtersJson);
382 }
383
SetFilters(const std::string & jsonStr)384 void AppEventObserver::SetFilters(const std::string& jsonStr)
385 {
386 filters_.clear();
387 if (jsonStr.empty()) {
388 return;
389 }
390 Json::Value filtersJson;
391 Json::Reader reader(Json::Features::strictMode());
392 if (!reader.parse(jsonStr, filtersJson)) {
393 HILOG_ERROR(LOG_CORE, "parse filters failed, please check the style of json");
394 return;
395 }
396 if (!filtersJson.isArray() || filtersJson.empty()) {
397 HILOG_WARN(LOG_CORE, "filters is empty");
398 return;
399 }
400 for (Json::ArrayIndex i = 0; i < filtersJson.size(); ++i) {
401 if (filtersJson[i].isObject()) {
402 std::string domain = EventJsonUtil::ParseString(filtersJson[i], DOMAIN_PROPERTY);
403 std::unordered_set<std::string> names;
404 EventJsonUtil::ParseStrings(filtersJson[i], NAMES_PROPERTY, names);
405 uint32_t types = EventJsonUtil::ParseUInt32(filtersJson[i], TYPES_PROPERTY);
406 filters_.emplace_back(AppEventFilter(domain, names, types));
407 }
408 }
409 }
410 } // namespace HiAppEvent
411 } // namespace HiviewDFX
412 } // namespace OHOS
413