• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #include "common_event_manager_service.h"
17 
18 #include "ability_manager_helper.h"
19 #include "access_token_helper.h"
20 #include "accesstoken_kit.h"
21 #include "bundle_manager_helper.h"
22 #include "common_event_constant.h"
23 #include "datetime_ex.h"
24 #include "event_log_wrapper.h"
25 #include "hitrace_meter_adapter.h"
26 #include "ipc_skeleton.h"
27 #include "parameters.h"
28 #include "publish_manager.h"
29 #include "system_ability_definition.h"
30 #include "xcollie/watchdog.h"
31 #include "ces_inner_error_code.h"
32 
33 namespace OHOS {
34 namespace EventFwk {
35 namespace {
36 const std::string NOTIFICATION_CES_CHECK_SA_PERMISSION = "notification.ces.check.sa.permission";
37 }  // namespace
38 
39 using namespace OHOS::Notification;
40 
CommonEventManagerService()41 CommonEventManagerService::CommonEventManagerService()
42     : serviceRunningState_(ServiceRunningState::STATE_NOT_START),
43       runner_(nullptr),
44       handler_(nullptr)
45 {
46     supportCheckSaPermission_ = OHOS::system::GetParameter(NOTIFICATION_CES_CHECK_SA_PERMISSION, "false");
47     EVENT_LOGD("instance created");
48 }
49 
~CommonEventManagerService()50 CommonEventManagerService::~CommonEventManagerService()
51 {
52     EVENT_LOGD("instance destroyed");
53 }
54 
Init()55 ErrCode CommonEventManagerService::Init()
56 {
57     EVENT_LOGD("ready to init");
58     innerCommonEventManager_ = std::make_shared<InnerCommonEventManager>();
59     if (!innerCommonEventManager_) {
60         EVENT_LOGE("Failed to init without inner service");
61         return ERR_INVALID_OPERATION;
62     }
63 
64     commonEventSrvQueue_ = std::make_shared<ffrt::queue>("CesSrvMain");
65     serviceRunningState_ = ServiceRunningState::STATE_RUNNING;
66 
67     return ERR_OK;
68 }
69 
IsReady() const70 bool CommonEventManagerService::IsReady() const
71 {
72     if (!innerCommonEventManager_) {
73         EVENT_LOGE("innerCommonEventManager is null");
74         return false;
75     }
76 
77     if (!commonEventSrvQueue_) {
78         EVENT_LOGE("queue object is null");
79         return false;
80     }
81 
82     return true;
83 }
84 
PublishCommonEvent(const CommonEventData & event,const CommonEventPublishInfo & publishinfo,const sptr<IRemoteObject> & commonEventListener,const int32_t & userId)85 int32_t CommonEventManagerService::PublishCommonEvent(const CommonEventData &event,
86     const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener,
87     const int32_t &userId)
88 {
89     EVENT_LOGD("enter");
90 
91     if (!IsReady()) {
92         EVENT_LOGE("CommonEventManagerService not ready");
93         return ERR_NOTIFICATION_CESM_ERROR;
94     }
95 
96     if (userId != ALL_USER && userId != CURRENT_USER && userId != UNDEFINED_USER) {
97         bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
98         if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
99             EVENT_LOGE("publish to special user must be system application.");
100             return ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP;
101         }
102     }
103 
104     return PublishCommonEventDetailed(event,
105         publishinfo,
106         commonEventListener,
107         IPCSkeleton::GetCallingPid(),
108         IPCSkeleton::GetCallingUid(),
109         IPCSkeleton::GetCallingTokenID(),
110         userId);
111 }
112 
PublishCommonEvent(const CommonEventData & event,const CommonEventPublishInfo & publishinfo,const sptr<IRemoteObject> & commonEventListener,const uid_t & uid,const int32_t & callerToken,const int32_t & userId)113 bool CommonEventManagerService::PublishCommonEvent(const CommonEventData &event,
114     const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener, const uid_t &uid,
115     const int32_t &callerToken, const int32_t &userId)
116 {
117     EVENT_LOGD("enter");
118 
119     if (!IsReady()) {
120         EVENT_LOGE("CommonEventManagerService not ready");
121         return false;
122     }
123 
124     if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
125         EVENT_LOGE("Only sa can publish common event as proxy.");
126         return false;
127     }
128 
129     return PublishCommonEventDetailed(
130         event, publishinfo, commonEventListener, UNDEFINED_PID, uid, callerToken, userId) == ERR_OK ? true : false;
131 }
132 
PublishCommonEventDetailed(const CommonEventData & event,const CommonEventPublishInfo & publishinfo,const sptr<IRemoteObject> & commonEventListener,const pid_t & pid,const uid_t & uid,const int32_t & clientToken,const int32_t & userId)133 int32_t CommonEventManagerService::PublishCommonEventDetailed(const CommonEventData &event,
134     const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener, const pid_t &pid,
135     const uid_t &uid, const int32_t &clientToken, const int32_t &userId)
136 {
137     HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
138 
139     EVENT_LOGD("clientToken = %{public}d", clientToken);
140     if (AccessTokenHelper::IsDlpHap(clientToken)) {
141         EVENT_LOGE("DLP hap not allowed to send common event");
142         return ERR_NOTIFICATION_CES_NOT_SA_SYSTEM_APP;
143     }
144     struct tm recordTime = {0};
145     if (!GetSystemCurrentTime(&recordTime)) {
146         EVENT_LOGE("Failed to GetSystemCurrentTime");
147         return ERR_NOTIFICATION_SYS_ERROR;
148     }
149 
150     if (DelayedSingleton<PublishManager>::GetInstance()->CheckIsFloodAttack(uid)) {
151         EVENT_LOGE("Too many common events have been sent in a short period from (pid = %{public}d, uid = "
152                    "%{public}d, userId = %{public}d)",
153             pid,
154             uid,
155             userId);
156         return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
157     }
158 
159     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
160     wptr<CommonEventManagerService> weakThis = this;
161     std::function<void()> publishCommonEventFunc = [wp,
162         event,
163         publishinfo,
164         commonEventListener,
165         recordTime,
166         pid,
167         uid,
168         clientToken,
169         userId,
170         weakThis] () {
171         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
172         if (innerCommonEventManager == nullptr) {
173             EVENT_LOGE("innerCommonEventManager not exist");
174             return;
175         }
176         std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(uid);
177         sptr<CommonEventManagerService> commonEventManagerService = weakThis.promote();
178         if (commonEventManagerService == nullptr) {
179             EVENT_LOGE("CommonEventManager not exist");
180             return;
181         }
182         bool ret = innerCommonEventManager->PublishCommonEvent(event,
183             publishinfo,
184             commonEventListener,
185             recordTime,
186             pid,
187             uid,
188             clientToken,
189             userId,
190             bundleName,
191             commonEventManagerService);
192         if (!ret) {
193             EVENT_LOGE("failed to publish event %{public}s", event.GetWant().GetAction().c_str());
194         }
195     };
196     EVENT_LOGD("start to submit publish commonEvent <%{public}d>", uid);
197     commonEventSrvQueue_->submit(publishCommonEventFunc);
198     return ERR_OK;
199 }
200 
SubscribeCommonEvent(const CommonEventSubscribeInfo & subscribeInfo,const sptr<IRemoteObject> & commonEventListener)201 int32_t CommonEventManagerService::SubscribeCommonEvent(
202     const CommonEventSubscribeInfo &subscribeInfo, const sptr<IRemoteObject> &commonEventListener)
203 {
204     HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
205     EVENT_LOGD("enter");
206 
207     if (!IsReady()) {
208         EVENT_LOGE("CommonEventManagerService not ready");
209         return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
210     }
211 
212     struct tm recordTime = {0};
213     if (!GetSystemCurrentTime(&recordTime)) {
214         EVENT_LOGE("Failed to GetSystemCurrentTime");
215         return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
216     }
217 
218     auto callingUid = IPCSkeleton::GetCallingUid();
219     auto callingPid = IPCSkeleton::GetCallingPid();
220     std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(callingUid);
221     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
222     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
223     std::function<void()> subscribeCommonEventFunc = [wp,
224         subscribeInfo,
225         commonEventListener,
226         recordTime,
227         callingPid,
228         callingUid,
229         callerToken,
230         bundleName] () {
231         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
232         if (innerCommonEventManager == nullptr) {
233             EVENT_LOGE("innerCommonEventManager not exist");
234             return;
235         }
236         bool ret = innerCommonEventManager->SubscribeCommonEvent(subscribeInfo,
237             commonEventListener,
238             recordTime,
239             callingPid,
240             callingUid,
241             callerToken,
242             bundleName);
243         if (!ret) {
244             EVENT_LOGE("failed to subscribe event");
245         }
246     };
247 
248     EVENT_LOGD("start to submit subscribe commonEvent <%{public}d>", callingUid);
249     commonEventSrvQueue_->submit(subscribeCommonEventFunc);
250     return ERR_OK;
251 }
252 
UnsubscribeCommonEvent(const sptr<IRemoteObject> & commonEventListener)253 int32_t CommonEventManagerService::UnsubscribeCommonEvent(const sptr<IRemoteObject> &commonEventListener)
254 {
255     HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
256     EVENT_LOGD("enter");
257 
258     if (!IsReady()) {
259         EVENT_LOGE("CommonEventManagerService not ready");
260         return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
261     }
262 
263     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
264     std::function<void()> unsubscribeCommonEventFunc = [wp, commonEventListener] () {
265         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
266         if (innerCommonEventManager == nullptr) {
267             EVENT_LOGE("innerCommonEventManager not exist");
268             return;
269         }
270         bool ret = innerCommonEventManager->UnsubscribeCommonEvent(commonEventListener);
271         if (!ret) {
272             EVENT_LOGE("failed to unsubscribe event");
273         }
274     };
275 
276     commonEventSrvQueue_->submit(unsubscribeCommonEventFunc);
277     return ERR_OK;
278 }
279 
GetStickyCommonEvent(const std::string & event,CommonEventData & eventData)280 bool CommonEventManagerService::GetStickyCommonEvent(const std::string &event, CommonEventData &eventData)
281 {
282     EVENT_LOGD("enter");
283 
284     if (!IsReady()) {
285         EVENT_LOGE("CommonEventManagerService not ready");
286         return false;
287     }
288 
289     if (event.empty()) {
290         EVENT_LOGE("event is empty");
291         return false;
292     }
293 
294     auto callingUid = IPCSkeleton::GetCallingUid();
295     std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(callingUid);
296     const std::string permission = "ohos.permission.COMMONEVENT_STICKY";
297     bool ret = AccessTokenHelper::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission);
298     if (!ret) {
299         EVENT_LOGE("No permission to get a sticky common event from %{public}s (uid = %{public}d)",
300             bundleName.c_str(),
301             callingUid);
302         return false;
303     }
304 
305     return innerCommonEventManager_->GetStickyCommonEvent(event, eventData);
306 }
307 
DumpState(const uint8_t & dumpType,const std::string & event,const int32_t & userId,std::vector<std::string> & state)308 bool CommonEventManagerService::DumpState(const uint8_t &dumpType, const std::string &event, const int32_t &userId,
309     std::vector<std::string> &state)
310 {
311     EVENT_LOGD("enter");
312 
313     auto callerToken = IPCSkeleton::GetCallingTokenID();
314     if (!AccessTokenHelper::VerifyShellToken(callerToken) && !AccessTokenHelper::VerifyNativeToken(callerToken)) {
315         EVENT_LOGE("Not subsystem or shell request");
316         return false;
317     }
318     if (!IsReady()) {
319         EVENT_LOGE("CommonEventManagerService not ready");
320         return false;
321     }
322 
323     innerCommonEventManager_->DumpState(dumpType, event, userId, state);
324 
325     return true;
326 }
327 
FinishReceiver(const sptr<IRemoteObject> & proxy,const int32_t & code,const std::string & receiverData,const bool & abortEvent)328 bool CommonEventManagerService::FinishReceiver(
329     const sptr<IRemoteObject> &proxy, const int32_t &code, const std::string &receiverData, const bool &abortEvent)
330 {
331     EVENT_LOGD("enter");
332 
333     if (!IsReady()) {
334         EVENT_LOGE("CommonEventManagerService not ready");
335         return false;
336     }
337     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
338     std::function<void()> finishReceiverFunc = [wp, proxy, code, receiverData, abortEvent] () {
339         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
340         if (innerCommonEventManager == nullptr) {
341             EVENT_LOGE("innerCommonEventManager not exist");
342             return;
343         }
344         innerCommonEventManager->FinishReceiver(proxy, code, receiverData, abortEvent);
345     };
346 
347     commonEventSrvQueue_->submit(finishReceiverFunc);
348     return true;
349 }
350 
Freeze(const uid_t & uid)351 bool CommonEventManagerService::Freeze(const uid_t &uid)
352 {
353     EVENT_LOGD("enter");
354 
355     if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
356         EVENT_LOGE("Not subsystem request");
357         return false;
358     }
359     if (!IsReady()) {
360         EVENT_LOGE("CommonEventManagerService not ready");
361         return false;
362     }
363     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
364     std::function<void()> freezeFunc = [wp, uid] () {
365         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
366         if (innerCommonEventManager == nullptr) {
367             EVENT_LOGE("innerCommonEventManager not exist");
368             return;
369         }
370         innerCommonEventManager->Freeze(uid);
371     };
372 
373     commonEventSrvQueue_->submit(freezeFunc);
374     return true;
375 }
376 
Unfreeze(const uid_t & uid)377 bool CommonEventManagerService::Unfreeze(const uid_t &uid)
378 {
379     EVENT_LOGD("enter");
380 
381     if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
382         EVENT_LOGE("Not subsystem request");
383         return false;
384     }
385     if (!IsReady()) {
386         EVENT_LOGE("CommonEventManagerService not ready");
387         return false;
388     }
389 
390     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
391     std::function<void()> unfreezeFunc = [wp, uid] () {
392         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
393         if (innerCommonEventManager == nullptr) {
394             EVENT_LOGE("innerCommonEventManager not exist");
395             return;
396         }
397         innerCommonEventManager->Unfreeze(uid);
398     };
399 
400     commonEventSrvQueue_->submit(unfreezeFunc);
401     return true;
402 }
403 
UnfreezeAll()404 bool CommonEventManagerService::UnfreezeAll()
405 {
406     EVENT_LOGD("enter");
407 
408     if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
409         EVENT_LOGE("Not subsystem request");
410         return false;
411     }
412     if (!IsReady()) {
413         EVENT_LOGE("CommonEventManagerService not ready");
414         return false;
415     }
416 
417     std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
418     std::function<void()> unfreezeAllFunc = [wp] () {
419         std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
420         if (innerCommonEventManager == nullptr) {
421             EVENT_LOGE("innerCommonEventManager not exist");
422             return;
423         }
424         innerCommonEventManager->UnfreezeAll();
425     };
426 
427     commonEventSrvQueue_->submit(unfreezeAllFunc);
428     return true;
429 }
430 
Dump(int fd,const std::vector<std::u16string> & args)431 int CommonEventManagerService::Dump(int fd, const std::vector<std::u16string> &args)
432 {
433     EVENT_LOGD("enter");
434 
435     auto callerToken = IPCSkeleton::GetCallingTokenID();
436     if (!AccessTokenHelper::VerifyShellToken(callerToken) && !AccessTokenHelper::VerifyNativeToken(callerToken)) {
437         EVENT_LOGE("Not subsystem or shell request");
438         return ERR_NOTIFICATION_CES_COMMON_PERMISSION_DENIED;
439     }
440     if (!IsReady()) {
441         EVENT_LOGE("CommonEventManagerService not ready");
442         return ERR_INVALID_VALUE;
443     }
444     std::string result;
445     innerCommonEventManager_->HiDump(args, result);
446     int ret = dprintf(fd, "%s\n", result.c_str());
447     if (ret < 0) {
448         EVENT_LOGE("dprintf error");
449         return ERR_INVALID_VALUE;
450     }
451     return ERR_OK;
452 }
453 
RemoveStickyCommonEvent(const std::string & event)454 int32_t CommonEventManagerService::RemoveStickyCommonEvent(const std::string &event)
455 {
456     EVENT_LOGI("enter");
457 
458     if (!IsReady()) {
459         EVENT_LOGE("CommonEventManagerService not ready");
460         return ERR_NOTIFICATION_CESM_ERROR;
461     }
462 
463     auto tokenId = IPCSkeleton::GetCallingTokenID();
464     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(tokenId);
465     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
466         EVENT_LOGE("Not system application or subsystem request.");
467         return ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP;
468     }
469 
470     const std::string permission = "ohos.permission.COMMONEVENT_STICKY";
471     bool ret = AccessTokenHelper::VerifyAccessToken(tokenId, permission);
472     if (!ret && (!isSubsystem || supportCheckSaPermission_.compare("true") == 0)) {
473         EVENT_LOGE("No permission.");
474         return ERR_NOTIFICATION_CES_COMMON_PERMISSION_DENIED;
475     }
476 
477     return innerCommonEventManager_->RemoveStickyCommonEvent(event, IPCSkeleton::GetCallingUid());
478 }
479 
SetStaticSubscriberState(bool enable)480 int32_t CommonEventManagerService::SetStaticSubscriberState(bool enable)
481 {
482     if (!AccessTokenHelper::IsSystemApp()) {
483         EVENT_LOGE("Not system application");
484         return ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP;
485     }
486 
487     return innerCommonEventManager_->SetStaticSubscriberState(enable);
488 }
489 }  // namespace EventFwk
490 }  // namespace OHOS
491