/* * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "advanced_notification_service.h" #include #include #include #include "access_token_helper.h" #include "ans_inner_errors.h" #include "ans_log_wrapper.h" #include "ans_trace_wrapper.h" #include "ans_permission_def.h" #include "errors.h" #include "common_event_manager.h" #include "common_event_support.h" #include "os_account_manager_helper.h" #include "ipc_skeleton.h" #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED #include "smart_reminder_center.h" #endif #include "advanced_notification_inline.h" #include "notification_config_parse.h" #include "notification_extension_wrapper.h" #include "notification_analytics_util.h" #include "liveview_all_scenarios_extension_wrapper.h" namespace OHOS { namespace Notification { namespace { constexpr char KEY_NAME[] = "AGGREGATE_CONFIG"; constexpr char CTRL_LIST_KEY_NAME[] = "NOTIFICATION_CTL_LIST_PKG"; constexpr char CALL_UI_BUNDLE[] = "com.ohos.callui"; constexpr uint32_t NOTIFICATION_SETTING_FLAG_BASE = 0x11; const std::set unAffectDevices = { NotificationConstant::LITEWEARABLE_DEVICE_TYPE, NotificationConstant::WEARABLE_DEVICE_TYPE }; } ErrCode AdvancedNotificationService::AddSlots(const std::vector> &slots) { ANS_LOGD("called"); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { return ERR_ANS_PERMISSION_DENIED; } sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (slots.size() == 0) { return ERR_ANS_INVALID_PARAM; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); std::vector> addSlots; for (auto slot : slots) { sptr originalSlot; result =NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slot->GetType(), originalSlot); if ((result == ERR_OK) && (originalSlot != nullptr)) { continue; } GenerateSlotReminderMode(slot, bundleOption, true); addSlots.push_back(slot); } if (addSlots.size() == 0) { result = ERR_OK; } else { result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, addSlots); } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetSlots(std::vector> &slots) { ANS_LOGD("called"); std::vector> slots_temp; sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("NotificationSvrQueue_ is nullptr."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetNotificationAllSlots(bundleOption, slots); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; slots.clear(); } NotificationConstant::SWITCH_STATE enableStatus = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; result = NotificationPreferences::GetInstance()->IsSilentReminderEnabled(bundleOption, enableStatus); if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON) { for (auto slot : slots) { sptr value(new NotificationSlot(*slot)); value->SetReminderMode(value->GetSilentReminderMode()); slots_temp.emplace_back(value); ANS_LOGD("GetSlotsByBundle ReminderMode:%{public}d", value->GetReminderMode()); } slots = slots_temp; } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetSlotsByBundle( const sptr &bundleOption, std::vector> &slots) { ANS_LOGD("called"); std::vector> slots_temp; bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { ANS_LOGD("IsSystemApp is false."); return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { ANS_LOGD("GenerateValidBundleOption failed."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetNotificationAllSlots(bundle, slots); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; slots.clear(); } NotificationConstant::SWITCH_STATE enableStatus = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; result = NotificationPreferences::GetInstance()->IsSilentReminderEnabled(bundle, enableStatus); if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON) { for (auto slot : slots) { sptr value(new NotificationSlot(*slot)); value->SetReminderMode(value->GetSilentReminderMode()); slots_temp.emplace_back(value); ANS_LOGD("GetSlotsByBundle ReminderMode:%{public}d", slot->GetReminderMode()); } slots = slots_temp; } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetSlotByBundle( const sptr &bundleOption, int32_t slotTypeInt, sptr &slot) { ANS_LOGD("called"); NotificationConstant::SlotType slotType = static_cast(slotTypeInt); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { ANS_LOGD("IsSystemApp is false."); return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundleOption == nullptr) { ANS_LOGD("Failed to generateBundleOption."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; sptr slotFromDb = nullptr; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundle, slotType, slotFromDb); if (slotFromDb != nullptr) { slot = new (std::nothrow) NotificationSlot(*slotFromDb); } NotificationConstant::SWITCH_STATE enableStatus = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; NotificationPreferences::GetInstance()->IsSilentReminderEnabled(bundle, enableStatus); if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON && slot != nullptr) { slot->SetReminderMode(slot->GetSilentReminderMode()); } })); notificationSvrQueue_->wait(handler); if (slot != nullptr) { ANS_LOGD("GetSlotByBundle, authStatus: %{public}d), authHintCnt: %{public}d", slot->GetAuthorizedStatus(), slot->GetAuthHintCnt()); } return result; } ErrCode AdvancedNotificationService::UpdateSlots( const sptr &bundleOption, const std::vector> &slots) { ANS_LOGD("called"); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_6, EventBranchId::BRANCH_6); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Message("Not system app."); NotificationAnalyticsUtil::ReportModifyEvent(message); ANS_LOGE("Not system app."); return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { ANS_LOGD("AccessTokenHelper::CheckPermission is false."); message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Message("CheckPermission is false."); NotificationAnalyticsUtil::ReportModifyEvent(message); return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("notificationSvrQueue_ is nullptr."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->UpdateNotificationSlots(bundle, slots); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST; message.ErrorCode(result).Message("Slot type not exist."); NotificationAnalyticsUtil::ReportModifyEvent(message); ANS_LOGE("Slot type not exist."); } })); notificationSvrQueue_->wait(handler); if (result == ERR_OK) { PublishSlotChangeCommonEvent(bundle); } return result; } ErrCode AdvancedNotificationService::RemoveAllSlots() { ANS_LOGD("called"); sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { ANS_LOGD("GenerateBundleOption defeat."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); sptr liveViewSlot; bool isLiveViewSlotExist = true; // retain liveview slot before removeNotificationAllSlots if (NotificationPreferences::GetInstance()->GetNotificationSlot( bundleOption, NotificationConstant::SlotType::LIVE_VIEW, liveViewSlot) != ERR_OK) { isLiveViewSlotExist = false; } result = NotificationPreferences::GetInstance()->RemoveNotificationAllSlots(bundleOption); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; } if (!isLiveViewSlotExist) { return; } // retain liveview slot when caller is not sa or systemapp if ((result == ERR_OK) && (IsAllowedRemoveSlot(bundleOption, NotificationConstant::SlotType::LIVE_VIEW) != ERR_OK)) { std::vector> slots; slots.push_back(liveViewSlot); (void)NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, slots); } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::AddSlotByType(int32_t slotTypeInt) { ANS_LOGD("called"); NotificationConstant::SlotType slotType = static_cast(slotTypeInt); if (!AccessTokenHelper::IsSystemApp() && slotType == NotificationConstant::SlotType::EMERGENCY_INFORMATION) { ANS_LOGE("Non system app used illegal slot type."); return ERR_ANS_INVALID_PARAM; } sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalidity."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); sptr slot; result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot); if ((result == ERR_OK) && (slot != nullptr)) { return; } slot = new (std::nothrow) NotificationSlot(slotType); if (slot == nullptr) { ANS_LOGE("Failed to create NotificationSlot instance"); return; } GenerateSlotReminderMode(slot, bundleOption); std::vector> slots; slots.push_back(slot); result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, slots); })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetEnabledForBundleSlotSelf(int32_t slotTypeInt, bool &enabled) { NotificationConstant::SlotType slotType = static_cast(slotTypeInt); ANS_LOGD("slotType: %{public}d", slotType); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_15, EventBranchId::BRANCH_0); message.Message("st:" + std::to_string(slotType) + "en:" + std::to_string(enabled)); sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); sptr slot; result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot); if (result != ERR_OK) { ANS_LOGE("Get enable slot self: GetNotificationSlot failed"); return; } if (slot == nullptr) { ANS_LOGW("Get enable slot: object is null, enabled default true"); enabled = true; result = ERR_OK; return; } enabled = slot->GetEnable(); })); notificationSvrQueue_->wait(handler); NotificationAnalyticsUtil::ReportModifyEvent(message); return result; } ErrCode AdvancedNotificationService::GetSlotFlagsAsBundle(const sptr &bundleOption, uint32_t &slotFlags) { ANS_LOGD("called"); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { ANS_LOGD("Bundle is null."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetNotificationSlotFlagsForBundle(bundle, slotFlags); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; slotFlags = DEFAULT_SLOT_FLAGS; } NotificationConstant::SWITCH_STATE enableStatus = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; NotificationPreferences::GetInstance()->IsSilentReminderEnabled(bundle, enableStatus); if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON) { slotFlags = SILENT_REMINDER__SLOT_FLAGS; } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetNotificationSettings(uint32_t &slotFlags) { ANS_LOGD("called"); sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { ANS_LOGD("Failed to generateBundleOption."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetNotificationSlotFlagsForBundle(bundleOption, slotFlags); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; slotFlags = DEFAULT_SLOT_FLAGS; } slotFlags = slotFlags & NOTIFICATION_SETTING_FLAG_BASE; })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::SetSlotFlagsAsBundle(const sptr &bundleOption, uint32_t slotFlags) { ANS_LOGD("called"); if (bundleOption == nullptr) { ANS_LOGE("BundleOption is null."); return ERR_ANS_INVALID_BUNDLE; } HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_8, EventBranchId::BRANCH_2); message.Message(bundleOption->GetBundleName() + "_" + std::to_string(bundleOption->GetUid()) + " slotFlags:" + std::to_string(slotFlags)); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { ANS_LOGE("IsSystemApp is false."); message.ErrorCode(ERR_ANS_NON_SYSTEM_APP).Append(" Not SystemApp"); NotificationAnalyticsUtil::ReportModifyEvent(message); return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { ANS_LOGE("Permission denied."); message.ErrorCode(ERR_ANS_PERMISSION_DENIED).Append(" Permission denied"); NotificationAnalyticsUtil::ReportModifyEvent(message); return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { ANS_LOGE("Bundle is null."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalidity."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h( std::bind([&]() { result = NotificationPreferences::GetInstance()->SetNotificationSlotFlagsForBundle(bundle, slotFlags); if (result != ERR_OK) { return; } ANS_LOGI("Set slotflags %{public}d to %{public}s.", slotFlags, bundle->GetBundleName().c_str()); result = UpdateSlotReminderModeBySlotFlags(bundle, slotFlags); })); notificationSvrQueue_->wait(handler); ANS_LOGI("%{public}s_%{public}d, slotFlags: %{public}d, SetSlotFlagsAsBundle result: %{public}d", bundleOption->GetBundleName().c_str(), bundleOption->GetUid(), slotFlags, result); message.ErrorCode(result); NotificationAnalyticsUtil::ReportModifyEvent(message); return result; } ErrCode AdvancedNotificationService::AssignValidNotificationSlot(const std::shared_ptr &record, const sptr &bundleOption) { sptr slot; NotificationConstant::SlotType slotType = record->request->GetSlotType(); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_7, EventBranchId::BRANCH_3).SlotType(slotType); ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot); if ((result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) || (result == ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST)) { slot = new (std::nothrow) NotificationSlot(slotType); if (slot == nullptr) { ANS_LOGE("Failed to create NotificationSlot instance"); return ERR_NO_MEMORY; } GenerateSlotReminderMode(slot, bundleOption); if (record->request->IsSystemLiveView() || record->isAtomicService) { ANS_LOGI("System live view or atomicService no need add sloty."); result = ERR_OK; } else { std::vector> slots; slots.push_back(slot); result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundleOption, slots); } } if (result == ERR_OK) { std::string bundleName = bundleOption->GetBundleName(); if (slot != nullptr && (bundleName == CALL_UI_BUNDLE || slot->GetEnable() || record->request->IsSystemLiveView() || (slot->GetType() == NotificationConstant::SlotType::LIVE_VIEW && DelayedSingleton::GetInstance()->IsLiveViewEnabled(bundleName)))) { record->slot = slot; } else { result = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_ENABLED; ANS_LOGE("Type[%{public}d] slot enable closed", slotType); } } if (result != ERR_OK) { message.ErrorCode(result).Message("assign slot failed"); NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); } return result; } ErrCode AdvancedNotificationService::UpdateSlotReminderModeBySlotFlags( const sptr &bundle, uint32_t slotFlags) { std::vector> slots; HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_1); ErrCode ret = NotificationPreferences::GetInstance()->GetNotificationAllSlots(bundle, slots); if (ret != ERR_OK) { message.Message("Failed to get slots by bundle, ret:" + std::to_string(ret), true); NotificationAnalyticsUtil::ReportModifyEvent(message); return ret; } message.BundleName((bundle == nullptr) ? "" : bundle->GetBundleName()); if (slots.empty()) { message.Message("The bundle has no slots.", true); NotificationAnalyticsUtil::ReportModifyEvent(message); return ERR_OK; } for (auto slot : slots) { auto configSlotReminderMode = DelayedSingleton::GetInstance()->GetConfigSlotReminderModeByType(slot->GetType()); slot->SetReminderMode(slotFlags & configSlotReminderMode); std::string bundleName = (bundle == nullptr) ? "" : bundle->GetBundleName(); ANS_LOGD("Update reminderMode of %{public}d in %{public}s, value is %{public}d.", slot->GetType(), bundleName.c_str(), slot->GetReminderMode()); } ret = NotificationPreferences::GetInstance()->UpdateNotificationSlots(bundle, slots); if (ret == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { ret = ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST; message.ErrorCode(ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST).Message("Slot type not exist."); NotificationAnalyticsUtil::ReportModifyEvent(message); } return ret; } void AdvancedNotificationService::GenerateSlotReminderMode(const sptr &slot, const sptr &bundle, bool isSpecifiedSlot, uint32_t defaultSlotFlags) { uint32_t slotFlags = defaultSlotFlags; auto ret = NotificationPreferences::GetInstance()->GetNotificationSlotFlagsForBundle(bundle, slotFlags); if (ret != ERR_OK) { ANS_LOGE("Failed to get slotflags for bundle, use default slotflags"); } auto configSlotReminderMode = DelayedSingleton::GetInstance()->GetConfigSlotReminderModeByType(slot->GetType()); if (isSpecifiedSlot) { slot->SetReminderMode(configSlotReminderMode & slotFlags & slot->GetReminderMode()); } else { slot->SetReminderMode(configSlotReminderMode & slotFlags); } std::string bundleName = (bundle == nullptr) ? "" : bundle->GetBundleName(); ANS_LOGI("The reminder mode of %{public}d is %{public}d in %{public}s,specifiedSlot:%{public}d default:%{public}u", slot->GetType(), slot->GetReminderMode(), bundleName.c_str(), isSpecifiedSlot, defaultSlotFlags); } uint32_t AdvancedNotificationService::GetDefaultSlotFlags(const sptr &request) { auto flags = DEFAULT_SLOT_FLAGS; uint32_t notificationControlFlags = request->GetNotificationControlFlags(); // SA publish own's notification with banner if ((notificationControlFlags & NotificationConstant::ReminderFlag::SA_SELF_BANNER_FLAG) != 0) { ANS_LOGI("Creator:%{public}s %{public}d,Owner: %{public}s %{public}d, controlFlags:%{public}d", request->GetCreatorBundleName().c_str(), request->GetCreatorUid(), request->GetOwnerBundleName().c_str(), request->GetOwnerUid(), request->GetNotificationControlFlags()); } if (((notificationControlFlags & NotificationConstant::ReminderFlag::SA_SELF_BANNER_FLAG) != 0) && (request->GetCreatorUid() == IPCSkeleton::GetCallingUid() && request->GetCreatorBundleName().empty() && request->GetOwnerBundleName().empty())) { return (flags |= NotificationConstant::ReminderFlag::BANNER_FLAG); } return flags; } void AdvancedNotificationService::SetRequestBySlotType(const sptr &request, const sptr &bundleOption) { ANS_LOGD("Called."); auto flags = std::make_shared(); request->SetFlags(flags); #ifdef NOTIFICATION_SMART_REMINDER_SUPPORTED bool systemVoip = (request->GetClassification() == NotificationConstant::ANS_VOIP && request->GetSlotType() == NotificationConstant::LIVE_VIEW); if (!systemVoip) { DelayedSingleton::GetInstance()->ReminderDecisionProcess(request); } else { ANS_LOGI("systemVoip"); } #endif NotificationConstant::SlotType type = request->GetSlotType(); sptr slot; NotificationConstant::SlotType slotType = request->GetSlotType(); ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot); if (slot == nullptr) { slot = new (std::nothrow) NotificationSlot(slotType); if (slot == nullptr) { ANS_LOGE("Failed to create NotificationSlot instance"); return; } uint32_t slotFlags = GetDefaultSlotFlags(request); GenerateSlotReminderMode(slot, bundleOption, false, slotFlags); } auto slotReminderMode = slot->GetReminderMode(); if ((slotReminderMode & NotificationConstant::ReminderFlag::SOUND_FLAG) != 0) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::SOUND_FLAG, true); } else { request->SetDistributedFlagBit( NotificationConstant::ReminderFlag::SOUND_FLAG, false, unAffectDevices); } if ((slotReminderMode & NotificationConstant::ReminderFlag::LOCKSCREEN_FLAG) != 0) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::LOCKSCREEN_FLAG, true); } else { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::LOCKSCREEN_FLAG, false); } if ((slotReminderMode & NotificationConstant::ReminderFlag::BANNER_FLAG) != 0) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::BANNER_FLAG, true); } else { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::BANNER_FLAG, false); } if ((slotReminderMode & NotificationConstant::ReminderFlag::LIGHTSCREEN_FLAG) != 0) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::LIGHTSCREEN_FLAG, true); } else { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::LIGHTSCREEN_FLAG, false); } if ((slotReminderMode & NotificationConstant::ReminderFlag::VIBRATION_FLAG) != 0) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::VIBRATION_FLAG, true); } else { request->SetDistributedFlagBit( NotificationConstant::ReminderFlag::VIBRATION_FLAG, false, unAffectDevices); } if ((slotReminderMode & NotificationConstant::ReminderFlag::STATUSBAR_ICON_FLAG) != 0) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::STATUSBAR_ICON_FLAG, true); } else { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::STATUSBAR_ICON_FLAG, false); } ANS_LOGI("SetFlags-init,Key = %{public}s flags = %{public}d", request->GetKey().c_str(), request->GetFlags()->GetReminderFlags()); HandleFlagsWithRequest(request, bundleOption); } void AdvancedNotificationService::HandleFlagsWithRequest(const sptr &request, const sptr &bundleOption) { NotificationConstant::SWITCH_STATE enableStatus = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; if (request->IsCommonLiveView()) { LIVEVIEW_ALL_SCENARIOS_EXTENTION_WRAPPER->UpdateLiveviewReminderFlags(request); LIVEVIEW_ALL_SCENARIOS_EXTENTION_WRAPPER->UpdateLiveviewVoiceContent(request); } else if (!request->IsSystemLiveView()) { NotificationPreferences::GetInstance()->IsSilentReminderEnabled(bundleOption, enableStatus); if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON) { request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::SOUND_FLAG, false, unAffectDevices); request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::LOCKSCREEN_FLAG, false); request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::BANNER_FLAG, false); request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::LIGHTSCREEN_FLAG, false); request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::VIBRATION_FLAG, false, unAffectDevices); } } ANS_LOGI("SetFlags- HandleFlag Key = %{public}s flags = %{public}d class = %{public}s silent = %{public}d", request->GetKey().c_str(), request->GetFlags()->GetReminderFlags(), request->GetClassification().c_str(), enableStatus); if (request->GetClassification() == NotificationConstant::ANS_VOIP && request->GetSlotType() == NotificationConstant::LIVE_VIEW) { return; } } ErrCode AdvancedNotificationService::GetSlotByType(int32_t slotTypeInt, sptr &slot) { ANS_LOGD("called"); NotificationConstant::SlotType slotType = static_cast(slotTypeInt); sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { ANS_LOGD("Failed to generateBundleOption."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } sptr slotFromDb = nullptr; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGI("ffrt enter!"); NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slotFromDb); if (slotFromDb != nullptr) { ANS_LOGI("slotFromDb != nullptr"); slot = new (std::nothrow) NotificationSlot(*slotFromDb); } NotificationConstant::SWITCH_STATE enableStatus = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; NotificationPreferences::GetInstance()->IsSilentReminderEnabled(bundleOption, enableStatus); if (enableStatus == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON && slot != nullptr) { slot->SetReminderMode(slot->GetSilentReminderMode()); } })); notificationSvrQueue_->wait(handler); // if get slot failed, it still return ok. return ERR_OK; } ErrCode AdvancedNotificationService::RemoveSlotByType(int32_t slotTypeInt) { ANS_LOGD("called"); NotificationConstant::SlotType slotType = static_cast(slotTypeInt); sptr bundleOption = GenerateBundleOption(); if (bundleOption == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("notificationSvrQueue_ is nullptr."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = IsAllowedRemoveSlot(bundleOption, slotType); if (result != ERR_OK) { ANS_LOGE("Liveview slot cann't remove."); return; } NotificationPreferences::GetInstance()->RemoveNotificationSlot(bundleOption, slotType); })); notificationSvrQueue_->wait(handler); // if remove slot failed, it still return ok. return result; } ErrCode AdvancedNotificationService::GetSlotNumAsBundle( const sptr &bundleOption, uint64_t &num) { ANS_LOGD("called"); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { ANS_LOGD("Bundle is null."); return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetNotificationSlotsNumForBundle(bundle, num); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; num = 0; } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::AddSlotThenPublishEvent( const sptr &slot, const sptr &bundle, bool enabled, bool isForceControl) { bool allowed = false; NotificationConstant::SWITCH_STATE state = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; ErrCode result = NotificationPreferences::GetInstance()->GetNotificationsEnabledForBundle(bundle, state); if (result == ERR_OK) { allowed = (state == NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_ON || state == NotificationConstant::SWITCH_STATE::USER_MODIFIED_ON); } if (result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { result = ERR_OK; allowed = CheckApiCompatibility(bundle); SetDefaultNotificationEnabled(bundle, allowed); } slot->SetEnable(enabled); slot->SetForceControl(isForceControl); slot->SetAuthorizedStatus(NotificationSlot::AuthorizedStatus::AUTHORIZED); std::vector> slots; slots.push_back(slot); result = NotificationPreferences::GetInstance()->AddNotificationSlots(bundle, slots); if (result != ERR_OK) { ANS_LOGE("Set enable slot: AddNotificationSlot failed"); return result; } if (!slot->GetEnable()) { RemoveNotificationBySlot(bundle, slot, NotificationConstant::DISABLE_SLOT_REASON_DELETE); } else { if (!slot->GetForceControl() && !allowed) { RemoveNotificationBySlot(bundle, slot, NotificationConstant::DISABLE_NOTIFICATION_REASON_DELETE); } } PublishSlotChangeCommonEvent(bundle); return result; } ErrCode AdvancedNotificationService::SetEnabledForBundleSlotInner( const sptr &bundleOption, const sptr &bundle, const NotificationConstant::SlotType &slotType, bool enabled, bool isForceControl) { sptr slot; ErrCode result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundle, slotType, slot); if (result == ERR_ANS_PREFERENCES_NOTIFICATION_SLOT_TYPE_NOT_EXIST || result == ERR_ANS_PREFERENCES_NOTIFICATION_BUNDLE_NOT_EXIST) { slot = new (std::nothrow) NotificationSlot(slotType); if (slot == nullptr) { ANS_LOGE("Failed to create NotificationSlot ptr."); return ERR_ANS_NO_MEMORY; } GenerateSlotReminderMode(slot, bundleOption); return AddSlotThenPublishEvent(slot, bundle, enabled, isForceControl); } else if ((result == ERR_OK) && (slot != nullptr)) { if (slot->GetEnable() == enabled && slot->GetForceControl() == isForceControl) { slot->SetAuthorizedStatus(NotificationSlot::AuthorizedStatus::AUTHORIZED); std::vector> slots; slots.push_back(slot); return NotificationPreferences::GetInstance()->AddNotificationSlots(bundle, slots); } NotificationPreferences::GetInstance()->RemoveNotificationSlot(bundle, slotType); return AddSlotThenPublishEvent(slot, bundle, enabled, isForceControl); } ANS_LOGE("Set enable slot: GetNotificationSlot failed"); return result; } ErrCode AdvancedNotificationService::SetEnabledForBundleSlot(const sptr &bundleOption, int32_t slotTypeInt, bool enabled, bool isForceControl) { NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION); NotificationConstant::SlotType slotType = static_cast(slotTypeInt); ANS_LOGD("slotType: %{public}d, enabled: %{public}d, isForceControl: %{public}d", slotType, enabled, isForceControl); ErrCode result = CheckCommonParams(); if (result != ERR_OK) { return result; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { return ERR_ANS_INVALID_BUNDLE; } HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_5, EventBranchId::BRANCH_4); message.Message(bundleOption->GetBundleName() + "_" +std::to_string(bundleOption->GetUid()) + " slotType: " + std::to_string(static_cast(slotType)) + " enabled: " +std::to_string(enabled) + "isForceControl" + std::to_string(isForceControl)); ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { result = SetEnabledForBundleSlotInner(bundleOption, bundle, slotType, enabled, isForceControl); })); notificationSvrQueue_->wait(handler); SendEnableNotificationSlotHiSysEvent(bundleOption, slotType, enabled, result); message.ErrorCode(result); NotificationAnalyticsUtil::ReportModifyEvent(message); ANS_LOGI("%{public}s_%{public}d, SetEnabledForBundleSlot successful.", bundleOption->GetBundleName().c_str(), bundleOption->GetUid()); return result; } ErrCode AdvancedNotificationService::GetEnabledForBundleSlot( const sptr &bundleOption, int32_t slotTypeInt, bool &enabled) { NotificationConstant::SlotType slotType = static_cast(slotTypeInt); ANS_LOGD("slotType: %{public}d", slotType); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { ANS_LOGD("VerifyNativeToken and isSystemApp failed."); return ERR_ANS_NON_SYSTEM_APP; } if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { return ERR_ANS_PERMISSION_DENIED; } sptr bundle = GenerateValidBundleOption(bundleOption); if (bundle == nullptr) { return ERR_ANS_INVALID_BUNDLE; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); sptr slot; result = NotificationPreferences::GetInstance()->GetNotificationSlot(bundle, slotType, slot); if (result != ERR_OK) { ANS_LOGE("Get slot failed %{public}d", result); return; } if (slot == nullptr) { ANS_LOGW("null slot, default true"); enabled = true; result = ERR_OK; return; } enabled = slot->GetEnable(); })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetAllLiveViewEnabledBundles( std::vector &bundleOption) { ANS_LOGD("Called."); if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { ANS_LOGE("Permission denied."); return ERR_ANS_PERMISSION_DENIED; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } int32_t userId = 100; OsAccountManagerHelper::GetInstance().GetCurrentActiveUserId(userId); ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&, userId]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->GetAllLiveViewEnabledBundles(userId, bundleOption); if (result != ERR_OK) { ANS_LOGE("Get all notification enable status failed"); return; } })); notificationSvrQueue_->wait(handler); return result; } bool AdvancedNotificationService::PublishSlotChangeCommonEvent(const sptr &bundleOption) { if (bundleOption == nullptr) { return false; } NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION); ANS_LOGD("bundle [%{public}s : %{public}d]", bundleOption->GetBundleName().c_str(), bundleOption->GetUid()); EventFwk::Want want; AppExecFwk::ElementName element; element.SetBundleName(bundleOption->GetBundleName()); want.SetElement(element); want.SetParam(AppExecFwk::Constants::UID, bundleOption->GetUid()); want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_SLOT_CHANGE); EventFwk::CommonEventData commonData {want}; if (!EventFwk::CommonEventManager::PublishCommonEvent(commonData)) { ANS_LOGE("PublishCommonEvent failed"); return false; } return true; } ErrCode AdvancedNotificationService::SetAdditionConfig(const std::string &key, const std::string &value) { ANS_LOGD("SetAdditionConfig called (%{public}s, %{public}s).", key.c_str(), value.c_str()); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_8, EventBranchId::BRANCH_1); message.Message(" key:" + key + " value" + value); if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER) && !AccessTokenHelper::CheckPermission(OHOS_PERMISSION_MANAGE_EDM_POLICY)) { ANS_LOGE("Permission denied."); message.ErrorCode(ERR_ANS_PERMISSION_DENIED).Append(" Permission denied"); NotificationAnalyticsUtil::ReportModifyEvent(message); return ERR_ANS_PERMISSION_DENIED; } if (notificationSvrQueue_ == nullptr) { ANS_LOGE("Serial queue is invalid."); return ERR_ANS_INVALID_PARAM; } if (key == RING_TRUST_PKG_KEY) { std::lock_guard lock(soundPermissionInfo_->dbMutex_); soundPermissionInfo_->needUpdateCache_ = true; } bool isSyncConfig = (strcmp(key.c_str(), KEY_NAME) == 0 || strcmp(key.c_str(), CTRL_LIST_KEY_NAME) == 0); if (isSyncConfig) { #ifdef ENABLE_ANS_EXT_WRAPPER ErrCode sync_result = EXTENTION_WRAPPER->SyncAdditionConfig(key, value); if (sync_result != ERR_OK) { ANS_LOGE("Sync addition config result: %{public}d, key: %{public}s, value: %{public}s", sync_result, key.c_str(), value.c_str()); message.ErrorCode(sync_result).Append(" Sync failed"); NotificationAnalyticsUtil::ReportModifyEvent(message); return sync_result; } #endif } ErrCode result = ERR_OK; ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); result = NotificationPreferences::GetInstance()->SetKvToDb(key, value, SUBSCRIBE_USER_INIT); })); notificationSvrQueue_->wait(handler); ANS_LOGI("Set addition config result: %{public}d, key: %{public}s, value: %{public}s", result, key.c_str(), value.c_str()); message.ErrorCode(result); NotificationAnalyticsUtil::ReportModifyEvent(message); return result; } bool AdvancedNotificationService::IsAgentRelationship(const std::string &agentBundleName, const std::string &sourceBundleName) { return NotificationPreferences::GetInstance()->IsAgentRelationship(agentBundleName, sourceBundleName); } } // namespace Notification } // namespace OHOS