1 /*
2 * Copyright (c) 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 "errors.h"
19 #include "ans_log_wrapper.h"
20 #include "access_token_helper.h"
21 #include "notification_preferences.h"
22 #include "notification_analytics_util.h"
23 #include "badge_number_callback_data.h"
24 #include "advanced_notification_inline.h"
25 #include "notification_subscriber_manager.h"
26 #include "enabled_notification_callback_data.h"
27
28 #include "ipc_skeleton.h"
29
30 namespace OHOS {
31 namespace Notification {
32
33 constexpr int32_t BADGE_NUM_LIMIT = 0;
34
SetNotificationBadgeNum(int32_t num)35 ErrCode AdvancedNotificationService::SetNotificationBadgeNum(int32_t num)
36 {
37 ANS_LOGD("called");
38
39 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
40 if (bundleOption == nullptr) {
41 ANS_LOGD("null bundleOption");
42 return ERR_ANS_INVALID_BUNDLE;
43 }
44
45 if (notificationSvrQueue_ == nullptr) {
46 ANS_LOGE("null notificationSvrQueue");
47 return ERR_ANS_INVALID_PARAM;
48 }
49 ErrCode result = ERR_OK;
50 ffrt::task_handle handler = notificationSvrQueue_->submit_h(
51 std::bind([&]() {
52 ANS_LOGD("called");
53 result = NotificationPreferences::GetInstance()->SetTotalBadgeNums(bundleOption, num);
54 }));
55 notificationSvrQueue_->wait(handler);
56 return result;
57 }
58
SetShowBadgeEnabledForBundle(const sptr<NotificationBundleOption> & bundleOption,bool enabled)59 ErrCode AdvancedNotificationService::SetShowBadgeEnabledForBundle(
60 const sptr<NotificationBundleOption> &bundleOption, bool enabled)
61 {
62 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_13, EventBranchId::BRANCH_0);
63 if (bundleOption == nullptr) {
64 ANS_LOGE("null bundleOption");
65 NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_BUNDLE));
66 return ERR_ANS_INVALID_BUNDLE;
67 }
68
69 message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) +
70 " en" + std::to_string(enabled));
71
72 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
73 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
74 ANS_LOGE("IsSystemApp is false.");
75 message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).BranchId(BRANCH_1);
76 NotificationAnalyticsUtil::ReportModifyEvent(message);
77 return ERR_ANS_NON_SYSTEM_APP;
78 }
79
80 if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
81 ANS_LOGE("Permission Denied.");
82 message.ErrorCode(ERR_ANS_PERMISSION_DENIED).BranchId(BRANCH_2);
83 NotificationAnalyticsUtil::ReportModifyEvent(message);
84 return ERR_ANS_PERMISSION_DENIED;
85 }
86
87 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
88 if (bundle == nullptr) {
89 ANS_LOGE("null bundle");
90 return ERR_ANS_INVALID_BUNDLE;
91 }
92
93 if (notificationSvrQueue_ == nullptr) {
94 ANS_LOGE("null notificationSvrQueue");
95 return ERR_ANS_INVALID_PARAM;
96 }
97 ErrCode result = ERR_OK;
98 ffrt::task_handle handler = notificationSvrQueue_->submit_h(
99 std::bind([&]() {
100 ANS_LOGD("called");
101 result = NotificationPreferences::GetInstance()->SetShowBadge(bundle, enabled);
102 if (result == ERR_OK) {
103 HandleBadgeEnabledChanged(bundle, enabled);
104 }
105 }));
106 notificationSvrQueue_->wait(handler);
107 ANS_LOGI("%{public}s_%{public}d, enabled: %{public}s, Set show badge enabled for bundle result: %{public}d",
108 bundleOption->GetBundleName().c_str(), bundleOption->GetUid(), std::to_string(enabled).c_str(), result);
109 message.ErrorCode(result).BranchId(BRANCH_3);
110 NotificationAnalyticsUtil::ReportModifyEvent(message);
111 return result;
112 }
113
HandleBadgeEnabledChanged(const sptr<NotificationBundleOption> & bundleOption,bool enabled)114 void AdvancedNotificationService::HandleBadgeEnabledChanged(
115 const sptr<NotificationBundleOption> &bundleOption, bool enabled)
116 {
117 sptr<EnabledNotificationCallbackData> enabledData = new (std::nothrow)
118 EnabledNotificationCallbackData(bundleOption->GetBundleName(), bundleOption->GetUid(), enabled);
119 if (enabledData == nullptr) {
120 ANS_LOGE("null enabledData");
121 return;
122 }
123
124 NotificationSubscriberManager::GetInstance()->NotifyBadgeEnabledChanged(enabledData);
125 }
126
GetShowBadgeEnabledForBundle(const sptr<NotificationBundleOption> & bundleOption,bool & enabled)127 ErrCode AdvancedNotificationService::GetShowBadgeEnabledForBundle(
128 const sptr<NotificationBundleOption> &bundleOption, bool &enabled)
129 {
130 ANS_LOGD("called");
131
132 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
133 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
134 ANS_LOGD("VerifyNativeToken is bogus.");
135 return ERR_ANS_NON_SYSTEM_APP;
136 }
137
138 if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
139 return ERR_ANS_PERMISSION_DENIED;
140 }
141
142 sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
143 if (bundle == nullptr) {
144 ANS_LOGE("null bundle");
145 return ERR_ANS_INVALID_BUNDLE;
146 }
147
148 if (notificationSvrQueue_ == nullptr) {
149 ANS_LOGE("null notificationSvrQueue");
150 return ERR_ANS_INVALID_PARAM;
151 }
152 ErrCode result = ERR_OK;
153 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
154 ANS_LOGD("called");
155 result = NotificationPreferences::GetInstance()->IsShowBadge(bundle, enabled);
156 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
157 result = ERR_OK;
158 enabled = true;
159 }
160 }));
161 notificationSvrQueue_->wait(handler);
162 return result;
163 }
164
GetShowBadgeEnabled(bool & enabled)165 ErrCode AdvancedNotificationService::GetShowBadgeEnabled(bool &enabled)
166 {
167 ANS_LOGD("called");
168
169 sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
170 if (bundleOption == nullptr) {
171 return ERR_ANS_INVALID_BUNDLE;
172 }
173
174 if (notificationSvrQueue_ == nullptr) {
175 ANS_LOGE("null notificationSvrQueue");
176 return ERR_ANS_INVALID_PARAM;
177 }
178 ErrCode result = ERR_OK;
179 ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
180 ANS_LOGD("called");
181 result = NotificationPreferences::GetInstance()->IsShowBadge(bundleOption, enabled);
182 if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
183 result = ERR_OK;
184 enabled = true;
185 }
186 }));
187 notificationSvrQueue_->wait(handler);
188 return result;
189 }
190
SetBadgeNumber(int32_t badgeNumber,const std::string & instanceKey)191 ErrCode AdvancedNotificationService::SetBadgeNumber(int32_t badgeNumber, const std::string &instanceKey)
192 {
193 ANS_LOGD("called");
194 if (notificationSvrQueue_ == nullptr) {
195 ANS_LOGE("null notificationSvrQueue");
196 return ERR_ANS_INVALID_PARAM;
197 }
198 int32_t callingUid = IPCSkeleton::GetCallingUid();
199 std::string bundleName = GetClientBundleName();
200 ANS_LOGD("SetBadgeNumber receive instanceKey:%{public}s", instanceKey.c_str());
201 sptr<BadgeNumberCallbackData> badgeData = new (std::nothrow) BadgeNumberCallbackData(
202 bundleName, instanceKey, callingUid, badgeNumber);
203 if (badgeData == nullptr) {
204 ANS_LOGE("Null badgeData.");
205 return ERR_ANS_NO_MEMORY;
206 }
207
208 ffrt::task_handle handler = notificationSvrQueue_->submit_h([badgeData]() {
209 ANS_LOGD("called");
210 NotificationSubscriberManager::GetInstance()->SetBadgeNumber(badgeData);
211 });
212
213 return ERR_OK;
214 }
215
SetBadgeNumberForDhByBundle(const sptr<NotificationBundleOption> & bundleOption,int32_t badgeNumber)216 ErrCode AdvancedNotificationService::SetBadgeNumberForDhByBundle(
217 const sptr<NotificationBundleOption> &bundleOption, int32_t badgeNumber)
218 {
219 if (bundleOption == nullptr) {
220 ANS_LOGE("null bundleOption");
221 return ERR_ANS_INVALID_PARAM;
222 }
223 if (bundleOption->GetBundleName().empty()) {
224 ANS_LOGE("SetBadgeNumberForDhByBundle Invalid bundle name.");
225 return ERR_ANS_INVALID_PARAM;
226 }
227 if (bundleOption->GetUid() <= DEFAULT_UID) {
228 ANS_LOGE("SetBadgeNumberForDhByBundle invalid uid");
229 return ERR_ANS_INVALID_PARAM;
230 }
231 if (badgeNumber < BADGE_NUM_LIMIT) {
232 ANS_LOGE("SetBadgeNumberForDhByBundle invalid badgeNumber");
233 return ERR_ANS_INVALID_PARAM;
234 }
235 ANS_LOGI("SetBadgeNumberForDhByBundle bundleName = %{public}s uid = %{public}d",
236 bundleOption->GetBundleName().c_str(), bundleOption->GetUid());
237 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_7, EventBranchId::BRANCH_6);
238 message.Message(bundleOption->GetBundleName() + "_" +std::to_string(bundleOption->GetUid()) +
239 " badgeNumber: " + std::to_string(badgeNumber));
240
241 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
242 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
243 message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Append(" Not system app.");
244 NotificationAnalyticsUtil::ReportModifyEvent(message);
245 ANS_LOGE("Not system app.");
246 return ERR_ANS_NON_SYSTEM_APP;
247 }
248
249 if (notificationSvrQueue_ == nullptr) {
250 return ERR_ANS_INVALID_PARAM;
251 }
252
253 sptr<BadgeNumberCallbackData> badgeData = new (std::nothrow) BadgeNumberCallbackData(
254 bundleOption->GetBundleName(), bundleOption->GetUid(), badgeNumber);
255 if (badgeData == nullptr) {
256 ANS_LOGE("Null badgeData.");
257 return ERR_ANS_NO_MEMORY;
258 }
259
260 ffrt::task_handle handler = notificationSvrQueue_->submit_h([badgeData]() {
261 ANS_LOGD("called");
262 NotificationSubscriberManager::GetInstance()->SetBadgeNumber(badgeData);
263 });
264
265 return ERR_OK;
266 }
267
SetBadgeNumberByBundle(const sptr<NotificationBundleOption> & bundleOption,int32_t badgeNumber)268 ErrCode AdvancedNotificationService::SetBadgeNumberByBundle(
269 const sptr<NotificationBundleOption> &bundleOption, int32_t badgeNumber)
270 {
271 if (bundleOption == nullptr || bundleOption->GetBundleName().empty()) {
272 return ERR_ANS_INVALID_PARAM;
273 }
274 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_7, EventBranchId::BRANCH_6);
275 message.Message(bundleOption->GetBundleName() + "_" +std::to_string(bundleOption->GetUid()) +
276 " badgeNumber: " + std::to_string(badgeNumber));
277
278 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
279 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
280 message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Append(" Not system app.");
281 NotificationAnalyticsUtil::ReportModifyEvent(message);
282 ANS_LOGE("Not system app.");
283 return ERR_ANS_NON_SYSTEM_APP;
284 }
285
286 sptr<NotificationBundleOption> bundle = bundleOption;
287 ErrCode result = CheckBundleOptionValid(bundle);
288 if (result != ERR_OK) {
289 ANS_LOGE("Bundle is invalid.");
290 return result;
291 }
292
293 if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER)) {
294 std::string bundleName = GetClientBundleName();
295 if (bundleName.empty()) {
296 ANS_LOGE("Failed to get client bundle name.");
297 return result;
298 }
299 bool isAgent = false;
300 isAgent = IsAgentRelationship(bundleName, bundle->GetBundleName());
301 if (!isAgent) {
302 message.ErrorCode(ERR_ANS_NO_AGENT_SETTING).Append(" No agent setting.");
303 NotificationAnalyticsUtil::ReportModifyEvent(message);
304 ANS_LOGE("No agent setting.");
305 return ERR_ANS_NO_AGENT_SETTING;
306 }
307 }
308
309 if (notificationSvrQueue_ == nullptr) {
310 return ERR_ANS_INVALID_PARAM;
311 }
312
313 sptr<BadgeNumberCallbackData> badgeData = new (std::nothrow) BadgeNumberCallbackData(
314 bundle->GetBundleName(), bundle->GetUid(), badgeNumber);
315 if (badgeData == nullptr) {
316 ANS_LOGE("Null badgeData.");
317 return ERR_ANS_NO_MEMORY;
318 }
319
320 ffrt::task_handle handler = notificationSvrQueue_->submit_h([badgeData]() {
321 ANS_LOGD("called");
322 NotificationSubscriberManager::GetInstance()->SetBadgeNumber(badgeData);
323 });
324
325 return ERR_OK;
326 }
327 } // Notification
328 } // OHOS