1 /*
2  * Copyright (c) 2021-2024 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 "access_token_helper.h"
23 #include "ans_inner_errors.h"
24 #include "ans_log_wrapper.h"
25 #include "ans_permission_def.h"
26 #include "errors.h"
27 #include "common_event_manager.h"
28 #include "common_event_support.h"
29 #include "hitrace_meter_adapter.h"
30 #include "os_account_manager_helper.h"
31 #include "ipc_skeleton.h"
32 #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED
33 #include "smart_reminder_center.h"
34 #else
35 #include "notification_config_parse.h"
36 #endif
37 
38 #include "advanced_notification_inline.cpp"
39 #include "notification_extension_wrapper.h"
40 #include "notification_analytics_util.h"
41 #include "notification_trust_list.h"
42 
43 namespace OHOS {
44 namespace Notification {
45 namespace {
46     constexpr char KEY_NAME[] = "AGGREGATE_CONFIG";
47     constexpr char CTRL_LIST_KEY_NAME[] = "NOTIFICATION_CTL_LIST_PKG";
48     constexpr char CALL_UI_BUNDLE[] = "com.ohos.callui";
49 }
50 
AddSlots(const std::vector<sptr<NotificationSlot>> & slots)51 ErrCode AdvancedNotificationService::AddSlots(const std::vector<sptr<NotificationSlot>> &slots)
52 {
53     ANS_LOGD("%{public}s", __FUNCTION__);
54 
55     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
56     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
57         return ERR_ANS_NON_SYSTEM_APP;
58     }
59 
60     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
61         return ERR_ANS_PERMISSION_DENIED;
62     }
63 
64     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
65     if (bundleOption == nullptr) {
66         return ERR_ANS_INVALID_BUNDLE;
67     }
68 
69     if (slots.size() == 0) {
70         return ERR_ANS_INVALID_PARAM;
71     }
72 
73     if (notificationSvrQueue_ == nullptr) {
74         ANS_LOGE("Serial queue is invalid.");
75         return ERR_ANS_INVALID_PARAM;
76     }
77     ErrCode result = ERR_OK;
78     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
79         ANS_LOGD("ffrt enter!");
80         std::vector<sptr<NotificationSlot>> addSlots;
81         for (auto slot : slots) {
82             sptr<NotificationSlot> originalSlot;
83             result =NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption,
84                 slot->GetType(), originalSlot);
85             if ((result == ERR_OK) && (originalSlot != nullptr)) {
86                 continue;
87             }
88 
89             GenerateSlotReminderMode(slot, bundleOption, true);
90             addSlots.push_back(slot);
91         }
92 
93         if (addSlots.size() == 0) {
94             result = ERR_OK;
95         } else {
96             result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, addSlots);
97         }
98     }));
99     notificationSvrQueue_->wait(handler);
100     return result;
101 }
102 
GetSlots(std::vector<sptr<NotificationSlot>> & slots)103 ErrCode AdvancedNotificationService::GetSlots(std::vector<sptr<NotificationSlot>> &slots)
104 {
105     ANS_LOGD("%{public}s", __FUNCTION__);
106 
107     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
108     if (bundleOption == nullptr) {
109         return ERR_ANS_INVALID_BUNDLE;
110     }
111 
112     if (notificationSvrQueue_ == nullptr) {
113         ANS_LOGE("NotificationSvrQueue_ is nullptr.");
114         return ERR_ANS_INVALID_PARAM;
115     }
116     ErrCode result = ERR_OK;
117     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
118         ANS_LOGD("ffrt enter!");
119         result = NotificationPreferences::GetInstance()->GetNotificationAllSlots(bundleOption, slots);
120         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
121             result = ERR_OK;
122             slots.clear();
123         }
124     }));
125     notificationSvrQueue_->wait(handler);
126     return result;
127 }
128 
GetSlotsByBundle(const sptr<NotificationBundleOption> & bundleOption,std::vector<sptr<NotificationSlot>> & slots)129 ErrCode AdvancedNotificationService::GetSlotsByBundle(
130     const sptr<NotificationBundleOption> &bundleOption, std::vector<sptr<NotificationSlot>> &slots)
131 {
132     ANS_LOGD("%{public}s", __FUNCTION__);
133 
134     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
135     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
136         ANS_LOGD("IsSystemApp is false.");
137         return ERR_ANS_NON_SYSTEM_APP;
138     }
139 
140     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
141         return ERR_ANS_PERMISSION_DENIED;
142     }
143 
144     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
145     if (bundle == nullptr) {
146         ANS_LOGD("GenerateValidBundleOption failed.");
147         return ERR_ANS_INVALID_BUNDLE;
148     }
149 
150     if (notificationSvrQueue_ == nullptr) {
151         ANS_LOGE("Serial queue is invalid.");
152         return ERR_ANS_INVALID_PARAM;
153     }
154     ErrCode result = ERR_OK;
155     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
156         ANS_LOGD("ffrt enter!");
157         result = NotificationPreferences::GetInstance()->GetNotificationAllSlots(bundle, slots);
158         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
159             result = ERR_OK;
160             slots.clear();
161         }
162     }));
163 
164     notificationSvrQueue_->wait(handler);
165     return result;
166 }
167 
GetSlotByBundle(const sptr<NotificationBundleOption> & bundleOption,const NotificationConstant::SlotType & slotType,sptr<NotificationSlot> & slot)168 ErrCode AdvancedNotificationService::GetSlotByBundle(
169     const sptr<NotificationBundleOption> &bundleOption, const NotificationConstant::SlotType &slotType,
170     sptr<NotificationSlot> &slot)
171 {
172     ANS_LOGD("%{public}s", __FUNCTION__);
173 
174     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
175     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
176         ANS_LOGD("IsSystemApp is false.");
177         return ERR_ANS_NON_SYSTEM_APP;
178     }
179 
180     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
181         return ERR_ANS_PERMISSION_DENIED;
182     }
183 
184     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
185     if (bundleOption == nullptr) {
186         ANS_LOGD("Failed to generateBundleOption.");
187         return ERR_ANS_INVALID_BUNDLE;
188     }
189 
190     if (notificationSvrQueue_ == nullptr) {
191         ANS_LOGE("Serial queue is invalid.");
192         return ERR_ANS_INVALID_PARAM;
193     }
194     ErrCode result = ERR_OK;
195     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
196         ANS_LOGD("ffrt enter!");
197         result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundle, slotType, slot);
198     }));
199     notificationSvrQueue_->wait(handler);
200     if (slot != nullptr) {
201         ANS_LOGD("GetSlotByBundle, authStatus: %{public}d), authHintCnt: %{public}d",
202             slot->GetAuthorizedStatus(), slot->GetAuthHintCnt());
203     }
204     return result;
205 }
206 
UpdateSlots(const sptr<NotificationBundleOption> & bundleOption,const std::vector<sptr<NotificationSlot>> & slots)207 ErrCode AdvancedNotificationService::UpdateSlots(
208     const sptr<NotificationBundleOption> &bundleOption, const std::vector<sptr<NotificationSlot>> &slots)
209 {
210     ANS_LOGD("%{public}s", __FUNCTION__);
211 
212     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
213     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
214         return ERR_ANS_NON_SYSTEM_APP;
215     }
216 
217     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
218         ANS_LOGD("AccessTokenHelper::CheckPermission is false.");
219         return ERR_ANS_PERMISSION_DENIED;
220     }
221 
222     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
223     if (bundle == nullptr) {
224         return ERR_ANS_INVALID_BUNDLE;
225     }
226 
227     if (notificationSvrQueue_ == nullptr) {
228         ANS_LOGE("notificationSvrQueue_ is nullptr.");
229         return ERR_ANS_INVALID_PARAM;
230     }
231     ErrCode result = ERR_OK;
232     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
233         ANS_LOGD("ffrt enter!");
234         result = NotificationPreferences::GetInstance()->UpdateNotificationSlots(bundle, slots);
235         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
236             result = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST;
237         }
238     }));
239     notificationSvrQueue_->wait(handler);
240 
241     if (result == ERR_OK) {
242         PublishSlotChangeCommonEvent(bundle);
243     }
244 
245     return result;
246 }
247 
RemoveAllSlots()248 ErrCode AdvancedNotificationService::RemoveAllSlots()
249 {
250     ANS_LOGD("%{public}s", __FUNCTION__);
251 
252     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
253     if (bundleOption == nullptr) {
254         ANS_LOGD("GenerateBundleOption defeat.");
255         return ERR_ANS_INVALID_BUNDLE;
256     }
257 
258     if (notificationSvrQueue_ == nullptr) {
259         ANS_LOGE("Serial queue is invalid.");
260         return ERR_ANS_INVALID_PARAM;
261     }
262     ErrCode result = ERR_OK;
263     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
264         ANS_LOGD("ffrt enter!");
265         sptr<NotificationSlot> liveViewSlot;
266 
267         bool isLiveViewSlotExist = true;
268         // retain liveview slot before removeNotificationAllSlots
269         if (NotificationPreferences::GetInstance()->GetNotificationSlot(
270             bundleOption, NotificationConstant::SlotType::LIVE_VIEW, liveViewSlot) != ERR_OK) {
271             isLiveViewSlotExist = false;
272         }
273 
274         result = NotificationPreferences::GetInstance()->RemoveNotificationAllSlots(bundleOption);
275         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
276             result = ERR_OK;
277         }
278 
279         if (!isLiveViewSlotExist) {
280             return;
281         }
282         // retain liveview slot when caller is not sa or systemapp
283         if ((result == ERR_OK) &&
284             (IsAllowedRemoveSlot(bundleOption, NotificationConstant::SlotType::LIVE_VIEW) != ERR_OK)) {
285             std::vector<sptr<NotificationSlot>> slots;
286 
287             slots.push_back(liveViewSlot);
288             (void)NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, slots);
289         }
290     }));
291     notificationSvrQueue_->wait(handler);
292     return result;
293 }
294 
AddSlotByType(NotificationConstant::SlotType slotType)295 ErrCode AdvancedNotificationService::AddSlotByType(NotificationConstant::SlotType slotType)
296 {
297     ANS_LOGD("%{public}s", __FUNCTION__);
298 
299     if (!AccessTokenHelper::IsSystemApp() && slotType == NotificationConstant::SlotType::EMERGENCY_INFORMATION) {
300         ANS_LOGE("Non system app used illegal slot type.");
301         return ERR_ANS_INVALID_PARAM;
302     }
303 
304     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
305     if (bundleOption == nullptr) {
306         return ERR_ANS_INVALID_BUNDLE;
307     }
308 
309     if (notificationSvrQueue_ == nullptr) {
310         ANS_LOGE("Serial queue is invalidity.");
311         return ERR_ANS_INVALID_PARAM;
312     }
313     ErrCode result = ERR_OK;
314     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
315         ANS_LOGD("ffrt enter!");
316         sptr<NotificationSlot> slot;
317         result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
318         if ((result == ERR_OK) && (slot != nullptr)) {
319             return;
320         }
321 
322         slot = new (std::nothrow) NotificationSlot(slotType);
323         if (slot == nullptr) {
324             ANS_LOGE("Failed to create NotificationSlot instance");
325             return;
326         }
327 
328         GenerateSlotReminderMode(slot, bundleOption);
329         std::vector<sptr<NotificationSlot>> slots;
330         slots.push_back(slot);
331         result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, slots);
332     }));
333     notificationSvrQueue_->wait(handler);
334     return result;
335 }
336 
GetEnabledForBundleSlotSelf(const NotificationConstant::SlotType & slotType,bool & enabled)337 ErrCode AdvancedNotificationService::GetEnabledForBundleSlotSelf(
338     const NotificationConstant::SlotType &slotType, bool &enabled)
339 {
340     ANS_LOGD("slotType: %{public}d", slotType);
341 
342     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
343     if (bundleOption == nullptr) {
344         return ERR_ANS_INVALID_BUNDLE;
345     }
346 
347     if (notificationSvrQueue_ == nullptr) {
348         ANS_LOGE("Serial queue is invalid.");
349         return ERR_ANS_INVALID_PARAM;
350     }
351     ErrCode result = ERR_OK;
352     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
353         ANS_LOGD("ffrt enter!");
354         sptr<NotificationSlot> slot;
355         result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
356         if (result != ERR_OK) {
357             ANS_LOGE("Get enable slot self: GetNotificationSlot failed");
358             return;
359         }
360         if (slot == nullptr) {
361             ANS_LOGW("Get enable slot: object is null, enabled default true");
362             enabled = true;
363             result = ERR_OK;
364             return;
365         }
366         enabled = slot->GetEnable();
367     }));
368     notificationSvrQueue_->wait(handler);
369 
370     return result;
371 }
372 
GetSlotFlagsAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint32_t & slotFlags)373 ErrCode AdvancedNotificationService::GetSlotFlagsAsBundle(const sptr<NotificationBundleOption> &bundleOption,
374     uint32_t &slotFlags)
375 {
376     ANS_LOGD("%{public}s", __FUNCTION__);
377     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
378     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
379         return ERR_ANS_NON_SYSTEM_APP;
380     }
381 
382     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
383         return ERR_ANS_PERMISSION_DENIED;
384     }
385 
386     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
387     if (bundle == nullptr) {
388         ANS_LOGD("Bundle is null.");
389         return ERR_ANS_INVALID_BUNDLE;
390     }
391 
392     if (notificationSvrQueue_ == nullptr) {
393         ANS_LOGE("Serial queue is invalid.");
394         return ERR_ANS_INVALID_PARAM;
395     }
396     ErrCode result = ERR_OK;
397     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
398         ANS_LOGD("ffrt enter!");
399         result = NotificationPreferences::GetInstance()->GetNotificationSlotFlagsForBundle(bundle, slotFlags);
400         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
401             result = ERR_OK;
402             slotFlags = DEFAULT_SLOT_FLAGS;
403         }
404     }));
405     notificationSvrQueue_->wait(handler);
406 
407     return result;
408 }
409 
SetSlotFlagsAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint32_t slotFlags)410 ErrCode AdvancedNotificationService::SetSlotFlagsAsBundle(const sptr<NotificationBundleOption> &bundleOption,
411     uint32_t slotFlags)
412 {
413     ANS_LOGD("%{public}s", __FUNCTION__);
414     if (bundleOption == nullptr) {
415         ANS_LOGE("BundleOption is null.");
416         return ERR_ANS_INVALID_BUNDLE;
417     }
418 
419     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_8, EventBranchId::BRANCH_2);
420     message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) +
421             " slotFlags:" + std::to_string(slotFlags));
422     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
423     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
424         ANS_LOGE("IsSystemApp is false.");
425         message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Append(" Not SystemApp");
426         NotificationAnalyticsUtil::ReportModifyEvent(message);
427         return ERR_ANS_NON_SYSTEM_APP;
428     }
429 
430     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
431         ANS_LOGE("Permission denied.");
432         message.ErrorCode(ERR_ANS_PERMISSION_DENIED).Append(" Permission denied");
433         NotificationAnalyticsUtil::ReportModifyEvent(message);
434         return ERR_ANS_PERMISSION_DENIED;
435     }
436 
437     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
438     if (bundle == nullptr) {
439         ANS_LOGE("Bundle is null.");
440         return ERR_ANS_INVALID_BUNDLE;
441     }
442 
443     if (notificationSvrQueue_ == nullptr) {
444         ANS_LOGE("Serial queue is invalidity.");
445         return ERR_ANS_INVALID_PARAM;
446     }
447     ErrCode result = ERR_OK;
448     ffrt::task_handle handler = notificationSvrQueue_->submit_h(
449         std::bind([&]() {
450             result = NotificationPreferences::GetInstance()->SetNotificationSlotFlagsForBundle(bundle, slotFlags);
451             if (result != ERR_OK) {
452                 return;
453             }
454             ANS_LOGI("Set slotflags %{public}d to %{public}s.", slotFlags, bundle->GetBundleName().c_str());
455             result = UpdateSlotReminderModeBySlotFlags(bundle, slotFlags);
456         }));
457     notificationSvrQueue_->wait(handler);
458     ANS_LOGI("%{public}s_%{public}d, slotFlags: %{public}d, SetSlotFlagsAsBundle result: %{public}d",
459         bundleOption->GetBundleName().c_str(), bundleOption->GetUid(), slotFlags, result);
460     message.ErrorCode(result);
461     NotificationAnalyticsUtil::ReportModifyEvent(message);
462     return result;
463 }
464 
AssignValidNotificationSlot(const std::shared_ptr<NotificationRecord> & record,const sptr<NotificationBundleOption> & bundleOption)465 ErrCode AdvancedNotificationService::AssignValidNotificationSlot(const std::shared_ptr<NotificationRecord> &record,
466     const sptr<NotificationBundleOption> &bundleOption)
467 {
468     sptr<NotificationSlot> slot;
469     NotificationConstant::SlotType slotType = record->request->GetSlotType();
470     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_7, EventBranchId::BRANCH_3).SlotType(slotType);
471     ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
472     if ((result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) ||
473         (result == ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST)) {
474         slot = new (std::nothrow) NotificationSlot(slotType);
475         if (slot == nullptr) {
476             ANS_LOGE("Failed to create NotificationSlot instance");
477             return ERR_NO_MEMORY;
478         }
479 
480         GenerateSlotReminderMode(slot, bundleOption);
481         std::vector<sptr<NotificationSlot>> slots;
482         slots.push_back(slot);
483         result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, slots);
484     }
485     if (result == ERR_OK) {
486         if (slot != nullptr &&
487             (bundleOption->GetBundleName() == CALL_UI_BUNDLE || slot->GetEnable() ||
488             (record->request->GetAgentBundle() != nullptr && record->request->IsSystemLiveView()) ||
489             (slot->GetType() == NotificationConstant::SlotType::LIVE_VIEW &&
490             DelayedSingleton<NotificationTrustList>::GetInstance()->IsLiveViewTrtust(bundleOption->GetBundleName())))) {
491             record->slot = slot;
492         } else {
493             result = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_ENABLED;
494             ANS_LOGE("Type[%{public}d] slot enable closed", slotType);
495         }
496     }
497     if (result != ERR_OK) {
498         message.ErrorCode(result).Message("assign slot failed");
499         NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message);
500     }
501     return result;
502 }
503 
UpdateSlotReminderModeBySlotFlags(const sptr<NotificationBundleOption> & bundle,uint32_t slotFlags)504 ErrCode AdvancedNotificationService::UpdateSlotReminderModeBySlotFlags(
505     const sptr<NotificationBundleOption> &bundle, uint32_t slotFlags)
506 {
507     std::vector<sptr<NotificationSlot>> slots;
508     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_1);
509     ErrCode ret = NotificationPreferences::GetInstance()->GetNotificationAllSlots(bundle, slots);
510     if (ret != ERR_OK) {
511         message.Message("Failed to get slots by bundle, ret:" + std::to_string(ret), true);
512         NotificationAnalyticsUtil::ReportModifyEvent(message);
513         return ret;
514     }
515 
516     message.BundleName((bundle == nullptr) ? "" : bundle->GetBundleName());
517     if (slots.empty()) {
518         message.Message("The bundle has no slots.", true);
519         NotificationAnalyticsUtil::ReportModifyEvent(message);
520         return ERR_OK;
521     }
522 
523     for (auto slot : slots) {
524         auto configSlotReminderMode = DelayedSingleton<NotificationConfigParse>::GetInstance()->
525             GetConfigSlotReminderModeByType(slot->GetType(), bundle);
526         slot->SetReminderMode(slotFlags & configSlotReminderMode);
527         std::string bundleName = (bundle == nullptr) ? "" : bundle->GetBundleName();
528         ANS_LOGD("Update reminderMode of %{public}d in %{public}s, value is %{public}d.",
529             slot->GetType(), bundleName.c_str(), slot->GetReminderMode());
530     }
531 
532     ret = NotificationPreferences::GetInstance()->UpdateNotificationSlots(bundle, slots);
533     if (ret == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
534         ret = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST;
535     }
536     return ret;
537 }
538 
GenerateSlotReminderMode(const sptr<NotificationSlot> & slot,const sptr<NotificationBundleOption> & bundle,bool isSpecifiedSlot,uint32_t defaultSlotFlags)539 void AdvancedNotificationService::GenerateSlotReminderMode(const sptr<NotificationSlot> &slot,
540     const sptr<NotificationBundleOption> &bundle, bool isSpecifiedSlot, uint32_t defaultSlotFlags)
541 {
542     uint32_t slotFlags = defaultSlotFlags;
543     auto ret = NotificationPreferences::GetInstance()->GetNotificationSlotFlagsForBundle(bundle, slotFlags);
544     if (ret != ERR_OK) {
545         ANS_LOGI("Failed to get slotflags for bundle, use default slotflags.");
546     }
547 
548     auto configSlotReminderMode = DelayedSingleton<NotificationConfigParse>::GetInstance()->
549         GetConfigSlotReminderModeByType(slot->GetType(), bundle);
550     if (isSpecifiedSlot) {
551         slot->SetReminderMode(configSlotReminderMode & slotFlags & slot->GetReminderMode());
552     } else {
553         slot->SetReminderMode(configSlotReminderMode & slotFlags);
554     }
555 
556     std::string bundleName = (bundle == nullptr) ? "" : bundle->GetBundleName();
557     ANS_LOGI("The reminder mode of %{public}d is %{public}d in %{public}s,specifiedSlot:%{public}d default:%{public}u",
558         slot->GetType(), slot->GetReminderMode(), bundleName.c_str(), isSpecifiedSlot, defaultSlotFlags);
559 }
560 
GetDefaultSlotFlags(const sptr<NotificationRequest> & request)561 uint32_t AdvancedNotificationService::GetDefaultSlotFlags(const sptr<NotificationRequest> &request)
562 {
563     auto flags = DEFAULT_SLOT_FLAGS;
564     uint32_t notificationControlFlags = request->GetNotificationControlFlags();
565     // SA publish own's notification with banner
566     if ((notificationControlFlags & NotificationConstant::ReminderFlag::SA_SELF_BANNER_FLAG) != 0) {
567         ANS_LOGI("Creator:%{public}s %{public}d,Owner: %{public}s %{public}d, controlFlags:%{public}d",
568             request->GetCreatorBundleName().c_str(), request->GetCreatorUid(), request->GetOwnerBundleName().c_str(),
569             request->GetOwnerUid(), request->GetNotificationControlFlags());
570     }
571     if (((notificationControlFlags & NotificationConstant::ReminderFlag::SA_SELF_BANNER_FLAG) != 0) &&
572         (request->GetCreatorUid() == IPCSkeleton::GetCallingUid() && request->GetCreatorBundleName().empty() &&
573         request->GetOwnerBundleName().empty())) {
574         return (flags |= NotificationConstant::ReminderFlag::BANNER_FLAG);
575     }
576 
577     return flags;
578 }
579 
SetRequestBySlotType(const sptr<NotificationRequest> & request,const sptr<NotificationBundleOption> & bundleOption)580 void AdvancedNotificationService::SetRequestBySlotType(const sptr<NotificationRequest> &request,
581     const sptr<NotificationBundleOption> &bundleOption)
582 {
583     ANS_LOGD("Called.");
584     NotificationConstant::SlotType type = request->GetSlotType();
585     auto flags = std::make_shared<NotificationFlags>();
586 
587     sptr<NotificationSlot> slot;
588     NotificationConstant::SlotType slotType = request->GetSlotType();
589     ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
590     if (slot == nullptr) {
591         slot = new (std::nothrow) NotificationSlot(slotType);
592         if (slot == nullptr) {
593             ANS_LOGE("Failed to create NotificationSlot instance");
594             return;
595         }
596         uint32_t slotFlags = GetDefaultSlotFlags(request);
597         GenerateSlotReminderMode(slot, bundleOption, false, slotFlags);
598     }
599 
600     auto slotReminderMode = slot->GetReminderMode();
601     if ((slotReminderMode & NotificationConstant::ReminderFlag::SOUND_FLAG) != 0) {
602         flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN);
603     }
604 
605     if ((slotReminderMode & NotificationConstant::ReminderFlag::LOCKSCREEN_FLAG) != 0) {
606         flags->SetLockScreenVisblenessEnabled(true);
607     }
608 
609     if ((slotReminderMode & NotificationConstant::ReminderFlag::BANNER_FLAG) != 0) {
610         flags->SetBannerEnabled(true);
611     }
612 
613     if ((slotReminderMode & NotificationConstant::ReminderFlag::LIGHTSCREEN_FLAG) != 0) {
614         flags->SetLightScreenEnabled(true);
615     }
616 
617     if ((slotReminderMode & NotificationConstant::ReminderFlag::VIBRATION_FLAG) != 0) {
618         flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN);
619     }
620 
621     if ((slotReminderMode & NotificationConstant::ReminderFlag::STATUSBAR_ICON_FLAG) != 0) {
622         flags->SetStatusIconEnabled(true);
623     }
624 
625     request->SetFlags(flags);
626     ANS_LOGI("SetFlags-GetRemindMode, notificationKey = %{public}s flags = %{public}d",
627         request->GetKey().c_str(), flags->GetReminderFlags());
628 #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED
629     DelayedSingleton<SmartReminderCenter>::GetInstance()->ReminderDecisionProcess(request);
630 #endif
631 }
632 
GetSlotByType(const NotificationConstant::SlotType & slotType,sptr<NotificationSlot> & slot)633 ErrCode AdvancedNotificationService::GetSlotByType(
634     const NotificationConstant::SlotType &slotType, sptr<NotificationSlot> &slot)
635 {
636     ANS_LOGD("%{public}s", __FUNCTION__);
637 
638     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
639     if (bundleOption == nullptr) {
640         ANS_LOGD("Failed to generateBundleOption.");
641         return ERR_ANS_INVALID_BUNDLE;
642     }
643 
644     if (notificationSvrQueue_ == nullptr) {
645         ANS_LOGE("Serial queue is invalid.");
646         return ERR_ANS_INVALID_PARAM;
647     }
648     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
649         ANS_LOGD("ffrt enter!");
650         NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
651     }));
652     notificationSvrQueue_->wait(handler);
653     // if get slot failed, it still return ok.
654     return ERR_OK;
655 }
656 
RemoveSlotByType(const NotificationConstant::SlotType & slotType)657 ErrCode AdvancedNotificationService::RemoveSlotByType(const NotificationConstant::SlotType &slotType)
658 {
659     ANS_LOGD("%{public}s", __FUNCTION__);
660 
661     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
662     if (bundleOption == nullptr) {
663         return ERR_ANS_INVALID_BUNDLE;
664     }
665 
666     if (notificationSvrQueue_ == nullptr) {
667         ANS_LOGE("notificationSvrQueue_ is nullptr.");
668         return ERR_ANS_INVALID_PARAM;
669     }
670 
671     ErrCode result = ERR_OK;
672     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
673         ANS_LOGD("ffrt enter!");
674         result = IsAllowedRemoveSlot(bundleOption, slotType);
675         if (result != ERR_OK) {
676             ANS_LOGE("Liveview slot cann't remove.");
677             return;
678         }
679 
680         NotificationPreferences::GetInstance()->RemoveNotificationSlot(bundleOption, slotType);
681     }));
682     notificationSvrQueue_->wait(handler);
683     // if remove slot failed, it still return ok.
684     return result;
685 }
686 
GetSlotNumAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint64_t & num)687 ErrCode AdvancedNotificationService::GetSlotNumAsBundle(
688     const sptr<NotificationBundleOption> &bundleOption, uint64_t &num)
689 {
690     ANS_LOGD("%{public}s", __FUNCTION__);
691 
692     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
693     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
694         return ERR_ANS_NON_SYSTEM_APP;
695     }
696 
697     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
698         return ERR_ANS_PERMISSION_DENIED;
699     }
700 
701     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
702     if (bundle == nullptr) {
703         ANS_LOGD("Bundle is null.");
704         return ERR_ANS_INVALID_BUNDLE;
705     }
706 
707     if (notificationSvrQueue_ == nullptr) {
708         ANS_LOGE("Serial queue is invalid.");
709         return ERR_ANS_INVALID_PARAM;
710     }
711     ErrCode result = ERR_OK;
712     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
713         ANS_LOGD("ffrt enter!");
714         result = NotificationPreferences::GetInstance()->GetNotificationSlotsNumForBundle(bundle, num);
715         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
716             result = ERR_OK;
717             num = 0;
718         }
719     }));
720     notificationSvrQueue_->wait(handler);
721 
722     return result;
723 }
724 
GetAllNotificationEnabledBundles(std::vector<NotificationBundleOption> & bundleOption)725 ErrCode AdvancedNotificationService::GetAllNotificationEnabledBundles(
726     std::vector<NotificationBundleOption> &bundleOption)
727 {
728     ANS_LOGD("Called.");
729     if (!AccessTokenHelper::IsSystemApp()) {
730         ANS_LOGE("Is not system app.");
731         return ERR_ANS_NON_SYSTEM_APP;
732     }
733     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
734         ANS_LOGE("Permission denied.");
735         return ERR_ANS_PERMISSION_DENIED;
736     }
737     if (notificationSvrQueue_ == nullptr) {
738         ANS_LOGE("Serial queue is invalid.");
739         return ERR_ANS_INVALID_PARAM;
740     }
741     ErrCode result = ERR_OK;
742     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
743         ANS_LOGD("ffrt enter!");
744         result = NotificationPreferences::GetInstance()->GetAllNotificationEnabledBundles(bundleOption);
745         if (result != ERR_OK) {
746             ANS_LOGE("Get all notification enable status failed");
747             return;
748         }
749     }));
750     notificationSvrQueue_->wait(handler);
751 
752     return result;
753 }
754 
PublishSlotChangeCommonEvent(const sptr<NotificationBundleOption> & bundleOption)755 bool AdvancedNotificationService::PublishSlotChangeCommonEvent(const sptr<NotificationBundleOption> &bundleOption)
756 {
757     if (bundleOption == nullptr) {
758         return false;
759     }
760     HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
761     ANS_LOGD("bundle [%{public}s : %{public}d]", bundleOption->GetBundleName().c_str(), bundleOption->GetUid());
762 
763     EventFwk::Want want;
764     AppExecFwk::ElementName element;
765     element.SetBundleName(bundleOption->GetBundleName());
766     want.SetElement(element);
767     want.SetParam(AppExecFwk::Constants::UID, bundleOption->GetUid());
768     want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_SLOT_CHANGE);
769     EventFwk::CommonEventData commonData {want};
770     if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData)) {
771         ANS_LOGE("PublishCommonEvent failed");
772         return false;
773     }
774 
775     return true;
776 }
777 
SetAdditionConfig(const std::string & key,const std::string & value)778 ErrCode AdvancedNotificationService::SetAdditionConfig(const std::string &key, const std::string &value)
779 {
780     ANS_LOGD("SetAdditionConfig called (%{public}s, %{public}s).", key.c_str(), value.c_str());
781     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_8, EventBranchId::BRANCH_1);
782     message.Message(" key:" + key + " value" + value);
783     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER)) {
784         ANS_LOGE("Permission denied.");
785         message.ErrorCode(ERR_ANS_PERMISSION_DENIED).Append(" Permission denied");
786         NotificationAnalyticsUtil::ReportModifyEvent(message);
787         return ERR_ANS_PERMISSION_DENIED;
788     }
789 
790     if (notificationSvrQueue_ == nullptr) {
791         ANS_LOGE("Serial queue is invalid.");
792         return ERR_ANS_INVALID_PARAM;
793     }
794 
795     if (key == RING_TRUST_PKG_KEY) {
796         std::lock_guard<std::mutex> lock(soundPermissionInfo_->dbMutex_);
797         soundPermissionInfo_->needUpdateCache_ = true;
798     }
799 
800     bool isSyncConfig = (strcmp(key.c_str(), KEY_NAME) == 0 ||
801         strcmp(key.c_str(), CTRL_LIST_KEY_NAME) == 0);
802     if (isSyncConfig) {
803 #ifdef ENABLE_ANS_EXT_WRAPPER
804     ErrCode sync_result = EXTENTION_WRAPPER->SyncAdditionConfig(key, value);
805     if (sync_result != ERR_OK) {
806         ANS_LOGE("Sync addition config result: %{public}d, key: %{public}s, value: %{public}s",
807             sync_result, key.c_str(), value.c_str());
808         message.Message("Set addition config " + key + " ret " + std::to_string(sync_result));
809         message.ErrorCode(sync_result);
810         NotificationAnalyticsUtil::ReportModifyEvent(message);
811         return sync_result;
812     }
813 #endif
814     }
815     ErrCode result = ERR_OK;
816     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
817         ANS_LOGD("ffrt enter!");
818         result = NotificationPreferences::GetInstance()->SetKvToDb(key, value, SUBSCRIBE_USER_INIT);
819     }));
820     notificationSvrQueue_->wait(handler);
821     ANS_LOGI("Set addition config result: %{public}d, key: %{public}s, value: %{public}s",
822         result, key.c_str(), value.c_str());
823     if (result != ERR_OK) {
824         message.ErrorCode(result);
825         message.Message("Set addition config " + key + " ret " + std::to_string(result));
826         NotificationAnalyticsUtil::ReportModifyEvent(message);
827     }
828     return result;
829 }
830 
IsAgentRelationship(const std::string & agentBundleName,const std::string & sourceBundleName)831 bool AdvancedNotificationService::IsAgentRelationship(const std::string &agentBundleName,
832     const std::string &sourceBundleName)
833 {
834     return NotificationPreferences::GetInstance()->IsAgentRelationship(agentBundleName, sourceBundleName);
835 }
836 }  // namespace Notification
837 }  // namespace OHOS
838