diff --git a/bundle.json b/bundle.json index 9a6f3ee2e6062989551b44a2b0a7c4540ccd73ad..7c191896c4d94a5d467de3c4e68a5e73876c390a 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/IAnsManager.idl b/frameworks/ans/IAnsManager.idl index 48812d68095b3f0bf836dc6d943efc5ffc2edbf5..18b4e511d613a8c90faf64981bd863acebb9bbd1 100644 --- a/frameworks/ans/IAnsManager.idl +++ b/frameworks/ans/IAnsManager.idl @@ -331,5 +331,11 @@ interface OHOS.Notification.IAnsManager { void GetTargetDeviceBundleList([in] String deviceType, [in] String deviceId, [out] String[] bundleList, [out] String[] labelList); + void GetUserGrantedEnabledBundles([in] sptr targetBundle, [out] sptr[] enabledBundles); + + void GetUserGrantedEnabledBundlesForSelf([out] sptr[] bundles); + + void SetUserGrantedBundleState([in] sptr targetBundle, [in] sptr[] enabledBundles, [in] boolean enabled); + [macrodef NOTIFICATION_SMART_REMINDER_SUPPORTED] void RegisterSwingCallback([in] IRemoteObject swingCallback); } diff --git a/frameworks/ans/src/notification_helper.cpp b/frameworks/ans/src/notification_helper.cpp index bcdcab6c6449a23b80d78973e50c96d1ef1967f7..7e883f5c3c9b7c7d049a5382f3db269174045087 100644 --- a/frameworks/ans/src/notification_helper.cpp +++ b/frameworks/ans/src/notification_helper.cpp @@ -789,5 +789,23 @@ ErrCode NotificationHelper::GetLiveViewConfig(const std::vector& bu { return DelayedSingleton::GetInstance()->GetLiveViewConfig(bundleList); } + +ErrCode NotificationHelper::GetUserGrantedEnabledBundles( + const NotificationBundleOption& targetBundle, std::vector>& enabledBundles) +{ + return DelayedSingleton::GetInstance()->GetUserGrantedEnabledBundles(targetBundle, enabledBundles); +} + +ErrCode NotificationHelper::GetUserGrantedEnabledBundlesForSelf(std::vector>& bundles) +{ + return DelayedSingleton::GetInstance()->GetUserGrantedEnabledBundlesForSelf(bundles); +} + +ErrCode NotificationHelper::SetUserGrantedBundleState(const NotificationBundleOption& targetBundle, + const std::vector>& enabledBundles, bool enabled) +{ + return DelayedSingleton::GetInstance()->SetUserGrantedBundleState( + targetBundle, enabledBundles, enabled); +} } // namespace Notification } // namespace OHOS diff --git a/frameworks/core/common/include/ans_permission_def.h b/frameworks/core/common/include/ans_permission_def.h index bd6d9347b44ce968c283408a163f50c38b3c3522..6defe9c875b40440c5721e0c8d76bfd701db0da9 100644 --- a/frameworks/core/common/include/ans_permission_def.h +++ b/frameworks/core/common/include/ans_permission_def.h @@ -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/include/ans_notification.h b/frameworks/core/include/ans_notification.h index 0f54553b2288ee5249d82c801e21970c6a3a55c8..ed5c087479733965b94d5456767ec3f431bdade5 100644 --- a/frameworks/core/include/ans_notification.h +++ b/frameworks/core/include/ans_notification.h @@ -1435,6 +1435,32 @@ public: */ ErrCode GetLiveViewConfig(const std::vector& bundleList); + /** + * @brief Obtains the list of bundleOption which subscribed by targetBundle + * @param targetBundle The bundle option to be queried. + * @param enabledBundles the list of subscribed bundle options. + * @return Returns get result. + */ + ErrCode GetUserGrantedEnabledBundles(const NotificationBundleOption& targetBundle, + std::vector>& enabledBundles); + + /** + * @brief Obtains the list of bundleOption which granted by user. + * @param bundles The returned list. + * @return Returns get result. + */ + ErrCode GetUserGrantedEnabledBundlesForSelf(std::vector>& bundles); + + /** + * @brief Set the bundleOptions of the extensionAbility to be subscribed or unsubscribed. + * @param targetBundle The bundle option to be set. + * @param enabledBundles The bundle option list to be configured. + * @param enabled Set enabled or not. + * @return Returns set result. + */ + ErrCode SetUserGrantedBundleState(const NotificationBundleOption& targetBundle, + const std::vector>& enabledBundles, bool enabled); + private: /** * @brief Gets Ans Manager proxy. diff --git a/frameworks/core/src/ans_notification.cpp b/frameworks/core/src/ans_notification.cpp index 704f8734e61a35b6af51aac1bda88417cb34f280..ed087f826f30e70fe5e96341473e47b3c34c1ae9 100644 --- a/frameworks/core/src/ans_notification.cpp +++ b/frameworks/core/src/ans_notification.cpp @@ -2593,5 +2593,67 @@ ErrCode AnsNotification::GetDistributedDevicelist(std::vector &devi } return proxy->GetDistributedDevicelist(deviceTypes); } + +ErrCode AnsNotification::GetUserGrantedEnabledBundles( + const NotificationBundleOption& targetBundle, std::vector>& enabledBundles) +{ + ANS_LOGD("called"); + if (targetBundle.GetBundleName().empty()) { + ANS_LOGE("Invalid bundle name."); + return ERR_ANS_INVALID_PARAM; + } + + sptr proxy = GetAnsManagerProxy(); + if (!proxy) { + ANS_LOGE("Get ans manager proxy fail"); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + + sptr bo(new (std::nothrow) NotificationBundleOption(targetBundle)); + if (bo == nullptr) { + ANS_LOGE("null bundleOption"); + return ERR_ANS_INVALID_PARAM; + } + return proxy->GetUserGrantedEnabledBundles(bo, enabledBundles); +} + +ErrCode AnsNotification::GetUserGrantedEnabledBundlesForSelf(std::vector>& bundles) +{ + ANS_LOGD("called"); + sptr proxy = GetAnsManagerProxy(); + if (!proxy) { + ANS_LOGE("Get ans manager proxy fail"); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + + return proxy->GetUserGrantedEnabledBundlesForSelf(bundles); +} + +ErrCode AnsNotification::SetUserGrantedBundleState(const NotificationBundleOption& targetBundle, + const std::vector>& enabledBundles, bool enabled) +{ + ANS_LOGD("called"); + if (targetBundle.GetBundleName().empty()) { + ANS_LOGE("Invalid bundle name."); + return ERR_ANS_INVALID_PARAM; + } + if (enabledBundles.empty()) { + ANS_LOGE("Invalid enabledBundles."); + return ERR_ANS_INVALID_PARAM; + } + + sptr proxy = GetAnsManagerProxy(); + if (!proxy) { + ANS_LOGE("Get ans manager proxy fail"); + return ERR_ANS_SERVICE_NOT_CONNECTED; + } + + sptr bo(new (std::nothrow) NotificationBundleOption(targetBundle)); + if (bo == nullptr) { + ANS_LOGE("null bundleOption"); + return ERR_ANS_INVALID_PARAM; + } + return proxy->SetUserGrantedBundleState(bo, enabledBundles, enabled); +} } // namespace Notification } // namespace OHOS diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn index ac0505b7841a38f8f784120ab7559e7bc100501f..b015fdc68e46a4aff2184e732b5e2d824240f556 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/extension_subscription/init_module.h b/frameworks/js/napi/include/extension_subscription/init_module.h new file mode 100644 index 0000000000000000000000000000000000000000..fecde4b5095424e7c0e88e2ac365907265f4fbca --- /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 0000000000000000000000000000000000000000..bf43dec7dafac434c07aac233f1967f1a6ad6cd5 --- /dev/null +++ b/frameworks/js/napi/include/extension_subscription/napi_notification_extension.h @@ -0,0 +1,41 @@ +/* + * 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 NotificationExtensionUserGrantedParams { + NotificationBundleOption targetBundle; + bool enabled = false; + std::vector> bundles; +}; + +struct AsyncCallbackInfoNotificationExtensionUserGranted { + napi_env env = nullptr; + napi_async_work asyncWork = nullptr; + CallbackPromiseInfo info; + NotificationExtensionUserGrantedParams params; +}; + +napi_value NapiGetUserGrantedEnableBundles(napi_env env, napi_callback_info info); +napi_value NapiSetUserGrantedBundleState(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/extension_subscription/BUILD.gn b/frameworks/js/napi/src/extension_subscription/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8d3c4c015224c34919a9c8daf27c538028346025 --- /dev/null +++ b/frameworks/js/napi/src/extension_subscription/BUILD.gn @@ -0,0 +1,94 @@ +# Copyright (c) 2022-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. + +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 0000000000000000000000000000000000000000..d02d5ab41cecdab59fc39f36a25c545bca068e73 --- /dev/null +++ b/frameworks/js/napi/src/extension_subscription/init_module.cpp @@ -0,0 +1,62 @@ +/* + * 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("getUserGrantedEnableBundles", NapiGetUserGrantedEnableBundles), + DECLARE_NAPI_FUNCTION("setUserGrantedBundleState", NapiSetUserGrantedBundleState), + }; + + 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 0000000000000000000000000000000000000000..36dd52e8cd1b8aa0c05013a916113df081e49ea6 --- /dev/null +++ b/frameworks/js/napi/src/extension_subscription/napi_notification_extension.cpp @@ -0,0 +1,330 @@ +/* + * 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 ParseParametersForGetUserGrantedEnableBundle(const napi_env& env, const napi_callback_info& info, + NotificationExtensionUserGrantedParams& params, bool& isForSelf) +{ + isForSelf = false; + size_t argc = NAPI_GET_USER_GRANTED_ENABLE_BUNDLES_MAX_PARA; + napi_value argv[NAPI_GET_USER_GRANTED_ENABLE_BUNDLES_MAX_PARA] = { nullptr }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + + if (argc < NAPI_GET_USER_GRANTED_ENABLE_BUNDLES_MAX_PARA) { + isForSelf = true; + return Common::NapiGetNull(env); + } + + napi_valuetype valuetype = napi_undefined; + // argv[0]: targetBundle + NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Argument type is incorrect. Object expected."); + std::string msg = "Incorrect parameter types.The type of param must be object."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + auto retValue = Common::GetBundleOption(env, argv[PARAM0], params.targetBundle); + if (retValue == nullptr) { + ANS_LOGE("GetBundleOption failed."); + Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED); + return nullptr; + } + + return Common::NapiGetNull(env); +} + +napi_value ParseParametersForSetUserGrantedBundleState(const napi_env& env, const napi_callback_info& info, + NotificationExtensionUserGrantedParams& params) +{ + ANS_LOGD("called"); + + size_t argc = NAPI_SET_USER_GRANTED_BUNDLE_STATE_MAX_PARA; + napi_value argv[NAPI_SET_USER_GRANTED_BUNDLE_STATE_MAX_PARA] = {nullptr}; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL)); + if (argc < NAPI_SET_USER_GRANTED_BUNDLE_STATE_MAX_PARA) { + ANS_LOGE("Wrong number of arguments."); + Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED); + return nullptr; + } + + napi_valuetype valuetype = napi_undefined; + // argv[0]: targetBundle + NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype)); + if (valuetype != napi_object) { + ANS_LOGE("Argument type is incorrect. Object expected."); + std::string msg = "Incorrect parameter types.The type of param must be object."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + auto retValue = Common::GetBundleOption(env, argv[PARAM0], params.targetBundle); + if (retValue == nullptr) { + ANS_LOGE("GetBundleOption failed."); + Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED); + return nullptr; + } + + // argv[1]: enabledBundles + bool isArray = false; + napi_is_array(env, argv[PARAM1], &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[PARAM1], &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 bundle = nullptr; + napi_get_element(env, argv[PARAM1], index, &bundle); + NAPI_CALL_BASE(env, napi_typeof(env, bundle, &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) NotificationBundleOption(); + if (item == nullptr) { + ANS_LOGE("Failed to create NotificationBundleOption."); + std::string msg = "Parameter verification failed. Failed to create NotificationBundleOption ptr"; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + auto retValue = Common::GetBundleOption(env, bundle, *item); + if (retValue == nullptr) { + ANS_LOGE("null retValue"); + Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED); + return nullptr; + } + params.bundles.emplace_back(item); + } + + // argv[2]: enabled + NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype)); + if (valuetype != napi_boolean) { + ANS_LOGE("Wrong argument type. Bool expected."); + std::string msg = "Incorrect parameter types.The type of param must be boolean."; + Common::NapiThrow(env, ERROR_PARAM_INVALID, msg); + return nullptr; + } + napi_get_value_bool(env, argv[PARAM2], ¶ms.enabled); + + return Common::NapiGetNull(env); +} + +void AsyncCompleteCallbackUserGrantedReturnVoid(napi_env env, napi_status status, void *data) +{ + ANS_LOGD("called"); + if (!data) { + ANS_LOGE("Invalid async callback data"); + return; + } + AsyncCallbackInfoNotificationExtensionUserGranted* 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 AsyncCompleteCallbackRetrunBundleOptionArray(napi_env env, napi_status status, void *data) +{ + ANS_LOGD("called"); + if (!data) { + ANS_LOGE("Invalid async callback data"); + return; + } + AsyncCallbackInfoNotificationExtensionUserGranted* 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->params.bundles) { + if (item == nullptr) { + ANS_LOGW("Invalid NotificationBundleOption object ptr."); + continue; + } + napi_value bundleOption = nullptr; + napi_create_object(env, &bundleOption); + if (!Common::SetBundleOption(env, *item, bundleOption)) { + ANS_LOGW("Set NotificationBundleOption object failed."); + continue; + } + napi_set_element(env, arr, count, bundleOption); + ++count; + } + ANS_LOGI("count = %{public}d", count); + result = arr; + if ((count == 0) && (asynccallbackinfo->params.bundles.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 NapiGetUserGrantedEnableBundles(napi_env env, napi_callback_info info) +{ + ANS_LOGD("called"); + + AsyncCallbackInfoNotificationExtensionUserGranted* asynccallbackinfo = new (std::nothrow) + AsyncCallbackInfoNotificationExtensionUserGranted { .env = env, .asyncWork = nullptr }; + if (!asynccallbackinfo) { + Common::NapiThrow(env, ERROR_INTERNAL_ERROR); + return Common::JSParaError(env, nullptr); + } + + bool isForSelf = false; + if (ParseParametersForGetUserGrantedEnableBundle(env, info, asynccallbackinfo->params, isForSelf) == 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, "getUserGrantedEnableBundles", NAPI_AUTO_LENGTH, &resourceName); + // Asynchronous function call + if (isForSelf) { + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANS_LOGD("getUserGrantedEnableBundles work excute."); + AsyncCallbackInfoNotificationExtensionUserGranted *asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + asynccallbackinfo->info.errorCode = + NotificationHelper::GetUserGrantedEnabledBundlesForSelf(asynccallbackinfo->params.bundles); + ANS_LOGI("GetUserGrantedEnabledBundles errorCode = %{public}d", asynccallbackinfo->info.errorCode); + } + }, + AsyncCompleteCallbackRetrunBundleOptionArray, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + } else { + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANS_LOGD("getUserGrantedEnableBundles work excute."); + AsyncCallbackInfoNotificationExtensionUserGranted *asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + asynccallbackinfo->info.errorCode = NotificationHelper::GetUserGrantedEnabledBundles( + asynccallbackinfo->params.targetBundle, asynccallbackinfo->params.bundles); + ANS_LOGI("GetUserGrantedEnabledBundles errorCode = %{public}d", asynccallbackinfo->info.errorCode); + } + }, + AsyncCompleteCallbackRetrunBundleOptionArray, + (void *)asynccallbackinfo, + &asynccallbackinfo->asyncWork); + } + + napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated); + + return promise; +} + +napi_value NapiSetUserGrantedBundleState(napi_env env, napi_callback_info info) +{ + ANS_LOGD("called"); + + AsyncCallbackInfoNotificationExtensionUserGranted* asynccallbackinfo = new (std::nothrow) + AsyncCallbackInfoNotificationExtensionUserGranted { .env = env, .asyncWork = nullptr }; + if (!asynccallbackinfo) { + Common::NapiThrow(env, ERROR_INTERNAL_ERROR); + return Common::JSParaError(env, nullptr); + } + + if (ParseParametersForSetUserGrantedBundleState(env, info, asynccallbackinfo->params) == 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, "setUserGrantedBundleState", NAPI_AUTO_LENGTH, &resourceName); + // Asynchronous function call + napi_create_async_work(env, + nullptr, + resourceName, + [](napi_env env, void *data) { + ANS_LOGD("setUserGrantedBundleState work excute."); + AsyncCallbackInfoNotificationExtensionUserGranted *asynccallbackinfo = + static_cast(data); + if (asynccallbackinfo) { + asynccallbackinfo->info.errorCode = + NotificationHelper::SetUserGrantedBundleState(asynccallbackinfo->params.targetBundle, + asynccallbackinfo->params.bundles, asynccallbackinfo->params.enabled); + ANS_LOGI("errorCode = %{public}d", asynccallbackinfo->info.errorCode); + } + }, + AsyncCompleteCallbackUserGrantedReturnVoid, + (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_helper.h b/interfaces/inner_api/notification_helper.h index 9344b108c445723b809bda1036d3ab30feb8193e..1dd7db06ed8b67712541abb542272455d4772453 100644 --- a/interfaces/inner_api/notification_helper.h +++ b/interfaces/inner_api/notification_helper.h @@ -1435,6 +1435,32 @@ public: * @return Returns set result. */ static ErrCode GetLiveViewConfig(const std::vector& bundleList); + + /** + * @brief Obtains the list of bundleOption which subscribed by targetBundle + * @param targetBundle The bundle option to be queried. + * @param enabledBundles the list of subscribed bundle options. + * @return Returns get result. + */ + static ErrCode GetUserGrantedEnabledBundles(const NotificationBundleOption& targetBundle, + std::vector>& enabledBundles); + + /** + * @brief Obtains the list of bundleOption which granted by self. + * @param bundles The returned list. + * @return Returns get result. + */ + static ErrCode GetUserGrantedEnabledBundlesForSelf(std::vector>& bundles); + + /** + * @brief Set the bundleOptions of the extensionAbility to be subscribed or unsubscribed. + * @param targetBundle The bundle option to be set. + * @param enabledBundles The bundle option list to be configured. + * @param enabled Set enabled or not. + * @return Returns set result. + */ + static ErrCode SetUserGrantedBundleState(const NotificationBundleOption& targetBundle, + const std::vector>& enabledBundles, bool enabled); }; } // namespace Notification } // namespace OHOS diff --git a/services/ans/BUILD.gn b/services/ans/BUILD.gn index 754e060d5b45459f872f372982d8463f8994e351..f44b4974a2e0eeea19697d38ccb2d6ce7280a6af 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 ed0e690f262838a045adb77f25d7c771df1e9bf7..7e0518378ff44f29935209dbae09854a72b6f527 100644 --- a/services/ans/include/advanced_notification_service.h +++ b/services/ans/include/advanced_notification_service.h @@ -1446,6 +1446,15 @@ public: const std::string& value) override; ErrCode GetLiveViewConfig(const std::vector& bundleList) override; + + ErrCode GetUserGrantedEnabledBundles(const sptr& targetBundle, + std::vector>& enabledBundles) override; + + ErrCode GetUserGrantedEnabledBundlesForSelf(std::vector>& bundles) override; + + ErrCode SetUserGrantedBundleState(const sptr& targetBundle, + const std::vector>& enabledBundles, bool enabled) 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 a400e46f54b2098971a186da02a069caf7d00cb3..fc9129e9ce50375d0f3f915ab62fbf19e10c417b 100644 --- a/services/ans/include/notification_clone_bundle_info.h +++ b/services/ans/include/notification_clone_bundle_info.h @@ -64,9 +64,13 @@ public: void AddSlotInfo(const SlotInfo &slotInfo); std::vector GetSlotInfo() const; + void SetExtensionSubscriptionBundles(const std::vector>& bundles); + const std::vector>& GetExtensionSubscriptionBundles() const; + void ToJson(nlohmann::json &jsonObject) const; void FromJson(const nlohmann::json &root); void SlotsFromJson(const nlohmann::json &jsonObject); + void SubscriptionBundlesFromJson(const nlohmann::json &jsonObject); std::string Dump() const; private: @@ -78,6 +82,7 @@ private: NotificationConstant::SWITCH_STATE isEnabledNotification_ = NotificationConstant::SWITCH_STATE::SYSTEM_DEFAULT_OFF; std::vector slotsInfo_; NotificationConstant::SWITCH_STATE silentReminderEnabled_; + std::vector> extensionSubscriptionBundles_; }; } // namespace Notification } // namespace OHOS diff --git a/services/ans/include/notification_preferences.h b/services/ans/include/notification_preferences.h index b7b6b0c175a84c8b8b15865acb53e1a38029c58c..43959c1c83a485b7ff14403bc6a5ebd45a119263 100644 --- a/services/ans/include/notification_preferences.h +++ b/services/ans/include/notification_preferences.h @@ -574,6 +574,15 @@ public: bool SetLiveViewRebuildFlag(int32_t userId); ErrCode InitBundlesInfo(int32_t userId, std::unordered_map& bundlesMap); void GetAllLiveViewBundles(std::vector>& bundleOption); + ErrCode GetExtensionSubscriptionBundles( + const sptr& bundleOption, std::vector>& bundles); + ErrCode SetExtensionSubscriptionBundles( + const sptr& bundleOption, const std::vector>& bundles); + ErrCode AddExtensionSubscriptionBundles( + const sptr& bundleOption, const std::vector>& bundles); + ErrCode RemoveExtensionSubscriptionBundles( + const sptr& bundleOption, const std::vector>& bundles); + 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 fe92e48d8c4fd10123f325026c10835cd793b304..116cd245b05479f1a7c7b02f230b04d4db3b2943 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 PutExtensionSubscriptionBundles(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 ParseBundleExtensionSubscriptionBundles( + 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 158441557c3eb766be7eea3fcc163d8cc6a19e13..38964141f265879819c19e287e2217b33e7dfa45 100644 --- a/services/ans/include/notification_preferences_info.h +++ b/services/ans/include/notification_preferences_info.h @@ -226,6 +226,12 @@ public: int32_t GetBundleUid() const; void SetSlotEnabled(NotificationConstant::SlotType slotType, bool enabled); bool GetSlotEnabled(NotificationConstant::SlotType slotType, bool &enabled) const; + void GetExtensionSubscriptionBundles(std::vector>& bundles) const; + std::string GetExtensionSubscriptionBundlesJson() const; + void SetExtensionSubscriptionBundles(const std::vector>& bundles); + bool SetExtensionSubscriptionBundlesFromJson(const std::string& json); + void AddExtensionSubscriptionBundles(const std::vector>& bundles); + void RemoveExtensionSubscriptionBundles(const std::vector>& bundles); private: std::string bundleName_; @@ -239,6 +245,7 @@ public: bool hasPoppedDialog_ = BUNDLE_POPPED_DIALOG; std::map> slots_; std::map slotFlagsMap_; + std::map> extensionSubscriptionBundles_; }; /* 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 0000000000000000000000000000000000000000..3d6b6b9a12794489e5acd2ce3689f63be1472626 --- /dev/null +++ b/services/ans/src/advanced_notification_extension_subscription.cpp @@ -0,0 +1,145 @@ +/* + * 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::GetUserGrantedEnabledBundles( + const sptr& targetBundle, std::vector>& enabledBundles) +{ + ANS_LOGD("AdvancedNotificationService::GetUserGrantedEnabledBundles"); + 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(targetBundle); + if (bundle == nullptr) { + ANS_LOGE("Bundle is null."); + 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 GetUserGrantedEnabledBundles!"); + result = NotificationPreferences::GetInstance()->GetExtensionSubscriptionBundles(bundle, enabledBundles); + if (result != ERR_OK) { + ANS_LOGE("Failed to get enabled bundles from database, ret: %{public}d", result); + return; + } + })); + notificationSvrQueue_->wait(handler); + return result; +} + +ErrCode AdvancedNotificationService::GetUserGrantedEnabledBundlesForSelf( + std::vector>& bundles) +{ + ANS_LOGD("AdvancedNotificationService::GetUserGrantedEnabledBundlesForSelf"); + 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 GetUserGrantedEnabledBundlesForSelf!"); + result = NotificationPreferences::GetInstance()->GetExtensionSubscriptionBundles(bundleOption, bundles); + if (result != ERR_OK) { + ANS_LOGE("Failed to get enabled bundles from database, ret: %{public}d", result); + return; + } + })); + notificationSvrQueue_->wait(handler); + + return result; +} + +ErrCode AdvancedNotificationService::SetUserGrantedBundleState( + const sptr& targetBundle, + const std::vector>& enabledBundles, bool enabled) +{ + ANS_LOGD("AdvancedNotificationService::SetUserGrantedBundleState"); + 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(targetBundle); + if (bundle == nullptr) { + ANS_LOGE("Bundle is null."); + 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 SetUserGrantedBundleState!"); + result = enabled ? + NotificationPreferences::GetInstance()->AddExtensionSubscriptionBundles( + bundle, enabledBundles) : + NotificationPreferences::GetInstance()->RemoveExtensionSubscriptionBundles( + bundle, enabledBundles); + if (result != ERR_OK) { + ANS_LOGE("Failed to set enabled bundles to database, 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 bcae685ddfb09b9d6301e63c5ccbb3914a3bc2c1..4c57ebf0c56ed7d7add99f82292f5b89c6c71e70 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()->SetExtensionSubscriptionBundles( + bundle, cloneBundleInfo.GetExtensionSubscriptionBundles()) == ERR_OK) { + // handle bundle subscription bundles changed + } else { + ANS_LOGW("Set subscription bundles 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 a189acbbd8a0bc8a8844c6c8b506fa596202f790..ee7d76cacc8d2f63903ac31d037d98345115a491 100644 --- a/services/ans/src/clone/notification_clone_bundle_info.cpp +++ b/services/ans/src/clone/notification_clone_bundle_info.cpp @@ -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_BUNDLES = "extensionSubscriptionBundles"; constexpr int32_t CONST_ENABLE_INT = 1; } void NotificationCloneBundleInfo::SetBundleName(const std::string &name) @@ -124,6 +125,17 @@ std::vector NotificationCloneBundleInfo:: return slotsInfo_; } +void NotificationCloneBundleInfo::SetExtensionSubscriptionBundles( + const std::vector>& bundles) +{ + extensionSubscriptionBundles_ = bundles; +} + +const std::vector>& NotificationCloneBundleInfo::GetExtensionSubscriptionBundles() const +{ + return extensionSubscriptionBundles_; +} + void NotificationCloneBundleInfo::ToJson(nlohmann::json &jsonObject) const { if (!slotsInfo_.empty()) { @@ -139,6 +151,16 @@ void NotificationCloneBundleInfo::ToJson(nlohmann::json &jsonObject) const jsonObject[BUNDLE_INFO_SLOT_LIST] = jsonNodes; } + if (!extensionSubscriptionBundles_.empty()) { + nlohmann::json jsonNodes = nlohmann::json::array(); + for (const auto& bundle : extensionSubscriptionBundles_) { + nlohmann::json jsonNode; + bundle->ToJson(jsonNode); + jsonNodes.emplace_back(jsonNode); + } + jsonObject[BUNDLE_INFO_SUBSCRIPTION_BUNDLES] = jsonNodes; + } + jsonObject[BUNDLE_INFO_NAME] = bundleName_; jsonObject[BUNDLE_INFO_APP_INDEX] = appIndex_; jsonObject[BUNDLE_INFO_SLOT_FLAGS] = slotFlags_; @@ -175,6 +197,18 @@ void NotificationCloneBundleInfo::SlotsFromJson(const nlohmann::json &jsonObject } } +void NotificationCloneBundleInfo::SubscriptionBundlesFromJson(const nlohmann::json &jsonObject) +{ + if (!jsonObject.contains(BUNDLE_INFO_SUBSCRIPTION_BUNDLES) || + !jsonObject[BUNDLE_INFO_SUBSCRIPTION_BUNDLES].is_array()) { + return; + } + + for (auto &bundleJson : jsonObject.at(BUNDLE_INFO_SUBSCRIPTION_BUNDLES)) { + extensionSubscriptionBundles_.emplace_back(NotificationBundleOption::FromJson(bundleJson)); + } +} + 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); + SubscriptionBundlesFromJson(jsonObject); } std::string NotificationCloneBundleInfo::SlotInfo::Dump() const { diff --git a/services/ans/src/notification_preferences.cpp b/services/ans/src/notification_preferences.cpp index 38b662af96056ffed4442982c593c90c7a5ab4dc..4b22cd1db80bd3449984fe74a231bd52298aadf3 100644 --- a/services/ans/src/notification_preferences.cpp +++ b/services/ans/src/notification_preferences.cpp @@ -1727,6 +1727,125 @@ ErrCode NotificationPreferences::GetDistributedDevicelist(std::vector& bundleOption, std::vector>& bundles) +{ + 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)) { + bundleInfo.GetExtensionSubscriptionBundles(bundles); + } else { + ANS_LOGW("Notification bundle does not exsit."); + bundles.clear(); + } + return ERR_OK; +} + +ErrCode NotificationPreferences::SetExtensionSubscriptionBundles( + const sptr& bundleOption, const std::vector>& bundles) +{ + 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.SetExtensionSubscriptionBundles(bundles); + if (preferncesDB_ == nullptr) { + ANS_LOGE("the prefernces db is nullptr"); + return ERR_ANS_SERVICE_NOT_READY; + } + if (preferncesDB_->PutExtensionSubscriptionBundles(bundleInfo)) { + preferencesInfo.SetBundleInfo(bundleInfo); + preferencesInfo_ = preferencesInfo; + return ERR_OK; + } else { + return ERR_ANS_PREFERENCES_NOTIFICATION_DB_OPERATION_FAILED; + } +} + +ErrCode NotificationPreferences::AddExtensionSubscriptionBundles( + const sptr& bundleOption, const std::vector>& bundles) +{ + 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.AddExtensionSubscriptionBundles(bundles); + if (preferncesDB_ == nullptr) { + ANS_LOGE("the prefernces db is nullptr"); + return ERR_ANS_SERVICE_NOT_READY; + } + if (preferncesDB_->PutExtensionSubscriptionBundles(bundleInfo)) { + preferencesInfo.SetBundleInfo(bundleInfo); + preferencesInfo_ = preferencesInfo; + return ERR_OK; + } else { + return ERR_ANS_PREFERENCES_NOTIFICATION_DB_OPERATION_FAILED; + } +} + +ErrCode NotificationPreferences::RemoveExtensionSubscriptionBundles( + const sptr& bundleOption, const std::vector>& bundles) +{ + 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.RemoveExtensionSubscriptionBundles(bundles); + if (preferncesDB_ == nullptr) { + ANS_LOGE("the prefernces db is nullptr"); + return ERR_ANS_SERVICE_NOT_READY; + } + if (preferncesDB_->PutExtensionSubscriptionBundles(bundleInfo)) { + preferencesInfo.SetBundleInfo(bundleInfo); + preferencesInfo_ = preferencesInfo; + return ERR_OK; + } else { + return ERR_ANS_PREFERENCES_NOTIFICATION_DB_OPERATION_FAILED; + } +} + 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 e95c31de17e9f2ea332e6f5975b1560c028acab1..8de17ba0821423c24802f576c4cce8003a44f797 100644 --- a/services/ans/src/notification_preferences_database.cpp +++ b/services/ans/src/notification_preferences_database.cpp @@ -233,6 +233,8 @@ 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_BUNDLES = "extensionSubscriptionBundles"; + constexpr char RELATIONSHIP_JSON_KEY_SERVICE[] = "service"; constexpr char RELATIONSHIP_JSON_KEY_APP[] = "app"; @@ -729,6 +731,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_BUNDLES), + bundleInfo.GetExtensionSubscriptionBundlesJson(), values); if (!CheckRdbStore()) { ANS_LOGE("null RdbStore"); return false; @@ -1259,6 +1263,9 @@ void NotificationPreferencesDatabase::ParseBundlePropertyFromDisturbeDB( if (typeStr.compare(KEY_BUNDLE_SLOTFLGS_TYPE) == 0) { return ParseBundleSlotFlags(bundleInfo, valueStr); } + if (typeStr.compare(KEY_EXTENSION_SUBSCRIPTION_BUNDLES) == 0) { + return ParseBundleExtensionSubscriptionBundles(bundleInfo, valueStr); + } } void NotificationPreferencesDatabase::ParseSlot(const std::string &findString, sptr &slot, @@ -1646,6 +1653,13 @@ void NotificationPreferencesDatabase::ParseSlotReminderMode( slot->SetReminderMode(reminderMode); } +void NotificationPreferencesDatabase::ParseBundleExtensionSubscriptionBundles( + NotificationPreferencesInfo::BundleInfo &bundleInfo, const std::string &value) const +{ + ANS_LOGD("ParseBundleExtensionSubscriptionBundles bundle bundels: %{public}s.", value.c_str()); + bundleInfo.SetExtensionSubscriptionBundlesFromJson(value); +} + std::string NotificationPreferencesDatabase::GenerateBundleLablel( const NotificationPreferencesInfo::BundleInfo &bundleInfo) const { @@ -2596,6 +2610,30 @@ bool NotificationPreferencesDatabase::IsSmartReminderEnabled(const std::string d return result; } +bool NotificationPreferencesDatabase::PutExtensionSubscriptionBundles( + 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_BUNDLES), + bundleInfo.GetExtensionSubscriptionBundlesJson(), 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 9eb121215945cb4ee078977fdf57df3bcca545db..1c18f2268617b31e449d229644a8897476b5906c 100644 --- a/services/ans/src/notification_preferences_info.cpp +++ b/services/ans/src/notification_preferences_info.cpp @@ -222,6 +222,81 @@ int32_t NotificationPreferencesInfo::BundleInfo::GetBundleUid() const return uid_; } +void NotificationPreferencesInfo::BundleInfo::GetExtensionSubscriptionBundles( + std::vector>& bundles) const +{ + bundles.clear(); + for (const auto& item : extensionSubscriptionBundles_) { + bundles.emplace_back(item.second); + } +} + +std::string NotificationPreferencesInfo::BundleInfo::GetExtensionSubscriptionBundlesJson() const +{ + std::vector> bundles; + GetExtensionSubscriptionBundles(bundles); + auto jsonObject = nlohmann::json::array(); + for (const auto& item : bundles) { + nlohmann::json jsonNode; + item->ToJson(jsonNode); + jsonObject.emplace_back(jsonNode); + } + return jsonObject.dump(); +} + +void NotificationPreferencesInfo::BundleInfo::SetExtensionSubscriptionBundles( + const std::vector>& bundles) +{ + extensionSubscriptionBundles_.clear(); + AddExtensionSubscriptionBundles(bundles); +} + +bool NotificationPreferencesInfo::BundleInfo::SetExtensionSubscriptionBundlesFromJson(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 bundle list failed due to data is discarded or not array"); + return false; + } + + std::vector> bundles; + for (const auto &item : jsonObject) { + bundles.emplace_back(NotificationBundleOption::FromJson(item)); + } + SetExtensionSubscriptionBundles(bundles); + + return true; +} + +void NotificationPreferencesInfo::BundleInfo::AddExtensionSubscriptionBundles( + const std::vector>& bundles) +{ + for (const auto& item : bundles) { + std::string bundleKey = item->GetBundleName() + std::to_string(item->GetUid()); + extensionSubscriptionBundles_.insert_or_assign(bundleKey, item); + } +} + +void NotificationPreferencesInfo::BundleInfo::RemoveExtensionSubscriptionBundles( + const std::vector>& bundles) +{ + for (const auto& item : bundles) { + std::string bundleKey = item->GetBundleName() + std::to_string(item->GetUid()); + auto iter = extensionSubscriptionBundles_.find(bundleKey); + if (iter != extensionSubscriptionBundles_.end()) { + extensionSubscriptionBundles_.erase(iter); + } + } +} + void NotificationPreferencesInfo::SetBundleInfo(BundleInfo &info) { std::string bundleKey = info.GetBundleName().append(std::to_string(info.GetBundleUid())); @@ -393,6 +468,9 @@ void NotificationPreferencesInfo::GetAllCLoneBundlesInfo(const int32_t &userId, (slot->GetAuthorizedStatus() ==NotificationSlot::AuthorizedStatus::AUTHORIZED); cloneBundleInfo.AddSlotInfo(slotInfo); } + std::vector> bundles; + iter->second.GetExtensionSubscriptionBundles(bundles); + cloneBundleInfo.SetExtensionSubscriptionBundles(bundles); auto silentReminderIter = silentReminderInfos_.find(bundleItem.second); if (silentReminderIter != silentReminderInfos_.end()) { auto enableStatus = silentReminderIter->second.enableStatus;