• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_store.h"
20 #include "hiappevent_base.h"
21 #include "hilog/log.h"
22 
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace HiAppEvent {
26 namespace {
27 const HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_AppEventObserver" };
28 
MeetNumberCondition(int currNum,int maxNum)29 bool MeetNumberCondition(int currNum, int maxNum)
30 {
31     return maxNum > 0 && currNum >= maxNum;
32 }
33 
GetStr(const std::unordered_set<std::string> & strSet)34 std::string GetStr(const std::unordered_set<std::string>& strSet)
35 {
36     if (strSet.empty()) {
37         return "[]";
38     }
39     std::stringstream strStream("[");
40     for (const auto& str : strSet) {
41         strStream << str << ",";
42     }
43     strStream.seekp(-1, std::ios_base::end); // -1 for delete ','
44     strStream << "]";
45     return strStream.str();
46 }
47 
GetStr(const std::vector<EventConfig> & eventConfigs)48 std::string GetStr(const std::vector<EventConfig>& eventConfigs)
49 {
50     if (eventConfigs.empty()) {
51         return "[]";
52     }
53     std::stringstream strStream("[");
54     for (const auto& eventConfig : eventConfigs) {
55         strStream << eventConfig.ToString() << ",";
56     }
57     strStream.seekp(-1, std::ios_base::end); // -1 for delete ','
58     strStream << "]";
59     return strStream.str();
60 }
61 }
62 
AppEventFilter(const std::string & domain,const std::unordered_set<std::string> & names,uint32_t types)63 AppEventFilter::AppEventFilter(const std::string& domain, const std::unordered_set<std::string>& names,
64     uint32_t types) : domain(domain), names(names), types(types)
65 {}
66 
AppEventFilter(const std::string & domain,uint32_t types)67 AppEventFilter::AppEventFilter(const std::string& domain, uint32_t types) : domain(domain), types(types)
68 {}
69 
IsValidEvent(std::shared_ptr<AppEventPack> event) const70 bool AppEventFilter::IsValidEvent(std::shared_ptr<AppEventPack> event) const
71 {
72     if (!domain.empty() && domain != event->GetDomain()) {
73         return false;
74     }
75     if (!names.empty() && (names.find(event->GetName()) == names.end())) {
76         return false;
77     }
78     if (types != 0 && !(types & (1 << event->GetType()))) { // 1: bit mask
79         return false;
80     }
81     return true;
82 }
83 
IsValidEvent(std::shared_ptr<AppEventPack> event) const84 bool EventConfig::IsValidEvent(std::shared_ptr<AppEventPack> event) const
85 {
86     if (domain.empty() && name.empty()) {
87         return false;
88     }
89     if (!domain.empty() && (domain != event->GetDomain())) {
90         return false;
91     }
92     if (!name.empty() && (name != event->GetName())) {
93         return false;
94     }
95     return true;
96 }
97 
IsRealTimeEvent(std::shared_ptr<AppEventPack> event) const98 bool EventConfig::IsRealTimeEvent(std::shared_ptr<AppEventPack> event) const
99 {
100     return IsValidEvent(event) && isRealTime;
101 }
102 
ToString() const103 std::string EventConfig::ToString() const
104 {
105     std::stringstream strStream;
106     strStream << "{" << domain << "," << name << "," << isRealTime << "}";
107     return strStream.str();
108 }
109 
ToString() const110 std::string TriggerCondition::ToString() const
111 {
112     std::stringstream strStream;
113     strStream << "{" << row << "," << size << "," << timeout << "," << onStartup << "," << onBackground << "}";
114     return strStream.str();
115 }
116 
ToString() const117 std::string ReportConfig::ToString() const
118 {
119     std::stringstream strStream;
120     strStream << "{" << name << "," << debugMode << "," << routeInfo << "," << appId << "," << triggerCond.ToString()
121         << "," << GetStr(userIdNames) << "," << GetStr(userPropertyNames) << "," << GetStr(eventConfigs) << "}";
122     return strStream.str();
123 }
124 
VerifyEvent(std::shared_ptr<AppEventPack> event)125 bool AppEventObserver::VerifyEvent(std::shared_ptr<AppEventPack> event)
126 {
127     if (filters_.empty()) {
128         return true;
129     }
130     auto it = std::find_if(filters_.begin(), filters_.end(), [event](const auto& filter) {
131         return filter.IsValidEvent(event);
132     });
133     return it != filters_.end();
134 }
135 
IsRealTimeEvent(std::shared_ptr<AppEventPack> event)136 bool AppEventObserver::IsRealTimeEvent(std::shared_ptr<AppEventPack> event)
137 {
138     const auto& eventConfigs = reportConfig_.eventConfigs;
139     if (eventConfigs.empty()) {
140         return false;
141     }
142     auto it = std::find_if(eventConfigs.begin(), eventConfigs.end(), [event](const auto& config) {
143         return config.IsRealTimeEvent(event);
144     });
145     return it != eventConfigs.end();
146 }
147 
ProcessEvent(std::shared_ptr<AppEventPack> event)148 void AppEventObserver::ProcessEvent(std::shared_ptr<AppEventPack> event)
149 {
150     HiLog::Debug(LABEL, "observer=%{public}s start to process event", name_.c_str());
151     ++currCond_.row;
152     currCond_.size += static_cast<int>(event->GetEventStr().size());
153     if (MeetProcessCondition()) {
154         OnTrigger(currCond_);
155         ResetCurrCondition();
156     }
157 }
158 
MeetProcessCondition()159 bool AppEventObserver::MeetProcessCondition()
160 {
161     return MeetNumberCondition(currCond_.row, reportConfig_.triggerCond.row)
162         || MeetNumberCondition(currCond_.size, reportConfig_.triggerCond.size);
163 }
164 
ResetCurrCondition()165 void AppEventObserver::ResetCurrCondition()
166 {
167     currCond_.row = 0;
168     currCond_.size = 0;
169     currCond_.timeout = 0;
170 }
171 
OnTrigger(const TriggerCondition & triggerCond)172 void AppEventObserver::OnTrigger(const TriggerCondition& triggerCond)
173 {
174     std::vector<std::shared_ptr<AppEventPack>> events;
175     QueryEventsFromDb(events);
176     if (!events.empty()) {
177         OnEvents(events);
178     }
179 }
180 
QueryEventsFromDb(std::vector<std::shared_ptr<AppEventPack>> & events)181 void AppEventObserver::QueryEventsFromDb(std::vector<std::shared_ptr<AppEventPack>>& events)
182 {
183     if (AppEventStore::GetInstance().TakeEvents(events, seq_) != 0) {
184         HiLog::Warn(LABEL, "failed to take data from observer=%{public}s, seq=%{public}" PRId64,
185             name_.c_str(), seq_);
186         return;
187     }
188     HiLog::Info(LABEL, "end to take data from observer=%{public}s, seq=%{public}" PRId64 ", size=%{public}zu",
189         name_.c_str(), seq_, events.size());
190 }
191 
ProcessTimeout()192 void AppEventObserver::ProcessTimeout()
193 {
194     ++currCond_.timeout;
195     if (!MeetTimeoutCondition()) {
196         return;
197     }
198     OnTrigger(currCond_);
199     ResetCurrCondition();
200 }
201 
MeetTimeoutCondition()202 bool AppEventObserver::MeetTimeoutCondition()
203 {
204     return MeetNumberCondition(currCond_.timeout, reportConfig_.triggerCond.timeout) && currCond_.row > 0;
205 }
206 
ProcessStartup()207 void AppEventObserver::ProcessStartup()
208 {
209     if (!MeetStartupCondition()) {
210         return;
211     }
212     OnTrigger(currCond_);
213     ResetCurrCondition();
214 }
215 
MeetStartupCondition()216 bool AppEventObserver::MeetStartupCondition()
217 {
218     return reportConfig_.triggerCond.onStartup && currCond_.row > 0;
219 }
220 
ProcessBackground()221 void AppEventObserver::ProcessBackground()
222 {
223     if (!MeetBackgroundCondition()) {
224         return;
225     }
226     OnTrigger(currCond_);
227     ResetCurrCondition();
228 }
229 
MeetBackgroundCondition()230 bool AppEventObserver::MeetBackgroundCondition()
231 {
232     return reportConfig_.triggerCond.onBackground && currCond_.row > 0;
233 }
234 
GetName()235 std::string AppEventObserver::GetName()
236 {
237     return name_;
238 }
239 
GetSeq()240 int64_t AppEventObserver::GetSeq()
241 {
242     return seq_;
243 }
244 
GetReportConfig()245 ReportConfig AppEventObserver::GetReportConfig()
246 {
247     return reportConfig_;
248 }
249 
SetSeq(int64_t seq)250 void AppEventObserver::SetSeq(int64_t seq)
251 {
252     seq_ = seq;
253 }
254 
SetCurrCondition(const TriggerCondition & triggerCond)255 void AppEventObserver::SetCurrCondition(const TriggerCondition& triggerCond)
256 {
257     currCond_ = triggerCond;
258 }
259 
SetReportConfig(const ReportConfig & reportConfig)260 void AppEventObserver::SetReportConfig(const ReportConfig& reportConfig)
261 {
262     reportConfig_ = reportConfig;
263 
264     filters_.clear();
265     // if event configs is empty, do not report event
266     if (reportConfig.eventConfigs.empty()) {
267         filters_.emplace_back(AppEventFilter()); // invalid filter
268         return;
269     }
270 
271     for (const auto& eventConfig : reportConfig.eventConfigs) {
272         if (eventConfig.domain.empty() && eventConfig.name.empty()) {
273             continue;
274         }
275         std::unordered_set<std::string> names;
276         if (!eventConfig.name.empty()) {
277             names.emplace(eventConfig.name);
278         }
279         filters_.emplace_back(AppEventFilter(eventConfig.domain, names));
280     }
281 }
282 
GenerateHashCode()283 int64_t AppEventObserver::GenerateHashCode()
284 {
285     return reportConfig_.name.empty()
286         ? 0 // default hash code for watcher
287         : static_cast<int64_t>(std::hash<std::string>{}(reportConfig_.ToString()));
288 }
289 
HasOsDomain()290 bool AppEventObserver::HasOsDomain()
291 {
292     if (filters_.empty()) {
293         return false;
294     }
295     for (const auto& filter : filters_) {
296         if (filter.domain == "OS") {
297             return true;
298         }
299     }
300     return false;
301 }
302 } // namespace HiAppEvent
303 } // namespace HiviewDFX
304 } // namespace OHOS
305