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