From 492b6c3eb748dfd7103e7652f2326d5d2f81a3b7 Mon Sep 17 00:00:00 2001 From: zhengzhuolan Date: Thu, 11 Sep 2025 19:44:47 +0800 Subject: [PATCH] extension subscription: subscribe info Signed-off-by: zhengzhuolan --- bundle.json | 1 + frameworks/ans/BUILD.gn | 1 + frameworks/ans/IAnsManager.idl | 7 + ...tification_extension_subscription_info.cpp | 148 +++++++ frameworks/ans/src/notification_helper.cpp | 16 + .../core/common/include/ans_convert_enum.h | 24 +- .../core/common/include/ans_permission_def.h | 3 +- .../core/common/src/ans_convert_enum.cpp | 29 +- frameworks/core/include/ans_notification.h | 23 ++ frameworks/core/src/ans_notification.cpp | 44 +++ frameworks/js/napi/BUILD.gn | 8 +- frameworks/js/napi/include/constant.h | 3 +- .../extension_subscription/init_module.h | 50 +++ .../napi_notification_extension.h | 36 ++ frameworks/js/napi/src/constant.cpp | 20 +- .../napi/src/extension_subscription/BUILD.gn | 94 +++++ .../extension_subscription/init_module.cpp | 63 +++ .../napi_notification_extension.cpp | 360 ++++++++++++++++++ interfaces/inner_api/notification_constant.h | 6 +- ...notification_extension_subscription_info.h | 138 +++++++ interfaces/inner_api/notification_helper.h | 23 ++ services/ans/BUILD.gn | 1 + .../include/advanced_notification_service.h | 8 + .../include/notification_clone_bundle_info.h | 8 +- .../ans/include/notification_preferences.h | 5 + .../notification_preferences_database.h | 3 + .../include/notification_preferences_info.h | 6 + ...ed_notification_extension_subscription.cpp | 141 +++++++ .../ans/src/advanced_notification_utils.cpp | 8 +- .../clone/notification_clone_bundle_info.cpp | 37 +- services/ans/src/notification_preferences.cpp | 59 +++ .../src/notification_preferences_database.cpp | 37 ++ .../ans/src/notification_preferences_info.cpp | 48 +++ 33 files changed, 1448 insertions(+), 10 deletions(-) create mode 100644 frameworks/ans/src/notification_extension_subscription_info.cpp create mode 100644 frameworks/js/napi/include/extension_subscription/init_module.h create mode 100644 frameworks/js/napi/include/extension_subscription/napi_notification_extension.h create mode 100644 frameworks/js/napi/src/extension_subscription/BUILD.gn create mode 100644 frameworks/js/napi/src/extension_subscription/init_module.cpp create mode 100644 frameworks/js/napi/src/extension_subscription/napi_notification_extension.cpp create mode 100644 interfaces/inner_api/notification_extension_subscription_info.h create mode 100644 services/ans/src/advanced_notification_extension_subscription.cpp diff --git a/bundle.json b/bundle.json index 9a6f3ee2e..7c191896c 100644 --- a/bundle.json +++ b/bundle.json @@ -130,6 +130,7 @@ ], "fwk_group": [ "//base/notification/distributed_notification_service/frameworks/ans:ans_client", + "//base/notification/distributed_notification_service/frameworks/js/napi:napi_extension_subscription", "//base/notification/distributed_notification_service/frameworks/js/napi:napi_notification", "//base/notification/distributed_notification_service/frameworks/js/napi:napi_reminder", "//base/notification/distributed_notification_service/interfaces/ndk:ohnotification", diff --git a/frameworks/ans/BUILD.gn b/frameworks/ans/BUILD.gn index f930ffb37..eb515c408 100644 --- a/frameworks/ans/BUILD.gn +++ b/frameworks/ans/BUILD.gn @@ -102,6 +102,7 @@ ohos_shared_library("ans_innerkits") { "${frameworks_module_ans_path}/src/notification_distributed_options.cpp", "${frameworks_module_ans_path}/src/notification_do_not_disturb_date.cpp", "${frameworks_module_ans_path}/src/notification_do_not_disturb_profile.cpp", + "${frameworks_module_ans_path}/src/notification_extension_subscription_info.cpp", "${frameworks_module_ans_path}/src/notification_flags.cpp", "${frameworks_module_ans_path}/src/notification_helper.cpp", "${frameworks_module_ans_path}/src/notification_icon_button.cpp", diff --git a/frameworks/ans/IAnsManager.idl b/frameworks/ans/IAnsManager.idl index 48812d680..4aecbd5be 100644 --- a/frameworks/ans/IAnsManager.idl +++ b/frameworks/ans/IAnsManager.idl @@ -23,6 +23,7 @@ sequenceable OHOS.Notification.DistributedBundleOption; sequenceable OHOS.Notification.NotificationDisable; sequenceable OHOS.Notification.NotificationDoNotDisturbDate; sequenceable OHOS.Notification.NotificationDoNotDisturbProfile; +sequenceable OHOS.Notification.NotificationExtensionSubscriptionInfo; sequenceable OHOS.Notification.NotificationRequest; sequenceable OHOS.Notification.NotificationSlot; sequenceable OHOS.Notification.NotificationSubscribeInfo; @@ -331,5 +332,11 @@ interface OHOS.Notification.IAnsManager { void GetTargetDeviceBundleList([in] String deviceType, [in] String deviceId, [out] String[] bundleList, [out] String[] labelList); + void NotificationExtensionSubscribe([in] sptr[] infos); + + void NotificationExtensionUnsubscribe(); + + void GetSubscribeInfo([out] sptr[] infos); + [macrodef NOTIFICATION_SMART_REMINDER_SUPPORTED] void RegisterSwingCallback([in] IRemoteObject swingCallback); } diff --git a/frameworks/ans/src/notification_extension_subscription_info.cpp b/frameworks/ans/src/notification_extension_subscription_info.cpp new file mode 100644 index 000000000..da6fe5e68 --- /dev/null +++ b/frameworks/ans/src/notification_extension_subscription_info.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 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 +#include "ans_log_wrapper.h" +#include "notification_extension_subscription_info.h" +#include "parcel.h" + +namespace OHOS { +namespace Notification { +NotificationExtensionSubscriptionInfo::NotificationExtensionSubscriptionInfo( + const std::string& addr, const NotificationConstant::SubscribeType type) + : addr_(addr), type_(type) +{} + +NotificationExtensionSubscriptionInfo::~NotificationExtensionSubscriptionInfo() +{} + +std::string NotificationExtensionSubscriptionInfo::GetAddr() const +{ + return addr_; +} + +void NotificationExtensionSubscriptionInfo::SetAddr(const std::string& addr) +{ + addr_ = addr; +} + +bool NotificationExtensionSubscriptionInfo::IsHfp() const +{ + return isHfp_; +} + +void NotificationExtensionSubscriptionInfo::SetHfp(const bool& hfp) +{ + isHfp_ = hfp; +} + +NotificationConstant::SubscribeType NotificationExtensionSubscriptionInfo::GetType() const +{ + return type_; +} + +void NotificationExtensionSubscriptionInfo::SetType(const NotificationConstant::SubscribeType type) +{ + type_ = type; +} + +std::string NotificationExtensionSubscriptionInfo::Dump() +{ + return "NotificationExtensionSubscriptionInfo{ " + "addr = " + addr_ + + ", type = " + std::to_string(static_cast(type_)) + + " }"; +} + +bool NotificationExtensionSubscriptionInfo::Marshalling(Parcel& parcel) const +{ + if (!parcel.WriteString(addr_)) { + ANS_LOGE("Failed to write address"); + return false; + } + + if (!parcel.WriteInt32(static_cast(type_))) { + ANS_LOGE("Failed to write type"); + return false; + } + + return true; +} + +NotificationExtensionSubscriptionInfo *NotificationExtensionSubscriptionInfo::Unmarshalling(Parcel& parcel) +{ + auto pNotificationExtensionSubscriptionInfo = new (std::nothrow) NotificationExtensionSubscriptionInfo(); + if (pNotificationExtensionSubscriptionInfo && !pNotificationExtensionSubscriptionInfo->ReadFromParcel(parcel)) { + delete pNotificationExtensionSubscriptionInfo; + pNotificationExtensionSubscriptionInfo = nullptr; + } + + return pNotificationExtensionSubscriptionInfo; +} + +bool NotificationExtensionSubscriptionInfo::ReadFromParcel(Parcel& parcel) +{ + if (!parcel.ReadString(addr_)) { + ANS_LOGE("Failed to read address"); + return false; + } + + type_ = static_cast(parcel.ReadInt32()); + + return true; +} + +bool NotificationExtensionSubscriptionInfo::ToJson(nlohmann::json& jsonObject) const +{ + jsonObject["addr"] = addr_; + jsonObject["isHfp"] = isHfp_; + jsonObject["type"] = static_cast(type_); + + return true; +} + +NotificationExtensionSubscriptionInfo* NotificationExtensionSubscriptionInfo::FromJson(const nlohmann::json& jsonObject) +{ + if (jsonObject.is_null() or !jsonObject.is_object()) { + ANS_LOGE("Invalid JSON object"); + return nullptr; + } + + auto *pDistributedBundleOption = new (std::nothrow) NotificationExtensionSubscriptionInfo(); + if (pDistributedBundleOption == nullptr) { + ANS_LOGE("null pDistributedBundleOption"); + return nullptr; + } + + const auto& jsonEnd = jsonObject.cend(); + + if (jsonObject.find("addr") != jsonEnd && jsonObject.at("addr").is_string()) { + pDistributedBundleOption->addr_ = jsonObject.at("addr").get(); + } + + if (jsonObject.find("isHfp") != jsonEnd && jsonObject.at("isHfp").is_boolean()) { + pDistributedBundleOption->isHfp_ = jsonObject.at("isHfp").get(); + } + + if (jsonObject.find("type") != jsonEnd && jsonObject.at("type").is_number_integer()) { + auto typeValue = jsonObject.at("type").get(); + pDistributedBundleOption->type_ = static_cast(typeValue); + } + + return pDistributedBundleOption; +} + +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ans/src/notification_helper.cpp b/frameworks/ans/src/notification_helper.cpp index bcdcab6c6..eeb85d1f1 100644 --- a/frameworks/ans/src/notification_helper.cpp +++ b/frameworks/ans/src/notification_helper.cpp @@ -789,5 +789,21 @@ ErrCode NotificationHelper::GetLiveViewConfig(const std::vector& bu { return DelayedSingleton::GetInstance()->GetLiveViewConfig(bundleList); } + +ErrCode NotificationHelper::NotificationExtensionSubscribe( + const std::vector>& infos) +{ + return DelayedSingleton::GetInstance()->NotificationExtensionSubscribe(infos); +} + +ErrCode NotificationHelper::NotificationExtensionUnsubscribe() +{ + return DelayedSingleton::GetInstance()->NotificationExtensionUnsubscribe(); +} + +ErrCode NotificationHelper::GetSubscribeInfo(std::vector>& infos) +{ + return DelayedSingleton::GetInstance()->GetSubscribeInfo(infos); +} } // namespace Notification } // namespace OHOS diff --git a/frameworks/core/common/include/ans_convert_enum.h b/frameworks/core/common/include/ans_convert_enum.h index b8ec30e66..f6abda55e 100644 --- a/frameworks/core/common/include/ans_convert_enum.h +++ b/frameworks/core/common/include/ans_convert_enum.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 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 @@ -143,6 +143,10 @@ enum class SwitchState { SYSTEM_DEFAULT_ON }; +enum class SubscribeType { + BLUETOOTH = 0 +}; + class AnsEnumUtil { public: /** @@ -297,6 +301,24 @@ public: * @return Returns true if success, returns false otherwise */ static bool LiveViewTypesCToJS(const NotificationLocalLiveViewContent::LiveViewTypes &in, LiveViewTypes &out); + + /** + * @brief Converts subscribe types from js to native + * + * @param inType Indicates a js subscribe type object + * @param outType Indicates a subscribe type object + * @return Returns true if success, returns false otherwise + */ + static bool SubscribeTypeJSToC(const SubscribeType &inType, NotificationConstant::SubscribeType &outType); + + /** + * @brief Converts subscribe status type from native to js + * + * @param inType Indicates a native subscribe status object + * @param outType Indicates a js subscribe status object + * @return Returns true if success, returns false otherwise + */ + static bool SubscribeTypeCToJS(const NotificationConstant::SubscribeType &inType, SubscribeType &outType); }; } } diff --git a/frameworks/core/common/include/ans_permission_def.h b/frameworks/core/common/include/ans_permission_def.h index bd6d9347b..fc0997dcd 100644 --- a/frameworks/core/common/include/ans_permission_def.h +++ b/frameworks/core/common/include/ans_permission_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -26,6 +26,7 @@ constexpr char OHOS_PERMISSION_SET_UNREMOVABLE_NOTIFICATION[] = "ohos.permission constexpr char OHOS_PERMISSION_NOTIFICATION_AGENT_CONTROLLER[] = "ohos.permission.NOTIFICATION_AGENT_CONTROLLER"; constexpr char OHOS_PERMISSION_SEND_NOTIFICATION_CROSS_USER[] = "ohos.permission.SEND_NOTIFICATION_CROSS_USER"; constexpr char OHOS_PERMISSION_MANAGE_EDM_POLICY[] = "ohos.permission.MANAGE_EDM_POLICY"; +constexpr char OHOS_PERMISSION_SUBSCRIBE_NOTIFICATION[] = "ohos.permission.SUBSCRIBE_NOTIFICATION"; } // namespace Notification } // namespace OHOS diff --git a/frameworks/core/common/src/ans_convert_enum.cpp b/frameworks/core/common/src/ans_convert_enum.cpp index 90dc89a25..1fdd15448 100644 --- a/frameworks/core/common/src/ans_convert_enum.cpp +++ b/frameworks/core/common/src/ans_convert_enum.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 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 @@ -517,5 +517,32 @@ bool AnsEnumUtil::LiveViewTypesCToJS(const NotificationLocalLiveViewContent::Liv return true; } + +bool AnsEnumUtil::SubscribeTypeJSToC(const SubscribeType &inType, NotificationConstant::SubscribeType &outType) +{ + switch (inType) { + case SubscribeType::BLUETOOTH: + outType = NotificationConstant::SubscribeType::BLUETOOTH; + break; + default: + ANS_LOGE("SubscribeType %{public}d", inType); + return false; + } + return true; +} + +bool AnsEnumUtil::SubscribeTypeCToJS(const NotificationConstant::SubscribeType &inType, SubscribeType &outType) +{ + switch (inType) { + case NotificationConstant::SubscribeType::BLUETOOTH: + outType = SubscribeType::BLUETOOTH; + break; + default: + ANS_LOGD("SubscribeType %{public}d", inType); + return false; + } + + return true; +} } } diff --git a/frameworks/core/include/ans_notification.h b/frameworks/core/include/ans_notification.h index 0f54553b2..5a6b4ab04 100644 --- a/frameworks/core/include/ans_notification.h +++ b/frameworks/core/include/ans_notification.h @@ -22,6 +22,7 @@ #include "ans_dialog_host_client.h" #include "ans_subscriber_listener.h" #include "ians_manager.h" +#include "notification_extension_subscription_info.h" #include "notification_local_live_view_subscriber.h" #include "notification_subscriber.h" #include "want_params.h" @@ -1435,6 +1436,28 @@ public: */ ErrCode GetLiveViewConfig(const std::vector& bundleList); + /** + * @brief Subscribe the notification when the bluetooth addr is connected. + * + * @param infos The info to be subscribe. + * @return Returns subscribe result. + */ + ErrCode NotificationExtensionSubscribe(const std::vector>& infos); + + /** + * @brief Unsubscribe the notification. + * + * @return Returns unsubscribe result. + */ + ErrCode NotificationExtensionUnsubscribe(); + + /** + * @brief Obtains the subscribe info for app. + * @param infos The returned subscribe info. + * @return Returns get result. + */ + ErrCode GetSubscribeInfo(std::vector>& infos); + private: /** * @brief Gets Ans Manager proxy. diff --git a/frameworks/core/src/ans_notification.cpp b/frameworks/core/src/ans_notification.cpp index 704f8734e..a49295340 100644 --- a/frameworks/core/src/ans_notification.cpp +++ b/frameworks/core/src/ans_notification.cpp @@ -2593,5 +2593,49 @@ ErrCode AnsNotification::GetDistributedDevicelist(std::vector &devi } return proxy->GetDistributedDevicelist(deviceTypes); } + +ErrCode AnsNotification::NotificationExtensionSubscribe( + const std::vector>& infos) +{ + ANS_LOGD("called"); + if (infos.empty()) { + ANS_LOGE("Invalid infos."); + return ERR_ANS_INVALID_PARAM; + } + + sptr proxy = GetAnsManagerProxy(); + if (!proxy) { + ANS_LOGE("Get ans manager proxy fail"); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + + return proxy->NotificationExtensionSubscribe(infos); +} + +ErrCode AnsNotification::NotificationExtensionUnsubscribe() +{ + ANS_LOGD("called"); + + sptr proxy = GetAnsManagerProxy(); + if (!proxy) { + ANS_LOGE("Get ans manager proxy fail"); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + + return proxy->NotificationExtensionUnsubscribe(); +} + +ErrCode AnsNotification::GetSubscribeInfo(std::vector>& infos) +{ + ANS_LOGD("called"); + + sptr proxy = GetAnsManagerProxy(); + if (!proxy) { + ANS_LOGE("Get ans manager proxy fail"); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + + return proxy->GetSubscribeInfo(infos); +} } // namespace Notification } // namespace OHOS diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn index ac0505b78..b015fdc68 100644 --- a/frameworks/js/napi/BUILD.gn +++ b/frameworks/js/napi/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2023 Huawei Device Co., Ltd. +# Copyright (c) 2021-2025 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 @@ -29,6 +29,12 @@ group("napi_notification") { ] } +group("napi_extension_subscription") { + deps = [ + "src/extension_subscription:notificationextensionsubscription", + ] +} + cflags = [ "-fno-math-errno", "-fno-unroll-loops", diff --git a/frameworks/js/napi/include/constant.h b/frameworks/js/napi/include/constant.h index 54d921ca8..eadc8c856 100644 --- a/frameworks/js/napi/include/constant.h +++ b/frameworks/js/napi/include/constant.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -32,6 +32,7 @@ napi_value DeviceRemindTypeInit(napi_env env, napi_value exports); napi_value ConstantInit(napi_env env, napi_value exports); napi_value LiveViewStatusInit(napi_env env, napi_value exports); napi_value SwitchStateInit(napi_env env, napi_value exports); +napi_value SubscribeTypeInit(napi_env env, napi_value exports); } // namespace NotificationNapi } // namespace OHOS diff --git a/frameworks/js/napi/include/extension_subscription/init_module.h b/frameworks/js/napi/include/extension_subscription/init_module.h new file mode 100644 index 000000000..fecde4b50 --- /dev/null +++ b/frameworks/js/napi/include/extension_subscription/init_module.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 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. + */ +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_EXTENSION_SUBSCRIPTION_INIT_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_EXTENSION_SUBSCRIPTION_INIT_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace NotificationNapi { +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((constructor)) void RegisterModule(void); +napi_value NotificationSubscribeInit(napi_env env, napi_value exports); +static napi_value Init(napi_env env, napi_value exports); + +#ifdef __cplusplus +} +#endif + +/* + * Module define + */ +napi_module _module_subscribe = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "notificationExtensionSubscription", + .nm_priv = ((void *)0), + .reserved = {0} + +}; +} // namespace NotificationNapi +} // namespace OHOS +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_EXTENSION_SUBSCRIPTION_INIT_H diff --git a/frameworks/js/napi/include/extension_subscription/napi_notification_extension.h b/frameworks/js/napi/include/extension_subscription/napi_notification_extension.h new file mode 100644 index 000000000..00d934180 --- /dev/null +++ b/frameworks/js/napi/include/extension_subscription/napi_notification_extension.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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. + */ +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_NOTIFICATION_EXTENSION_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_NOTIFICATION_EXTENSION_H + +#include "common.h" + +namespace OHOS { +namespace NotificationNapi { +using namespace OHOS::Notification; + +struct AsyncCallbackInfoNotificationExtensionSubscription { + napi_env env = nullptr; + napi_async_work asyncWork = nullptr; + CallbackPromiseInfo info; + std::vector> subscriptionInfo; +}; + +napi_value NapiNotificationExtensionSubscribe(napi_env env, napi_callback_info info); +napi_value NapiNotificationExtensionUnsubscribe(napi_env env, napi_callback_info info); +napi_value NapiGetSubscribeInfo(napi_env env, napi_callback_info info); +} // namespace NotificationNapi +} // namespace OHOS +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_NOTIFICATION_EXTENSION_H \ No newline at end of file diff --git a/frameworks/js/napi/src/constant.cpp b/frameworks/js/napi/src/constant.cpp index 629674270..ba4864d43 100644 --- a/frameworks/js/napi/src/constant.cpp +++ b/frameworks/js/napi/src/constant.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -366,6 +366,23 @@ napi_value SwitchStateInit(napi_env env, napi_value exports) return exports; } +napi_value SubscribeTypeInit(napi_env env, napi_value exports) +{ + ANS_LOGD("%{public}s, called", __func__); + + napi_value obj = nullptr; + napi_create_object(env, &obj); + + SetNamedPropertyByInteger(env, obj, (int32_t)SubscribeType::BLUETOOTH, "BLUETOOTH"); + + napi_property_descriptor exportFuncs[] = { + DECLARE_NAPI_PROPERTY("SubscribeType", obj), + }; + + napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs); + return exports; +} + napi_value ConstantInit(napi_env env, napi_value exports) { RemoveReasonInit(env, exports); @@ -383,6 +400,7 @@ napi_value ConstantInit(napi_env env, napi_value exports) NotificationFlagTypeInit(env, exports); LiveViewStatusInit(env, exports); SwitchStateInit(env, exports); + SubscribeTypeInit(env, exports); return exports; } } // namespace NotificationNapi diff --git a/frameworks/js/napi/src/extension_subscription/BUILD.gn b/frameworks/js/napi/src/extension_subscription/BUILD.gn new file mode 100644 index 000000000..e7c77b5f0 --- /dev/null +++ b/frameworks/js/napi/src/extension_subscription/BUILD.gn @@ -0,0 +1,94 @@ +# Copyright (c) 2022-2025 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. + +import("//base/notification/distributed_notification_service/notification.gni") +import("//build/ohos.gni") + +cflags = [ + "-fno-math-errno", + "-fno-unroll-loops", + "-fmerge-all-constants", + "-fno-ident", + "-Oz", + "-flto", + "-ffunction-sections", + "-fdata-sections", +] + +config("native_module_config") { + visibility = [ ":*" ] + + include_dirs = [] + + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_shared_library("notificationextensionsubscription") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + include_dirs = [ + "../../include", + "../../include/extension_subscription", + ] + + configs = [ ":native_module_config" ] + + sources = [ + "../common.cpp", + "../common_utils.cpp", + "../constant.cpp", + "init_module.cpp", + "napi_notification_extension.cpp", + ] + + deps = [ "${frameworks_module_ans_path}:ans_innerkits" ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:napi_base_context", + "ability_runtime:napi_common", + "ability_runtime:napi_wantagent_common", + "ability_runtime:runtime", + "ability_runtime:ui_extension", + "ability_runtime:wantagent_innerkits", + "access_token:libtokenid_sdk", + "ace_engine:ace_uicontent", + "c_utils:utils", + "ffrt:libffrt", + "hilog:libhilog", + "hitrace:libhitracechain", + "image_framework:image", + "ipc:ipc_single", + "napi:ace_napi", + "relational_store:native_rdb", + ] + + relative_install_dir = "module" + subsystem_name = "${subsystem_name}" + part_name = "${component_name}" +} diff --git a/frameworks/js/napi/src/extension_subscription/init_module.cpp b/frameworks/js/napi/src/extension_subscription/init_module.cpp new file mode 100644 index 000000000..a736946ba --- /dev/null +++ b/frameworks/js/napi/src/extension_subscription/init_module.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 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 "constant.h" +#include "init_module.h" +#include "napi_notification_extension.h" + +namespace OHOS { +namespace NotificationNapi { +using namespace OHOS::Notification; + +EXTERN_C_START + +napi_value NotificationSubscribeInit(napi_env env, napi_value exports) +{ + ANS_LOGD("called"); + + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("subscribe", NapiNotificationExtensionSubscribe), + DECLARE_NAPI_FUNCTION("unsubscribe", NapiNotificationExtensionUnsubscribe), + DECLARE_NAPI_FUNCTION("getSubscribeInfo", NapiGetSubscribeInfo), + }; + + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + + return exports; +} +/* + * Module export function + */ +static napi_value Init(napi_env env, napi_value exports) +{ + /* + * Propertise define + */ + NotificationSubscribeInit(env, exports); + ConstantInit(env, exports); + + return exports; +} + +/* + * Module register function + */ +__attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module_subscribe); +} +EXTERN_C_END +} // namespace NotificationNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/src/extension_subscription/napi_notification_extension.cpp b/frameworks/js/napi/src/extension_subscription/napi_notification_extension.cpp new file mode 100644 index 000000000..2a4460ebc --- /dev/null +++ b/frameworks/js/napi/src/extension_subscription/napi_notification_extension.cpp @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2025 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 "napi_notification_extension.h" + +#include "ans_inner_errors.h" +#include "js_native_api.h" +#include "js_native_api_types.h" + +namespace OHOS { +namespace NotificationNapi { +namespace { +const int SUBSCRIBE_MAX_PARA = 1; +const int NAPI_GET_USER_GRANTED_STATE_MAX_PARA = 1; +const int NAPI_SET_USER_GRANTED_STATE_MAX_PARA = 2; +const int NAPI_GET_USER_GRANTED_ENABLE_BUNDLES_MAX_PARA = 1; +const int NAPI_SET_USER_GRANTED_BUNDLE_STATE_MAX_PARA = 3; +} + +napi_value GetNotificationExtensionSubscriptionInfo( + const napi_env& env, const napi_value& value, sptr& info) +{ + ANS_LOGD("called"); + + if (info == nullptr) { + ANS_LOGW("Invalid NotificationExtensionSubscriptionInfo object ptr."); + return nullptr; + } + + bool hasProperty {false}; + napi_valuetype valuetype = napi_undefined; + napi_value result = nullptr; + + // addr: string + char str[STR_MAX_SIZE] = {0}; + size_t strLen = 0; + napi_get_named_property(env, value, "addr", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_string) { + ANS_LOGE("Wrong argument type. string expected."); + std::string msg = "Incorrect parameter addr. The type of addr must be string."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + NAPI_CALL(env, napi_get_value_string_utf8(env, result, str, STR_MAX_SIZE - 1, &strLen)); + info->SetAddr(str); + + // type: SubscribeType + int32_t type = 0; + napi_get_named_property(env, value, "type", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_number) { + ANS_LOGE("Wrong argument type. number expected."); + std::string msg = "Incorrect parameter uid. The type of uid must be number."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + napi_get_value_int32(env, result, &type); + NotificationConstant::SubscribeType outType = NotificationConstant::SubscribeType::BLUETOOTH; + if (!AnsEnumUtil::SubscribeTypeJSToC(SubscribeType(type), outType)) { + std::string msg = "Incorrect parameter types. SubscribeType name must be in enum."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + info->SetType(outType); + + return Common::NapiGetNull(env); +} + +napi_value SetNotificationExtensionSubscriptionInfo( + const napi_env& env, const sptr& info, napi_value& result) +{ + if (info == nullptr) { + ANS_LOGW("Invalid NotificationExtensionSubscriptionInfo object ptr."); + return nullptr; + } + + napi_value value = nullptr; + + // addr: string + napi_create_string_utf8(env, info->GetAddr().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "addr", value); + + // type: SubscribeType + SubscribeType outType = SubscribeType::BLUETOOTH; + if (!AnsEnumUtil::SubscribeTypeCToJS(info->GetType(), outType)) { + return nullptr; + } + napi_create_int32(env, static_cast(outType), &value); + napi_set_named_property(env, result, "type", value); + + return result; +} + +napi_value ParseParameters(const napi_env& env, const napi_callback_info& info, + std::vector>& subscriptionInfo) +{ + ANS_LOGD("called"); + + size_t argc = SUBSCRIBE_MAX_PARA; + napi_value argv[SUBSCRIBE_MAX_PARA] = {nullptr}; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if (argc < SUBSCRIBE_MAX_PARA) { + ANS_LOGE("Wrong number of arguments."); + Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED); + return nullptr; + } + + // argv[0]: info + napi_valuetype valuetype = napi_undefined; + bool isArray = false; + napi_is_array(env, argv[PARAM0], &isArray); + if (!isArray) { + ANS_LOGE("Wrong argument type. Array expected."); + std::string msg = "Incorrect parameter types.The type of param must be array."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + uint32_t length = 0; + napi_get_array_length(env, argv[PARAM0], &length); + if (length == 0) { + ANS_LOGD("The array is empty."); + std::string msg = "Mandatory parameters are left unspecified. The array is empty."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + for (size_t index = 0; index < length; index++) { + napi_value nNotificationExtensionSubscriptionInfo = nullptr; + napi_get_element(env, argv[PARAM0], index, &nNotificationExtensionSubscriptionInfo); + NAPI_CALL_BASE(env, napi_typeof(env, nNotificationExtensionSubscriptionInfo, &valuetype), nullptr); + if (valuetype != napi_object) { + ANS_LOGE("Wrong argument type. Object expected."); + std::string msg = "Incorrect parameter types.The type of param must be object."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + sptr item = + new (std::nothrow) NotificationExtensionSubscriptionInfo(); + if (item == nullptr) { + ANS_LOGE("Failed to create NotificationExtensionSubscriptionInfo."); + std::string msg = + "Parameter verification failed. Failed to create NotificationExtensionSubscriptionInfo ptr"; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + auto retValue = GetNotificationExtensionSubscriptionInfo( + env, nNotificationExtensionSubscriptionInfo, item); + if (retValue == nullptr) { + ANS_LOGE("null retValue"); + Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED); + return nullptr; + } + subscriptionInfo.emplace_back(item); + } + + return Common::NapiGetNull(env); +} + +void AsyncCompleteCallbackSubscriptionReturnVoid(napi_env env, napi_status status, void *data) +{ + ANS_LOGD("called"); + if (!data) { + ANS_LOGE("Invalid async callback data"); + return; + } + AsyncCallbackInfoNotificationExtensionSubscription* asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env)); + if (asynccallbackinfo->info.callback != nullptr) { + napi_delete_reference(env, asynccallbackinfo->info.callback); + } + napi_delete_async_work(env, asynccallbackinfo->asyncWork); + delete asynccallbackinfo; + asynccallbackinfo = nullptr; + } +} + +void AsyncCompleteCallbackReturnSubscribeInfoArray(napi_env env, napi_status status, void *data) +{ + ANS_LOGD("called"); + if (!data) { + ANS_LOGE("Invalid async callback data"); + return; + } + AsyncCallbackInfoNotificationExtensionSubscription* asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + napi_value result = nullptr; + if (asynccallbackinfo->info.errorCode != ERR_OK) { + result = Common::NapiGetNull(env); + } else { + napi_value arr = nullptr; + int32_t count = 0; + napi_create_array(env, &arr); + for (auto item : asynccallbackinfo->subscriptionInfo) { + if (item == nullptr) { + ANS_LOGW("Invalid NotificationExtensionSubscriptionInfo object ptr."); + continue; + } + napi_value notificationExtensionSubscriptionInfo = nullptr; + napi_create_object(env, ¬ificationExtensionSubscriptionInfo); + if (!SetNotificationExtensionSubscriptionInfo(env, item, notificationExtensionSubscriptionInfo)) { + ANS_LOGW("Set NotificationExtensionSubscriptionInfo object failed."); + continue; + } + napi_set_element(env, arr, count, notificationExtensionSubscriptionInfo); + ++count; + } + ANS_LOGI("count = %{public}d", count); + result = arr; + if ((count == 0) && (asynccallbackinfo->subscriptionInfo.size() > 0)) { + asynccallbackinfo->info.errorCode = ERROR; + result = Common::NapiGetNull(env); + } + } + Common::ReturnCallbackPromise(env, asynccallbackinfo->info, result); + if (asynccallbackinfo->info.callback != nullptr) { + napi_delete_reference(env, asynccallbackinfo->info.callback); + } + napi_delete_async_work(env, asynccallbackinfo->asyncWork); + delete asynccallbackinfo; + asynccallbackinfo = nullptr; + } +} + +napi_value NapiNotificationExtensionSubscribe(napi_env env, napi_callback_info info) +{ + ANS_LOGD("called"); + + AsyncCallbackInfoNotificationExtensionSubscription* asynccallbackinfo = new (std::nothrow) + AsyncCallbackInfoNotificationExtensionSubscription { .env = env, .asyncWork = nullptr }; + if (!asynccallbackinfo) { + Common::NapiThrow(env, ERROR_INTERNAL_ERROR); + return Common::JSParaError(env, nullptr); + } + + if (ParseParameters(env, info, asynccallbackinfo->subscriptionInfo) == nullptr) { + Common::NapiThrow(env, ERROR_PARAM_INVALID); + return Common::NapiGetUndefined(env); + } + + napi_value promise = nullptr; + Common::PaddingCallbackPromiseInfo(env, nullptr, asynccallbackinfo->info, promise); + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "notificationExtensionSubscribe", NAPI_AUTO_LENGTH, &resourceName); + // Asynchronous function call + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANS_LOGD("notificationExtensionSubscribe work excute."); + AsyncCallbackInfoNotificationExtensionSubscription *asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + asynccallbackinfo->info.errorCode = + NotificationHelper::NotificationExtensionSubscribe(asynccallbackinfo->subscriptionInfo); + ANS_LOGI("errorCode = %{public}d", asynccallbackinfo->info.errorCode); + } + }, + AsyncCompleteCallbackSubscriptionReturnVoid, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + + napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated); + + return promise; +} + +napi_value NapiNotificationExtensionUnsubscribe(napi_env env, napi_callback_info info) +{ + ANS_LOGD("called"); + + AsyncCallbackInfoNotificationExtensionSubscription* asynccallbackinfo = new (std::nothrow) + AsyncCallbackInfoNotificationExtensionSubscription { .env = env, .asyncWork = nullptr }; + if (!asynccallbackinfo) { + Common::NapiThrow(env, ERROR_INTERNAL_ERROR); + return Common::JSParaError(env, nullptr); + } + napi_value promise = nullptr; + Common::PaddingCallbackPromiseInfo(env, nullptr, asynccallbackinfo->info, promise); + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "notificationExtensionUnsubscribe", NAPI_AUTO_LENGTH, &resourceName); + // Asynchronous function call + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANS_LOGD("notificationExtensionUnsubscribe work excute."); + AsyncCallbackInfoNotificationExtensionSubscription *asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + asynccallbackinfo->info.errorCode = + NotificationHelper::NotificationExtensionUnsubscribe(); + ANS_LOGI("errorCode = %{public}d", asynccallbackinfo->info.errorCode); + } + }, + AsyncCompleteCallbackSubscriptionReturnVoid, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + + napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated); + + return promise; +} + +napi_value NapiGetSubscribeInfo(napi_env env, napi_callback_info info) +{ + ANS_LOGD("called"); + + AsyncCallbackInfoNotificationExtensionSubscription* asynccallbackinfo = new (std::nothrow) + AsyncCallbackInfoNotificationExtensionSubscription { .env = env, .asyncWork = nullptr }; + if (!asynccallbackinfo) { + Common::NapiThrow(env, ERROR_INTERNAL_ERROR); + return Common::JSParaError(env, nullptr); + } + napi_value promise = nullptr; + Common::PaddingCallbackPromiseInfo(env, nullptr, asynccallbackinfo->info, promise); + + napi_value resourceName = nullptr; + napi_create_string_latin1(env, "getSubscribeInfo", NAPI_AUTO_LENGTH, &resourceName); + // Asynchronous function call + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANS_LOGD("getSubscribeInfo work excute."); + AsyncCallbackInfoNotificationExtensionSubscription *asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + asynccallbackinfo->info.errorCode = + NotificationHelper::GetSubscribeInfo(asynccallbackinfo->subscriptionInfo); + ANS_LOGI("errorCode = %{public}d", asynccallbackinfo->info.errorCode); + } + }, + AsyncCompleteCallbackReturnSubscribeInfoArray, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + + napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated); + + return promise; +} +} // namespace NotificationNapi +} // namespace OHOS diff --git a/interfaces/inner_api/notification_constant.h b/interfaces/inner_api/notification_constant.h index 501d91b4a..3d8087cbf 100644 --- a/interfaces/inner_api/notification_constant.h +++ b/interfaces/inner_api/notification_constant.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -187,6 +187,10 @@ public: SUPPORT }; + enum class SubscribeType { + BLUETOOTH = 0 + }; + static const int32_t DEFAULT_REASON_DELETE = 0; /** diff --git a/interfaces/inner_api/notification_extension_subscription_info.h b/interfaces/inner_api/notification_extension_subscription_info.h new file mode 100644 index 000000000..343043907 --- /dev/null +++ b/interfaces/inner_api/notification_extension_subscription_info.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2025 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. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_EXTENSION_SUBSCRIPTION_INFO_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_EXTENSION_SUBSCRIPTION_INFO_H + +#include "notification_constant.h" +#include "notification_json_convert.h" +#include "parcel.h" + +namespace OHOS { +namespace Notification { +class NotificationExtensionSubscriptionInfo : public Parcelable, public NotificationJsonConvertionBase { +public: + NotificationExtensionSubscriptionInfo() = default; + + /** + * @brief A constructor used to create a NotificationExtensionSubscriptionInfo instance based on the address and + * type. + * + * @param addr Indicates the address. + * @param type Indicates the type. + */ + NotificationExtensionSubscriptionInfo(const std::string& addr, const NotificationConstant::SubscribeType type); + + virtual ~NotificationExtensionSubscriptionInfo(); + + /** + * @brief Get addr. + * + * @return Returns addr. + */ + std::string GetAddr() const; + + /** + * @brief Sets addr. + * + * @param addr addr info. + */ + void SetAddr(const std::string& addr); + + /** + * @brief Get hfp. + * + * @return Returns hfp value. + */ + bool IsHfp() const; + + /** + * @brief Sets hfp. + * + * @param hfp hfp status. + */ + void SetHfp(const bool& hfp); + + /** + * @brief Get type. + * + * @return Returns type value. + */ + NotificationConstant::SubscribeType GetType() const; + + /** + * @brief Sets type. + * + * @param type type value. + */ + void SetType(const NotificationConstant::SubscribeType type); + + /** + * @brief Returns a string representation of the object. + * + * @return Returns a string representation of the object. + */ + std::string Dump(); + + /** + * @brief Marshal a object into a Parcel. + * + * @param parcel Indicates the object into the parcel + * @return Returns true if succeed; returns false otherwise. + */ + virtual bool Marshalling(Parcel& parcel) const override; + + /** + * @brief Unmarshal object from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns the NotificationExtensionSubscriptionInfo + */ + static NotificationExtensionSubscriptionInfo *Unmarshalling(Parcel& parcel); + + /** + * @brief Converts a notification extension subscription info object into a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ToJson(nlohmann::json& jsonObject) const override; + + /** + * @brief Creates a notification extension subscription info object from a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns the NotificationExtensionSubscriptionInfo. + */ + static NotificationExtensionSubscriptionInfo *FromJson(const nlohmann::json& jsonObject); + +private: + /** + * @brief Read data from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns true if read success; returns false otherwise. + */ + bool ReadFromParcel(Parcel& parcel); + +private: + std::string addr_ {}; + bool isHfp_ = false; + NotificationConstant::SubscribeType type_ = NotificationConstant::SubscribeType::BLUETOOTH; +}; +} // namespace Notification +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_EXTENSION_SUBSCRIPTION_INFO_H \ No newline at end of file diff --git a/interfaces/inner_api/notification_helper.h b/interfaces/inner_api/notification_helper.h index 9344b108c..406c491c0 100644 --- a/interfaces/inner_api/notification_helper.h +++ b/interfaces/inner_api/notification_helper.h @@ -23,6 +23,7 @@ #include "notification_do_not_disturb_date.h" #include "notification_do_not_disturb_profile.h" #include "enabled_notification_callback_data.h" +#include "notification_extension_subscription_info.h" #include "notification_request.h" #include "notification_slot.h" #include "notification_sorting_map.h" @@ -1435,6 +1436,28 @@ public: * @return Returns set result. */ static ErrCode GetLiveViewConfig(const std::vector& bundleList); + + /** + * @brief Subscribe the notification when the bluetooth addr is connected. + * + * @param infos The info to be subscribe. + * @return Returns subscribe result. + */ + static ErrCode NotificationExtensionSubscribe( + const std::vector>& infos); + + /** + * @brief Unsubscribe the notification. + * @return Returns unsubscribe result. + */ + static ErrCode NotificationExtensionUnsubscribe(); + + /** + * @brief Obtains the subscribe info for app. + * @param infos The returned subscribe info. + * @return Returns get result. + */ + static ErrCode GetSubscribeInfo(std::vector>& infos); }; } // namespace Notification } // namespace OHOS diff --git a/services/ans/BUILD.gn b/services/ans/BUILD.gn index 754e060d5..f44b4974a 100644 --- a/services/ans/BUILD.gn +++ b/services/ans/BUILD.gn @@ -68,6 +68,7 @@ ohos_source_set("ans_service_sources") { "src/advanced_notification_manager/advanced_notification_cancel.cpp", "src/advanced_notification_clone_service.cpp", "src/advanced_notification_event_service.cpp", + "src/advanced_notification_extension_subscription.cpp", "src/advanced_notification_flow_control_service.cpp", "src/advanced_notification_inline.cpp", "src/advanced_notification_live_view_service.cpp", diff --git a/services/ans/include/advanced_notification_service.h b/services/ans/include/advanced_notification_service.h index ed0e690f2..f4043114d 100644 --- a/services/ans/include/advanced_notification_service.h +++ b/services/ans/include/advanced_notification_service.h @@ -1446,6 +1446,14 @@ public: const std::string& value) override; ErrCode GetLiveViewConfig(const std::vector& bundleList) override; + + ErrCode NotificationExtensionSubscribe( + const std::vector>& infos) override; + + ErrCode NotificationExtensionUnsubscribe() override; + + ErrCode GetSubscribeInfo(std::vector>& infos) override; + protected: /** * @brief Query whether there is a agent relationship between the two apps. diff --git a/services/ans/include/notification_clone_bundle_info.h b/services/ans/include/notification_clone_bundle_info.h index a400e46f5..00c4c93c8 100644 --- a/services/ans/include/notification_clone_bundle_info.h +++ b/services/ans/include/notification_clone_bundle_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 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 @@ -22,6 +22,7 @@ #include "notification_constant.h" #include "notification_bundle_option.h" #include "notification_do_not_disturb_profile.h" +#include "notification_extension_subscription_info.h" #include "notification_constant.h" namespace OHOS { @@ -64,9 +65,13 @@ public: void AddSlotInfo(const SlotInfo &slotInfo); std::vector GetSlotInfo() const; + void SetExtensionSubscriptionInfos(const std::vector>& infos); + const std::vector>& GetExtensionSubscriptionInfos() const; + void ToJson(nlohmann::json &jsonObject) const; void FromJson(const nlohmann::json &root); void SlotsFromJson(const nlohmann::json &jsonObject); + void SubscriptionInfosFromJson(const nlohmann::json &jsonObject); std::string Dump() const; private: @@ -78,6 +83,7 @@ private: NotificationConstant::SWITCH_STATE isEnabledNotification_ = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; std::vector slotsInfo_; NotificationConstant::SWITCH_STATE silentReminderEnabled_; + std::vector> extensionSubscriptionInfos_; }; } // namespace Notification } // namespace OHOS diff --git a/services/ans/include/notification_preferences.h b/services/ans/include/notification_preferences.h index b7b6b0c17..77c8d3fa7 100644 --- a/services/ans/include/notification_preferences.h +++ b/services/ans/include/notification_preferences.h @@ -574,6 +574,11 @@ public: bool SetLiveViewRebuildFlag(int32_t userId); ErrCode InitBundlesInfo(int32_t userId, std::unordered_map& bundlesMap); void GetAllLiveViewBundles(std::vector>& bundleOption); + ErrCode GetExtensionSubscriptionInfos(const sptr& bundleOption, + std::vector>& infos); + ErrCode SetExtensionSubscriptionInfos(const sptr& bundleOption, + const std::vector>& infos); + ErrCode ClearExtensionSubscriptionInfos(const sptr& bundleOption); private: bool GetBundleInfo(NotificationPreferencesInfo &preferencesInfo, const sptr &bundleOption, NotificationPreferencesInfo::BundleInfo &info) const; diff --git a/services/ans/include/notification_preferences_database.h b/services/ans/include/notification_preferences_database.h index fe92e48d8..befe39f90 100644 --- a/services/ans/include/notification_preferences_database.h +++ b/services/ans/include/notification_preferences_database.h @@ -339,6 +339,7 @@ public: int32_t SetKvToDb(const std::string &key, const std::string &value, const int32_t &userId); int32_t SetByteToDb(const std::string &key, const std::vector &value, const int32_t &userId); int32_t GetKvFromDb(const std::string &key, std::string &value, const int32_t &userId); + bool PutExtensionSubscriptionInfos(const NotificationPreferencesInfo::BundleInfo& bundleInfo); #ifdef ENABLE_ANS_PRIVILEGED_MESSAGE_EXT_WRAPPER int32_t GetKvFromDb(const std::string &key, std::string &value, const int32_t &userId, int32_t &retCode); #endif @@ -504,6 +505,8 @@ private: void ParseSlotAuthorizedStatus(sptr &slot, const std::string &value) const; void ParseSlotAuthHitnCnt(sptr &slot, const std::string &value) const; void ParseSlotReminderMode(sptr &slot, const std::string &value) const; + void ParseBundleExtensionSubscriptionInfos( + NotificationPreferencesInfo::BundleInfo& bundleInfo, const std::string& value) const; bool UpdateCloneToDisturbeDB(const int32_t &userId, const std::unordered_map values); diff --git a/services/ans/include/notification_preferences_info.h b/services/ans/include/notification_preferences_info.h index 158441557..86db6e032 100644 --- a/services/ans/include/notification_preferences_info.h +++ b/services/ans/include/notification_preferences_info.h @@ -22,6 +22,7 @@ #include "notification_bundle_option.h" #include "notification_do_not_disturb_date.h" +#include "notification_extension_subscription_info.h" #include "notification_slot.h" #include "preferences_constant.h" #include "advanced_notification_service.h" @@ -226,6 +227,10 @@ public: int32_t GetBundleUid() const; void SetSlotEnabled(NotificationConstant::SlotType slotType, bool enabled); bool GetSlotEnabled(NotificationConstant::SlotType slotType, bool &enabled) const; + const std::vector>& GetExtensionSubscriptionInfos() const; + std::string GetExtensionSubscriptionInfosJson() const; + void SetExtensionSubscriptionInfos(const std::vector>& infos); + bool SetExtensionSubscriptionInfosFromJson(const std::string& json); private: std::string bundleName_; @@ -239,6 +244,7 @@ public: bool hasPoppedDialog_ = BUNDLE_POPPED_DIALOG; std::map> slots_; std::map slotFlagsMap_; + std::vector> extensionSubscriptionInfos_; }; /* diff --git a/services/ans/src/advanced_notification_extension_subscription.cpp b/services/ans/src/advanced_notification_extension_subscription.cpp new file mode 100644 index 000000000..543f4e196 --- /dev/null +++ b/services/ans/src/advanced_notification_extension_subscription.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2025 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 "access_token_helper.h" +#include "advanced_notification_service.h" +#include "ans_inner_errors.h" +#include "ans_log_wrapper.h" +#include "ans_trace_wrapper.h" +#include "ans_permission_def.h" +#include "bundle_manager_helper.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "errors.h" +#include "ipc_skeleton.h" +#include "notification_preferences.h" +#include "os_account_manager_helper.h" + +namespace OHOS { +namespace Notification { +namespace { +constexpr const char* ANS_EXTENSION_SERVICE_MODULE_NAME = "libans_extension_service.z.so"; +} + +ErrCode AdvancedNotificationService::NotificationExtensionSubscribe( + const std::vector>& infos) +{ + ANS_LOGD("AdvancedNotificationService::NotificationExtensionSubscribe"); + if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_SUBSCRIBE_NOTIFICATION)) { + return ERR_ANS_PERMISSION_DENIED; + } + + if (infos.empty()) { + ANS_LOGE("subscribe list is empty."); + return ERR_ANS_INVALID_PARAM; + } + + sptr bundleOption = GenerateBundleOption(); + if (bundleOption == nullptr) { + ANS_LOGE("Failed to create NotificationBundleOption"); + 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()->SetExtensionSubscriptionInfos(bundleOption, infos); + if (result != ERR_OK) { + ANS_LOGE("Failed to insert subscription info into db, ret: %{public}d", result); + return; + } + })); + notificationSvrQueue_->wait(handler); + + // ExtensionService condition check + // ExtensionService load + // call ExtensionService interface + + return result; +} + +ErrCode AdvancedNotificationService::NotificationExtensionUnsubscribe() +{ + ANS_LOGD("AdvancedNotificationService::NotificationExtensionUnsubscribe"); + if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_SUBSCRIBE_NOTIFICATION)) { + return ERR_ANS_PERMISSION_DENIED; + } + + sptr bundleOption = GenerateBundleOption(); + if (bundleOption == nullptr) { + ANS_LOGE("Failed to create NotificationBundleOption"); + 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()->ClearExtensionSubscriptionInfos(bundleOption); + if (result != ERR_OK) { + ANS_LOGE("Failed to insert subscription info into db, ret: %{public}d", result); + return; + } + })); + notificationSvrQueue_->wait(handler); + // ExtensionService condition check + // ExtensionService unload + + return result; +} + +ErrCode AdvancedNotificationService::GetSubscribeInfo(std::vector>& infos) +{ + ANS_LOGD("AdvancedNotificationService::GetSubscribeInfo"); + if (!AccessTokenHelper::CheckPermission(OHOS_PERMISSION_SUBSCRIBE_NOTIFICATION)) { + return ERR_ANS_PERMISSION_DENIED; + } + + sptr bundleOption = GenerateBundleOption(); + if (bundleOption == nullptr) { + ANS_LOGE("Failed to create NotificationBundleOption"); + 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()->GetExtensionSubscriptionInfos(bundleOption, infos); + if (result != ERR_OK) { + ANS_LOGE("Failed to insert subscription info into db, ret: %{public}d", result); + return; + } + })); + notificationSvrQueue_->wait(handler); + + return result; +} +} // namespace Notification +} // namespace OHOS diff --git a/services/ans/src/advanced_notification_utils.cpp b/services/ans/src/advanced_notification_utils.cpp index bcae685dd..23de3856f 100644 --- a/services/ans/src/advanced_notification_utils.cpp +++ b/services/ans/src/advanced_notification_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -1982,6 +1982,12 @@ void AdvancedNotificationService::UpdateCloneBundleInfo(const NotificationCloneB } else { ANS_LOGW("Set notification badge failed."); } + if (NotificationPreferences::GetInstance()->SetExtensionSubscriptionInfos( + bundle, cloneBundleInfo.GetExtensionSubscriptionInfos()) == ERR_OK) { + // handle bundle subscription infos changed + } else { + ANS_LOGW("Set subscription infos failed."); + } UpdateCloneBundleInfoFoSilentReminder(cloneBundleInfo, bundle); })); diff --git a/services/ans/src/clone/notification_clone_bundle_info.cpp b/services/ans/src/clone/notification_clone_bundle_info.cpp index a189acbbd..25f96806c 100644 --- a/services/ans/src/clone/notification_clone_bundle_info.cpp +++ b/services/ans/src/clone/notification_clone_bundle_info.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2024-2024 Huawei Device Co., Ltd. +* Copyright (c) 2024-2025 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 @@ -33,6 +33,7 @@ constexpr const char *BUNDLE_INFO_SLOT_ENABLE = "slotEnable"; constexpr const char *BUNDLE_INFO_SLOT_CONTROL = "slotControl"; constexpr const char *BUNDLE_INFO_SILENT_REMINDER = "enabledSilentReminder"; constexpr const char *BUNDLE_INFO_SLOT_AUTHSTATUS = "slotAuthorized"; +constexpr const char *BUNDLE_INFO_SUBSCRIPTION_INFO = "extensionSubscriptionInfo"; constexpr int32_t CONST_ENABLE_INT = 1; } void NotificationCloneBundleInfo::SetBundleName(const std::string &name) @@ -124,6 +125,18 @@ std::vector NotificationCloneBundleInfo:: return slotsInfo_; } +void NotificationCloneBundleInfo::SetExtensionSubscriptionInfos( + const std::vector>& infos) +{ + extensionSubscriptionInfos_ = infos; +} + +const std::vector>& + NotificationCloneBundleInfo::GetExtensionSubscriptionInfos() const +{ + return extensionSubscriptionInfos_; +} + void NotificationCloneBundleInfo::ToJson(nlohmann::json &jsonObject) const { if (!slotsInfo_.empty()) { @@ -139,6 +152,16 @@ void NotificationCloneBundleInfo::ToJson(nlohmann::json &jsonObject) const jsonObject[BUNDLE_INFO_SLOT_LIST] = jsonNodes; } + if (!extensionSubscriptionInfos_.empty()) { + nlohmann::json jsonNodes = nlohmann::json::array(); + for (const auto& info : extensionSubscriptionInfos_) { + nlohmann::json jsonNode; + info->ToJson(jsonNode); + jsonNodes.emplace_back(jsonNode); + } + jsonObject[BUNDLE_INFO_SUBSCRIPTION_INFO] = jsonNodes; + } + jsonObject[BUNDLE_INFO_NAME] = bundleName_; jsonObject[BUNDLE_INFO_APP_INDEX] = appIndex_; jsonObject[BUNDLE_INFO_SLOT_FLAGS] = slotFlags_; @@ -175,6 +198,17 @@ void NotificationCloneBundleInfo::SlotsFromJson(const nlohmann::json &jsonObject } } +void NotificationCloneBundleInfo::SubscriptionInfosFromJson(const nlohmann::json &jsonObject) +{ + if (!jsonObject.contains(BUNDLE_INFO_SUBSCRIPTION_INFO) || !jsonObject[BUNDLE_INFO_SUBSCRIPTION_INFO].is_array()) { + return; + } + + for (auto &infoJson : jsonObject.at(BUNDLE_INFO_SUBSCRIPTION_INFO)) { + extensionSubscriptionInfos_.emplace_back(NotificationExtensionSubscriptionInfo::FromJson(infoJson)); + } +} + void NotificationCloneBundleInfo::FromJson(const nlohmann::json &jsonObject) { if (jsonObject.is_null() || !jsonObject.is_object()) { @@ -215,6 +249,7 @@ void NotificationCloneBundleInfo::FromJson(const nlohmann::json &jsonObject) } } SlotsFromJson(jsonObject); + SubscriptionInfosFromJson(jsonObject); } std::string NotificationCloneBundleInfo::SlotInfo::Dump() const { diff --git a/services/ans/src/notification_preferences.cpp b/services/ans/src/notification_preferences.cpp index 38b662af9..47c3cd179 100644 --- a/services/ans/src/notification_preferences.cpp +++ b/services/ans/src/notification_preferences.cpp @@ -1727,6 +1727,65 @@ ErrCode NotificationPreferences::GetDistributedDevicelist(std::vector& bundleOption, + std::vector>& infos) +{ + ANS_LOGD("called"); + if (bundleOption == nullptr || bundleOption->GetBundleName().empty()) { + ANS_LOGE("Invalid bundle option"); + return ERR_ANS_INVALID_PARAM; + } + ErrCode result = ERR_OK; + NotificationPreferencesInfo::BundleInfo bundleInfo; + std::lock_guard lock(preferenceMutex_); + if (GetBundleInfo(preferencesInfo_, bundleOption, bundleInfo)) { + infos = bundleInfo.GetExtensionSubscriptionInfos(); + } else { + ANS_LOGW("Notification bundle does not exsit."); + infos.clear(); + } + return ERR_OK; +} + + ErrCode NotificationPreferences::SetExtensionSubscriptionInfos(const sptr& bundleOption, + const std::vector>& infos) +{ + ANS_LOGD("called"); + if (bundleOption == nullptr || bundleOption->GetBundleName().empty()) { + ANS_LOGE("Invalid bundle option"); + return ERR_ANS_INVALID_PARAM; + } + std::lock_guard lock(preferenceMutex_); + NotificationPreferencesInfo preferencesInfo = preferencesInfo_; + NotificationPreferencesInfo::BundleInfo bundleInfo; + if (!GetBundleInfo(preferencesInfo_, bundleOption, bundleInfo)) { + bundleInfo.SetBundleName(bundleOption->GetBundleName()); + bundleInfo.SetBundleUid(bundleOption->GetUid()); + NotificationConstant::SWITCH_STATE defaultState = CheckApiCompatibility(bundleOption) ? + NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_ON : + NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; + bundleInfo.SetEnableNotification(defaultState); + } + bundleInfo.SetExtensionSubscriptionInfos(infos); + if (preferncesDB_ == nullptr) { + ANS_LOGE("the prefernces db is nullptr"); + return ERR_ANS_SERVICE_NOT_READY; + } + if (preferncesDB_->PutExtensionSubscriptionInfos(bundleInfo)) { + preferencesInfo.SetBundleInfo(bundleInfo); + preferencesInfo_ = preferencesInfo; + return ERR_OK; + } else { + return ERR_ANS_PREFERENCES_NOTIFICATION_DB_OPERATION_FAILED; + } +} + +ErrCode NotificationPreferences::ClearExtensionSubscriptionInfos(const sptr& bundleOption) +{ + ANS_LOGD("called"); + return SetExtensionSubscriptionInfos(bundleOption, std::vector>()); +} + ErrCode NotificationPreferences::SetSubscriberExistFlag(const std::string& deviceType, bool existFlag) { ANS_LOGD("%{public}s", __FUNCTION__); diff --git a/services/ans/src/notification_preferences_database.cpp b/services/ans/src/notification_preferences_database.cpp index e95c31de1..b0f8a07c7 100644 --- a/services/ans/src/notification_preferences_database.cpp +++ b/services/ans/src/notification_preferences_database.cpp @@ -233,6 +233,7 @@ const static std::string KEY_SLOT_AUTH_HINT_CNT = "authHintCnt"; */ const static std::string KEY_REMINDER_MODE = "reminderMode"; +const static std::string KEY_EXTENSION_SUBSCRIPTION_INFO = "extensionSubscriptionInfo"; constexpr char RELATIONSHIP_JSON_KEY_SERVICE[] = "service"; constexpr char RELATIONSHIP_JSON_KEY_APP[] = "app"; @@ -729,6 +730,8 @@ bool NotificationPreferencesDatabase::PutBundlePropertyValueToDisturbeDB( std::to_string(bundleInfo.GetHasPoppedDialog()), values); GenerateEntry(GenerateBundleKey(bundleKey, KEY_BUNDLE_UID), std::to_string(bundleInfo.GetBundleUid()), values); + GenerateEntry(GenerateBundleKey(bundleKey, KEY_EXTENSION_SUBSCRIPTION_INFO), + bundleInfo.GetExtensionSubscriptionInfosJson(), values); if (!CheckRdbStore()) { ANS_LOGE("null RdbStore"); return false; @@ -1259,6 +1262,9 @@ void NotificationPreferencesDatabase::ParseBundlePropertyFromDisturbeDB( if (typeStr.compare(KEY_BUNDLE_SLOTFLGS_TYPE) == 0) { return ParseBundleSlotFlags(bundleInfo, valueStr); } + if (typeStr.compare(KEY_EXTENSION_SUBSCRIPTION_INFO) == 0) { + return ParseBundleExtensionSubscriptionInfos(bundleInfo, valueStr); + } } void NotificationPreferencesDatabase::ParseSlot(const std::string &findString, sptr &slot, @@ -1646,6 +1652,13 @@ void NotificationPreferencesDatabase::ParseSlotReminderMode( slot->SetReminderMode(reminderMode); } +void NotificationPreferencesDatabase::ParseBundleExtensionSubscriptionInfos( + NotificationPreferencesInfo::BundleInfo &bundleInfo, const std::string &value) const +{ + ANS_LOGD("ParseBundleExtensionSubscriptionInfos bundle infos: %{public}s.", value.c_str()); + bundleInfo.SetExtensionSubscriptionInfosFromJson(value); +} + std::string NotificationPreferencesDatabase::GenerateBundleLablel( const NotificationPreferencesInfo::BundleInfo &bundleInfo) const { @@ -2596,6 +2609,30 @@ bool NotificationPreferencesDatabase::IsSmartReminderEnabled(const std::string d return result; } +bool NotificationPreferencesDatabase::PutExtensionSubscriptionInfos( + const NotificationPreferencesInfo::BundleInfo& bundleInfo) +{ + if (bundleInfo.GetBundleName().empty()) { + ANS_LOGE("Bundle name is null."); + return false; + } + + if (!CheckBundle(bundleInfo.GetBundleName(), bundleInfo.GetBundleUid())) { + return false; + } + + if (!CheckRdbStore()) { + ANS_LOGE("null RdbStore"); + return false; + } + std::string bundleKey = GenerateBundleLablel(bundleInfo); + int32_t userId = -1; + OsAccountManagerHelper::GetInstance().GetOsAccountLocalIdFromUid(bundleInfo.GetBundleUid(), userId); + int32_t result = rdbDataManager_->InsertData(GenerateBundleKey(bundleKey, KEY_EXTENSION_SUBSCRIPTION_INFO), + bundleInfo.GetExtensionSubscriptionInfosJson(), userId); + return (result == NativeRdb::E_OK); +} + bool NotificationPreferencesDatabase::SetDistributedEnabledBySlot( const NotificationConstant::SlotType &slotType, const std::string &deviceType, const bool enabled) { diff --git a/services/ans/src/notification_preferences_info.cpp b/services/ans/src/notification_preferences_info.cpp index 9eb121215..4079a1a7e 100644 --- a/services/ans/src/notification_preferences_info.cpp +++ b/services/ans/src/notification_preferences_info.cpp @@ -222,6 +222,53 @@ int32_t NotificationPreferencesInfo::BundleInfo::GetBundleUid() const return uid_; } +const std::vector>& + NotificationPreferencesInfo::BundleInfo::GetExtensionSubscriptionInfos() const +{ + return extensionSubscriptionInfos_; +} + +std::string NotificationPreferencesInfo::BundleInfo::GetExtensionSubscriptionInfosJson() const +{ + auto jsonObject = nlohmann::json::array(); + for (const auto& item : extensionSubscriptionInfos_) { + nlohmann::json jsonNode; + item->ToJson(jsonNode); + jsonObject.emplace_back(jsonNode); + } + return jsonObject.dump(); +} + +void NotificationPreferencesInfo::BundleInfo::SetExtensionSubscriptionInfos( + const std::vector>& infos) +{ + extensionSubscriptionInfos_ = infos; +} + +bool NotificationPreferencesInfo::BundleInfo::SetExtensionSubscriptionInfosFromJson(const std::string& json) +{ + if (json.empty() || !nlohmann::json::accept(json)) { + ANS_LOGE("Invalid json string"); + return false; + } + nlohmann::json jsonObject = nlohmann::json::parse(json, nullptr, false); + if (jsonObject.is_null() || jsonObject.empty()) { + ANS_LOGE("Invalid JSON object"); + return false; + } + if (jsonObject.is_discarded() || !jsonObject.is_array()) { + ANS_LOGE("Parse extension subscription info list failed due to data is discarded or not array"); + return false; + } + + extensionSubscriptionInfos_.clear(); + for (const auto &item : jsonObject) { + extensionSubscriptionInfos_.emplace_back(NotificationExtensionSubscriptionInfo::FromJson(item)); + } + + return true; +} + void NotificationPreferencesInfo::SetBundleInfo(BundleInfo &info) { std::string bundleKey = info.GetBundleName().append(std::to_string(info.GetBundleUid())); @@ -393,6 +440,7 @@ void NotificationPreferencesInfo::GetAllCLoneBundlesInfo(const int32_t &userId, (slot->GetAuthorizedStatus() ==NotificationSlot::AuthorizedStatus::AUTHORIZED); cloneBundleInfo.AddSlotInfo(slotInfo); } + cloneBundleInfo.SetExtensionSubscriptionInfos(iter->second.GetExtensionSubscriptionInfos()); auto silentReminderIter = silentReminderInfos_.find(bundleItem.second); if (silentReminderIter != silentReminderInfos_.end()) { auto enableStatus = silentReminderIter->second.enableStatus; -- Gitee