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