• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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",
558         slot->GetType(), slot->GetReminderMode(), bundleName.c_str());
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         (request->GetCreatorUid() == IPCSkeleton::GetCallingUid() && request->GetCreatorBundleName().empty() &&
568         request->GetOwnerBundleName().empty() && request->GetOwnerUid() == DEFAULT_UID)) {
569         return (flags |= NotificationConstant::ReminderFlag::BANNER_FLAG);
570     }
571 
572     return flags;
573 }
574 
SetRequestBySlotType(const sptr<NotificationRequest> & request,const sptr<NotificationBundleOption> & bundleOption)575 void AdvancedNotificationService::SetRequestBySlotType(const sptr<NotificationRequest> &request,
576     const sptr<NotificationBundleOption> &bundleOption)
577 {
578     ANS_LOGD("Called.");
579     NotificationConstant::SlotType type = request->GetSlotType();
580     auto flags = std::make_shared<NotificationFlags>();
581 
582     sptr<NotificationSlot> slot;
583     NotificationConstant::SlotType slotType = request->GetSlotType();
584     ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
585     if (slot == nullptr) {
586         slot = new (std::nothrow) NotificationSlot(slotType);
587         if (slot == nullptr) {
588             ANS_LOGE("Failed to create NotificationSlot instance");
589             return;
590         }
591         uint32_t slotFlags = GetDefaultSlotFlags(request);
592         GenerateSlotReminderMode(slot, bundleOption, false, slotFlags);
593     }
594 
595     auto slotReminderMode = slot->GetReminderMode();
596     if ((slotReminderMode & NotificationConstant::ReminderFlag::SOUND_FLAG) != 0) {
597         flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN);
598     }
599 
600     if ((slotReminderMode & NotificationConstant::ReminderFlag::LOCKSCREEN_FLAG) != 0) {
601         flags->SetLockScreenVisblenessEnabled(true);
602     }
603 
604     if ((slotReminderMode & NotificationConstant::ReminderFlag::BANNER_FLAG) != 0) {
605         flags->SetBannerEnabled(true);
606     }
607 
608     if ((slotReminderMode & NotificationConstant::ReminderFlag::LIGHTSCREEN_FLAG) != 0) {
609         flags->SetLightScreenEnabled(true);
610     }
611 
612     if ((slotReminderMode & NotificationConstant::ReminderFlag::VIBRATION_FLAG) != 0) {
613         flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN);
614     }
615 
616     if ((slotReminderMode & NotificationConstant::ReminderFlag::STATUSBAR_ICON_FLAG) != 0) {
617         flags->SetStatusIconEnabled(true);
618     }
619 
620     request->SetFlags(flags);
621     ANS_LOGI("SetFlags-GetRemindMode, notificationKey = %{public}s flags = %{public}d",
622         request->GetKey().c_str(), flags->GetReminderFlags());
623 #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED
624     DelayedSingleton<SmartReminderCenter>::GetInstance()->ReminderDecisionProcess(request);
625 #endif
626 }
627 
GetSlotByType(const NotificationConstant::SlotType & slotType,sptr<NotificationSlot> & slot)628 ErrCode AdvancedNotificationService::GetSlotByType(
629     const NotificationConstant::SlotType &slotType, sptr<NotificationSlot> &slot)
630 {
631     ANS_LOGD("%{public}s", __FUNCTION__);
632 
633     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
634     if (bundleOption == nullptr) {
635         ANS_LOGD("Failed to generateBundleOption.");
636         return ERR_ANS_INVALID_BUNDLE;
637     }
638 
639     if (notificationSvrQueue_ == nullptr) {
640         ANS_LOGE("Serial queue is invalid.");
641         return ERR_ANS_INVALID_PARAM;
642     }
643     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
644         ANS_LOGD("ffrt enter!");
645         NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot);
646     }));
647     notificationSvrQueue_->wait(handler);
648     // if get slot failed, it still return ok.
649     return ERR_OK;
650 }
651 
RemoveSlotByType(const NotificationConstant::SlotType & slotType)652 ErrCode AdvancedNotificationService::RemoveSlotByType(const NotificationConstant::SlotType &slotType)
653 {
654     ANS_LOGD("%{public}s", __FUNCTION__);
655 
656     sptr<NotificationBundleOption> bundleOption = GenerateBundleOption();
657     if (bundleOption == nullptr) {
658         return ERR_ANS_INVALID_BUNDLE;
659     }
660 
661     if (notificationSvrQueue_ == nullptr) {
662         ANS_LOGE("notificationSvrQueue_ is nullptr.");
663         return ERR_ANS_INVALID_PARAM;
664     }
665 
666     ErrCode result = ERR_OK;
667     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
668         ANS_LOGD("ffrt enter!");
669         result = IsAllowedRemoveSlot(bundleOption, slotType);
670         if (result != ERR_OK) {
671             ANS_LOGE("Liveview slot cann't remove.");
672             return;
673         }
674 
675         NotificationPreferences::GetInstance()->RemoveNotificationSlot(bundleOption, slotType);
676     }));
677     notificationSvrQueue_->wait(handler);
678     // if remove slot failed, it still return ok.
679     return result;
680 }
681 
GetSlotNumAsBundle(const sptr<NotificationBundleOption> & bundleOption,uint64_t & num)682 ErrCode AdvancedNotificationService::GetSlotNumAsBundle(
683     const sptr<NotificationBundleOption> &bundleOption, uint64_t &num)
684 {
685     ANS_LOGD("%{public}s", __FUNCTION__);
686 
687     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
688     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
689         return ERR_ANS_NON_SYSTEM_APP;
690     }
691 
692     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
693         return ERR_ANS_PERMISSION_DENIED;
694     }
695 
696     sptr<NotificationBundleOption> bundle = GenerateValidBundleOption(bundleOption);
697     if (bundle == nullptr) {
698         ANS_LOGD("Bundle is null.");
699         return ERR_ANS_INVALID_BUNDLE;
700     }
701 
702     if (notificationSvrQueue_ == nullptr) {
703         ANS_LOGE("Serial queue is invalid.");
704         return ERR_ANS_INVALID_PARAM;
705     }
706     ErrCode result = ERR_OK;
707     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
708         ANS_LOGD("ffrt enter!");
709         result = NotificationPreferences::GetInstance()->GetNotificationSlotsNumForBundle(bundle, num);
710         if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) {
711             result = ERR_OK;
712             num = 0;
713         }
714     }));
715     notificationSvrQueue_->wait(handler);
716 
717     return result;
718 }
719 
GetAllNotificationEnabledBundles(std::vector<NotificationBundleOption> & bundleOption)720 ErrCode AdvancedNotificationService::GetAllNotificationEnabledBundles(
721     std::vector<NotificationBundleOption> &bundleOption)
722 {
723     ANS_LOGD("Called.");
724     if (!AccessTokenHelper::IsSystemApp()) {
725         ANS_LOGE("Is not system app.");
726         return ERR_ANS_NON_SYSTEM_APP;
727     }
728     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) {
729         ANS_LOGE("Permission denied.");
730         return ERR_ANS_PERMISSION_DENIED;
731     }
732     if (notificationSvrQueue_ == nullptr) {
733         ANS_LOGE("Serial queue is invalid.");
734         return ERR_ANS_INVALID_PARAM;
735     }
736     ErrCode result = ERR_OK;
737     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
738         ANS_LOGD("ffrt enter!");
739         result = NotificationPreferences::GetInstance()->GetAllNotificationEnabledBundles(bundleOption);
740         if (result != ERR_OK) {
741             ANS_LOGE("Get all notification enable status failed");
742             return;
743         }
744     }));
745     notificationSvrQueue_->wait(handler);
746 
747     return result;
748 }
749 
PublishSlotChangeCommonEvent(const sptr<NotificationBundleOption> & bundleOption)750 bool AdvancedNotificationService::PublishSlotChangeCommonEvent(const sptr<NotificationBundleOption> &bundleOption)
751 {
752     if (bundleOption == nullptr) {
753         return false;
754     }
755     HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
756     ANS_LOGD("bundle [%{public}s : %{public}d]", bundleOption->GetBundleName().c_str(), bundleOption->GetUid());
757 
758     EventFwk::Want want;
759     AppExecFwk::ElementName element;
760     element.SetBundleName(bundleOption->GetBundleName());
761     want.SetElement(element);
762     want.SetParam(AppExecFwk::Constants::UID, bundleOption->GetUid());
763     want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_SLOT_CHANGE);
764     EventFwk::CommonEventData commonData {want};
765     if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData)) {
766         ANS_LOGE("PublishCommonEvent failed");
767         return false;
768     }
769 
770     return true;
771 }
772 
SetAdditionConfig(const std::string & key,const std::string & value)773 ErrCode AdvancedNotificationService::SetAdditionConfig(const std::string &key, const std::string &value)
774 {
775     ANS_LOGD("SetAdditionConfig called (%{public}s, %{public}s).", key.c_str(), value.c_str());
776     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_8, EventBranchId::BRANCH_1);
777     message.Message(" key:" + key + " value" + value);
778     if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER)) {
779         ANS_LOGE("Permission denied.");
780         message.ErrorCode(ERR_ANS_PERMISSION_DENIED).Append(" Permission denied");
781         NotificationAnalyticsUtil::ReportModifyEvent(message);
782         return ERR_ANS_PERMISSION_DENIED;
783     }
784 
785     if (notificationSvrQueue_ == nullptr) {
786         ANS_LOGE("Serial queue is invalid.");
787         return ERR_ANS_INVALID_PARAM;
788     }
789 
790     if (key == RING_TRUST_PKG_KEY) {
791         std::lock_guard<std::mutex> lock(soundPermissionInfo_->dbMutex_);
792         soundPermissionInfo_->needUpdateCache_ = true;
793     }
794 
795     bool isSyncConfig = (strcmp(key.c_str(), KEY_NAME) == 0 ||
796         strcmp(key.c_str(), CTRL_LIST_KEY_NAME) == 0);
797     if (isSyncConfig) {
798 #ifdef ENABLE_ANS_EXT_WRAPPER
799     ErrCode sync_result = EXTENTION_WRAPPER->SyncAdditionConfig(key, value);
800     if (sync_result != ERR_OK) {
801         ANS_LOGE("Sync addition config result: %{public}d, key: %{public}s, value: %{public}s",
802             sync_result, key.c_str(), value.c_str());
803         message.ErrorCode(sync_result).Append(" Sync failed");
804         NotificationAnalyticsUtil::ReportModifyEvent(message);
805         return sync_result;
806     }
807 #endif
808     }
809     ErrCode result = ERR_OK;
810     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() {
811         ANS_LOGD("ffrt enter!");
812         result = NotificationPreferences::GetInstance()->SetKvToDb(key, value, SUBSCRIBE_USER_INIT);
813     }));
814     notificationSvrQueue_->wait(handler);
815     ANS_LOGI("Set addition config result: %{public}d, key: %{public}s, value: %{public}s",
816         result, key.c_str(), value.c_str());
817     message.ErrorCode(result);
818     NotificationAnalyticsUtil::ReportModifyEvent(message);
819     return result;
820 }
821 
IsAgentRelationship(const std::string & agentBundleName,const std::string & sourceBundleName)822 bool AdvancedNotificationService::IsAgentRelationship(const std::string &agentBundleName,
823     const std::string &sourceBundleName)
824 {
825     return NotificationPreferences::GetInstance()->IsAgentRelationship(agentBundleName, sourceBundleName);
826 }
827 }  // namespace Notification
828 }  // namespace OHOS
829