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