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