1 /*
2 * Copyright (c) 2021-2025 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 "advanced_notification_service.h"
17
18 #include <functional>
19 #include <iomanip>
20 #include <sstream>
21
22 #include "accesstoken_kit.h"
23 #include "ans_const_define.h"
24 #include "ans_inner_errors.h"
25 #include "ans_log_wrapper.h"
26 #include "ans_trace_wrapper.h"
27 #include "errors.h"
28
29 #include "ipc_skeleton.h"
30 #include "notification_constant.h"
31 #include "os_account_manager_helper.h"
32 #ifdef DISTRIBUTED_NOTIFICATION_SUPPORTED
33 #include "distributed_notification_manager.h"
34 #include "distributed_preferences.h"
35 #include "distributed_screen_status_manager.h"
36 #endif
37
38 #include "advanced_notification_inline.h"
39 #include "notification_analytics_util.h"
40
41 namespace OHOS {
42 namespace Notification {
43
Subscribe(const sptr<IAnsSubscriber> & subscriber)44 ErrCode AdvancedNotificationService::Subscribe(const sptr<IAnsSubscriber> &subscriber)
45 {
46 return Subscribe(subscriber, nullptr);
47 }
48
Subscribe(const sptr<IAnsSubscriber> & subscriber,const sptr<NotificationSubscribeInfo> & info)49 ErrCode AdvancedNotificationService::Subscribe(
50 const sptr<IAnsSubscriber> &subscriber, const sptr<NotificationSubscribeInfo> &info)
51 {
52 NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
53 ANS_LOGD("%{public}s", __FUNCTION__);
54 ErrCode errCode = ERR_OK;
55 do {
56 if (subscriber == nullptr) {
57 errCode = ERR_ANS_INVALID_PARAM;
58 break;
59 }
60
61 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
62 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
63 ANS_LOGE("Client is not a system app or subsystem");
64 errCode = ERR_ANS_NON_SYSTEM_APP;
65 break;
66 }
67
68 if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
69 errCode = ERR_ANS_PERMISSION_DENIED;
70 break;
71 }
72
73 if (info != nullptr && info->GetAppUserId() != SUBSCRIBE_USER_ALL) {
74 errCode = CheckUserIdParams(info->GetAppUserId());
75 if (errCode != ERR_OK) {
76 break;
77 }
78 }
79
80 errCode = NotificationSubscriberManager::GetInstance()->AddSubscriber(subscriber, info);
81 if (errCode != ERR_OK) {
82 break;
83 }
84 } while (0);
85 SendSubscribeHiSysEvent(IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), info, errCode);
86 return errCode;
87 }
88
SubscribeSelf(const sptr<IAnsSubscriber> & subscriber)89 ErrCode AdvancedNotificationService::SubscribeSelf(const sptr<IAnsSubscriber> &subscriber)
90 {
91 NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
92 ANS_LOGD("%{public}s", __FUNCTION__);
93 sptr<NotificationSubscribeInfo> sptrInfo = new (std::nothrow) NotificationSubscribeInfo();
94 if (sptrInfo == nullptr) {
95 ANS_LOGE("Failed to create sptrInfo");
96 return ERR_ANS_NO_MEMORY;
97 }
98 ErrCode errCode = ERR_OK;
99 do {
100 if (subscriber == nullptr) {
101 errCode = ERR_ANS_INVALID_PARAM;
102 break;
103 }
104
105 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
106 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
107 ANS_LOGE("Client is not a system app or subsystem");
108 errCode = ERR_ANS_NON_SYSTEM_APP;
109 break;
110 }
111
112 int32_t uid = IPCSkeleton().GetCallingUid();
113 // subscribeSelf doesn't need OHOS_PERMISSION_NOTIFICATION_CONTROLLER permission
114 std::string bundle;
115 std::shared_ptr<BundleManagerHelper> bundleManager = BundleManagerHelper::GetInstance();
116 if (bundleManager != nullptr) {
117 bundle = bundleManager->GetBundleNameByUid(uid);
118 }
119
120 sptrInfo->AddAppName(bundle);
121 sptrInfo->SetSubscriberUid(uid);
122 sptrInfo->SetIsSubscribeSelf(true);
123
124 errCode = NotificationSubscriberManager::GetInstance()->AddSubscriber(subscriber, sptrInfo);
125 if (errCode != ERR_OK) {
126 break;
127 }
128 } while (0);
129
130 if (errCode == ERR_OK) {
131 int32_t callingUid = IPCSkeleton::GetCallingUid();
132 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
133 LivePublishProcess::GetInstance()->AddLiveViewSubscriber(callingUid);
134 }));
135 notificationSvrQueue_->wait(handler);
136 }
137 SendSubscribeHiSysEvent(IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), sptrInfo, errCode);
138 return errCode;
139 }
140
Unsubscribe(const sptr<IAnsSubscriber> & subscriber)141 ErrCode AdvancedNotificationService::Unsubscribe(const sptr<IAnsSubscriber> &subscriber)
142 {
143 return Unsubscribe(subscriber, nullptr);
144 }
145
Unsubscribe(const sptr<IAnsSubscriber> & subscriber,const sptr<NotificationSubscribeInfo> & info)146 ErrCode AdvancedNotificationService::Unsubscribe(
147 const sptr<IAnsSubscriber> &subscriber, const sptr<NotificationSubscribeInfo> &info)
148 {
149 NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
150 ANS_LOGD("%{public}s", __FUNCTION__);
151
152 SendUnSubscribeHiSysEvent(IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), info);
153 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_6, EventBranchId::BRANCH_3);
154 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
155 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
156 ANS_LOGE("Client is not a system app or subsystem");
157 message.Message("Unsubscribe notification: " + std::to_string(ERR_ANS_NON_SYSTEM_APP));
158 NotificationAnalyticsUtil::ReportModifyEvent(message);
159 return ERR_ANS_NON_SYSTEM_APP;
160 }
161
162 if (subscriber == nullptr) {
163 message.Message("Unsubscribe notification: " + std::to_string(ERR_ANS_INVALID_PARAM));
164 NotificationAnalyticsUtil::ReportModifyEvent(message);
165 return ERR_ANS_INVALID_PARAM;
166 }
167
168 ErrCode errCode = NotificationSubscriberManager::GetInstance()->RemoveSubscriber(subscriber, info);
169 if (errCode != ERR_OK) {
170 return errCode;
171 }
172
173 return ERR_OK;
174 }
175 } // namespace Notification
176 } // namespace OHOS
177