/* * Copyright (c) 2021-2023 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_permission_def.h" #include "errors.h" #include "common_event_manager.h" #include "common_event_support.h" #include "hitrace_meter_adapter.h" #include "ipc_skeleton.h" #include "advanced_notification_inline.cpp" namespace OHOS { namespace Notification { ErrCode AdvancedNotificationService::AddSlots(const std::vector> &slots) { ANS_LOGD("%{public}s", __FUNCTION__); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!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; } else { 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("%{public}s", __FUNCTION__); 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(); } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetSlotsByBundle( const sptr &bundleOption, std::vector> &slots) { ANS_LOGD("%{public}s", __FUNCTION__); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { ANS_LOGD("IsSystemApp is false."); return ERR_ANS_NON_SYSTEM_APP; } if (!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(); } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::UpdateSlots( const sptr &bundleOption, const std::vector> &slots) { ANS_LOGD("%{public}s", __FUNCTION__); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!CheckPermission(OHOS_PERMISSION_NOTIFICATION_CONTROLLER)) { ANS_LOGD("CheckPermission is false."); 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; } })); notificationSvrQueue_->wait(handler); if (result == ERR_OK) { PublishSlotChangeCommonEvent(bundle); } return result; } ErrCode AdvancedNotificationService::RemoveAllSlots() { ANS_LOGD("%{public}s", __FUNCTION__); 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(NotificationConstant::SlotType slotType) { ANS_LOGD("%{public}s", __FUNCTION__); 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; } else { slot = new (std::nothrow) NotificationSlot(slotType); if (slot == nullptr) { ANS_LOGE("Failed to create NotificationSlot instance"); return; } std::vector> slots; slots.push_back(slot); result = NotificationPreferences::GetInstance().AddNotificationSlots(bundleOption, slots); } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::GetEnabledForBundleSlotSelf( const NotificationConstant::SlotType &slotType, bool &enabled) { ANS_LOGD("slotType: %{public}d", slotType); 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); return result; } ErrCode AdvancedNotificationService::GetSlotFlagsAsBundle(const sptr &bundleOption, uint32_t &slotFlags) { ANS_LOGD("%{public}s", __FUNCTION__); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!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 = 0; } })); notificationSvrQueue_->wait(handler); return result; } ErrCode AdvancedNotificationService::SetSlotFlagsAsBundle(const sptr &bundleOption, uint32_t slotFlags) { ANS_LOGD("%{public}s", __FUNCTION__); if (bundleOption == nullptr) { ANS_LOGD("BundleOption is null."); return ERR_ANS_INVALID_BUNDLE; } bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { ANS_LOGD("IsSystemApp is false."); return ERR_ANS_NON_SYSTEM_APP; } if (!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 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); })); notificationSvrQueue_->wait(handler); return result; } void AdvancedNotificationService::SetRequestBySlotType(const sptr &request) { ANS_LOGD("%{public}s", __FUNCTION__); NotificationConstant::SlotType type = request->GetSlotType(); auto flags = std::make_shared(); switch (type) { case NotificationConstant::SlotType::SOCIAL_COMMUNICATION: flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN); flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN); break; case NotificationConstant::SlotType::SERVICE_REMINDER: flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN); flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN); break; case NotificationConstant::SlotType::CONTENT_INFORMATION: flags->SetSoundEnabled(NotificationConstant::FlagStatus::CLOSE); flags->SetVibrationEnabled(NotificationConstant::FlagStatus::CLOSE); break; case NotificationConstant::SlotType::LIVE_VIEW: flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN); flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN); break; case NotificationConstant::SlotType::OTHER: flags->SetSoundEnabled(NotificationConstant::FlagStatus::CLOSE); flags->SetVibrationEnabled(NotificationConstant::FlagStatus::CLOSE); break; case NotificationConstant::SlotType::CUSTOMER_SERVICE: flags->SetSoundEnabled(NotificationConstant::FlagStatus::OPEN); flags->SetVibrationEnabled(NotificationConstant::FlagStatus::OPEN); break; default: break; } request->SetFlags(flags); } ErrCode AdvancedNotificationService::GetSlotByType( const NotificationConstant::SlotType &slotType, sptr &slot) { ANS_LOGD("%{public}s", __FUNCTION__); 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; } ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); NotificationPreferences::GetInstance().GetNotificationSlot(bundleOption, slotType, slot); })); notificationSvrQueue_->wait(handler); // if get slot failed, it still return ok. return ERR_OK; } ErrCode AdvancedNotificationService::RemoveSlotByType(const NotificationConstant::SlotType &slotType) { ANS_LOGD("%{public}s", __FUNCTION__); 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("%{public}s", __FUNCTION__); bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID()); if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) { return ERR_ANS_NON_SYSTEM_APP; } if (!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; } bool AdvancedNotificationService::PublishSlotChangeCommonEvent(const sptr &bundleOption) { if (bundleOption == nullptr) { return false; } HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__); 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; } } // namespace Notification } // namespace OHOS