1 /*
2  * Copyright (c) 2021-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 
16 #include "sys_event_service_ohos.h"
17 
18 #include <codecvt>
19 #include <regex>
20 #include <set>
21 
22 #include "accesstoken_kit.h"
23 #include "data_publisher.h"
24 #include "event_query_wrapper_builder.h"
25 #include "if_system_ability_manager.h"
26 #include "ipc_skeleton.h"
27 #include "iservice_registry.h"
28 #include "hiview_logger.h"
29 #include "ret_code.h"
30 #include "running_status_log_util.h"
31 #include "string_ex.h"
32 #include "string_util.h"
33 #include "system_ability_definition.h"
34 #include "sys_event_sequence_mgr.h"
35 #include "time_util.h"
36 
37 using namespace std;
38 using namespace OHOS::HiviewDFX::EventStore;
39 
40 namespace OHOS {
41 namespace HiviewDFX {
42 DEFINE_LOG_TAG("HiView-SysEventService");
43 namespace {
44 constexpr pid_t HID_ROOT = 0;
45 constexpr pid_t HID_SHELL = 2000;
46 constexpr pid_t HID_OHOS = 1000;
47 const std::vector<int> EVENT_TYPES = {1, 2, 3, 4}; // FAULT = 1, STATISTIC = 2 SECURITY = 3, BEHAVIOR = 4
48 constexpr uint32_t INVALID_EVENT_TYPE = 0;
49 const string READ_DFX_SYSEVENT_PERMISSION = "ohos.permission.READ_DFX_SYSEVENT";
50 const string DFX_DUMP_PERMISSION = "ohos.permission.DUMP";
51 constexpr size_t REGEX_LEN_LIMIT = 32; // max(domainLen, nameLen, tagLen)
52 
IsMatchedWithRegex(const string & rule,const string & match)53 bool IsMatchedWithRegex(const string& rule, const string& match)
54 {
55     if (rule.empty()) {
56         return true;
57     }
58     if ((rule.length() > REGEX_LEN_LIMIT) || !StringUtil::IsValidRegex(rule)) {
59         return false;
60     }
61     smatch result;
62     const regex pattern(rule);
63     return regex_search(match, result, pattern);
64 }
65 
MatchContent(int type,const string & rule,const string & match)66 bool MatchContent(int type, const string& rule, const string& match)
67 {
68     if (match.empty()) {
69         return false;
70     }
71     switch (type) {
72         case RuleType::WHOLE_WORD:
73             return rule.empty() || match.compare(rule) == 0;
74         case RuleType::PREFIX:
75             return rule.empty() || match.find(rule) == 0;
76         case RuleType::REGULAR:
77             return IsMatchedWithRegex(rule, match);
78         default:
79             HIVIEW_LOGE("invalid rule type %{public}d.", type);
80             return false;
81     }
82 }
83 
MatchEventType(int rule,int match)84 bool MatchEventType(int rule, int match)
85 {
86     return rule == INVALID_EVENT_TYPE || rule == match;
87 }
88 
IsMatchedRule(const OHOS::HiviewDFX::SysEventRule & rule,const string & domain,const string & eventName,const string & tag,uint32_t eventType)89 bool IsMatchedRule(const OHOS::HiviewDFX::SysEventRule& rule, const string& domain,
90     const string& eventName, const string& tag, uint32_t eventType)
91 {
92     if (rule.tag.empty()) {
93         return MatchContent(rule.ruleType, rule.domain, domain)
94             && MatchContent(rule.ruleType, rule.eventName, eventName)
95             && MatchEventType(rule.eventType, eventType);
96     }
97     return MatchContent(rule.ruleType, rule.tag, tag)
98         && MatchEventType(rule.eventType, eventType);
99 }
100 
MatchRules(const SysEventRuleGroupOhos & rules,const string & domain,const string & eventName,const string & tag,uint32_t eventType)101 bool MatchRules(const SysEventRuleGroupOhos& rules, const string& domain, const string& eventName,
102     const string& tag, uint32_t eventType)
103 {
104     return any_of(rules.begin(), rules.end(), [domain, eventName, tag, eventType] (auto& rule) {
105         if (IsMatchedRule(rule, domain, eventName, tag, eventType)) {
106             HIVIEW_LOGD("rule type is %{public}d, domain is %{public}s, eventName is %{public}s, "
107                 "tag is %{public}s, eventType is %{public}u for matched",
108                 rule.ruleType, rule.domain.empty() ? "empty" : rule.domain.c_str(),
109                 rule.eventName.empty() ? "empty" : rule.eventName.c_str(),
110                 rule.tag.empty() ? "empty" : rule.tag.c_str(), eventType);
111             return true;
112         }
113         return false;
114     });
115 }
116 
CheckEventSubscriberAddingValidity(const std::vector<std::string> & events)117 int32_t CheckEventSubscriberAddingValidity(const std::vector<std::string>& events)
118 {
119     size_t maxEventNum = 30;  // count of total events is limited to 30.
120     if (events.size() > maxEventNum) {
121         OHOS::HiviewDFX::RunningStatusLogUtil::LogTooManyEvents(maxEventNum);
122         return ERR_TOO_MANY_EVENTS;
123     }
124     return IPC_CALL_SUCCEED;
125 }
126 
CheckEventQueryingValidity(const SysEventQueryRuleGroupOhos & rules,size_t limit)127 int32_t CheckEventQueryingValidity(const SysEventQueryRuleGroupOhos& rules, size_t limit)
128 {
129     if (rules.size() > limit) {
130         OHOS::HiviewDFX::RunningStatusLogUtil::LogTooManyQueryRules(rules);
131         return ERR_TOO_MANY_QUERY_RULES;
132     }
133     return IPC_CALL_SUCCEED;
134 }
135 }
136 
137 OHOS::HiviewDFX::NotifySysEvent SysEventServiceOhos::gISysEventNotify_;
138 sptr<OHOS::HiviewDFX::SysEventServiceOhos> SysEventServiceOhos::instance(new SysEventServiceOhos);
139 
GetInstance()140 sptr<OHOS::HiviewDFX::SysEventServiceOhos> SysEventServiceOhos::GetInstance()
141 {
142     return instance;
143 }
144 
StartService(SysEventServiceBase * service,const OHOS::HiviewDFX::NotifySysEvent notify)145 void SysEventServiceOhos::StartService(SysEventServiceBase *service,
146     const OHOS::HiviewDFX::NotifySysEvent notify)
147 {
148     gISysEventNotify_ = notify;
149     GetSysEventService(service);
150     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
151     if (samgr == nullptr) {
152         HIVIEW_LOGE("failed to find SystemAbilityManager.");
153         return;
154     }
155     if (instance == nullptr) {
156         HIVIEW_LOGE("SysEventServiceOhos service is null.");
157         return;
158     }
159     int ret = samgr->AddSystemAbility(DFX_SYS_EVENT_SERVICE_ABILITY_ID, instance);
160     if (ret != 0) {
161         HIVIEW_LOGE("failed to add sys event service ability.");
162     }
163 }
164 
GetTagByDomainAndName(const string & eventDomain,const string & eventName)165 string SysEventServiceOhos::GetTagByDomainAndName(const string& eventDomain, const string& eventName)
166 {
167     if (getTagFunc_ == nullptr) {
168         return "";
169     }
170     return getTagFunc_(eventDomain, eventName);
171 }
172 
GetTypeByDomainAndName(const string & eventDomain,const string & eventName)173 uint32_t SysEventServiceOhos::GetTypeByDomainAndName(const string& eventDomain, const string& eventName)
174 {
175     if (getTypeFunc_ == nullptr) {
176         return INVALID_EVENT_TYPE;
177     }
178     return getTypeFunc_(eventDomain, eventName);
179 }
180 
OnSysEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent> & event)181 void SysEventServiceOhos::OnSysEvent(std::shared_ptr<OHOS::HiviewDFX::SysEvent>& event)
182 {
183     {
184         lock_guard<mutex> lock(publisherMutex_);
185         dataPublisher_->OnSysEvent(event);
186     }
187     lock_guard<mutex> lock(listenersMutex_);
188     for (auto listener = registeredListeners_.begin(); listener != registeredListeners_.end(); ++listener) {
189         SysEventCallbackPtrOhos callback = iface_cast<ISysEventCallback>(listener->first);
190         if (callback == nullptr) {
191             HIVIEW_LOGE("interface is null, no need to match rules.");
192             continue;
193         }
194         bool isMatched = MatchRules(listener->second.second, event->domain_, event->eventName_,
195             event->GetTag(), event->eventType_);
196         HIVIEW_LOGD("pid %{public}d rules match %{public}s.", listener->second.first,
197             isMatched ? "success" : "fail");
198         if (isMatched) {
199             callback->Handle(Str8ToStr16(event->domain_), Str8ToStr16(event->eventName_),
200                 static_cast<uint32_t>(event->eventType_), Str8ToStr16(event->AsJsonStr()));
201         }
202     }
203 }
204 
OnRemoteDied(const wptr<IRemoteObject> & remote)205 void SysEventServiceOhos::OnRemoteDied(const wptr<IRemoteObject>& remote)
206 {
207     if (remote == nullptr) {
208         HIVIEW_LOGE("remote is null");
209         return;
210     }
211     auto remoteObject = remote.promote();
212     if (remoteObject == nullptr) {
213         HIVIEW_LOGE("object in remote is null.");
214         return;
215     }
216     if (debugModeCallback_ != nullptr) {
217         CallbackObjectOhos callbackObject = debugModeCallback_->AsObject();
218         if (callbackObject == remoteObject && isDebugMode_) {
219             HIVIEW_LOGE("quit debugmode.");
220             auto event = std::make_shared<Event>("SysEventSource");
221             event->messageType_ = Event::ENGINE_SYSEVENT_DEBUG_MODE;
222             event->SetValue("DEBUGMODE", "false");
223             gISysEventNotify_(event);
224             isDebugMode_ = false;
225         }
226     }
227     lock_guard<mutex> lock(listenersMutex_);
228     auto listener = registeredListeners_.find(remoteObject);
229     if (listener != registeredListeners_.end()) {
230         listener->first->RemoveDeathRecipient(deathRecipient_);
231         HIVIEW_LOGE("pid %{public}d has died and remove listener.", listener->second.first);
232         registeredListeners_.erase(listener);
233     }
234 }
235 
BindGetTagFunc(const GetTagByDomainNameFunc & getTagFunc)236 void SysEventServiceOhos::BindGetTagFunc(const GetTagByDomainNameFunc& getTagFunc)
237 {
238     getTagFunc_ = getTagFunc;
239 }
240 
BindGetTypeFunc(const GetTypeByDomainNameFunc & getTypeFunc)241 void SysEventServiceOhos::BindGetTypeFunc(const GetTypeByDomainNameFunc& getTypeFunc)
242 {
243     getTypeFunc_ = getTypeFunc;
244 }
245 
GetSysEventService(SysEventServiceBase * service)246 SysEventServiceBase* SysEventServiceOhos::GetSysEventService(SysEventServiceBase* service)
247 {
248     static SysEventServiceBase* ref = nullptr;
249     if (service != nullptr) {
250         ref = service;
251     }
252     return ref;
253 }
254 
AddListener(const std::vector<SysEventRule> & rules,const sptr<ISysEventCallback> & callback)255 int32_t SysEventServiceOhos::AddListener(const std::vector<SysEventRule>& rules,
256     const sptr<ISysEventCallback>& callback)
257 {
258     if (!HasAccessPermission()) {
259         return ERR_NO_PERMISSION;
260     }
261     size_t watchRuleCntLimit = 20; // count of listener rule for each watcher is limited to 20.
262     if (rules.size() > watchRuleCntLimit) {
263         OHOS::HiviewDFX::RunningStatusLogUtil::LogTooManyWatchRules(rules);
264         return ERR_TOO_MANY_WATCH_RULES;
265     }
266     lock_guard<mutex> lock(listenersMutex_);
267     size_t watcherTotalCntLimit = 30; // count of total watches is limited to 30.
268     if (registeredListeners_.size() >= watcherTotalCntLimit) {
269         OHOS::HiviewDFX::RunningStatusLogUtil::LogTooManyWatchers(watcherTotalCntLimit);
270         return ERR_TOO_MANY_WATCHERS;
271     }
272     auto service = GetSysEventService();
273     if (service == nullptr) {
274         HIVIEW_LOGE("subscribe fail, sys event service is null.");
275         return ERR_REMOTE_SERVICE_IS_NULL;
276     }
277     if (callback == nullptr) {
278         HIVIEW_LOGE("subscribe fail, callback is null.");
279         return ERR_LISTENER_NOT_EXIST;
280     }
281     CallbackObjectOhos callbackObject = callback->AsObject();
282     if (callbackObject == nullptr) {
283         HIVIEW_LOGE("subscribe fail, object in callback is null.");
284         return ERR_LISTENER_STATUS_INVALID;
285     }
286     int32_t uid = IPCSkeleton::GetCallingUid();
287     int32_t pid = IPCSkeleton::GetCallingPid();
288     pair<int32_t, SysEventRuleGroupOhos> rulesPair(pid, rules);
289     if (registeredListeners_.find(callbackObject) != registeredListeners_.end()) {
290         registeredListeners_[callbackObject] = rulesPair;
291         HIVIEW_LOGD("uid %{public}d pid %{public}d listener has been added and update rules.", uid, pid);
292         return IPC_CALL_SUCCEED;
293     }
294     if (!callbackObject->AddDeathRecipient(deathRecipient_)) {
295         HIVIEW_LOGE("subscribe fail, can not add death recipient.");
296         return ERR_ADD_DEATH_RECIPIENT;
297     }
298     registeredListeners_.insert(make_pair(callbackObject, rulesPair));
299     HIVIEW_LOGD("uid %{public}d pid %{public}d listener is added successfully, total is %{public}zu.",
300         uid, pid, registeredListeners_.size());
301     return IPC_CALL_SUCCEED;
302 }
303 
RemoveListener(const SysEventCallbackPtrOhos & callback)304 int32_t SysEventServiceOhos::RemoveListener(const SysEventCallbackPtrOhos& callback)
305 {
306     if (!HasAccessPermission()) {
307         return ERR_NO_PERMISSION;
308     }
309     auto service = GetSysEventService();
310     if (service == nullptr) {
311         HIVIEW_LOGE("sys event service is null.");
312         return ERR_REMOTE_SERVICE_IS_NULL;
313     }
314     if (callback == nullptr) {
315         HIVIEW_LOGE("callback is null.");
316         return ERR_LISTENER_NOT_EXIST;
317     }
318     CallbackObjectOhos callbackObject = callback->AsObject();
319     if (callbackObject == nullptr) {
320         HIVIEW_LOGE("object in callback is null.");
321         return ERR_LISTENER_STATUS_INVALID;
322     }
323     int32_t uid = IPCSkeleton::GetCallingUid();
324     int32_t pid = IPCSkeleton::GetCallingPid();
325     lock_guard<mutex> lock(listenersMutex_);
326     if (registeredListeners_.empty()) {
327         HIVIEW_LOGD("has no any listeners.");
328         return ERR_LISTENERS_EMPTY;
329     }
330     auto registeredListener = registeredListeners_.find(callbackObject);
331     if (registeredListener != registeredListeners_.end()) {
332         if (!callbackObject->RemoveDeathRecipient(deathRecipient_)) {
333             HIVIEW_LOGE("uid %{public}d pid %{public}d listener can not remove death recipient.", uid, pid);
334             return ERR_ADD_DEATH_RECIPIENT;
335         }
336         registeredListeners_.erase(registeredListener);
337         HIVIEW_LOGD("uid %{public}d pid %{public}d has found listener and removes it.", uid, pid);
338         return IPC_CALL_SUCCEED;
339     } else {
340         HIVIEW_LOGD("uid %{public}d pid %{public}d has not found listener.", uid, pid);
341         return ERR_LISTENER_NOT_EXIST;
342     }
343 }
344 
BuildEventQuery(std::shared_ptr<EventQueryWrapperBuilder> builder,const SysEventQueryRuleGroupOhos & rules)345 bool SysEventServiceOhos::BuildEventQuery(std::shared_ptr<EventQueryWrapperBuilder> builder,
346     const SysEventQueryRuleGroupOhos& rules)
347 {
348     if (builder == nullptr) {
349         return false;
350     }
351     auto callingUid = IPCSkeleton::GetCallingUid();
352     if (rules.empty() && (callingUid == HID_SHELL || callingUid == HID_ROOT ||
353         callingUid == HID_OHOS)) {
354         builder->Append("", "", 0, "");
355         return true;
356     }
357     return !any_of(rules.cbegin(), rules.cend(), [this, callingUid, &builder] (auto& rule) {
358         if (rule.domain.empty() && callingUid != HID_SHELL && callingUid != HID_ROOT &&
359             callingUid != HID_OHOS) {
360             return true;
361         }
362         return any_of(rule.eventList.cbegin(), rule.eventList.cend(),
363             [this, callingUid, &builder, &rule] (auto& eventName) {
364                 if (eventName.empty() && callingUid != HID_SHELL && callingUid != HID_ROOT &&
365                     callingUid != HID_OHOS) {
366                     return true;
367                 }
368                 auto eventType = this->GetTypeByDomainAndName(rule.domain, eventName);
369                 HIVIEW_LOGD("event type configured with domain[%{public}s] and name[%{public}s] "
370                     " is %{public}u, and event type in query rule is %{public}u.",
371                     rule.domain.c_str(), eventName.c_str(), eventType, rule.eventType);
372                 if ((!rule.domain.empty() && !eventName.empty() && eventType == INVALID_EVENT_TYPE) ||
373                     (eventType != INVALID_EVENT_TYPE && rule.eventType != INVALID_EVENT_TYPE &&
374                     eventType != rule.eventType)) {
375                     return false;
376                 }
377                 eventType = eventType == INVALID_EVENT_TYPE ? rule.eventType : eventType;
378                 builder->Append(rule.domain, eventName, eventType, rule.condition);
379                 return false;
380             });
381     });
382 }
383 
Query(const QueryArgument & queryArgument,const SysEventQueryRuleGroupOhos & rules,const OHOS::sptr<OHOS::HiviewDFX::IQuerySysEventCallback> & callback)384 int32_t SysEventServiceOhos::Query(const QueryArgument& queryArgument, const SysEventQueryRuleGroupOhos& rules,
385     const OHOS::sptr<OHOS::HiviewDFX::IQuerySysEventCallback>& callback)
386 {
387     if (callback == nullptr) {
388         return ERR_LISTENER_NOT_EXIST;
389     }
390     if (!HasAccessPermission()) {
391         callback->OnComplete(ERR_NO_PERMISSION, 0, EventStore::SysEventSequenceManager::GetInstance().GetSequence());
392         return ERR_NO_PERMISSION;
393     }
394     auto checkRet = CheckEventQueryingValidity(rules, 100); // count of query rule limits to 100 in query.
395     if (checkRet != IPC_CALL_SUCCEED) {
396         callback->OnComplete(checkRet, 0, EventStore::SysEventSequenceManager::GetInstance().GetSequence());
397         return checkRet;
398     }
399     auto queryWrapperBuilder = std::make_shared<EventQueryWrapperBuilder>(queryArgument);
400     auto buildRet = BuildEventQuery(queryWrapperBuilder, rules);
401     if (!buildRet || queryWrapperBuilder == nullptr || !queryWrapperBuilder->IsValid()) {
402         HIVIEW_LOGW("invalid query rule, exit sys event querying.");
403         callback->OnComplete(ERR_QUERY_RULE_INVALID, 0,
404             EventStore::SysEventSequenceManager::GetInstance().GetSequence());
405         return ERR_QUERY_RULE_INVALID;
406     }
407     if (queryArgument.maxEvents == 0) {
408         HIVIEW_LOGW("query count is 0, query complete directly.");
409         callback->OnComplete(IPC_CALL_SUCCEED, 0, EventStore::SysEventSequenceManager::GetInstance().GetSequence());
410         return IPC_CALL_SUCCEED;
411     }
412     auto queryWrapper = queryWrapperBuilder->Build();
413     if (queryWrapper == nullptr) {
414         HIVIEW_LOGW("query wrapper build failed.");
415         callback->OnComplete(ERR_QUERY_RULE_INVALID, 0,
416             EventStore::SysEventSequenceManager::GetInstance().GetSequence());
417         return ERR_QUERY_RULE_INVALID;
418     }
419     queryWrapper->SetMaxSequence(EventStore::SysEventSequenceManager::GetInstance().GetSequence());
420     auto queryRetCode = IPC_CALL_SUCCEED;
421     queryWrapper->Query(callback, queryRetCode);
422     return queryRetCode;
423 }
424 
HasAccessPermission() const425 bool SysEventServiceOhos::HasAccessPermission() const
426 {
427     using namespace Security::AccessToken;
428     auto tokenId = IPCSkeleton::GetFirstTokenID();
429     if (tokenId == 0) {
430         tokenId = IPCSkeleton::GetCallingTokenID();
431     }
432     if ((AccessTokenKit::VerifyAccessToken(tokenId, READ_DFX_SYSEVENT_PERMISSION) == RET_SUCCESS) ||
433         (AccessTokenKit::VerifyAccessToken(tokenId, DFX_DUMP_PERMISSION) == RET_SUCCESS)) {
434         return true;
435     }
436     return false;
437 }
438 
SetDebugMode(const SysEventCallbackPtrOhos & callback,bool mode)439 int32_t SysEventServiceOhos::SetDebugMode(const SysEventCallbackPtrOhos& callback, bool mode)
440 {
441     if (!HasAccessPermission()) {
442         return ERR_NO_PERMISSION;
443     }
444     if (mode == isDebugMode_) {
445         HIVIEW_LOGE("same config, no need set");
446         return ERR_DEBUG_MODE_SET_REPEAT;
447     }
448     auto event = std::make_shared<Event>("SysEventSource");
449     event->messageType_ = Event::ENGINE_SYSEVENT_DEBUG_MODE;
450     event->SetValue("DEBUGMODE", mode ? "true" : "false");
451     gISysEventNotify_(event);
452 
453     HIVIEW_LOGD("set debug mode %{public}s", mode ? "true" : "false");
454     debugModeCallback_ = callback;
455     isDebugMode_ = mode;
456     return IPC_CALL_SUCCEED;
457 }
458 
Dump(int32_t fd,const std::vector<std::u16string> & args)459 int SysEventServiceOhos::Dump(int32_t fd, const std::vector<std::u16string> &args)
460 {
461     if (fd < 0) {
462         HIVIEW_LOGE("invalid fd.");
463         return -1;
464     }
465     dprintf(fd, "%s\n", "Hiview SysEventService");
466     return 0;
467 }
468 
OnRemoteDied(const wptr<IRemoteObject> & remote)469 void CallbackDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
470 {
471     auto service = SysEventServiceOhos::GetInstance();
472     if (service == nullptr) {
473         HIVIEW_LOGE("SysEventServiceOhos service is null.");
474         return;
475     }
476     service->OnRemoteDied(remote);
477 }
478 
AddSubscriber(const SysEventQueryRuleGroupOhos & rules)479 int64_t SysEventServiceOhos::AddSubscriber(const SysEventQueryRuleGroupOhos &rules)
480 {
481     if (!HasAccessPermission()) {
482         return ERR_NO_PERMISSION;
483     }
484     std::vector<std::string> events;
485     MergeEventList(rules, events);
486     auto checkRet = CheckEventSubscriberAddingValidity(events);
487     if (checkRet != IPC_CALL_SUCCEED) {
488         return checkRet;
489     }
490     int32_t uid = IPCSkeleton::GetCallingUid();
491     lock_guard<mutex> lock(publisherMutex_);
492     auto ret = dataPublisher_->AddSubscriber(uid, events);
493     if (ret != IPC_CALL_SUCCEED) {
494         return ret;
495     }
496     return TimeUtil::GetMilliseconds();
497 }
498 
MergeEventList(const std::vector<SysEventQueryRule> & rules,std::vector<std::string> & events) const499 void SysEventServiceOhos::MergeEventList(const std::vector<SysEventQueryRule>& rules,
500     std::vector<std::string>& events) const
501 {
502     for_each(rules.cbegin(), rules.cend(), [&](const SysEventQueryRule &rule) {
503         auto eventList = rule.eventList;
504         for_each(eventList.cbegin(), eventList.cend(), [&](const std::string &event) {
505             events.push_back(event);
506         });
507     });
508 }
509 
RemoveSubscriber()510 int32_t SysEventServiceOhos::RemoveSubscriber()
511 {
512     if (!HasAccessPermission()) {
513         return ERR_NO_PERMISSION;
514     }
515     int32_t uid = IPCSkeleton::GetCallingUid();
516     lock_guard<mutex> lock(publisherMutex_);
517     auto ret = dataPublisher_->RemoveSubscriber(uid);
518     if (ret != IPC_CALL_SUCCEED) {
519         return ret;
520     }
521     return IPC_CALL_SUCCEED;
522 }
523 
Export(const QueryArgument & queryArgument,const SysEventQueryRuleGroupOhos & rules)524 int64_t SysEventServiceOhos::Export(const QueryArgument &queryArgument, const SysEventQueryRuleGroupOhos &rules)
525 {
526     if (!HasAccessPermission()) {
527         return ERR_NO_PERMISSION;
528     }
529     auto checkRet = CheckEventQueryingValidity(rules, 10); // count of query rule limits to 10 in export.
530     if (checkRet != IPC_CALL_SUCCEED) {
531         return checkRet;
532     }
533     int32_t uid = IPCSkeleton::GetCallingUid();
534     lock_guard<mutex> lock(publisherMutex_);
535     auto lastTimeStamp = dataPublisher_->GetTimeStampByUid(uid);
536     int64_t currentTime = static_cast<int64_t>(TimeUtil::GetMilliseconds());
537     if (std::abs(currentTime - lastTimeStamp) < TimeUtil::SECONDS_PER_HOUR * TimeUtil::SEC_TO_MILLISEC) {
538         HIVIEW_LOGD("forbid export, time frequency limit < 1 h.");
539         return ERR_EXPORT_FREQUENCY_OVER_LIMIT;
540     }
541 
542     auto queryWrapperBuilder = std::make_shared<EventQueryWrapperBuilder>(queryArgument);
543     auto buildRet = BuildEventQuery(queryWrapperBuilder, rules);
544     if (!buildRet || queryWrapperBuilder == nullptr || !queryWrapperBuilder->IsValid()) {
545         HIVIEW_LOGW("invalid query rule, exit sys event exporting.");
546         return ERR_QUERY_RULE_INVALID;
547     }
548     if (queryArgument.maxEvents == 0) {
549         HIVIEW_LOGW("export count is 0, export complete directly.");
550         return currentTime;
551     }
552     auto queryWrapper = queryWrapperBuilder->Build();
553     if (queryWrapper == nullptr) {
554         HIVIEW_LOGW("export wrapper build failed.");
555         return ERR_QUERY_RULE_INVALID;
556     }
557     queryWrapper->SetMaxSequence(EventStore::SysEventSequenceManager::GetInstance().GetSequence());
558     dataPublisher_->AddExportTask(queryWrapper, currentTime, uid);
559     return currentTime;
560 }
561 
SetWorkLoop(std::shared_ptr<EventLoop> looper)562 void SysEventServiceOhos::SetWorkLoop(std::shared_ptr<EventLoop> looper)
563 {
564     if (looper == nullptr) {
565         HIVIEW_LOGW("SetWorkLoop failed, looper is null.");
566         return;
567     }
568     dataPublisher_->SetWorkLoop(looper);
569 }
570 }  // namespace HiviewDFX
571 }  // namespace OHOS