diff --git a/frameworks/extension/BUILD.gn b/frameworks/extension/BUILD.gn index 220a2421c74bbaa83a8db4d482993b7cfac771c5..03d2b7bc828d9371134a2f013ce6e0e0df07f2fc 100644 --- a/frameworks/extension/BUILD.gn +++ b/frameworks/extension/BUILD.gn @@ -102,6 +102,69 @@ ohos_shared_library("static_subscriber_extension") { "ability_base:want", "ability_runtime:ability_context_native", "ability_runtime:ability_manager", + "ability_runtime:ani_common", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "napi:ace_napi", + ] + + subsystem_name = "notification" + part_name = "common_event_service" +} + +config("static_subscriber_extension_ani_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${ces_extension_path}/include", + "${ces_extension_path}/include/ani", + ] +} + +ohos_shared_library("static_subscriber_extension_ani") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + include_dirs = [] + + sources = [ + "${ces_extension_path}/src/ani/ani_common_event_utils.cpp", + "${ces_extension_path}/src/ani/ani_static_subscriber_extension.cpp", + "${ces_extension_path}/src/ani/ani_static_subscriber_extension_context.cpp", + "${ces_extension_path}/src/static_subscriber_extension.cpp", + "${ces_extension_path}/src/static_subscriber_extension_context.cpp", + "${ces_extension_path}/src/static_subscriber_stub_impl.cpp", + ] + + configs = [] + public_configs = [ ":static_subscriber_extension_ani_public_config" ] + + deps = [ + ":static_subscriber_extension", + ":static_subscriber_ipc", + "${ces_native_path}:cesfwk_innerkits" + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:ani_common", "ability_runtime:app_context", "ability_runtime:extensionkit_native", "ability_runtime:napi_common", @@ -114,6 +177,8 @@ ohos_shared_library("static_subscriber_extension") { "ipc:ipc_core", "ipc:ipc_napi", "napi:ace_napi", + "runtime_core:ani", + "runtime_core:ani_helpers", ] subsystem_name = "notification" @@ -169,6 +234,7 @@ ohos_shared_library("static_subscriber_extension_module") { group("cesfwk_extension") { deps = [ ":static_subscriber_extension", + ":static_subscriber_extension_ani", ":static_subscriber_extension_module", ":static_subscriber_ipc", ] diff --git a/frameworks/extension/include/ani/ani_common_event_utils.h b/frameworks/extension/include/ani/ani_common_event_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..2781a935a193a517c1f4917bc4a54fb01e95730f --- /dev/null +++ b/frameworks/extension/include/ani/ani_common_event_utils.h @@ -0,0 +1,39 @@ +/* + * 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_COMMON_EVENT_MANAGER_INCLUDE_ANI_COMMON_EVENT_UTILS_H +#define BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_COMMON_EVENT_UTILS_H + +#include +#include +#include +#include + +#include "common_event_manager.h" + +namespace OHOS { +namespace EventManagerFwkAni { +using CommonEventData = OHOS::EventFwk::CommonEventData; +class AniCommonEventUtils { +public: + static void ConvertCommonEventDataToEts(ani_env* env, ani_object& ani_data, const CommonEventData& commonEventData); + static void CreateNewObjectByClass(ani_env* env, const char* className, ani_class &cls, ani_object& ani_data); + template + static void CallSetter(ani_env* env, ani_class cls, ani_object object, const char* setterName, valueType value); + static void CreateAniDoubleObject(ani_env* env, ani_object &object, ani_double value); +}; +} // namespace EventManagerFwkAni +} // namespace OHOS +#endif // BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_COMMON_EVENT_UTILS_H \ No newline at end of file diff --git a/frameworks/extension/include/ani/ani_static_subscriber_extension.h b/frameworks/extension/include/ani/ani_static_subscriber_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..502f0f1f995f5ff5b570bded2080c5def55b3ee3 --- /dev/null +++ b/frameworks/extension/include/ani/ani_static_subscriber_extension.h @@ -0,0 +1,77 @@ +/* + * 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_COMMON_EVENT_MANAGER_INCLUDE_ANI_STATIC_SUBSCRIBER_EXTENSION_H +#define BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_STATIC_SUBSCRIBER_EXTENSION_H + +#include +#include +#include + +#include "ani_static_subscriber_extension_context.h" +#include "ability_handler.h" +#include "common_event_data.h" +#include "common_event_manager.h" +#include "extension_base.h" +#include "native_engine/native_engine.h" +#include "ohos_application.h" +#include "static_subscriber_extension.h" +#include "static_subscriber_extension_context.h" +#include "ets_runtime.h" +#include "ets_native_reference.h" + +namespace OHOS { +namespace EventManagerFwkAni { +using namespace OHOS::AppExecFwk; +using namespace OHOS::EventFwk; +using namespace OHOS::AbilityRuntime; +using CommonEventData = OHOS::EventFwk::CommonEventData; + +class StsStaticSubscriberExtension : public StaticSubscriberExtension { +public: + explicit StsStaticSubscriberExtension(AbilityRuntime::ETSRuntime &stsRuntime); + virtual ~StsStaticSubscriberExtension() override; + + static StsStaticSubscriberExtension* Create(const std::unique_ptr& stsRuntime); + + void Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + void OnStart(const AAFwk::Want& want) override; + + sptr OnConnect(const AAFwk::Want& want) override; + + void OnDisconnect(const AAFwk::Want& want) override; + + void OnStop() override; + + void OnReceiveEvent(const std::shared_ptr data) override; + + void ResetEnv(ani_env* env); + + std::weak_ptr GetWeakPtr(); + + void CallObjectMethod(bool withResult, const char* name, const char* signature, ...); + +private: + void BindContext(ani_env *env, const std::shared_ptr &application); + AbilityRuntime::ETSRuntime& stsRuntime_; + std::unique_ptr stsObj_; +}; +} // namespace EventManagerFwkAni +} // namespace OHOS +#endif // BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_STATIC_SUBSCRIBER_EXTENSION_H \ No newline at end of file diff --git a/frameworks/extension/include/ani/ani_static_subscriber_extension_context.h b/frameworks/extension/include/ani/ani_static_subscriber_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..580433c32f649f2869152f917b968f4a9724984d --- /dev/null +++ b/frameworks/extension/include/ani/ani_static_subscriber_extension_context.h @@ -0,0 +1,54 @@ +/* + * 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_COMMON_EVENT_MANAGER_INCLUDE_ANI_STATIC_SUBSCRIBER_EXTENSION_CONTEXT_H +#define BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_STATIC_SUBSCRIBER_EXTENSION_CONTEXT_H + +#include +#include +#include +#include + +#include "context.h" +#include "ohos_application.h" +#include "static_subscriber_extension_context.h" + +namespace OHOS { +namespace EventManagerFwkAni { +using namespace OHOS::EventFwk; +using namespace OHOS::AbilityRuntime; +namespace { +constexpr const char* STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME = + "L@ohos/application/StaticSubscriberExtensionContext/StaticSubscriberExtensionContext;"; +} + +ani_object CreateStaticSubscriberExtensionContext(ani_env *env, + std::shared_ptr context); + +class StsStaticSubscriberExtensionContext final { +public: + explicit StsStaticSubscriberExtensionContext(const std::shared_ptr& context) + : context_(context) {} + ~StsStaticSubscriberExtensionContext() = default; + + void StartAbilityInner(ani_env *env, ani_object aniObj, ani_object wantObj); + static StsStaticSubscriberExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); + std::shared_ptr GetAbilityContext(); + +private: + std::weak_ptr context_; +}; +} // namespace EventManagerFwkAni +} // namespace OHOS +#endif // BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_STATIC_SUBSCRIBER_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/frameworks/extension/include/js_static_subscriber_extension_context.h b/frameworks/extension/include/js_static_subscriber_extension_context.h index f0eab5a71ba0b2bd636bc9162628553afc3e30f1..6ac0e3ebf0068def4349f9edf2ec20c418f42901 100644 --- a/frameworks/extension/include/js_static_subscriber_extension_context.h +++ b/frameworks/extension/include/js_static_subscriber_extension_context.h @@ -25,6 +25,25 @@ namespace OHOS { namespace EventFwk { napi_value CreateJsStaticSubscriberExtensionContext(napi_env env, std::shared_ptr context); + +class JsStaticSubscriberExtensionContext final { +public: + explicit JsStaticSubscriberExtensionContext(const std::shared_ptr& context) + : context_(context) {} + ~JsStaticSubscriberExtensionContext() = default; + + static void Finalizer(napi_env env, void* data, void* hint) + { + std::unique_ptr( + static_cast(data)); + } + + static napi_value StartAbility(napi_env env, napi_callback_info info); + std::shared_ptr GetAbilityContext(); +private: + napi_value OnStartAbility(napi_env env, napi_callback_info info, bool isStartRecent = false); + std::weak_ptr context_; +}; } // namespace EventFwk } // namespace OHOS #endif // OHOS_COMMON_EVENT_SERVICE_JS_STATIC_SUBSCRIBER_EXTENSION_CONTEXT_H diff --git a/frameworks/extension/include/static_subscriber_stub_impl.h b/frameworks/extension/include/static_subscriber_stub_impl.h index 0de820eec546f607757a032c03198cc1acb8fbd3..d7f1d51a883dcb5c1c2978ffcee7c8a07ae5c50f 100644 --- a/frameworks/extension/include/static_subscriber_stub_impl.h +++ b/frameworks/extension/include/static_subscriber_stub_impl.h @@ -17,14 +17,15 @@ #define OHOS_COMMON_EVENT_SERVICE_STATIC_SUBSCRIBER_STUB_IMPL_H #include -#include "js_static_subscriber_extension.h" + +#include "static_subscriber_extension.h" #include "static_subscriber_stub.h" namespace OHOS { namespace EventFwk { class StaticSubscriberStubImpl : public StaticSubscriberStub { public: - explicit StaticSubscriberStubImpl(const std::shared_ptr& extension) + explicit StaticSubscriberStubImpl(const std::shared_ptr& extension) : extension_(extension) {} virtual ~StaticSubscriberStubImpl() = default; @@ -32,7 +33,7 @@ public: ErrCode OnReceiveEvent(const CommonEventData& data, int32_t& funcResult) override; private: - std::weak_ptr extension_; + std::weak_ptr extension_; }; } // namespace EventFwk } // namespace OHOS diff --git a/frameworks/extension/src/ani/ani_common_event_utils.cpp b/frameworks/extension/src/ani/ani_common_event_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..12f267d59de03afb50fc7c1d07f61c3f3e801a13 --- /dev/null +++ b/frameworks/extension/src/ani/ani_common_event_utils.cpp @@ -0,0 +1,131 @@ +/* + * 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 "ani_common_event_utils.h" + +#include "ani_common_want.h" +#include "event_log_wrapper.h" + +namespace OHOS { +namespace EventManagerFwkAni { + +using namespace OHOS::EventFwk; +using namespace OHOS::AppExecFwk; +#define SETTER_METHOD_NAME(property) "" #property + +void AniCommonEventUtils::CreateNewObjectByClass( + ani_env* env, const char* className, ani_class& cls, ani_object& ani_data) +{ + auto aniResult = ANI_ERROR; + ani_method ctor = nullptr; + aniResult = env->FindClass(className, &cls); + if (aniResult != ANI_OK) { + EVENT_LOGE("CreateNewObjectByClass findClass error. result: %{public}d.", aniResult); + return; + } + if (cls == nullptr) { + EVENT_LOGE("CreateNewObjectByClass cls is null."); + return; + } + aniResult = env->Class_FindMethod(cls, "", ":V", &ctor); + if (aniResult != ANI_OK) { + EVENT_LOGE("CreateNewObjectByClass Class_FindMethod error. result: %{public}d.", aniResult); + return; + } + aniResult = env->Object_New(cls, ctor, &ani_data); + if (aniResult != ANI_OK) { + EVENT_LOGE("CreateNewObjectByClass Object_New error. result: %{public}d.", aniResult); + } + return; +} + +template +void AniCommonEventUtils::CallSetter( + ani_env* env, ani_class cls, ani_object object, const char* setterName, valueType value) +{ + ani_status aniResult = ANI_ERROR; + ani_method setter; + aniResult = env->Class_FindMethod(cls, setterName, nullptr, &setter); + if (aniResult != ANI_OK) { + EVENT_LOGE("CallSetter Class_FindMethod error. result: %{public}d.", aniResult); + return; + } + aniResult = env->Object_CallMethod_Void(object, setter, value); + if (aniResult != ANI_OK) { + EVENT_LOGE("CallSetter Object_CallMethod_Void error. result: %{public}d.", aniResult); + } + return; +} + +void AniCommonEventUtils::CreateAniDoubleObject(ani_env* env, ani_object &object, ani_double value) +{ + ani_status aniResult = ANI_ERROR; + ani_class clsDouble = nullptr; + ani_method ctor; + aniResult = env->FindClass("Lstd/core/Double;", &clsDouble); + if (aniResult != ANI_OK) { + EVENT_LOGE("CreateAniDoubleObject FindClass error. result: %{public}d.", aniResult); + return; + } + aniResult = env->Class_FindMethod(clsDouble, "", "D:V", &ctor); + if (aniResult != ANI_OK) { + EVENT_LOGE("CreateAniDoubleObject Class_FindMethod error. result: %{public}d.", aniResult); + return; + } + aniResult = env->Object_New(clsDouble, ctor, &object, value); + if (aniResult != ANI_OK) { + EVENT_LOGE("CreateAniDoubleObject Object_New error. result: %{public}d.", aniResult); + return; + } +} + +void AniCommonEventUtils::ConvertCommonEventDataToEts( + ani_env* env, ani_object& ani_data, const CommonEventData& commonEventData) +{ + EVENT_LOGI("ConvertCommonEventDataToEts called"); + + ani_class cls = nullptr; + CreateNewObjectByClass(env, "LcommonEvent/commonEventData/CommonEventDataImpl;", cls, ani_data); + if ((ani_data == nullptr) || (cls == nullptr)) { + EVENT_LOGE("ConvertCommonEventDataToEts ani_data or cls is null."); + return; + } + + ani_string string = nullptr; + // set event [string] + env->String_NewUTF8( + commonEventData.GetWant().GetAction().c_str(), commonEventData.GetWant().GetAction().size(), &string); + CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(event), string); + + // set bundleName [string] + env->String_NewUTF8( + commonEventData.GetWant().GetBundle().c_str(), commonEventData.GetWant().GetBundle().size(), &string); + CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(bundleName), string); + + // set data [string] + env->String_NewUTF8(commonEventData.GetData().c_str(), commonEventData.GetData().size(), &string); + CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(data), string); + + // set code [number] + ani_object codeObject; + CreateAniDoubleObject(env, codeObject, static_cast(commonEventData.GetCode())); + CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(code), codeObject); + + // set parameters [Record] + ani_ref wantParamRef = WrapWantParams(env, commonEventData.GetWant().GetParams()); + CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(parameters), wantParamRef); +} + +} // namespace EventManagerFwkAni +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/extension/src/ani/ani_static_subscriber_extension.cpp b/frameworks/extension/src/ani/ani_static_subscriber_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d25b2b7f96251c1bc69a668563fca78de79dc09 --- /dev/null +++ b/frameworks/extension/src/ani/ani_static_subscriber_extension.cpp @@ -0,0 +1,355 @@ +/* + * 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 "ani_static_subscriber_extension.h" + +#include "ability_handler.h" +#include "ani_common_want.h" +#include "ani_common_event_utils.h" +#include "ani_static_subscriber_extension_context.h" +#include "application_context.h" +#include "context.h" +#include "connection_manager.h" +#include "event_log_wrapper.h" +#include "extension_base.h" +#include "interop_js/arkts_esvalue.h" +#include "interop_js/arkts_interop_js_api.h" +#include "js_static_subscriber_extension_context.h" +#include "native_engine/native_engine.h" +#include "ets_runtime.h" +#include "static_subscriber_stub_impl.h" + +#ifndef SYMBOL_EXPORT +#define SYMBOL_EXPORT __attribute__ ((visibility("default"))) +#endif + +namespace OHOS { +namespace EventManagerFwkAni { +using namespace OHOS::AppExecFwk; +using namespace OHOS::AbilityRuntime; +using namespace OHOS::EventFwk; +using namespace OHOS::EventManagerFwkAni; + +extern "C" SYMBOL_EXPORT StsStaticSubscriberExtension* OHOS_STS_StaticSubscriberExtension_Creation( + const std::unique_ptr& runtime) +{ + return StsStaticSubscriberExtension::Create(runtime); +} + +StsStaticSubscriberExtension* StsStaticSubscriberExtension::Create(const std::unique_ptr& runtime) +{ + return new StsStaticSubscriberExtension(static_cast(*runtime)); +} +StsStaticSubscriberExtension::StsStaticSubscriberExtension(ETSRuntime &stsRuntime) : stsRuntime_(stsRuntime) {} +StsStaticSubscriberExtension::~StsStaticSubscriberExtension() +{ + EVENT_LOGD("~StsStaticSubscriberExtension called"); +} + +void StsStaticSubscriberExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + if (record == nullptr) { + EVENT_LOGE("record null"); + return; + } + StaticSubscriberExtension::Init(record, application, handler, token); + if (Extension::abilityInfo_ == nullptr || Extension::abilityInfo_->srcEntrance.empty()) { + EVENT_LOGE("StaticSubscriberExtension Init abilityInfo error"); + return; + } + std::string srcPath(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + stsObj_ = stsRuntime_.LoadModule( + moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, abilityInfo_->srcEntrance); + if (stsObj_ == nullptr) { + EVENT_LOGE("stsObj_ null"); + return; + } + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + EVENT_LOGE("null env"); + return; + } + BindContext(env, application); + return; +} + +static void NativeStartAbility([[maybe_unused]] ani_env *env, ani_object aniObj, ani_object wantObj) +{ + EVENT_LOGD("StartAbility"); + auto context = StsStaticSubscriberExtensionContext::GetAbilityContext(env, aniObj); + if (context != nullptr) { + context->StartAbilityInner(env, aniObj, wantObj); + } +} + +static ani_ref TransferToDynamicContext(ani_env *env, [[maybe_unused]] ani_class, ani_object input) +{ + ani_ref undefinedRef {}; + env->GetUndefined(&undefinedRef); + auto aniNativeContext = StsStaticSubscriberExtensionContext::GetAbilityContext(env, input); + if (aniNativeContext == nullptr) { + EVENT_LOGE("context is null"); + return undefinedRef; + } + napi_env jsEnv; + arkts_napi_scope_open(env, &jsEnv); + auto napiContextValue = EventFwk::CreateJsStaticSubscriberExtensionContext(jsEnv, + aniNativeContext->GetAbilityContext()); + ani_ref result {}; + arkts_napi_scope_close_n(jsEnv, 1, &napiContextValue, &result); + return result; +} + +static ani_ref TransferToStaticContext(ani_env *env, [[maybe_unused]] ani_class, ani_object input) +{ + ani_ref undefinedRef {}; + env->GetUndefined(&undefinedRef); + EventFwk::JsStaticSubscriberExtensionContext *napiNativeContext = nullptr; + arkts_esvalue_unwrap(env, input, (void **)&napiNativeContext); + if (napiNativeContext == nullptr) { + EVENT_LOGE("context is null"); + return undefinedRef; + } + auto context = napiNativeContext->GetAbilityContext(); + if (context == nullptr) { + EVENT_LOGE("context is null"); + return undefinedRef; + } + auto aniContextValue = CreateStaticSubscriberExtensionContext(env, context); + ani_ref contextRef = nullptr; + if (env->GlobalReference_Create(aniContextValue, &contextRef) != ANI_OK) { + EVENT_LOGE("GlobalReference_Create contextObj failed"); + return undefinedRef; + } + return contextRef; +} + +static void ContextClean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + ani_long ptr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "ptr", &ptr)) { + return; + } + StsStaticSubscriberExtensionContext* context = reinterpret_cast(ptr); + if (context == nullptr) { + EVENT_LOGE("clean wrapper is null."); + return; + } + delete context; +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) +{ + EVENT_LOGI("ANI_Constructor call."); + ani_env* env; + ani_status status = ANI_ERROR; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + EVENT_LOGE("Unsupported ANI_VERSION_1."); + return ANI_ERROR; + } + + ani_class cls = nullptr; + if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + EVENT_LOGE("find class status : %{public}d", status); + return ANI_INVALID_ARGS; + } + std::array functions = { + ani_native_function { "nativeStartAbilitySync", "L@ohos/app/ability/Want/Want;:V", + reinterpret_cast(NativeStartAbility) }, + ani_native_function { "transferToDynamicContext", nullptr, + reinterpret_cast(TransferToDynamicContext) }, + ani_native_function { "transferToStaticContext", nullptr, + reinterpret_cast(TransferToStaticContext) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + EVENT_LOGE("bind method status : %{public}d", status); + return ANI_INVALID_TYPE; + } + ani_class cleanCls; + status = env->FindClass("L@ohos/application/StaticSubscriberExtensionContext/Cleaner;", &cleanCls); + if (status != ANI_OK) { + EVENT_LOGE("Not found L@ohos/application/StaticSubscriberExtensionContext/Cleaner"); + return ANI_INVALID_ARGS; + } + std::array cleanMethod = { + ani_native_function{"clean", nullptr, reinterpret_cast(ContextClean)}}; + status = env->Class_BindNativeMethods(cleanCls, cleanMethod.data(), cleanMethod.size()); + if (status != ANI_OK) { + EVENT_LOGE("Cannot bind native methods to Cleaner result %{public}d", status); + return ANI_INVALID_TYPE; + } + *result = ANI_VERSION_1; + return ANI_OK; +} +} + +void StsStaticSubscriberExtension::BindContext(ani_env* env, const std::shared_ptr &application) +{ + EVENT_LOGD("StsStaticSubscriberExtension BindContext Call"); + auto context = GetContext(); + if (context == nullptr) { + EVENT_LOGE("Failed to get context"); + return; + } + + ani_object contextObj = CreateStaticSubscriberExtensionContext(env, context); + if (contextObj == nullptr) { + EVENT_LOGE("null contextObj"); + return; + } + + ani_field contextField; + auto status = env->Class_FindField(stsObj_->aniCls, "context", &contextField); + if (status != ANI_OK) { + EVENT_LOGE("Class_GetField context failed"); + ResetEnv(env); + return; + } + ani_ref contextRef = nullptr; + if (env->GlobalReference_Create(contextObj, &contextRef) != ANI_OK) { + EVENT_LOGE("GlobalReference_Create contextObj failed"); + return; + } + if (env->Object_SetField_Ref(stsObj_->aniObj, contextField, contextRef) != ANI_OK) { + EVENT_LOGE("Object_SetField_Ref contextObj failed"); + env->GlobalReference_Delete(contextRef); + ResetEnv(env); + } +} + +std::weak_ptr StsStaticSubscriberExtension::GetWeakPtr() +{ + return std::static_pointer_cast(shared_from_this()); +} + +void StsStaticSubscriberExtension::OnReceiveEvent(std::shared_ptr data) +{ + const CommonEventData& commonEventData = *data; + EVENT_LOGD("OnReceiveEvent execute action = %{public}s", commonEventData.GetWant().GetAction().c_str()); + + if (handler_ == nullptr) { + EVENT_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + auto task = [wThis, commonEventData, this]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + ani_env* env = sThis->stsRuntime_.GetAniEnv(); + if (!env) { + EVENT_LOGE("task env not found env"); + return; + } + + ani_object ani_data {}; + AniCommonEventUtils::ConvertCommonEventDataToEts(env, ani_data, commonEventData); + const char* signature = "LcommonEvent/commonEventData/CommonEventData;:V"; + CallObjectMethod(false, "onReceiveEvent", signature, ani_data); + }; + handler_->PostTask(task, "CommonEvent" + data->GetWant().GetAction()); +} + +void StsStaticSubscriberExtension::ResetEnv(ani_env* env) +{ + env->DescribeError(); + env->ResetError(); +} + +void StsStaticSubscriberExtension::OnStart(const AAFwk::Want& want) +{ + EVENT_LOGD("%{public}s called.", __func__); + Extension::OnStart(want); +} + +void StsStaticSubscriberExtension::OnStop() +{ + EVENT_LOGD("%{public}s called.", __func__); + Extension::OnStop(); +} + +void StsStaticSubscriberExtension::OnDisconnect(const AAFwk::Want& want) +{ + EVENT_LOGD("%{public}s called.", __func__); + Extension::OnDisconnect(want); +} + +sptr StsStaticSubscriberExtension::OnConnect(const AAFwk::Want& want) +{ + EVENT_LOGD("%{public}s called.", __func__); + Extension::OnConnect(want); + sptr remoteObject = new (std::nothrow) StaticSubscriberStubImpl( + std::static_pointer_cast(shared_from_this())); + if (remoteObject == nullptr) { + EVENT_LOGE("failed to create StaticSubscriberStubImpl"); + return nullptr; + } + return remoteObject->AsObject(); +} + +void StsStaticSubscriberExtension::CallObjectMethod(bool withResult, const char *name, const char *signature, ...) +{ + ani_status status = ANI_ERROR; + ani_method method = nullptr; + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + EVENT_LOGE("env not found StsStaticSubscriberExtensions"); + return; + } + if (stsObj_ == nullptr) { + EVENT_LOGE("stsObj_ nullptr"); + return; + } + if ((status = env->Class_FindMethod(stsObj_->aniCls, name, signature, &method)) != ANI_OK) { + EVENT_LOGE("Class_FindMethod nullptr:%{public}d", status); + return; + } + if (method == nullptr) { + return; + } + + ani_ref res = nullptr; + va_list args; + if (withResult) { + va_start(args, signature); + if ((status = env->Object_CallMethod_Ref_V(stsObj_->aniObj, method, &res, args)) != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + } + va_end(args); + return; + } + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(stsObj_->aniObj, method, args)) != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + } + va_end(args); + return; +} +} // EventManagerFwkAni +} // OHOS \ No newline at end of file diff --git a/frameworks/extension/src/ani/ani_static_subscriber_extension_context.cpp b/frameworks/extension/src/ani/ani_static_subscriber_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e330fcfb2f3f97c22678bc9855878da6a235f14 --- /dev/null +++ b/frameworks/extension/src/ani/ani_static_subscriber_extension_context.cpp @@ -0,0 +1,121 @@ +/* + * 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 "ani_static_subscriber_extension_context.h" + +#include "ability_manager_client.h" +#include "ani_common_want.h" +#include "ani_common_start_options.h" +#include "ets_error_utils.h" +#include "ets_extension_context.h" +#include "event_log_wrapper.h" +#include "native_engine/native_engine.h" + + +namespace OHOS { +namespace EventManagerFwkAni { +using namespace OHOS::AbilityRuntime; + +void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj) +{ + EVENT_LOGD("StartAbilityInner"); + AAFwk::Want want; + ErrCode innerErrCode = ERR_OK; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + EVENT_LOGE("UnwrapWant filed"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return; + } + auto context = GetAbilityContext(); + if (context == nullptr) { + EVENT_LOGE("GetAbilityContext is nullptr"); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return; + } + innerErrCode = context->StartAbility(want); + if (innerErrCode != ERR_OK) { + EVENT_LOGE("StartAbility failed, code = %{public}d", innerErrCode); + EtsErrorUtil::ThrowErrorByNativeErr(env, innerErrCode); + } +} + +std::shared_ptr StsStaticSubscriberExtensionContext::GetAbilityContext() +{ + return context_.lock(); +} + +StsStaticSubscriberExtensionContext* StsStaticSubscriberExtensionContext::GetAbilityContext(ani_env *env, + ani_object obj) +{ + ani_long nativeContextLong; + ani_status status = ANI_ERROR; + if (env == nullptr) { + EVENT_LOGD("null env"); + return nullptr; + } + + status = env->Object_GetFieldByName_Long(obj, "nativeStaticSubscriberExtensionContext", &nativeContextLong); + if (status != ANI_OK) { + EVENT_LOGE("get property status: %{public}d", status); + return nullptr; + } + if (nativeContextLong == 0) { + EVENT_LOGE("nativeContextLong is zero"); + return nullptr; + } + return reinterpret_cast(nativeContextLong); +} + +ani_object CreateStaticSubscriberExtensionContext(ani_env *env, + std::shared_ptr context) +{ + if (env == nullptr) { + EVENT_LOGE("null env"); + return nullptr; + } + std::shared_ptr abilityInfo = nullptr; + if (context) { + abilityInfo = context->GetAbilityInfo(); + } + auto stsStaticSubscriberExtensionContext = new (std::nothrow) StsStaticSubscriberExtensionContext(context); + if (stsStaticSubscriberExtensionContext == nullptr) { + EVENT_LOGE("null sts context"); + return nullptr; + } + ani_object contextObj = nullptr; + ani_status status = ANI_ERROR; + ani_class cls = nullptr; + ani_method method = nullptr; + if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + EVENT_LOGE("find class status : %{public}d", status); + delete stsStaticSubscriberExtensionContext; + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK) { + EVENT_LOGE("find Method status: %{public}d", status); + delete stsStaticSubscriberExtensionContext; + return nullptr; + } + ani_long nativeContextLong = reinterpret_cast(stsStaticSubscriberExtensionContext); + if ((status = env->Object_New(cls, method, &contextObj, nativeContextLong)) != ANI_OK) { + EVENT_LOGE("new Object status: %{public}d", status); + delete stsStaticSubscriberExtensionContext; + return nullptr; + } + OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, abilityInfo); + return contextObj; +} +} // EventManagerFwkAni +} // OHOS \ No newline at end of file diff --git a/frameworks/extension/src/js_static_subscriber_extension_context.cpp b/frameworks/extension/src/js_static_subscriber_extension_context.cpp index 9a5f1ea8fa2708873cad8f6513a9eec4c4d5e79c..65e575a79563f8064483b3705d2947cbfdf783b0 100644 --- a/frameworks/extension/src/js_static_subscriber_extension_context.cpp +++ b/frameworks/extension/src/js_static_subscriber_extension_context.cpp @@ -31,26 +31,13 @@ namespace { constexpr size_t ARGC_ZERO = 0; constexpr size_t ARGC_ONE = 1; constexpr size_t ARGC_TWO = 2; -class JsStaticSubscriberExtensionContext final { -public: - explicit JsStaticSubscriberExtensionContext(const std::shared_ptr& context) - : context_(context) {} - ~JsStaticSubscriberExtensionContext() = default; - - static void Finalizer(napi_env env, void* data, void* hint) - { - EVENT_LOGI("Finalizer is called"); - std::unique_ptr( - static_cast(data)); - } - - static napi_value StartAbility(napi_env env, napi_callback_info info); -private: - napi_value OnStartAbility(napi_env env, napi_callback_info info, bool isStartRecent = false); - std::weak_ptr context_; -}; } // namespace +std::shared_ptr JsStaticSubscriberExtensionContext::GetAbilityContext() +{ + return context_.lock(); +} + napi_value JsStaticSubscriberExtensionContext::StartAbility(napi_env env, napi_callback_info info) { EVENT_LOGD("called."); diff --git a/frameworks/extension/src/loader/static_subscriber_extension_module_loader.cpp b/frameworks/extension/src/loader/static_subscriber_extension_module_loader.cpp index e3174a91f431f83080490e5214d705bbe93bfdec..b9cd694ef6f8bc376742eee5cf6337bd9cd846e2 100644 --- a/frameworks/extension/src/loader/static_subscriber_extension_module_loader.cpp +++ b/frameworks/extension/src/loader/static_subscriber_extension_module_loader.cpp @@ -17,9 +17,46 @@ #include "event_log_wrapper.h" #include "static_subscriber_extension.h" +#include "js_static_subscriber_extension.h" + +#include + +constexpr char STS_STATIC_SUBSCRIBER_EXT_LIB_NAME[] = "libstatic_subscriber_extension_ani.z.so"; +static constexpr char STS_STATIC_SUBSCRIBER_EXT_CREATE_FUNC[] = "OHOS_STS_StaticSubscriberExtension_Creation"; namespace OHOS { namespace EventFwk { + +typedef StaticSubscriberExtension* (*CREATE_FUNC)(const std::unique_ptr& runtime); + +__attribute__((no_sanitize("cfi"))) StaticSubscriberExtension* CreateStsExtension( + const std::unique_ptr& runtime) +{ + void *handle = dlopen(STS_STATIC_SUBSCRIBER_EXT_LIB_NAME, RTLD_LAZY); + if (handle == nullptr) { + EVENT_LOGE("open sts_static_subscriber_extension library %{public}s failed, reason: %{public}sn", + STS_STATIC_SUBSCRIBER_EXT_LIB_NAME, dlerror()); + return new (std::nothrow) StaticSubscriberExtension(); + } + + auto func = reinterpret_cast(dlsym(handle, STS_STATIC_SUBSCRIBER_EXT_CREATE_FUNC)); + if (func == nullptr) { + dlclose(handle); + EVENT_LOGE("get sts_static_subscriber_extension symbol %{public}s in %{public}s failed", + STS_STATIC_SUBSCRIBER_EXT_CREATE_FUNC, STS_STATIC_SUBSCRIBER_EXT_LIB_NAME); + return new (std::nothrow) StaticSubscriberExtension(); + } + + auto instance = func(runtime); + if (instance == nullptr) { + dlclose(handle); + EVENT_LOGE("get sts_static_subscriber_extension instance in %{public}s failed", + STS_STATIC_SUBSCRIBER_EXT_CREATE_FUNC); + return new (std::nothrow) StaticSubscriberExtension(); + } + return instance; +} + StaticSubscriberExtensionModuleLoader::StaticSubscriberExtensionModuleLoader() = default; StaticSubscriberExtensionModuleLoader::~StaticSubscriberExtensionModuleLoader() = default; @@ -27,7 +64,19 @@ AbilityRuntime::Extension* StaticSubscriberExtensionModuleLoader::Create( const std::unique_ptr& runtime) const { EVENT_LOGD("Create module loader."); - return StaticSubscriberExtension::Create(runtime); + if (!runtime) { + return StaticSubscriberExtension::Create(runtime); + } + + EVENT_LOGI("Create runtime"); + switch (runtime->GetLanguage()) { + case AbilityRuntime::Runtime::Language::JS: + return JsStaticSubscriberExtension::Create(runtime); + case AbilityRuntime::Runtime::Language::ETS: + return CreateStsExtension(runtime); + default: + return StaticSubscriberExtension::Create(runtime); + } } std::map StaticSubscriberExtensionModuleLoader::GetParams() diff --git a/frameworks/extension/src/static_subscriber_extension.cpp b/frameworks/extension/src/static_subscriber_extension.cpp index 1263419c807487a5e00dc5169f772ef9b5a558a8..edfce6e6b1fe73aea633723c7da785a5b7b6aef4 100644 --- a/frameworks/extension/src/static_subscriber_extension.cpp +++ b/frameworks/extension/src/static_subscriber_extension.cpp @@ -25,17 +25,7 @@ namespace EventFwk { using namespace OHOS::AppExecFwk; StaticSubscriberExtension* StaticSubscriberExtension::Create(const std::unique_ptr& runtime) { - if (!runtime) { - return new (std::nothrow) StaticSubscriberExtension(); - } - - EVENT_LOGI("Create runtime"); - switch (runtime->GetLanguage()) { - case AbilityRuntime::Runtime::Language::JS: - return JsStaticSubscriberExtension::Create(runtime); - default: - return new (std::nothrow) StaticSubscriberExtension(); - } + return new (std::nothrow) StaticSubscriberExtension(); } void StaticSubscriberExtension::Init(const std::shared_ptr& record, diff --git a/frameworks/extension/test/static_subscriber_proxy_test/BUILD.gn b/frameworks/extension/test/static_subscriber_proxy_test/BUILD.gn old mode 100755 new mode 100644 diff --git a/frameworks/extension/test/static_subscriber_stub_imp_test/BUILD.gn b/frameworks/extension/test/static_subscriber_stub_imp_test/BUILD.gn old mode 100755 new mode 100644 diff --git a/frameworks/extension/test/static_subscriber_stub_imp_test/static_subscriber_stub_imp_test.cpp b/frameworks/extension/test/static_subscriber_stub_imp_test/static_subscriber_stub_imp_test.cpp index b20ba20845563c8aa7d4300c6fa17ab5c32d6d7c..f82b4666ebc4d2d848e6643831db685b06b1c697 100644 --- a/frameworks/extension/test/static_subscriber_stub_imp_test/static_subscriber_stub_imp_test.cpp +++ b/frameworks/extension/test/static_subscriber_stub_imp_test/static_subscriber_stub_imp_test.cpp @@ -20,6 +20,7 @@ #define private public #define protected public #include "static_subscriber_stub_impl.h" +#include "js_static_subscriber_extension.h" #include "js_runtime.h" #undef private #undef protected @@ -61,7 +62,7 @@ HWTEST_F(StaticSubscriberStubImplTest, StaticSubscriberStubImpl_OnReceiveEvent_0 AbilityRuntime::Runtime::Options options; std::unique_ptr runtime = AbilityRuntime::Runtime::Create(options); - std::shared_ptr extension = std::make_shared( + std::shared_ptr extension = std::make_shared( static_cast(*runtime)); sptr object = new (std::nothrow) StaticSubscriberStubImpl(extension); EXPECT_TRUE(object != nullptr); @@ -80,7 +81,7 @@ HWTEST_F(StaticSubscriberStubImplTest, StaticSubscriberStubImpl_OnReceiveEvent_0 HWTEST_F(StaticSubscriberStubImplTest, StaticSubscriberStubImpl_OnReceiveEvent_002, TestSize.Level0) { GTEST_LOG_(INFO) << "StaticSubscriberStubImpl_OnReceiveEvent_002 start."; - const std::shared_ptr extension; + const std::shared_ptr extension; sptr object = new (std::nothrow) StaticSubscriberStubImpl(extension); EXPECT_TRUE(object != nullptr); const CommonEventData data; diff --git a/frameworks/extension/test/static_subscriber_stub_test/BUILD.gn b/frameworks/extension/test/static_subscriber_stub_test/BUILD.gn old mode 100755 new mode 100644 diff --git a/interfaces/kits/ani/BUILD.gn b/interfaces/kits/ani/BUILD.gn index e1e037faeb94d170666775bd081aa3f8c9b9362b..effea0b84f4084d09e40983ec5c535737e45c327 100644 --- a/interfaces/kits/ani/BUILD.gn +++ b/interfaces/kits/ani/BUILD.gn @@ -22,5 +22,7 @@ group("ani_common_event_packages") { "${interfaces_path}/kits/ani/common_event:commonEventSubscribeInfo_etc", "${interfaces_path}/kits/ani/common_event:commonEventSubscriber_etc", "${interfaces_path}/kits/ani/common_event:common_event_manager_etc", + "${interfaces_path}/kits/ani/common_event:static_subscriber_extension_ability_abc_etc", + "${interfaces_path}/kits/ani/common_event:static_subscriber_extension_context_abc_etc", ] } diff --git a/interfaces/kits/ani/common_event/BUILD.gn b/interfaces/kits/ani/common_event/BUILD.gn index 50df3f17751c6bc9b4ec1e66b6a444ecbe53c012..10e534d24bebd485915098d03b942468a6e49e91 100644 --- a/interfaces/kits/ani/common_event/BUILD.gn +++ b/interfaces/kits/ani/common_event/BUILD.gn @@ -49,6 +49,7 @@ ohos_shared_library("ani_commoneventmanager") { include_dirs = [ "${interfaces_path}/kits/ani/common_event/include", + "${interfaces_path}/kits/napi/napi_common_event/include", "${ces_core_path}/include", ] @@ -59,13 +60,22 @@ ohos_shared_library("ani_commoneventmanager") { "src/ani_common_event_utils.cpp", ] - deps = [ "${ces_native_path}:cesfwk_innerkits" ] + deps = [ + "${ces_native_path}:cesfwk_innerkits", + "${interfaces_path}/kits/napi/napi_common_event:napi_commoneventmanager", + ] external_deps = [ "ability_base:want", + "ability_runtime:ani_common", + "ability_runtime:napi_common", + "ability_runtime:runtime", "c_utils:utils", + "ffrt:libffrt", "hilog:libhilog", + "napi:ace_napi", "runtime_core:ani", + "runtime_core:ani_helpers", ] subsystem_name = "notification" @@ -146,3 +156,33 @@ ohos_prebuilt_etc("commonEventSubscriber_etc") { part_name = "common_event_service" deps = [ ":commonEventSubscriber" ] } + +generate_static_abc("static_subscriber_extension_ability") { + base_url = "./ets" + files = [ "./ets/@ohos.application.StaticSubscriberExtensionAbility.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/static_subscriber_extension_ability.abc" +} + +ohos_prebuilt_etc("static_subscriber_extension_ability_abc_etc") { + source = "$target_out_dir/static_subscriber_extension_ability.abc" + module_install_dir = "framework" + subsystem_name = "notification" + part_name = "common_event_service" + deps = [ ":static_subscriber_extension_ability" ] +} + +generate_static_abc("static_subscriber_extension_context") { + base_url = "./ets" + files = [ "./ets/@ohos.application.StaticSubscriberExtensionContext.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/static_subscriber_extension_context.abc" +} + +ohos_prebuilt_etc("static_subscriber_extension_context_abc_etc") { + source = "$target_out_dir/static_subscriber_extension_context.abc" + module_install_dir = "framework" + subsystem_name = "notification" + part_name = "common_event_service" + deps = [ ":static_subscriber_extension_context" ] +} diff --git a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..7ecf2941de77af17007492daf0454c60b52fcb5f --- /dev/null +++ b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import{ CommonEventData } from 'commonEvent.commonEventData'; +import StaticSubscriberExtensionContext from '@ohos.application.StaticSubscriberExtensionContext'; + +export default class StaticSubscriberExtensionAbility { + + context: StaticSubscriberExtensionContext = {}; + + onReceiveEvent(event: CommonEventData): void { + console.log("StsonReceiveEvent, event:" + event.code); + } +} \ No newline at end of file diff --git a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..8f7eaaab073a44d86f8db96e0e3d1287caaf58f9 --- /dev/null +++ b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets @@ -0,0 +1,89 @@ +/* + * 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. + */ +import { BusinessError, AsyncCallback } from '@ohos.base'; +import Want from '@ohos.app.ability.Want'; +import ExtensionContext from 'application.ExtensionContext'; +import hilog from '@ohos.hilog'; + +const TAG: string = 'commonEventManager'; + +class Cleaner { + private ptr: long = 0 + + constructor(ptr:long) { + this.ptr = ptr + } + native clean(): void +} + +function callback(cleaner: Cleaner): void { + cleaner.clean() +} +let destroyRegister = new FinalizationRegistry(callback) +let unregisterToken = new object() + + +type ResolveCallback = (data: T) => void; +type RejectCallback = (err: Error) => void; + +export class StaticSubscriberExtensionContext extends ExtensionContext { + static {loadLibrary("static_subscriber_extension_ani.z")} + private nativeStaticSubscriberExtensionContext: long = 0; + native nativeStartAbilitySync(want: Want): void; + + static native transferToDynamicContext(input: Object): Any; + static native transferToStaticContext(input: Any): Object; + + static transferDynamic(input: Object): Any { + return StaticSubscriberExtensionContext.transferToDynamicContext(input); + } + static transferStatic(input: Any): Object { + return StaticSubscriberExtensionContext.transferToStaticContext(input); + } + + startAbility(want: Want, callback: AsyncCallback): void { + let task = taskpool.execute(this.nativeStartAbilitySync, want); + task.then((e: NullishType)=>{ + callback(null, undefined); + }, (error: Object): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + startAbility(want: Want): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let task = taskpool.execute(this.nativeStartAbilitySync, want); + task.then((e: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + hilog.error(0xD001202, TAG, 'nativeStartAbilitySync Promise error'); + reject(error); + }); + }); + return pPromise; + } + + private cleaner: Cleaner | null = null; + constructor(wrapper:long) { + this.nativeStaticSubscriberExtensionContext = wrapper; + this.registerCleaner(this.nativeStaticSubscriberExtensionContext) + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr) + destroyRegister.register(this, this.cleaner!, unregisterToken); + } +} \ No newline at end of file diff --git a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets index 30688c11954df7f2911489c1f3eaa7e0839f982c..e78c2f89cc941205da24d087bb1da040543b78fc 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -14,21 +14,35 @@ */ import hilog from '@ohos.hilog'; -import{ AsyncCallback, BusinessError } from '@ohos.base'; +import{ AsyncCallback, Callback, BusinessError } from '@ohos.base'; import{ CommonEventPublishData } from 'commonEvent.commonEventPublishData'; import{ CommonEventData } from 'commonEvent.commonEventData'; import{ CommonEventSubscribeInfo } from 'commonEvent.commonEventSubscribeInfo'; import{ CommonEventSubscriber } from 'commonEvent.commonEventSubscriber'; const TAG: string = 'commonEventManager'; +const ERROR_PARAM_INVALID = 401; +const errorParamInvalid: BusinessError = {code: ERROR_PARAM_INVALID, data: "Invalid parameter"}; + +type ResolveCallback = (data: T) => void; +type RejectCallback = (err: Object) => void; + namespace commonEventManager { loadLibrary("ani_commoneventmanager.z"); export native function publishExecute(event: string):int; export native function publishWithOptionsExecute(event: string, options: CommonEventPublishData):int; + export native function publishAsUserExecute(event: string, userId: int):int; + export native function publishAsUserWithOptionsExecute(event: string, userId: int, + options: CommonEventPublishData):int; export native function createSubscriberExecute(subscribeInfo: CommonEventSubscribeInfo):CommonEventSubscriber; export native function subscribeExecute(subscriber: CommonEventSubscriber, callback: AsyncCallback):int; + export native function subscribeToEventExecute(subscriber: CommonEventSubscriber, + callback: Callback):int; export native function unsubscribeExecute(subscriber: CommonEventSubscriber):int; + export native function removeStickyCommonEventExecute(event: string):int; + export native function setStaticSubscriberStateExecute(enable: boolean):int; + export native function setStaticSubscriberStateWithEventsExecute(enable: boolean,events?: Array):int; export function publish(event: string, callback: AsyncCallback): void { hilog.info(0x0000, TAG, 'publish called event: %{public}s', event); @@ -36,10 +50,16 @@ namespace commonEventManager { task.then((e: NullishType)=>{ let resultCode: Int = e as Int; hilog.info(0x0000, TAG, 'publish call result:%{public}d.', resultCode.intValue()); - let r: BusinessError = { code: resultCode.intValue(), data: undefined }; - callback(r, undefined); - }, (err:Object): void => { + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } + }, (error:Object): void => { hilog.error(0x0000, TAG, 'publish error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } @@ -49,10 +69,53 @@ namespace commonEventManager { task.then((e: NullishType)=>{ let resultCode: Int = e as Int; hilog.info(0x0000, TAG, 'publish with option result:%{public}d.', resultCode.intValue()); - let r: BusinessError = { code: resultCode.intValue(), data: undefined }; - callback(r, undefined); - }, (err:Object): void => { + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } + }, (error:Object): void => { hilog.error(0x0000, TAG, 'publish with option error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + export function publishAsUser(event: string, userId: number, callback: AsyncCallback): void { + let publishAsUserId: Int = userId as Int; + let task = taskpool.execute(commonEventManager.publishAsUserExecute, event, publishAsUserId); + task.then((e: NullishType)=>{ + let resultCode: Int = e as Int; + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } + }, (error:Object): void => { + hilog.error(0xD001202, TAG, 'publishAsUser error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + export function publishAsUser(event: string, userId: number, options: CommonEventPublishData, + callback: AsyncCallback): void { + let publishAsUserId: Int = userId as Int; + let task = taskpool.execute(commonEventManager.publishAsUserWithOptionsExecute, event, publishAsUserId, options); + task.then((e: NullishType)=>{ + let resultCode: Int = e as Int; + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } + }, (error:Object): void => { + hilog.error(0xD001202, TAG, 'publishAsUser with option error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } @@ -63,23 +126,24 @@ namespace commonEventManager { task.then((e: NullishType)=>{ let result: CommonEventSubscriber = e as CommonEventSubscriber; hilog.info(0x0000, TAG, 'createSubscriber result.'); - let r: BusinessError = { code: 0, data: undefined }; - callback(r, result); - }, (err:Object): void => { + callback(null, result); + }, (error: Object): void => { hilog.error(0x0000, TAG, 'createSubscriber error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } export function createSubscriber(subscribeInfo: CommonEventSubscribeInfo):Promise { hilog.info(0x0000, TAG, 'createSubscriber Promise call'); let p = new Promise((resolve: (v: CommonEventSubscriber) => void, - reject: (error: Object) => void) => { + reject: (error: Error) => void) => { let p1 = taskpool.execute(commonEventManager.createSubscriberExecute, subscribeInfo); p1.then((e :NullishType)=>{ hilog.info(0x0000, TAG, 'createSubscriber Promise result.'); let result: CommonEventSubscriber = e as CommonEventSubscriber; resolve(result); - }, (err:Object): void => { + }, (err:Error): void => { hilog.error(0x0000, TAG, 'createSubscriber Promise error'); }); }); @@ -98,41 +162,373 @@ namespace commonEventManager { let resultCode: Int = e as Int; hilog.info(0x0000, TAG, 'subscribe result:%{public}d.', resultCode.intValue()); if (resultCode != 0) { - let a: CommonEventData; let r: BusinessError = { code: resultCode.intValue(), data: undefined }; - callback(r, a); + callback(r, undefined); } - }, (err:Object): void => { + }, (error:Object): void => { hilog.error(0x0000, TAG, 'subscribe error'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } + export function subscribeToEvent(subscriber: CommonEventSubscriber, callback: Callback): Promise { + hilog.info(0x0000, TAG, 'subscribeToEvent call.'); + let p = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let task = taskpool.execute(commonEventManager.subscribeToEventExecute, subscriber, callback); + task.then((e: NullishType)=> { + let resultCode: Int = e as Int; + hilog.info(0x0000, TAG, 'subscribeToEvent result: %{public}d.', resultCode.toInt()); + if (resultCode != 0) { + let r: BusinessError = { code: resultCode.toInt(), data: undefined }; + reject(r); + } else { + resolve(undefined); + } + }, (err: Error): void => { + hilog.error(0x0000, TAG, 'subscribeToEvent error'); + reject(err); + }); + }); + return p; + } + export function unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback): void { hilog.info(0x0000, TAG, 'unsubscribe call.'); let task = taskpool.execute(commonEventManager.unsubscribeExecute, subscriber); task.then((e: NullishType)=>{ let resultCode: Int = e as Int; hilog.info(0x0000, TAG, 'unsubscribe result:%{public}d.', resultCode.intValue()); - let r: BusinessError = { code: resultCode.intValue(), data: undefined }; if (callback != undefined) { - callback(r, undefined); + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } } - }, (err:Object): void => { + }, (error:Object): void => { hilog.error(0x0000, TAG, 'unsubscribe error'); + if (callback != undefined) { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + } + }); + } + + export function removeStickyCommonEvent(event: string, callback: AsyncCallback): void { + if (event == undefined) { + throw errorParamInvalid; + } + let task = taskpool.execute(commonEventManager.removeStickyCommonEventExecute, event); + task.then((e: NullishType)=>{ + let resultCode: Int = e as Int; + hilog.info(0x0000, TAG, 'unsubscribe result:%{public}d.', resultCode.intValue()); + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } + }, (error: Object): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + export function removeStickyCommonEvent(event: string): Promise { + if (event == undefined) { + throw errorParamInvalid; + } + let p = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let task = taskpool.execute(commonEventManager.removeStickyCommonEventExecute, event); + task.then((e: NullishType): void => { + let resultCode: Int = e as Int; + if (resultCode == 0) { + resolve(undefined); + } else { + let err: BusinessError = { code: resultCode.intValue(), data: undefined }; + reject(err); + } + }, (error: Object): void => { + hilog.error(0xD001202, TAG, 'removeStickyCommonEvent Promise error'); + reject(error); + }); + }); + return p; + } + + export function setStaticSubscriberState(enable: boolean, callback: AsyncCallback): void { + let task = taskpool.execute(commonEventManager.setStaticSubscriberStateExecute, enable); + task.then((e: NullishType)=>{ + let resultCode: Int = e as Int; + if (resultCode == 0) { + callback(null, undefined); + } else { + let err: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(err, undefined); + } + }, (error: Object): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } + export function setStaticSubscriberState(enable: boolean): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let task = taskpool.execute(commonEventManager.setStaticSubscriberStateExecute, enable); + task.then((e: NullishType): void => { + let resultCode: Int = e as Int; + if (resultCode == 0) { + resolve(undefined); + } else { + let err: BusinessError = { code: resultCode.intValue(), data: undefined }; + reject(err); + } + }, (error: Object): void => { + hilog.error(0xD001202, TAG, 'setStaticSubscriberState Promise error'); + reject(error); + }); + }); + return pPromise; + } + + export function setStaticSubscriberState(enable: boolean, events?: Array): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let task = taskpool.execute(commonEventManager.setStaticSubscriberStateWithEventsExecute, enable, events); + task.then((e: NullishType): void => { + let resultCode: Int = e as Int; + if (resultCode == 0) { + resolve(undefined); + } else { + let err: BusinessError = { code: resultCode.intValue(), data: undefined }; + reject(err); + } + }, (error: Object): void => { + hilog.error(0xD001202, TAG, 'setStaticSubscriberStateExecute Promise error.'); + reject(error); + }); + }); + return pPromise; + } + export enum Support { + COMMON_EVENT_BOOT_COMPLETED = 'usual.event.BOOT_COMPLETED', + COMMON_EVENT_LOCKED_BOOT_COMPLETED = 'usual.event.LOCKED_BOOT_COMPLETED', + COMMON_EVENT_SHUTDOWN = 'usual.event.SHUTDOWN', + COMMON_EVENT_BATTERY_CHANGED = 'usual.event.BATTERY_CHANGED', + COMMON_EVENT_BATTERY_LOW = 'usual.event.BATTERY_LOW', + COMMON_EVENT_BATTERY_OKAY = 'usual.event.BATTERY_OKAY', + COMMON_EVENT_POWER_CONNECTED = 'usual.event.POWER_CONNECTED', + COMMON_EVENT_POWER_DISCONNECTED = 'usual.event.POWER_DISCONNECTED', COMMON_EVENT_SCREEN_OFF = 'usual.event.SCREEN_OFF', COMMON_EVENT_SCREEN_ON = 'usual.event.SCREEN_ON', - COMMON_EVENT_USER_INFO_UPDATED = 'usual.event.USER_INFO_UPDATED', - COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOUT = 'common.event.DISTRIBUTED_ACCOUNT_LOGOUT', + COMMON_EVENT_THERMAL_LEVEL_CHANGED = 'usual.event.THERMAL_LEVEL_CHANGED', + COMMON_EVENT_ENTER_FORCE_SLEEP = 'usual.event.ENTER_FORCE_SLEEP', + COMMON_EVENT_EXIT_FORCE_SLEEP = 'usual.event.EXIT_FORCE_SLEEP', + COMMON_EVENT_ENTER_HIBERNATE = 'usual.event.ENTER_HIBERNATE', + COMMON_EVENT_EXIT_HIBERNATE = 'usual.event.EXIT_HIBERNATE', + COMMON_EVENT_TIME_TICK = 'usual.event.TIME_TICK', + COMMON_EVENT_TIME_CHANGED = 'usual.event.TIME_CHANGED', + COMMON_EVENT_DATE_CHANGED = 'usual.event.DATE_CHANGED', + COMMON_EVENT_TIMEZONE_CHANGED = 'usual.event.TIMEZONE_CHANGED', + COMMON_EVENT_CLOSE_SYSTEM_DIALOGS = 'usual.event.CLOSE_SYSTEM_DIALOGS', + COMMON_EVENT_PACKAGE_ADDED = 'usual.event.PACKAGE_ADDED', + COMMON_EVENT_PACKAGE_REPLACED = 'usual.event.PACKAGE_REPLACED', + COMMON_EVENT_MY_PACKAGE_REPLACED = 'usual.event.MY_PACKAGE_REPLACED', + COMMON_EVENT_PACKAGE_REMOVED = 'usual.event.PACKAGE_REMOVED', + COMMON_EVENT_BUNDLE_REMOVED = 'usual.event.BUNDLE_REMOVED', + COMMON_EVENT_PACKAGE_FULLY_REMOVED = 'usual.event.PACKAGE_FULLY_REMOVED', + COMMON_EVENT_PACKAGE_CHANGED = 'usual.event.PACKAGE_CHANGED', + COMMON_EVENT_PACKAGE_RESTARTED = 'usual.event.PACKAGE_RESTARTED', + COMMON_EVENT_PACKAGE_DATA_CLEARED = 'usual.event.PACKAGE_DATA_CLEARED', + COMMON_EVENT_PACKAGE_CACHE_CLEARED = 'usual.event.PACKAGE_CACHE_CLEARED', + COMMON_EVENT_PACKAGES_SUSPENDED = 'usual.event.PACKAGES_SUSPENDED', + COMMON_EVENT_PACKAGES_UNSUSPENDED = 'usual.event.PACKAGES_UNSUSPENDED', + COMMON_EVENT_MY_PACKAGE_SUSPENDED = 'usual.event.MY_PACKAGE_SUSPENDED', + COMMON_EVENT_MY_PACKAGE_UNSUSPENDED = 'usual.event.MY_PACKAGE_UNSUSPENDED', + COMMON_EVENT_UID_REMOVED = 'usual.event.UID_REMOVED', + COMMON_EVENT_PACKAGE_FIRST_LAUNCH = 'usual.event.PACKAGE_FIRST_LAUNCH', + COMMON_EVENT_PACKAGE_NEEDS_VERIFICATION = 'usual.event.PACKAGE_NEEDS_VERIFICATION', + COMMON_EVENT_PACKAGE_VERIFIED = 'usual.event.PACKAGE_VERIFIED', + COMMON_EVENT_EXTERNAL_APPLICATIONS_AVAILABLE = 'usual.event.EXTERNAL_APPLICATIONS_AVAILABLE', + COMMON_EVENT_EXTERNAL_APPLICATIONS_UNAVAILABLE = 'usual.event.EXTERNAL_APPLICATIONS_UNAVAILABLE', + COMMON_EVENT_CONFIGURATION_CHANGED = 'usual.event.CONFIGURATION_CHANGED', + COMMON_EVENT_LOCALE_CHANGED = 'usual.event.LOCALE_CHANGED', + COMMON_EVENT_MANAGE_PACKAGE_STORAGE = 'usual.event.MANAGE_PACKAGE_STORAGE', + COMMON_EVENT_DRIVE_MODE = 'common.event.DRIVE_MODE', + COMMON_EVENT_HOME_MODE = 'common.event.HOME_MODE', + COMMON_EVENT_OFFICE_MODE = 'common.event.OFFICE_MODE', + COMMON_EVENT_USER_STARTED = 'usual.event.USER_STARTED', + COMMON_EVENT_USER_BACKGROUND = 'usual.event.USER_BACKGROUND', + COMMON_EVENT_USER_FOREGROUND = 'usual.event.USER_FOREGROUND', + COMMON_EVENT_USER_SWITCHED = 'usual.event.USER_SWITCHED', + COMMON_EVENT_USER_STARTING = 'usual.event.USER_STARTING', + COMMON_EVENT_USER_UNLOCKED = 'usual.event.USER_UNLOCKED', + COMMON_EVENT_USER_STOPPING = 'usual.event.USER_STOPPING', + COMMON_EVENT_USER_STOPPED = 'usual.event.USER_STOPPED', COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGIN = 'common.event.DISTRIBUTED_ACCOUNT_LOGIN', + COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOUT = 'common.event.DISTRIBUTED_ACCOUNT_LOGOUT', + COMMON_EVENT_DISTRIBUTED_ACCOUNT_TOKEN_INVALID = 'common.event.DISTRIBUTED_ACCOUNT_TOKEN_INVALID', + COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOFF = 'common.event.DISTRIBUTED_ACCOUNT_LOGOFF', + COMMON_EVENT_WIFI_POWER_STATE = 'usual.event.wifi.POWER_STATE', + COMMON_EVENT_WIFI_SCAN_FINISHED = 'usual.event.wifi.SCAN_FINISHED', + COMMON_EVENT_WIFI_RSSI_VALUE = 'usual.event.wifi.RSSI_VALUE', + COMMON_EVENT_WIFI_CONN_STATE = 'usual.event.wifi.CONN_STATE', + COMMON_EVENT_WIFI_HOTSPOT_STATE = 'usual.event.wifi.HOTSPOT_STATE', + COMMON_EVENT_WIFI_AP_STA_JOIN = 'usual.event.wifi.WIFI_HS_STA_JOIN', + COMMON_EVENT_WIFI_AP_STA_LEAVE = 'usual.event.wifi.WIFI_HS_STA_LEAVE', + COMMON_EVENT_WIFI_MPLINK_STATE_CHANGE = 'usual.event.wifi.mplink.STATE_CHANGE', + COMMON_EVENT_WIFI_P2P_CONN_STATE = 'usual.event.wifi.p2p.CONN_STATE_CHANGE', + COMMON_EVENT_WIFI_P2P_STATE_CHANGED = 'usual.event.wifi.p2p.STATE_CHANGE', + COMMON_EVENT_WIFI_P2P_PEERS_STATE_CHANGED = 'usual.event.wifi.p2p.DEVICES_CHANGE', + COMMON_EVENT_WIFI_P2P_PEERS_DISCOVERY_STATE_CHANGED = 'usual.event.wifi.p2p.PEER_DISCOVERY_STATE_CHANGE', + COMMON_EVENT_WIFI_P2P_CURRENT_DEVICE_STATE_CHANGED = 'usual.event.wifi.p2p.CURRENT_DEVICE_CHANGE', + COMMON_EVENT_WIFI_P2P_GROUP_STATE_CHANGED = 'usual.event.wifi.p2p.GROUP_STATE_CHANGED', + COMMON_EVENT_BLUETOOTH_HANDSFREE_AG_CONNECT_STATE_UPDATE = + 'usual.event.bluetooth.handsfree.ag.CONNECT_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_HANDSFREE_AG_CURRENT_DEVICE_UPDATE = + 'usual.event.bluetooth.handsfree.ag.CURRENT_DEVICE_UPDATE', + COMMON_EVENT_BLUETOOTH_HANDSFREE_AG_AUDIO_STATE_UPDATE = + 'usual.event.bluetooth.handsfree.ag.AUDIO_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSOURCE_CONNECT_STATE_UPDATE = + 'usual.event.bluetooth.a2dpsource.CONNECT_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSOURCE_CURRENT_DEVICE_UPDATE = + 'usual.event.bluetooth.a2dpsource.CURRENT_DEVICE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSOURCE_PLAYING_STATE_UPDATE = + 'usual.event.bluetooth.a2dpsource.PLAYING_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSOURCE_AVRCP_CONNECT_STATE_UPDATE = + 'usual.event.bluetooth.a2dpsource.AVRCP_CONNECT_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSOURCE_CODEC_VALUE_UPDATE = + 'usual.event.bluetooth.a2dpsource.CODEC_VALUE_UPDATE', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_DISCOVERED = 'usual.event.bluetooth.remotedevice.DISCOVERED', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_CLASS_VALUE_UPDATE = + 'usual.event.bluetooth.remotedevice.CLASS_VALUE_UPDATE', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_ACL_CONNECTED = 'usual.event.bluetooth.remotedevice.ACL_CONNECTED', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_ACL_DISCONNECTED = 'usual.event.bluetooth.remotedevice.ACL_DISCONNECTED', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_NAME_UPDATE = 'usual.event.bluetooth.remotedevice.NAME_UPDATE', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_PAIR_STATE = 'usual.event.bluetooth.remotedevice.PAIR_STATE', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_BATTERY_VALUE_UPDATE = + 'usual.event.bluetooth.remotedevice.BATTERY_VALUE_UPDATE', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_SDP_RESULT = 'usual.event.bluetooth.remotedevice.SDP_RESULT', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_UUID_VALUE = 'usual.event.bluetooth.remotedevice.UUID_VALUE', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_PAIRING_REQ = 'usual.event.bluetooth.remotedevice.PAIRING_REQ', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_PAIRING_CANCEL = 'usual.event.bluetooth.remotedevice.PAIRING_CANCEL', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_CONNECT_REQ = 'usual.event.bluetooth.remotedevice.CONNECT_REQ', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_CONNECT_REPLY = 'usual.event.bluetooth.remotedevice.CONNECT_REPLY', + COMMON_EVENT_BLUETOOTH_REMOTEDEVICE_CONNECT_CANCEL = 'usual.event.bluetooth.remotedevice.CONNECT_CANCEL', + COMMON_EVENT_BLUETOOTH_HANDSFREEUNIT_CONNECT_STATE_UPDATE = + 'usual.event.bluetooth.handsfreeunit.CONNECT_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_HANDSFREEUNIT_AUDIO_STATE_UPDATE = + 'usual.event.bluetooth.handsfreeunit.AUDIO_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_HANDSFREEUNIT_AG_COMMON_EVENT = 'usual.event.bluetooth.handsfreeunit.AG_COMMON_EVENT', + COMMON_EVENT_BLUETOOTH_HANDSFREEUNIT_AG_CALL_STATE_UPDATE = + 'usual.event.bluetooth.handsfreeunit.AG_CALL_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_HOST_STATE_UPDATE = 'usual.event.bluetooth.host.STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_HOST_REQ_DISCOVERABLE = 'usual.event.bluetooth.host.REQ_DISCOVERABLE', + COMMON_EVENT_BLUETOOTH_HOST_REQ_ENABLE = 'usual.event.bluetooth.host.REQ_ENABLE', + COMMON_EVENT_BLUETOOTH_HOST_REQ_DISABLE = 'usual.event.bluetooth.host.REQ_DISABLE', + COMMON_EVENT_BLUETOOTH_HOST_SCAN_MODE_UPDATE = 'usual.event.bluetooth.host.SCAN_MODE_UPDATE', + COMMON_EVENT_BLUETOOTH_HOST_DISCOVERY_STARTED = 'usual.event.bluetooth.host.DISCOVERY_STARTED', + COMMON_EVENT_BLUETOOTH_HOST_DISCOVERY_FINISHED = 'usual.event.bluetooth.host.DISCOVERY_FINISHED', + COMMON_EVENT_BLUETOOTH_HOST_NAME_UPDATE = 'usual.event.bluetooth.host.NAME_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSINK_CONNECT_STATE_UPDATE = 'usual.event.bluetooth.a2dpsink.CONNECT_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSINK_PLAYING_STATE_UPDATE = 'usual.event.bluetooth.a2dpsink.PLAYING_STATE_UPDATE', + COMMON_EVENT_BLUETOOTH_A2DPSINK_AUDIO_STATE_UPDATE = 'usual.event.bluetooth.a2dpsink.AUDIO_STATE_UPDATE', + COMMON_EVENT_NFC_ACTION_ADAPTER_STATE_CHANGED = 'usual.event.nfc.action.ADAPTER_STATE_CHANGED', + COMMON_EVENT_NFC_ACTION_RF_FIELD_ON_DETECTED = 'usual.event.nfc.action.RF_FIELD_ON_DETECTED', + COMMON_EVENT_NFC_ACTION_RF_FIELD_OFF_DETECTED = 'usual.event.nfc.action.RF_FIELD_OFF_DETECTED', + COMMON_EVENT_DISCHARGING = 'usual.event.DISCHARGING', + COMMON_EVENT_CHARGING = 'usual.event.CHARGING', + COMMON_EVENT_CHARGE_TYPE_CHANGED = 'usual.event.CHARGE_TYPE_CHANGED', + COMMON_EVENT_DEVICE_IDLE_MODE_CHANGED = 'usual.event.DEVICE_IDLE_MODE_CHANGED', + COMMON_EVENT_CHARGE_IDLE_MODE_CHANGED = 'usual.event.CHARGE_IDLE_MODE_CHANGED', + COMMON_EVENT_DEVICE_IDLE_EXEMPTION_LIST_UPDATED = 'usual.event.DEVICE_IDLE_EXEMPTION_LIST_UPDATED', + COMMON_EVENT_POWER_SAVE_MODE_CHANGED = 'usual.event.POWER_SAVE_MODE_CHANGED', + COMMON_EVENT_USER_ADDED = 'usual.event.USER_ADDED', + COMMON_EVENT_USER_REMOVED = 'usual.event.USER_REMOVED', + COMMON_EVENT_ABILITY_ADDED = 'common.event.ABILITY_ADDED', + COMMON_EVENT_ABILITY_REMOVED = 'common.event.ABILITY_REMOVED', + COMMON_EVENT_ABILITY_UPDATED = 'common.event.ABILITY_UPDATED', + COMMON_EVENT_LOCATION_MODE_STATE_CHANGED = 'usual.event.location.MODE_STATE_CHANGED', + COMMON_EVENT_IVI_SLEEP = 'common.event.IVI_SLEEP', + COMMON_EVENT_IVI_PAUSE = 'common.event.IVI_PAUSE', + COMMON_EVENT_IVI_STANDBY = 'common.event.IVI_STANDBY', + COMMON_EVENT_IVI_LASTMODE_SAVE = 'common.event.IVI_LASTMODE_SAVE', + COMMON_EVENT_IVI_VOLTAGE_ABNORMAL = 'common.event.IVI_VOLTAGE_ABNORMAL', + COMMON_EVENT_IVI_HIGH_TEMPERATURE = 'common.event.IVI_HIGH_TEMPERATURE', + COMMON_EVENT_IVI_EXTREME_TEMPERATURE = 'common.event.IVI_EXTREME_TEMPERATURE', + COMMON_EVENT_IVI_TEMPERATURE_ABNORMAL = 'common.event.IVI_TEMPERATURE_ABNORMAL', + COMMON_EVENT_IVI_VOLTAGE_RECOVERY = 'common.event.IVI_VOLTAGE_RECOVERY', + COMMON_EVENT_IVI_TEMPERATURE_RECOVERY = 'common.event.IVI_TEMPERATURE_RECOVERY', + COMMON_EVENT_IVI_ACTIVE = 'common.event.IVI_ACTIVE', + COMMON_EVENT_USB_STATE = 'usual.event.hardware.usb.action.USB_STATE', + COMMON_EVENT_USB_PORT_CHANGED = 'usual.event.hardware.usb.action.USB_PORT_CHANGED', + COMMON_EVENT_USB_DEVICE_ATTACHED = 'usual.event.hardware.usb.action.USB_DEVICE_ATTACHED', + COMMON_EVENT_USB_DEVICE_DETACHED = 'usual.event.hardware.usb.action.USB_DEVICE_DETACHED', + COMMON_EVENT_USB_ACCESSORY_ATTACHED = 'usual.event.hardware.usb.action.USB_ACCESSORY_ATTACHED', + COMMON_EVENT_USB_ACCESSORY_DETACHED = 'usual.event.hardware.usb.action.USB_ACCESSORY_DETACHED', + COMMON_EVENT_DISK_REMOVED = 'usual.event.data.DISK_REMOVED', + COMMON_EVENT_DISK_UNMOUNTED = 'usual.event.data.DISK_UNMOUNTED', + COMMON_EVENT_DISK_MOUNTED = 'usual.event.data.DISK_MOUNTED', + COMMON_EVENT_DISK_BAD_REMOVAL = 'usual.event.data.DISK_BAD_REMOVAL', + COMMON_EVENT_DISK_UNMOUNTABLE = 'usual.event.data.DISK_UNMOUNTABLE', + COMMON_EVENT_DISK_EJECT = 'usual.event.data.DISK_EJECT', + COMMON_EVENT_VOLUME_REMOVED = 'usual.event.data.VOLUME_REMOVED', + COMMON_EVENT_VOLUME_UNMOUNTED = 'usual.event.data.VOLUME_UNMOUNTED', + COMMON_EVENT_VOLUME_MOUNTED = 'usual.event.data.VOLUME_MOUNTED', + COMMON_EVENT_VOLUME_BAD_REMOVAL = 'usual.event.data.VOLUME_BAD_REMOVAL', + COMMON_EVENT_VOLUME_EJECT = 'usual.event.data.VOLUME_EJECT', + COMMON_EVENT_VISIBLE_ACCOUNTS_UPDATED = 'usual.event.data.VISIBLE_ACCOUNTS_UPDATED', + COMMON_EVENT_ACCOUNT_DELETED = 'usual.event.data.ACCOUNT_DELETED', + COMMON_EVENT_FOUNDATION_READY = 'common.event.FOUNDATION_READY', + COMMON_EVENT_AIRPLANE_MODE_CHANGED = 'usual.event.AIRPLANE_MODE', + COMMON_EVENT_SPLIT_SCREEN = 'common.event.SPLIT_SCREEN', + COMMON_EVENT_SLOT_CHANGE = 'usual.event.SLOT_CHANGE', + COMMON_EVENT_SPN_INFO_CHANGED = 'usual.event.SPN_INFO_CHANGED', + COMMON_EVENT_QUICK_FIX_APPLY_RESULT = 'usual.event.QUICK_FIX_APPLY_RESULT', + COMMON_EVENT_QUICK_FIX_REVOKE_RESULT = 'usual.event.QUICK_FIX_REVOKE_RESULT', + COMMON_EVENT_USER_INFO_UPDATED = 'usual.event.USER_INFO_UPDATED', COMMON_EVENT_HTTP_PROXY_CHANGE = 'usual.event.HTTP_PROXY_CHANGE', + COMMON_EVENT_SIM_STATE_CHANGED = 'usual.event.SIM_STATE_CHANGED', + COMMON_EVENT_SMS_RECEIVE_COMPLETED = 'usual.event.SMS_RECEIVE_COMPLETED', + COMMON_EVENT_SMS_EMERGENCY_CB_RECEIVE_COMPLETED = 'usual.event.SMS_EMERGENCY_CB_RECEIVE_COMPLETED', + COMMON_EVENT_SMS_CB_RECEIVE_COMPLETED = 'usual.event.SMS_CB_RECEIVE_COMPLETED', + COMMON_EVENT_STK_COMMAND = 'usual.event.STK_COMMAND', + COMMON_EVENT_STK_SESSION_END = 'usual.event.STK_SESSION_END', + COMMON_EVENT_STK_CARD_STATE_CHANGED = 'usual.event.STK_CARD_STATE_CHANGED', + COMMON_EVENT_STK_ALPHA_IDENTIFIER = 'usual.event.STK_ALPHA_IDENTIFIER', + COMMON_EVENT_SMS_WAPPUSH_RECEIVE_COMPLETED = 'usual.event.SMS_WAPPUSH_RECEIVE_COMPLETED', + COMMON_EVENT_OPERATOR_CONFIG_CHANGED = 'usual.event.OPERATOR_CONFIG_CHANGED', + COMMON_EVENT_SIM_CARD_DEFAULT_SMS_SUBSCRIPTION_CHANGED = 'usual.event.SIM.DEFAULT_SMS_SUBSCRIPTION_CHANGED', + COMMON_EVENT_SIM_CARD_DEFAULT_DATA_SUBSCRIPTION_CHANGED = 'usual.event.SIM.DEFAULT_DATA_SUBSCRIPTION_CHANGED', + COMMON_EVENT_SIM_CARD_DEFAULT_MAIN_SUBSCRIPTION_CHANGED = 'usual.event.SIM.DEFAULT_MAIN_SUBSCRIPTION_CHANGED', + COMMON_EVENT_SET_PRIMARY_SLOT_STATUS = 'usual.event.SET_PRIMARY_SLOT_STATUS', + COMMON_EVENT_PRIMARY_SLOT_ROAMING = 'usual.event.PRIMARY_SLOT_ROAMING', + COMMON_EVENT_SIM_CARD_DEFAULT_VOICE_SUBSCRIPTION_CHANGED = + 'usual.event.SIM.DEFAULT_VOICE_SUBSCRIPTION_CHANGED', + COMMON_EVENT_CALL_STATE_CHANGED = 'usual.event.CALL_STATE_CHANGED', + COMMON_EVENT_CELLULAR_DATA_STATE_CHANGED = 'usual.event.CELLULAR_DATA_STATE_CHANGED', + COMMON_EVENT_NETWORK_STATE_CHANGED = 'usual.event.NETWORK_STATE_CHANGED', + COMMON_EVENT_SIGNAL_INFO_CHANGED = 'usual.event.SIGNAL_INFO_CHANGED', + COMMON_EVENT_INCOMING_CALL_MISSED = 'usual.event.INCOMING_CALL_MISSED', + COMMON_EVENT_RADIO_STATE_CHANGE = 'usual.event.RADIO_STATE_CHANGE', + COMMON_EVENT_DOMAIN_ACCOUNT_STATUS_CHANGED = 'usual.event.DOMAIN_ACCOUNT_STATUS_CHANGED', + COMMON_EVENT_SCREEN_UNLOCKED = 'usual.event.SCREEN_UNLOCKED', + COMMON_EVENT_SCREEN_LOCKED = 'usual.event.SCREEN_LOCKED', + COMMON_EVENT_CONNECTIVITY_CHANGE = 'usual.event.CONNECTIVITY_CHANGE', + COMMON_EVENT_SPECIAL_CODE = 'common.event.SPECIAL_CODE', + COMMON_EVENT_AUDIO_QUALITY_CHANGE = 'usual.event.AUDIO_QUALITY_CHANGE', + COMMON_EVENT_PRIVACY_STATE_CHANGED = 'usual.event.PRIVACY_STATE_CHANGED', + COMMON_EVENT_PACKAGE_INSTALLATION_STARTED = 'usual.event.PACKAGE_INSTALLATION_STARTED', + COMMON_EVENT_DYNAMIC_ICON_CHANGED = 'usual.event.DYNAMIC_ICON_CHANGED', COMMON_EVENT_MINORSMODE_ON = 'usual.event.MINORSMODE_ON', COMMON_EVENT_MINORSMODE_OFF = 'usual.event.MINORSMODE_OFF', - COMMON_EVENT_TIME_CHANGED = 'usual.event.TIME_CHANGED', - COMMON_EVENT_TIMEZONE_CHANGED = 'usual.event.TIMEZONE_CHANGED' + COMMON_EVENT_BUNDLE_RESOURCES_CHANGED = 'usual.event.BUNDLE_RESOURCES_CHANGED', + COMMON_EVENT_DATA_SHARE_READY = 'usual.event.DATA_SHARE_READY', + COMMON_EVENT_VPN_CONNECTION_STATUS_CHANGED = 'usual.event.VPN_CONNECTION_STATUS_CHANGED', + COMMON_EVENT_RESTORE_START = 'usual.event.RESTORE_START', + COMMON_EVENT_MANAGED_BROWSER_POLICY_CHANGED = 'usual.event.MANAGED_BROWSER_POLICY_CHANGED', } } diff --git a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscribeInfo.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscribeInfo.ets index 1f6d0914c9e11f72d8e0abc05fd6cd37bc09e5f3..77b8886e32236da73a2edc915cc96faa7328d183 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscribeInfo.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscribeInfo.ets @@ -21,3 +21,12 @@ export interface CommonEventSubscribeInfo { priority?: number; publisherBundleName?: string; } + +class CommonEventSubscribeInfoImpl implements CommonEventSubscribeInfo { + public events: Array = {}; + public publisherPermission?: string | undefined; + public publisherDeviceId?: string | undefined; + public userId?: number | undefined; + public priority?: number | undefined; + public publisherBundleName?: string | undefined; +} \ No newline at end of file diff --git a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets index fa4607b20371babb9a4c23656735067dbf2e17f9..846546e29c7751b0d4753de7e876bc8bb923f1f3 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets @@ -13,14 +13,489 @@ * limitations under the License. */ +import hilog from '@ohos.hilog'; +import { AsyncCallback, BusinessError } from '@ohos.base'; +import { CommonEventSubscribeInfo } from 'commonEvent.commonEventSubscribeInfo'; + +class Cleaner { + private ptr: long = 0 + + constructor(ptr:long) { + this.ptr = ptr + } + native clean(): void +} + +function callback(cleaner: Cleaner): void { + cleaner.clean() +} +let destroyRegister = new FinalizationRegistry(callback) +let unregisterToken = new object() + +type ResolveCallback = (data: T) => void; +type RejectCallback = (err: Error) => void; +const TAG: string = 'commonEventSubscriber'; export interface CommonEventSubscriber { - subscriberInstanceWrapper : long; + getCode(callback: AsyncCallback): void; + getCode(): Promise; getCodeSync(): number; + setCode(code: number, callback: AsyncCallback): void; + setCode(code: number): Promise; + setCodeSync(code: number): void; + getData(callback: AsyncCallback): void; + getData(): Promise; + getDataSync(): string; + setData(data: string, callback: AsyncCallback): void; + setData(data: string): Promise; + setDataSync(data: string): void; + setCodeAndData(code: number, data: string, callback: AsyncCallback): void; + setCodeAndData(code: number, data: string): Promise; + setCodeAndDataSync(code: number, data: string): void; + isOrderedCommonEvent(callback: AsyncCallback): void; + isOrderedCommonEvent(): Promise; + isOrderedCommonEventSync(): boolean; + isStickyCommonEvent(callback: AsyncCallback): void; + isStickyCommonEvent(): Promise; + isStickyCommonEventSync(): boolean; + abortCommonEvent(callback: AsyncCallback): void; + abortCommonEvent(): Promise; + abortCommonEventSync(): void; + clearAbortCommonEvent(callback: AsyncCallback): void; + clearAbortCommonEvent(): Promise; + clearAbortCommonEventSync(): void; + getAbortCommonEvent(callback: AsyncCallback): void; + getAbortCommonEvent(): Promise; + getAbortCommonEventSync(): boolean; + getSubscribeInfo(callback: AsyncCallback): void; + getSubscribeInfo(): Promise; + getSubscribeInfoSync(): CommonEventSubscribeInfo; + finishCommonEvent(callback: AsyncCallback): void; + finishCommonEvent(): Promise; } class CommonEventSubscriberInner implements CommonEventSubscriber { - public native subscriberInstanceWrapper : long = 0; + static {loadLibrary("ani_commoneventmanager.z")} + private subscriberInstanceWrapper: long = 0; + + public native nativeGetCode(): number; + public native nativeSetCode(code: int): int; + public native nativeGetData(): string; + public native nativeSetData(data: string): int; + public native nativeSetCodeAndData(code: int, data: string): int; + public native nativeIsOrderedCommonEvent(): boolean; + public native nativeIsStickyCommonEvent(): boolean; + public native nativeAbortCommonEvent(): int; + public native nativeClearAbortCommonEvent(): int; + public native nativeGetAbortCommonEvent(): boolean; + public native nativeGetSubscribeInfo(): CommonEventSubscribeInfo; + public native nativeFinishCommonEvent(): int; + + private static native transferToDynamicSubscriber(input: Object): Any; + private static native transferToStaticSubscriber(input: Any): Object; + + static transferDynamic(input: Object): Any { + return CommonEventSubscriberInner.transferToDynamicSubscriber(input); + } + static transferStatic(input: Any): Object { + return CommonEventSubscriberInner.transferToStaticSubscriber(input); + } + + public getCode(callback: AsyncCallback): void { + let p = taskpool.execute((): number => { return this.nativeGetCode(); }); + p.then((data: NullishType): void => { + let ret : number = data as number; + callback(null, ret); + }, (error: Error): void => { + let ret: number = -1; + let err: BusinessError = error as BusinessError; + callback(err, ret); + }); + } + + public getCode(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): number => { return this.nativeGetCode(); }); + p.then((data: NullishType): void => { + let ret : number = data as number; + resolve(ret); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + public getCodeSync(): number { - return 2; + let ret : number = 0; + try { + ret = this.nativeGetCode() as number; + return ret; + } catch (err) { + return ret; + } + } + + public setCode(code: number, callback: AsyncCallback): void { + let pcode: Int = code as Int; + let p = taskpool.execute((): int => { return this.nativeSetCode(pcode); }); + p.then((data: NullishType): void => { + callback(null, undefined); + }, (error: Error): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + public setCode(code: number): Promise { + let pcode: Int = code as Int; + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): int => { return this.nativeSetCode(pcode); }); + p.then((data: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public setCodeSync(code: number): void { + try { + let pcode: Int = code as Int; + this.nativeSetCode(pcode); + return; + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + } + } + + public getData(callback: AsyncCallback): void { + let p = taskpool.execute((): string => { return this.nativeGetData(); }); + p.then((data: NullishType): void => { + let ret : string = data as string; + callback(null, ret); + }, (error: Object): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }) + } + + public getData(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback):void => { + let p = taskpool.execute((): string => { return this.nativeGetData(); }); + p.then((data :NullishType): void => { + let ret : string = data as string; + resolve(ret); + }, (err:Error): void => { + reject(err); + }); + }); + return pPromise; + } + + public getDataSync(): string { + let ret : string = ''; + try { + ret = this.nativeGetData() as string; + return ret; + } catch (err) { + return ret; + } + } + + public setData(data: string, callback: AsyncCallback): void { + let p = taskpool.execute((): int => { return this.nativeSetData(data); }); + p.then((e: NullishType): void => { + callback(null, undefined); + }, (error: Error): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }) + } + + public setData(data: string): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): int => { return this.nativeSetData(data); }); + p.then((data: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public setDataSync(data: string): void { + try { + this.nativeSetData(data); + return; + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + } + } + + public setCodeAndData(code: number, data: string, callback: AsyncCallback): void { + let pcode: Int = code as Int; + let p = taskpool.execute((): int => { return this.nativeSetCodeAndData(pcode, data); }); + p.then((e: NullishType): void => { + callback(null, undefined); + }, (error: Error): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }) + } + + public setCodeAndData(code: number, data: string): Promise { + let pcode: Int = code as Int; + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): int => { return this.nativeSetCodeAndData(pcode, data); }); + p.then((data: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public setCodeAndDataSync(code: number, data: string): void { + try { + let pcode: Int = code as Int; + this.nativeSetCodeAndData(pcode, data); + return; + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + } + } + + public isOrderedCommonEvent(callback: AsyncCallback): void { + let p = taskpool.execute((): boolean => { return this.nativeIsOrderedCommonEvent(); }); + p.then((data: NullishType): void => { + let ret : boolean = data as boolean; + callback(null, ret); + }, (error: Error): void => { + let ret : boolean = false; + let err: BusinessError = error as BusinessError; + callback(err, ret); + }) + } + + public isOrderedCommonEvent(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): boolean => { return this.nativeIsOrderedCommonEvent(); }); + p.then((data: NullishType): void => { + let ret : boolean = data as boolean; + resolve(ret); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public isOrderedCommonEventSync(): boolean { + try { + return this.nativeIsOrderedCommonEvent(); + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + return false; + } + } + + public isStickyCommonEvent(callback: AsyncCallback): void { + let p = taskpool.execute((): boolean => { return this.nativeIsStickyCommonEvent(); }); + p.then((data: NullishType): void => { + let ret : boolean = data as boolean; + callback(null, ret); + }, (error: Error): void => { + let ret : boolean = false; + let err: BusinessError = error as BusinessError; + callback(err, ret); + }) + } + + public isStickyCommonEvent(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): boolean => { return this.nativeIsStickyCommonEvent(); }); + p.then((data: NullishType): void => { + let ret : boolean = data as boolean; + resolve(ret); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public isStickyCommonEventSync(): boolean { + try { + return this.nativeIsStickyCommonEvent(); + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + return false; + } + } + + public abortCommonEvent(callback: AsyncCallback): void { + let p = taskpool.execute((): int => { return this.nativeAbortCommonEvent(); }); + p.then((data: NullishType): void => { + callback(null, undefined); + }, (error: Error): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + public abortCommonEvent(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): int => { return this.nativeAbortCommonEvent(); }); + p.then((data: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public abortCommonEventSync(): void { + try { + this.nativeAbortCommonEvent(); + return; + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + } + } + + public clearAbortCommonEvent(callback: AsyncCallback): void { + let p = taskpool.execute((): int => { return this.nativeClearAbortCommonEvent(); }); + p.then((data: NullishType): void => { + callback(null, undefined); + }, (error: Error): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + public clearAbortCommonEvent(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): int => { return this.nativeClearAbortCommonEvent(); }); + p.then((data: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public clearAbortCommonEventSync(): void { + try { + this.nativeClearAbortCommonEvent(); + return; + } catch (err) { + hilog.error(0xD001202, TAG, 'asyncResult is nullptr'); + } + } + + public getAbortCommonEvent(callback: AsyncCallback): void { + let p = taskpool.execute((): boolean => { return this.nativeGetAbortCommonEvent(); }); + p.then((data: NullishType): void => { + let ret : boolean = data as boolean; + callback(null, ret); + }, (error: Error): void => { + let ret : boolean = false; + let err: BusinessError = error as BusinessError; + callback(err, ret); + }) + } + + public getAbortCommonEvent(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): boolean => { return this.nativeGetAbortCommonEvent(); }); + p.then((data: NullishType): void => { + let ret : boolean = data as boolean; + resolve(ret); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public getAbortCommonEventSync(): boolean { + let ret : boolean = false; + try { + ret = this.nativeGetAbortCommonEvent() as boolean; + return ret; + } catch (err) { + return ret; + } + } + + public getSubscribeInfo(callback: AsyncCallback): void { + let p = taskpool.execute((): CommonEventSubscribeInfo => { return this.nativeGetSubscribeInfo(); }); + p.then((data: NullishType): void => { + let ret : CommonEventSubscribeInfo = data as CommonEventSubscribeInfo; + callback(null, ret); + }, (error: Error): void => { + let ret : CommonEventSubscribeInfo ; + let err: BusinessError = error as BusinessError; + callback(err, ret); + }) + } + + public getSubscribeInfo(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, + reject: RejectCallback): void => { + let p = taskpool.execute((): CommonEventSubscribeInfo => { return this.nativeGetSubscribeInfo(); }); + p.then((data: NullishType): void => { + let ret : CommonEventSubscribeInfo = data as CommonEventSubscribeInfo; + resolve(ret); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + public getSubscribeInfoSync(): CommonEventSubscribeInfo { + return this.nativeGetSubscribeInfo(); + } + + public finishCommonEvent(callback: AsyncCallback): void { + let p = taskpool.execute((): int => { return this.nativeFinishCommonEvent(); }); + p.then((data: NullishType): void => { + callback(null, undefined); + }, (error: Error): void => { + let err: BusinessError = error as BusinessError; + callback(err, undefined); + }); + } + + public finishCommonEvent(): Promise { + let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { + let p = taskpool.execute((): int => { return this.nativeFinishCommonEvent(); }); + p.then((data: NullishType): void => { + resolve(undefined); + }, (error: Error): void => { + reject(error); + }); + }); + return pPromise; + } + + private cleaner: Cleaner | null = null; + + constructor(wrapper:long) { + if(this.subscriberInstanceWrapper == 0){ + this.subscriberInstanceWrapper = wrapper; + } + this.registerCleaner(this.subscriberInstanceWrapper) + } + + registerCleaner(ptr: long): void { + this.cleaner = new Cleaner(ptr) + destroyRegister.register(this, this.cleaner!, unregisterToken); } } \ No newline at end of file diff --git a/interfaces/kits/ani/common_event/include/ani_common_event.h b/interfaces/kits/ani/common_event/include/ani_common_event.h index 4c6b5b13efea4bf6f57d440b9d08c8f5c5ee5b30..a4968fea8bd1110272ce843ac243f72da457529c 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event.h @@ -20,25 +20,36 @@ #include #include "common_event_manager.h" +#include "ffrt.h" +#include "napi_common_event.h" + namespace OHOS { namespace EventManagerFwkAni { -class SubscriberInstance : public OHOS::EventFwk::CommonEventSubscriber { +using namespace OHOS::EventFwk; + +class SubscriberInstance : public OHOS::EventFwk::CommonEventSubscriber, + public std::enable_shared_from_this { public: SubscriberInstance(const OHOS::EventFwk::CommonEventSubscribeInfo& sp); virtual ~SubscriberInstance(); void OnReceiveEvent(const OHOS::EventFwk::CommonEventData& data) override; unsigned long long GetID(); - void SetEnv(ani_env* env); void SetVm(ani_vm* etsVm); + ani_vm* GetVm(); void SetCallback(const ani_object& callback); + ani_object GetCallback(); + void SetIsToEvent(bool isToEvent); + bool GetIsToEvent(); void ClearEnv(); private: - std::mutex envMutex_; - std::mutex callbackMutex_; + ffrt::mutex envMutex_; + ffrt::mutex callbackMutex_; + ffrt::mutex isToEventMutex_; ani_env* env_ = nullptr; ani_object callback_ = nullptr; + bool isToEvent_ = false; std::atomic_ullong id_; static std::atomic_ullong subscriberID_; ani_vm* etsVm_ = nullptr; @@ -58,8 +69,30 @@ struct subscriberInstanceInfo { std::shared_ptr commonEventResult = nullptr; }; -std::shared_ptr GetSubscriberByWrapper(SubscriberInstanceWrapper* wrapper); +static constexpr uint8_t DO_NOT_SUBSCRIBE = 0; +static constexpr uint8_t SUBSCRIBE_IN_NAPI_ENV = 1; +static constexpr uint8_t SUBSCRIBE_IN_ANI_ENV = 2; +struct SubscriberInstanceRelationship { + std::shared_ptr aniSubscriber_; + std::shared_ptr napiSubscriber_; + ani_ref napiSubscriberRef_; + ani_ref aniSubscriberRef_; + uint8_t subscribeEnv_ = DO_NOT_SUBSCRIBE; + bool aniSubscriberDestroyed_ = false; + bool napiSubscriberDestroyed_ = false; + ffrt::mutex relationMutex_; +}; + +std::shared_ptr GetSubscriber(ani_env* env, ani_ref subscribeRef); +std::shared_ptr GetAsyncCommonEventResult(ani_env* env, ani_ref subscribeRef); +std::shared_ptr GetAsyncCommonEventResult(std::shared_ptr subscriber); +std::shared_ptr GetSubscriberByWrapper(SubscriberInstanceWrapper* wrapper); +ani_ref CreateSubscriberRef(ani_env* env, SubscriberInstanceWrapper *subscriberWrapper); +void SetNapiSubscriberCallback(std::shared_ptr subscriberInstance); +int32_t UnsubscribeAndRemoveInstance(ani_env* env, const std::shared_ptr &subscriber); +std::shared_ptr GetTransferRelation(std::shared_ptr aniSubscriber, + std::shared_ptr napiSubscriber); } // namespace EventManagerFwkAni } // namespace OHOS #endif // BASE_NOTIFICATION_COMMON_EVENT_MANAGER_INCLUDE_ANI_COMMON_EVENT_MANAGER_H diff --git a/interfaces/kits/ani/common_event/include/ani_common_event_utils.h b/interfaces/kits/ani/common_event/include/ani_common_event_utils.h index 0a4002e11f86368d567d21ff3ff34c939c6d60bf..b24e577a3b40118570bfb08e537a1df1faa74341 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event_utils.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event_utils.h @@ -21,6 +21,7 @@ #include #include +#include "ani_common_event.h" #include "common_event_manager.h" namespace OHOS { @@ -31,22 +32,30 @@ using CommonEventData = OHOS::EventFwk::CommonEventData; class AniCommonEventUtils { public: static void GetStdString(ani_env* env, ani_string str, std::string& result); + static ani_status GetAniString(ani_env* env, const std::string str, ani_string &aniStr); static void GetStdStringArrayClass(ani_env* env, ani_object arrayObj, std::vector& strings); static void ConvertCommonEventPublishData(ani_env* env, ani_object optionsObject, EventFwk::Want& want, EventFwk::CommonEventData& commonEventData, EventFwk::CommonEventPublishInfo& commonEventPublishInfo); static void ConvertCommonEventSubscribeInfo( ani_env* env, ani_object infoObject, CommonEventSubscribeInfo& subscribeInfo); + static void GetCommonEventSubscribeInfoToEts( + ani_env* env, std::shared_ptr subscriber, ani_object &infoObject); static void ConvertCommonEventDataToEts(ani_env* env, ani_object& ani_data, const CommonEventData& commonEventData); static bool GetStringOrUndefined(ani_env* env, ani_object param, const char* name, std::string& res); + static bool GetDoubleOrUndefined(ani_env* env, ani_object param, const char* name, int32_t& res); static bool GetIntOrUndefined(ani_env* env, ani_object param, const char* name, int32_t& res); static bool GetBooleanOrUndefined(ani_env* env, ani_object param, const char* name, bool& res); static bool GetStringArrayOrUndefined( ani_env* env, ani_object param, const char* name, std::vector& res); + static bool GetWantParamsOrUndefined( + ani_env* env, ani_object param, const char* name, AAFwk::WantParams& wantParams); static void CreateNewObjectByClass(ani_env* env, const char* className, ani_class &cls, ani_object& ani_data); template static void CallSetter(ani_env* env, ani_class cls, ani_object object, const char* setterName, valueType value); static void CreateAniDoubleObject(ani_env* env, ani_object &object, ani_double value); static void CreateBusinessErrorObject(ani_env* env, ani_object &object, int32_t code, const std::string &message); + static ani_object GetAniStringArray(ani_env *env, std::vector strs); + static ani_object newArrayClass(ani_env *env, int length); }; } // namespace EventManagerFwkAni } // namespace OHOS diff --git a/interfaces/kits/ani/common_event/src/ani_common_event.cpp b/interfaces/kits/ani/common_event/src/ani_common_event.cpp index 13dda4b7410e2586548a0cdbcda00a617939bcc2..fe643c8f24e2edf42db306a6b6c4f6776a4f4826 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -16,15 +16,22 @@ #include "ani_common_event.h" #include "ani_common_event_utils.h" +#include "ces_inner_error_code.h" #include "event_log_wrapper.h" + +#include "interop_js/arkts_esvalue.h" +#include "interop_js/arkts_interop_js_api.h" + +#include + namespace OHOS { namespace EventManagerFwkAni { -using namespace OHOS::EventFwk; - std::atomic_ullong SubscriberInstance::subscriberID_ = 0; static std::map, std::shared_ptr> subscriberInstances; -static std::mutex subscriberInsMutex; +static ffrt::mutex subscriberInsMutex; +static ffrt::mutex transferRelationMutex; +static std::vector> transferRelations; static uint32_t publishExecute(ani_env* env, ani_string eventId) { @@ -53,101 +60,164 @@ static uint32_t publishWithOptionsExecute(ani_env* env, ani_string eventId, ani_ CommonEventPublishInfo commonEventPublishInfo; Want want; want.SetAction(eventIdStr); - commonEventData.SetWant(want); - AniCommonEventUtils::ConvertCommonEventPublishData( env, optionsObject, want, commonEventData, commonEventPublishInfo); + commonEventData.SetWant(want); auto errorCode = CommonEventManager::NewPublishCommonEvent(commonEventData, commonEventPublishInfo); EVENT_LOGI("publishWithOptionsExecute result: %{public}d.", errorCode); return errorCode; } -static ani_ref createSubscriberExecute(ani_env* env, ani_object infoObject) +static uint32_t publishAsUserExecute(ani_env* env, ani_string eventId, ani_int userId) +{ + EVENT_LOGD("publishAsUserExecute call."); + std::string eventIdStr; + AniCommonEventUtils::GetStdString(env, eventId, eventIdStr); + EVENT_LOGD("publishAsUserExecute eventIdStr: %{public}s, userId: %{public}d", eventIdStr.c_str(), userId); + + CommonEventData commonEventData; + CommonEventPublishInfo commonEventPublishInfo; + Want want; + want.SetAction(eventIdStr); + commonEventData.SetWant(want); + + auto errorCode = CommonEventManager::NewPublishCommonEventAsUser(commonEventData, commonEventPublishInfo, userId); + EVENT_LOGD("publishAsUserExecute result: %{public}d.", errorCode); + return errorCode; +} + +static uint32_t publishAsUserWithOptionsExecute(ani_env* env, ani_string eventId, ani_int userId, + ani_object optionsObject) +{ + EVENT_LOGD("publishAsUserWithOptionsExecute call."); + std::string eventIdStr; + AniCommonEventUtils::GetStdString(env, eventId, eventIdStr); + EVENT_LOGD("publishAsUserWithOptionsExecute eventIdStr: %{public}s, userId: %{public}d", + eventIdStr.c_str(), userId); + + CommonEventData commonEventData; + CommonEventPublishInfo commonEventPublishInfo; + Want want; + want.SetAction(eventIdStr); + commonEventData.SetWant(want); + + AniCommonEventUtils::ConvertCommonEventPublishData( + env, optionsObject, want, commonEventData, commonEventPublishInfo); + auto errorCode = CommonEventManager::NewPublishCommonEventAsUser(commonEventData, commonEventPublishInfo, userId); + EVENT_LOGD("publishAsUserWithOptionsExecute result: %{public}d.", errorCode); + return errorCode; +} + +ani_ref CreateSubscriberRef(ani_env* env, SubscriberInstanceWrapper *subscriberWrapper) { - EVENT_LOGI("createSubscriberExecute call."); - CommonEventSubscribeInfo subscribeInfo; - AniCommonEventUtils::ConvertCommonEventSubscribeInfo(env, infoObject, subscribeInfo); - auto ret = ANI_OK; - auto wrapper = new (std::nothrow) SubscriberInstanceWrapper(subscribeInfo); ani_class cls; + auto ret = ANI_OK; ret = env->FindClass("LcommonEvent/commonEventSubscriber/CommonEventSubscriberInner;", &cls); if (ret != ANI_OK) { EVENT_LOGE("createSubscriberExecute FindClass error. result: %{public}d.", ret); return nullptr; } ani_method ctor; - ret = env->Class_FindMethod(cls, "", ":V", &ctor); + ret = env->Class_FindMethod(cls, "", "J:V", &ctor); if (ret != ANI_OK) { EVENT_LOGE("createSubscriberExecute Class_FindMethod error. result: %{public}d.", ret); return nullptr; } ani_object subscriberObj; - ret = env->Object_New(cls, ctor, &subscriberObj); + ret = env->Object_New(cls, ctor, &subscriberObj, reinterpret_cast(subscriberWrapper)); if (ret != ANI_OK) { EVENT_LOGE("createSubscriberExecute Object_New error. result: %{public}d.", ret); return nullptr; } + return subscriberObj; +} - ani_method wrapperField; - ret = env->Class_FindMethod(cls, "subscriberInstanceWrapper", nullptr, &wrapperField); - if (ret != ANI_OK) { - EVENT_LOGE("createSubscriberExecute Class_FindField error. result: %{public}d.", ret); - return nullptr; - } - - ret = env->Object_CallMethod_Void(subscriberObj, wrapperField, reinterpret_cast(wrapper)); - if (ret != ANI_OK) { - EVENT_LOGE("createSubscriberExecute Object_SetField_Long error. result: %{public}d.", ret); +static ani_ref createSubscriberExecute(ani_env* env, ani_object infoObject) +{ + EVENT_LOGI("createSubscriberExecute call."); + CommonEventSubscribeInfo subscribeInfo; + AniCommonEventUtils::ConvertCommonEventSubscribeInfo(env, infoObject, subscribeInfo); + subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::ThreadMode::HANDLER); + auto wrapper = new (std::nothrow) SubscriberInstanceWrapper(subscribeInfo); + if (wrapper == nullptr) { return nullptr; } - - ani_ref resultRef = nullptr; - ret = env->GlobalReference_Create(subscriberObj, &resultRef); - if (ret != ANI_OK) { - EVENT_LOGE("createSubscriberExecute GlobalReference_Create error. result: %{public}d.", ret); + ani_ref subscriberObj = CreateSubscriberRef(env, wrapper); + if (subscriberObj == nullptr) { + delete wrapper; + wrapper = nullptr; return nullptr; } EVENT_LOGI("createSubscriberExecute end."); - return resultRef; + return subscriberObj; } static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object callback) { - EVENT_LOGI("subscribeExecute call."); - auto ret = ANI_OK; - - ani_long wrapper_long {}; - ret = env->Object_GetPropertyByName_Long( - static_cast(subscribeRef), "subscriberInstanceWrapper", &wrapper_long); - if (ret != ANI_OK) { - EVENT_LOGE("subscribeExecute Object_GetPropertyByName_Long error. result: %{public}d.", ret); + EVENT_LOGD("subscribeExecute call."); + auto subscriberInstance = GetSubscriber(env, subscribeRef); + if (subscriberInstance == nullptr) { + EVENT_LOGE("subscriberInstance is null."); return ANI_INVALID_ARGS; } - SubscriberInstanceWrapper* wrapper = nullptr; - wrapper = reinterpret_cast(wrapper_long); - if (wrapper == nullptr) { - EVENT_LOGE("subscribeExecute wrapper is null."); + ani_ref resultRef = nullptr; + auto ret = env->GlobalReference_Create(callback, &resultRef); + if (ret != ANI_OK || resultRef == nullptr) { + EVENT_LOGE("createSubscriberExecute GlobalReference_Create error. result: %{public}d.", ret); return ANI_INVALID_ARGS; } - auto subscriberInstance = GetSubscriberByWrapper(wrapper); + subscriberInstance->SetCallback(static_cast(resultRef)); + ani_vm* etsVm; + ret = env->GetVM(&etsVm); + if (ret != ANI_OK) { + EVENT_LOGE("OnReceiveEvent GetVM error. result: %{public}d.", ret); + return ANI_INVALID_ARGS; + } + subscriberInstance->SetVm(etsVm); + auto relation = GetTransferRelation(subscriberInstance, nullptr); + int32_t result = ERR_OK; + if (relation != nullptr) { + std::lock_guard lock(relation->relationMutex_); + if (relation->subscribeEnv_ == DO_NOT_SUBSCRIBE) { + result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); + if (result == ERR_OK) { + relation->subscribeEnv_ = SUBSCRIBE_IN_ANI_ENV; + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); + } + EVENT_LOGI("transfered subscribe result: %{public}d", result); + return result; + } + EVENT_LOGI("transfered already subscribe"); + return result; + } + result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); + if (result == ERR_OK) { + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); + } + EVENT_LOGI("subscribe result: %{public}d", result); + return result; +} + + +static uint32_t subscribeToEventExecute(ani_env* env, ani_ref subscribeRef, ani_object callback) +{ + EVENT_LOGD("subscribeToEventExecute call."); + auto subscriberInstance = GetSubscriber(env, subscribeRef); if (subscriberInstance == nullptr) { EVENT_LOGE("subscriberInstance is null."); return ANI_INVALID_ARGS; } - ani_ref resultRef = nullptr; - ret = env->GlobalReference_Create(callback, &resultRef); - if (ret != ANI_OK) { - EVENT_LOGE("createSubscriberExecute GlobalReference_Create error. result: %{public}d.", ret); + auto ret = env->GlobalReference_Create(callback, &resultRef); + if (ret != ANI_OK || resultRef == nullptr) { + EVENT_LOGE("GlobalReference_Create error. result: %{public}d.", ret); return ANI_INVALID_ARGS; } - if (resultRef == nullptr) { - EVENT_LOGE("subscribeExecute resultRef is null."); - } - subscriberInstance->SetEnv(env); subscriberInstance->SetCallback(static_cast(resultRef)); - + subscriberInstance->SetIsToEvent(true); ani_vm* etsVm; ret = env->GetVM(&etsVm); if (ret != ANI_OK) { @@ -155,15 +225,128 @@ static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object return ANI_INVALID_ARGS; } subscriberInstance->SetVm(etsVm); - auto result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); + auto relation = GetTransferRelation(subscriberInstance, nullptr); + int32_t result = ERR_OK; + if (relation != nullptr) { + std::lock_guard lock(relation->relationMutex_); + if (relation->subscribeEnv_ == DO_NOT_SUBSCRIBE) { + result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); + if (result == ERR_OK) { + relation->subscribeEnv_ = SUBSCRIBE_IN_ANI_ENV; + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); + } + EVENT_LOGI("transfered subscribe result: %{public}d", result); + return result; + } + EVENT_LOGI("transfered already subscribe"); + return result; + } + result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); + if (result == ERR_OK) { + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); + } + EVENT_LOGI("subscribeToEventExecute result: %{public}d", result); + return result; +} - EVENT_LOGI("subscribeExecute result: %{public}d.", result); +int32_t UnsubscribeAndRemoveInstance(ani_env* env, const std::shared_ptr &subscriber) +{ + EVENT_LOGD("unsubscribe 1.2 subscriber"); + auto result = CommonEventManager::NewUnSubscribeCommonEvent(subscriber); + if (result != ERR_OK) { + EVENT_LOGI("unsubscribe failed result: %{public}d.", result); + return result; + } + std::lock_guard lock(subscriberInsMutex); + auto item = subscriberInstances.find(subscriber); + if (item != subscriberInstances.end()) { + ani_ref callbackRef = static_cast(item->first->GetCallback()); + if (callbackRef != nullptr) { + env->GlobalReference_Delete(callbackRef); + item->first->SetCallback(nullptr); + } + subscriberInstances.erase(item); + } return result; } static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) { EVENT_LOGI("unsubscribeExecute call."); + auto subscriberInstance = GetSubscriber(env, subscribeRef); + if (subscriberInstance == nullptr) { + EVENT_LOGE("subscriberInstance is null."); + return ANI_INVALID_ARGS; + } + int32_t result = ERR_OK; + auto relation = GetTransferRelation(subscriberInstance, nullptr); + if (relation == nullptr) { + EVENT_LOGD("no transfered"); + return UnsubscribeAndRemoveInstance(env, subscriberInstance); + } + std::lock_guard lock(relation->relationMutex_); + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), + relation->napiSubscriber_); + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + result = UnsubscribeAndRemoveInstance(env, relation->aniSubscriber_); + } else { + EVENT_LOGD("transfered no subscribe"); + } + relation->subscribeEnv_ = DO_NOT_SUBSCRIBE; + return result; +} + +static uint32_t removeStickyCommonEventExecute(ani_env* env, ani_string eventId) +{ + EVENT_LOGD("removeStickyCommonEventExecute call"); + std::string eventIdStr; + AniCommonEventUtils::GetStdString(env, eventId, eventIdStr); + EVENT_LOGD("removeStickyCommonEventExecute eventIdStr: %{public}s.", eventIdStr.c_str()); + int returncode = CommonEventManager::RemoveStickyCommonEvent(eventIdStr); + EVENT_LOGD("removeStickyCommonEventExecute result: %{public}d.", returncode); + return returncode; +} + +static uint32_t setStaticSubscriberStateExecute(ani_env* env, ani_boolean enable) +{ + EVENT_LOGD("setStaticSubscriberStateExecute call"); + int returncode = CommonEventManager::SetStaticSubscriberState(enable); + if (returncode != ERR_OK) { + EVENT_LOGE("setStaticSubscriberStateExecute failed with error: %{public}d", returncode); + if (returncode != Notification::ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP && + returncode != Notification::ERR_NOTIFICATION_SEND_ERROR) { + returncode = Notification::ERR_NOTIFICATION_CESM_ERROR; + } + } + EVENT_LOGD("setStaticSubscriberStateExecute result: %{public}d", returncode); + return returncode; +} + +static uint32_t setStaticSubscriberStateWithEventsExecute(ani_env* env, ani_boolean enable, ani_object events) +{ + EVENT_LOGD("setStaticSubscriberStateWithEventsExecute call"); + std::vector eventList; + AniCommonEventUtils::GetStdStringArrayClass(env, events, eventList); + int returncode = (events == nullptr) ? + CommonEventManager::SetStaticSubscriberState(enable) : + CommonEventManager::SetStaticSubscriberState(eventList, enable); + if (returncode != ERR_OK) { + EVENT_LOGE("setStaticSubscriberStateWithEventsExecute failed with error: %{public}d", returncode); + if (returncode != Notification::ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP && + returncode != Notification::ERR_NOTIFICATION_SEND_ERROR) { + returncode = Notification::ERR_NOTIFICATION_CESM_ERROR; + } + } + EVENT_LOGD("setStaticSubscriberStateWithEventsExecute result: %{public}d.", returncode); + return returncode; +} + +std::shared_ptr GetSubscriber(ani_env* env, ani_ref subscribeRef) +{ + EVENT_LOGD("GetSubscriber excute"); auto ret = ANI_OK; ani_long wrapper_long {}; @@ -171,24 +354,16 @@ static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) static_cast(subscribeRef), "subscriberInstanceWrapper", &wrapper_long); if (ret != ANI_OK) { EVENT_LOGE("subscribeExecute Object_GetPropertyByName_Long error. result: %{public}d.", ret); - return ANI_INVALID_ARGS; + return nullptr; } SubscriberInstanceWrapper* wrapper = nullptr; wrapper = reinterpret_cast(wrapper_long); if (wrapper == nullptr) { EVENT_LOGE("unsubscribeExecute wrapper is null."); - return ANI_INVALID_ARGS; - } - - auto subscriberInstance = GetSubscriberByWrapper(wrapper); - if (subscriberInstance == nullptr) { - EVENT_LOGE("subscriberInstance is null."); - return ANI_INVALID_ARGS; + return nullptr; } - auto result = CommonEventManager::NewUnSubscribeCommonEvent(subscriberInstance); - EVENT_LOGI("unsubscribeExecute result: %{public}d.", result); - return result; + return GetSubscriberByWrapper(wrapper); } std::shared_ptr GetSubscriberByWrapper(SubscriberInstanceWrapper* wrapper) @@ -197,47 +372,48 @@ std::shared_ptr GetSubscriberByWrapper(SubscriberInstanceWra EVENT_LOGE("subscriber is null"); return nullptr; } - std::lock_guard lock(subscriberInsMutex); - for (auto subscriberInstance : subscriberInstances) { - if (subscriberInstance.first.get() == wrapper->GetSubscriber().get()) { - return subscriberInstance.first; - } + std::lock_guard lock(subscriberInsMutex); + auto item = subscriberInstances.find(wrapper->GetSubscriber()); + if (item != subscriberInstances.end()) { + return item->first; } return wrapper->GetSubscriber(); } SubscriberInstance::SubscriberInstance(const CommonEventSubscribeInfo& sp) : CommonEventSubscriber(sp) { - EVENT_LOGI("create SubscriberInstance"); + EVENT_LOGD("create SubscriberInstance"); id_ = ++subscriberID_; } SubscriberInstance::~SubscriberInstance() -{ - EVENT_LOGI("destroy SubscriberInstance"); -} +{} void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) { EVENT_LOGI("OnReceiveEvent execute action = %{public}s", data.GetWant().GetAction().c_str()); if (this->IsOrderedCommonEvent()) { - std::lock_guard lock(subscriberInsMutex); - for (auto subscriberInstance : subscriberInstances) { - if (subscriberInstance.first.get() == this) { - subscriberInstances[subscriberInstance.first] = GoAsyncCommonEvent(); - break; - } + auto subscriber = shared_from_this(); + auto asyncCommonEvent = GoAsyncCommonEvent(); + auto relation = GetTransferRelation(subscriber, nullptr); + if (relation != nullptr) { + EventManagerFwkNapi::SetAsyncCommonEventResult(relation->napiSubscriber_, asyncCommonEvent); + } + std::lock_guard lock(subscriberInsMutex); + auto item = subscriberInstances.find(subscriber); + if (item != subscriberInstances.end()) { + item->second = asyncCommonEvent; } } ani_env* etsEnv; - ani_status aniResult = ANI_ERROR; - ani_options aniArgs { 0, nullptr }; - aniResult = etsVm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv); + ani_status aniResult = ANI_OK; + aniResult = etsVm_->GetEnv(ANI_VERSION_1, &etsEnv); if (aniResult != ANI_OK) { - EVENT_LOGE("subscribeCallbackThreadFunciton FunctionalObject_Call error. result: %{public}d.", aniResult); + EVENT_LOGE("subscribeCallbackThreadFunciton GetEnv error. result: %{public}d.", aniResult); return; } + ani_object ani_data {}; AniCommonEventUtils::ConvertCommonEventDataToEts(etsEnv, ani_data, data); @@ -247,7 +423,7 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) EVENT_LOGE("subscribeCallbackThreadFunciton GetNull error. result: %{public}d.", aniResult); } - auto fnObject = reinterpret_cast(static_cast(callback_)); + auto fnObject = reinterpret_cast(reinterpret_cast(callback_)); if (fnObject == nullptr) { EVENT_LOGE("subscribeCallbackThreadFunciton fnObject is null."); return; @@ -255,17 +431,13 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) EVENT_LOGI("FunctionalObject_Call."); std::vector args = { nullObject, reinterpret_cast(ani_data) }; + if (GetIsToEvent()) { + args.erase(args.begin()); + } ani_ref result; aniResult = etsEnv->FunctionalObject_Call(fnObject, args.size(), args.data(), &result); if (aniResult != ANI_OK) { EVENT_LOGE("subscribeCallbackThreadFunciton FunctionalObject_Call error. result: %{public}d.", aniResult); - return; - } - - aniResult = etsVm_->DetachCurrentThread(); - if (aniResult != ANI_OK) { - EVENT_LOGE("subscribeCallbackThreadFunciton DetachCurrentThread error. result: %{public}d.", aniResult); - return; } } @@ -274,30 +446,39 @@ unsigned long long SubscriberInstance::GetID() return id_.load(); } -void SubscriberInstance::SetEnv(ani_env* env) -{ - EVENT_LOGD("SetEnv"); - std::lock_guard lock(envMutex_); - env_ = env; -} - void SubscriberInstance::SetVm(ani_vm* etsVm) { EVENT_LOGD("SetVm"); etsVm_ = etsVm; } +ani_vm* SubscriberInstance::GetVm() +{ + return etsVm_; +} + void SubscriberInstance::SetCallback(const ani_object& callback) { - std::lock_guard lockRef(callbackMutex_); + std::lock_guard lockRef(callbackMutex_); callback_ = callback; } -void SubscriberInstance::ClearEnv() +ani_object SubscriberInstance::GetCallback() { - EVENT_LOGD("Env expired, clear SubscriberInstance env"); - std::lock_guard lock(envMutex_); - env_ = nullptr; + std::lock_guard lockRef(callbackMutex_); + return callback_; +} + +void SubscriberInstance::SetIsToEvent(bool isToEvent) +{ + std::lock_guard lockRef(isToEventMutex_); + isToEvent_ = isToEvent; +} + +bool SubscriberInstance::GetIsToEvent() +{ + std::lock_guard lockRef(isToEventMutex_); + return isToEvent_; } SubscriberInstanceWrapper::SubscriberInstanceWrapper(const CommonEventSubscribeInfo& info) @@ -321,6 +502,559 @@ std::shared_ptr SubscriberInstanceWrapper::GetSubscriber() return subscriber; } +std::shared_ptr GetTransferRelation(std::shared_ptr aniSubscriber, + std::shared_ptr napiSubscriber) +{ + std::lock_guard lock(transferRelationMutex); + for (auto const &item : transferRelations) { + if ((napiSubscriber != nullptr && item->napiSubscriber_.get() == napiSubscriber.get()) || + (aniSubscriber != nullptr && item->aniSubscriber_.get() == aniSubscriber.get())) { + return item; + } + } + return nullptr; +} + +static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_class, ani_object input) +{ + ani_ref undefinedRef {}; + env->GetUndefined(&undefinedRef); + EventManagerFwkNapi::SubscriberInstanceWrapper *wrapper = nullptr; + arkts_esvalue_unwrap(env, input, (void **)&wrapper); + if (wrapper == nullptr) { + EVENT_LOGE("null wrapper"); + return undefinedRef; + } + auto napiSubscriber = wrapper->GetSubscriber(); + auto relation = GetTransferRelation(nullptr, napiSubscriber); + if (relation != nullptr) { + EVENT_LOGW("already transfered"); + return relation->aniSubscriberRef_; + } + auto aniWrapper = new (std::nothrow) SubscriberInstanceWrapper(napiSubscriber->GetSubscribeInfo()); + if (aniWrapper == nullptr) { + EVENT_LOGE("null aniWrapper"); + return undefinedRef; + } + ani_ref subscriberObj = CreateSubscriberRef(env, aniWrapper); + if (subscriberObj == nullptr) { + delete aniWrapper; + aniWrapper = nullptr; + return undefinedRef; + } + auto asyncCommonEventResult = EventManagerFwkNapi::GetAsyncCommonEventResult(napiSubscriber); + relation = std::make_shared(); + relation->aniSubscriber_ = aniWrapper->GetSubscriber(); + relation->napiSubscriber_ = napiSubscriber; + relation->aniSubscriberRef_ = subscriberObj; + relation->napiSubscriberRef_ = static_cast(input); + if (asyncCommonEventResult != nullptr || napiSubscriber->GetCallbackRef() != nullptr) { + relation->subscribeEnv_ = SUBSCRIBE_IN_NAPI_ENV; + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[aniWrapper->GetSubscriber()] = asyncCommonEventResult; + } + { + std::lock_guard lock(transferRelationMutex); + transferRelations.push_back(relation); + } + SetNapiSubscriberCallback(napiSubscriber); + return subscriberObj; +} + +static int32_t unsubscribeCallback(const std::shared_ptr &napiSubscriber) +{ + int32_t result = ERR_OK; + auto relation = GetTransferRelation(nullptr, napiSubscriber); + if (relation == nullptr) { + EVENT_LOGW("no transfer"); + return result; + } + std::lock_guard lock(relation->relationMutex_); + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), + relation->napiSubscriber_); + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + ani_env* etsEnv; + ani_status aniResult = ANI_OK; + ani_options aniArgs {0, nullptr}; + aniResult = relation->aniSubscriber_->GetVm()->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv); + if (aniResult != ANI_OK) { + EVENT_LOGE("GetEnv error. result: %{public}d.", aniResult); + return aniResult; + } + result = UnsubscribeAndRemoveInstance(etsEnv, relation->aniSubscriber_); + relation->aniSubscriber_->GetVm()->DetachCurrentThread(); + } + relation->subscribeEnv_ = DO_NOT_SUBSCRIBE; + return result; +} + +static int32_t subscribeCallback(const std::shared_ptr &napiSubscriber) +{ + auto relation = GetTransferRelation(nullptr, napiSubscriber); + if (relation == nullptr) { + EVENT_LOGW("no transfer"); + return CommonEventManager::NewSubscribeCommonEvent(napiSubscriber); + } + std::lock_guard lock(relation->relationMutex_); + if (relation->subscribeEnv_ != DO_NOT_SUBSCRIBE) { + EVENT_LOGW("transfered subscriber already subscribed in 1.%{public}d context", relation->subscribeEnv_); + return ERR_OK; + } + auto result = CommonEventManager::NewSubscribeCommonEvent(napiSubscriber); + if (result == ERR_OK) { + relation->subscribeEnv_ = SUBSCRIBE_IN_NAPI_ENV; + } + return result; +}; + +static int32_t gcCallback(const std::shared_ptr &napiSubscriber) +{ + auto relation = GetTransferRelation(nullptr, napiSubscriber); + if (relation == nullptr) { + EVENT_LOGW("no transfer"); + return ERR_OK; + } + int32_t result = ERR_OK; + bool allDestroyed = false; + { + std::lock_guard lock(relation->relationMutex_); + relation->napiSubscriberDestroyed_ = true; + if (relation->aniSubscriberDestroyed_) { + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), + relation->napiSubscriber_); + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + ani_env* etsEnv; + ani_status aniResult = ANI_OK; + ani_options aniArgs {0, nullptr}; + aniResult = relation->aniSubscriber_->GetVm()->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &etsEnv); + if (aniResult != ANI_OK) { + EVENT_LOGE("GetEnv error. result: %{public}d.", aniResult); + return aniResult; + } + result = UnsubscribeAndRemoveInstance(etsEnv, relation->aniSubscriber_); + relation->aniSubscriber_->GetVm()->DetachCurrentThread(); + } + allDestroyed = true; + } + } + if (allDestroyed) { + std::lock_guard lock(transferRelationMutex); + auto item = std::find(transferRelations.begin(), transferRelations.end(), relation); + if (item != transferRelations.end()) { + transferRelations.erase(item); + } + } + return result; +}; + +static void asyncResultCloneCallback(const std::shared_ptr &napiSubscriber, + const std::shared_ptr result) +{ + auto relation = GetTransferRelation(nullptr, napiSubscriber); + if (relation == nullptr) { + EVENT_LOGW("no transfer"); + return; + } + EVENT_LOGI("sync common event data"); + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[relation->aniSubscriber_] = result; + return; +}; + +static ani_ref transferToDynamicSubscriber(ani_env *env, [[maybe_unused]] ani_class, ani_object input) +{ + ani_ref undefinedRef {}; + env->GetUndefined(&undefinedRef); + napi_env jsEnv; + arkts_napi_scope_open(env, &jsEnv); + auto aniSubscriber = GetSubscriber(env, static_cast(input)); + if (aniSubscriber == nullptr) { + EVENT_LOGE("aniSubscriber is null."); + return undefinedRef; + } + auto relation = GetTransferRelation(aniSubscriber, nullptr); + if (relation != nullptr) { + EVENT_LOGW("already transfered"); + return relation->napiSubscriberRef_; + } + napi_value napiSubscriberValue = EventManagerFwkNapi::TransferedCommonEventSubscriberConstructor(jsEnv, + aniSubscriber->GetSubscribeInfo()); + if (napiSubscriberValue == nullptr) { + EVENT_LOGE("napiSubscriberValue is null."); + return undefinedRef; + } + ani_ref result {}; + auto napiSubscriber = EventManagerFwkNapi::GetSubscriber(jsEnv, napiSubscriberValue); + relation = std::make_shared(); + relation->aniSubscriber_ = aniSubscriber; + relation->napiSubscriber_ = napiSubscriber; + relation->aniSubscriberRef_ = static_cast(input); + relation->napiSubscriberRef_ = result; + std::shared_ptr asyncResult = GetAsyncCommonEventResult(aniSubscriber); + if (asyncResult != nullptr || aniSubscriber->GetCallback() != nullptr) { + relation->subscribeEnv_ = SUBSCRIBE_IN_ANI_ENV; + EventManagerFwkNapi::SetAsyncCommonEventResult(napiSubscriber, asyncResult); + } + { + std::lock_guard lock(transferRelationMutex); + transferRelations.push_back(relation); + } + SetNapiSubscriberCallback(napiSubscriber); + arkts_napi_scope_close_n(jsEnv, 1, &napiSubscriberValue, &result); + return result; +} + +void SetNapiSubscriberCallback(std::shared_ptr subscriberInstance) +{ + subscriberInstance->SetAniAsyncResultCloneCallback(asyncResultCloneCallback); + subscriberInstance->SetAniGcCallback(gcCallback); + subscriberInstance->SetAniUnsubscribeCallback(unsubscribeCallback); + subscriberInstance->SetAniSubscribeCallback(subscribeCallback); +} + +static void clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + ani_long ptr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "ptr", &ptr)) { + return; + } + SubscriberInstanceWrapper* wrapper = nullptr; + wrapper = reinterpret_cast(ptr); + if (wrapper == nullptr) { + EVENT_LOGE("clean wrapper is null."); + return; + } + auto subscriberInstance = GetSubscriberByWrapper(wrapper); + if (subscriberInstance == nullptr) { + EVENT_LOGE("subscriberInstance is null."); + return; + } + auto relation = GetTransferRelation(subscriberInstance, nullptr); + if (relation == nullptr) { + EVENT_LOGW("no transfer"); + UnsubscribeAndRemoveInstance(env, subscriberInstance); + return; + } + bool allDestroyed = false; + { + std::lock_guard lock(relation->relationMutex_); + relation->aniSubscriberDestroyed_ = true; + if (relation->napiSubscriberDestroyed_) { + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), + relation->napiSubscriber_); + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + UnsubscribeAndRemoveInstance(env, relation->aniSubscriber_); + } + allDestroyed = true; + } + } + if (allDestroyed) { + std::lock_guard lock(transferRelationMutex); + auto item = std::find(transferRelations.begin(), transferRelations.end(), relation); + if (item != transferRelations.end()) { + transferRelations.erase(item); + } + } + return; +} + +std::shared_ptr GetAsyncCommonEventResult(ani_env* env, ani_object object) +{ + EVENT_LOGD("subscriberInstance GetAsyncCommonEventResult."); + auto subscriberInstance = GetSubscriber(env, object); + if (subscriberInstance == nullptr) { + EVENT_LOGE("subscriberInstance is null."); + return nullptr; + } + return GetAsyncCommonEventResult(subscriberInstance); +} + +std::shared_ptr GetAsyncCommonEventResult(std::shared_ptr subscriber) +{ + if (subscriber == nullptr) { + EVENT_LOGE("subscriberInstance is null."); + return nullptr; + } + if (subscriberInstances.size() == 0) { + EVENT_LOGE("subscriberInstances is null."); + return nullptr; + } + std::lock_guard lock(subscriberInsMutex); + for (auto subscriberRes : subscriberInstances) { + if (subscriberRes.first.get() == subscriber.get()) { + return subscriberRes.second; + } + } + return nullptr; +} + +static ani_double getCode(ani_env *env, ani_object object) +{ + EVENT_LOGI("subscriberInstance getCode."); + auto subscriberRes = GetAsyncCommonEventResult(env, object); + int32_t code = 0; + if (subscriberRes != nullptr) { + code = subscriberRes->GetCode(); + } + ani_double returncode = static_cast(code); + return returncode; +} + +static uint32_t setCode(ani_env *env, ani_object object, ani_int code) +{ + EVENT_LOGD("subscriberInstance setCode."); + int32_t returncode = 0; + auto subscriberRes = GetAsyncCommonEventResult(env, object); + if (subscriberRes == nullptr) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + bool returnBoolean = subscriberRes->SetCode(code); + if (!returnBoolean) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + return returncode; +} + +static ani_string getData(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance getData."); + auto subscriberRes = GetAsyncCommonEventResult(env, object); + std::string str = ""; + if (subscriberRes != nullptr) { + str = subscriberRes->GetData(); + } + ani_string aniResult = nullptr; + AniCommonEventUtils::GetAniString(env, str, aniResult); + return aniResult; +} + +static uint32_t setData(ani_env *env, ani_object object, ani_string data) +{ + EVENT_LOGD("subscriberInstance setData."); + int32_t returncode = 0; + auto subscriberRes = GetAsyncCommonEventResult(env, object); + if (subscriberRes == nullptr) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + std::string stdData; + AniCommonEventUtils::GetStdString(env, data, stdData); + ani_boolean returnBoolean = static_cast(subscriberRes->SetData(stdData)); + if (!returnBoolean) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + return returncode; +} + +static uint32_t setCodeAndData(ani_env *env, ani_object object, ani_int code, ani_string data) +{ + EVENT_LOGD("subscriberInstance setCodeAndData."); + int32_t returncode = 0; + auto subscriberRes = GetAsyncCommonEventResult(env, object); + if (subscriberRes == nullptr) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + std::string stdData; + int32_t intCode = static_cast(code); + AniCommonEventUtils::GetStdString(env, data, stdData); + bool returnBoolean = subscriberRes->SetCodeAndData(intCode, stdData); + if (!returnBoolean) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + return returncode; +} + +static ani_boolean isOrderedCommonEvent(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance isOrderedCommonEvent."); + auto subscriberRes = GetAsyncCommonEventResult(env, object); + ani_boolean returnBoolean = ANI_FALSE; + if (subscriberRes != nullptr) { + returnBoolean = subscriberRes->IsOrderedCommonEvent() ? ANI_TRUE : ANI_FALSE; + } + return returnBoolean; +} + +static ani_boolean isStickyCommonEvent(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance isStickyCommonEvent."); + auto subscriberRes = GetAsyncCommonEventResult(env, object); + ani_boolean returnBoolean = ANI_FALSE; + if (subscriberRes != nullptr) { + returnBoolean = subscriberRes->IsStickyCommonEvent() ? ANI_TRUE : ANI_FALSE; + } + return returnBoolean; +} + +static uint32_t abortCommonEvent(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance abortCommonEvent."); + int32_t returncode = 0; + auto subscriberRes = GetAsyncCommonEventResult(env, object); + if (subscriberRes == nullptr) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + if (!(subscriberRes->AbortCommonEvent())) { + return returncode; + } + return returncode; +} + +static uint32_t clearAbortCommonEvent(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance clearAbortCommonEvent."); + int32_t returncode = 0; + auto subscriberRes = GetAsyncCommonEventResult(env, object); + if (subscriberRes == nullptr) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + if (!(subscriberRes->ClearAbortCommonEvent())) { + return returncode; + } + return returncode; +} + +static ani_boolean getAbortCommonEvent(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance getAbortCommonEvent."); + auto subscriberRes = GetAsyncCommonEventResult(env, object); + ani_boolean returnBoolean = ANI_FALSE; + if (subscriberRes != nullptr) { + returnBoolean = subscriberRes->GetAbortCommonEvent() ? ANI_TRUE : ANI_FALSE; + } + return returnBoolean; +} + +static ani_object getSubscribeInfo(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance getSubscribeInfo."); + auto subscriberInstance = GetSubscriber(env, object); + ani_object infoObject {}; + if (subscriberInstance == nullptr) { + EVENT_LOGE("subscriberInstance is null."); + ani_ref nullObject; + env->GetNull(&nullObject); + return static_cast(nullObject); + } + AniCommonEventUtils::GetCommonEventSubscribeInfoToEts(env, subscriberInstance, infoObject); + if (infoObject == nullptr) { + EVENT_LOGE("infoObject is null."); + ani_ref nullObject; + env->GetNull(&nullObject); + return static_cast(nullObject); + } + return infoObject; +} + +static uint32_t finishCommonEvent(ani_env *env, ani_object object) +{ + EVENT_LOGD("subscriberInstance finishCommonEvent."); + auto subscriberRes = GetAsyncCommonEventResult(env, object); + int32_t returncode = 0; + if (subscriberRes == nullptr) { + EVENT_LOGE("subscriberRes is null"); + return returncode; + } + if (!(subscriberRes->FinishCommonEvent())) { + return returncode; + } + return returncode; +} + +static std::array commonEventSubscriberFunctions = { + ani_native_function{"nativeGetCode", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::getCode)}, + ani_native_function{"nativeSetCode", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::setCode)}, + ani_native_function{"nativeGetData", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::getData)}, + ani_native_function{"nativeSetData", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::setData)}, + ani_native_function{"nativeSetCodeAndData", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::setCodeAndData)}, + ani_native_function{"nativeIsOrderedCommonEvent", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::isOrderedCommonEvent)}, + ani_native_function{"nativeIsStickyCommonEvent", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::isStickyCommonEvent)}, + ani_native_function{"nativeAbortCommonEvent", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::abortCommonEvent)}, + ani_native_function{"nativeClearAbortCommonEvent", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::clearAbortCommonEvent)}, + ani_native_function{"nativeGetAbortCommonEvent", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::getAbortCommonEvent)}, + ani_native_function{"nativeGetSubscribeInfo", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::getSubscribeInfo)}, + ani_native_function{"nativeFinishCommonEvent", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::finishCommonEvent)}, + ani_native_function{"transferToDynamicSubscriber", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::transferToDynamicSubscriber)}, + ani_native_function{"transferToStaticSubscriber", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::transferToStaticSubscriber)}, +}; + +static std::array commonEventManagerMethods = { + ani_native_function { "publishExecute", "Lstd/core/String;:I", + reinterpret_cast(OHOS::EventManagerFwkAni::publishExecute) }, + ani_native_function { "publishWithOptionsExecute", + "Lstd/core/String;LcommonEvent/commonEventPublishData/CommonEventPublishData;:I", + reinterpret_cast(OHOS::EventManagerFwkAni::publishWithOptionsExecute) }, + ani_native_function { "publishAsUserExecute", "Lstd/core/String;I:I", + reinterpret_cast(OHOS::EventManagerFwkAni::publishAsUserExecute) }, + ani_native_function { "publishAsUserWithOptionsExecute", + "Lstd/core/String;ILcommonEvent/commonEventPublishData/CommonEventPublishData;:I", + reinterpret_cast(OHOS::EventManagerFwkAni::publishAsUserWithOptionsExecute) }, + ani_native_function { "createSubscriberExecute", + "LcommonEvent/commonEventSubscribeInfo/CommonEventSubscribeInfo;:LcommonEvent/commonEventSubscriber/" + "CommonEventSubscriber;", + reinterpret_cast(OHOS::EventManagerFwkAni::createSubscriberExecute) }, + ani_native_function { + "subscribeExecute", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::subscribeExecute) }, + ani_native_function { + "subscribeToEventExecute", + nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::subscribeToEventExecute) }, + ani_native_function { "unsubscribeExecute", "LcommonEvent/commonEventSubscriber/CommonEventSubscriber;:I", + reinterpret_cast(OHOS::EventManagerFwkAni::unsubscribeExecute) }, + ani_native_function { "removeStickyCommonEventExecute", "Lstd/core/String;:I", + reinterpret_cast(OHOS::EventManagerFwkAni::removeStickyCommonEventExecute) }, + ani_native_function { "setStaticSubscriberStateExecute", "Z:I", + reinterpret_cast(OHOS::EventManagerFwkAni::setStaticSubscriberStateExecute) }, + ani_native_function { "setStaticSubscriberStateWithEventsExecute", nullptr, + reinterpret_cast(OHOS::EventManagerFwkAni::setStaticSubscriberStateWithEventsExecute) }, +}; + + +ani_status init(ani_env *env, ani_namespace kitNs) +{ + ani_status status = ANI_ERROR; + status = + env->Namespace_BindNativeFunctions(kitNs, commonEventManagerMethods.data(), commonEventManagerMethods.size()); + if (status != ANI_OK) { + EVENT_LOGE("Cannot bind native methods to L@ohos/event/common_event_manager/commonEventManager"); + return ANI_INVALID_TYPE; + } + + ani_class commonEventSubscriberCls; + status = env->FindClass("LcommonEvent/commonEventSubscriber/CommonEventSubscriberInner;", + &commonEventSubscriberCls); + if (status != ANI_OK) { + EVENT_LOGE("Not found LcommonEvent/commonEventSubscriber/CommonEventSubscriberInner"); + return ANI_INVALID_ARGS; + } + status = env->Class_BindNativeMethods(commonEventSubscriberCls, commonEventSubscriberFunctions.data(), + commonEventSubscriberFunctions.size()); + if (status != ANI_OK) { + EVENT_LOGE("Cannot bind native methods to LcommonEvent/commonEventSubscriber/CommonEventSubscriberInner"); + return ANI_INVALID_TYPE; + } + return status; +} + extern "C" { ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) { @@ -338,29 +1072,25 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) EVENT_LOGE("Not found L@ohos/commonEventManager/commonEventManager."); return ANI_INVALID_ARGS; } - - std::array methods = { - ani_native_function { "publishExecute", "Lstd/core/String;:I", - reinterpret_cast(OHOS::EventManagerFwkAni::publishExecute) }, - ani_native_function { "publishWithOptionsExecute", - "Lstd/core/String;LcommonEvent/commonEventPublishData/CommonEventPublishData;:I", - reinterpret_cast(OHOS::EventManagerFwkAni::publishWithOptionsExecute) }, - ani_native_function { "createSubscriberExecute", - "LcommonEvent/commonEventSubscribeInfo/CommonEventSubscribeInfo;:LcommonEvent/commonEventSubscriber/" - "CommonEventSubscriber;", - reinterpret_cast(OHOS::EventManagerFwkAni::createSubscriberExecute) }, - ani_native_function { - "subscribeExecute", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::subscribeExecute) }, - ani_native_function { "unsubscribeExecute", "LcommonEvent/commonEventSubscriber/CommonEventSubscriber;:I", - reinterpret_cast(OHOS::EventManagerFwkAni::unsubscribeExecute) }, - }; - - status = env->Namespace_BindNativeFunctions(kitNs, methods.data(), methods.size()); + status = init(env, kitNs); if (status != ANI_OK) { - EVENT_LOGE("Cannot bind native methods to L@ohos/event/common_event_manager/commonEventManager"); + EVENT_LOGE("Cannot bind native methods to L@ohos/events/emitter/emitter"); return ANI_INVALID_TYPE; } + ani_class cls; + status = env->FindClass("LcommonEvent/commonEventSubscriber/Cleaner;", &cls); + if (status != ANI_OK) { + EVENT_LOGE("Not found LcommonEvent/commonEventSubscriber/Cleaner"); + return ANI_INVALID_ARGS; + } + std::array cleanMethod = { + ani_native_function{"clean", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::clean)}}; + status = env->Class_BindNativeMethods(cls, cleanMethod.data(), cleanMethod.size()); + if (status != ANI_OK) { + EVENT_LOGE("Cannot bind native methods to LcommonEvent/commonEventSubscriber/Cleaner"); + return ANI_INVALID_TYPE; + } *result = ANI_VERSION_1; return ANI_OK; } diff --git a/interfaces/kits/ani/common_event/src/ani_common_event_utils.cpp b/interfaces/kits/ani/common_event/src/ani_common_event_utils.cpp index 496552f9a7fcc62e3d5f085069ccd2cb7d458a45..e683d11d0e8aa89652d975235b3723dead107caa 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event_utils.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event_utils.cpp @@ -14,6 +14,7 @@ */ #include "ani_common_event_utils.h" +#include "ani_common_want.h" #include "event_log_wrapper.h" namespace OHOS { @@ -41,6 +42,20 @@ void AniCommonEventUtils::GetStdString(ani_env* env, ani_string str, std::string result.resize(sz); } +ani_status AniCommonEventUtils::GetAniString(ani_env* env, const std::string str, ani_string& aniStr) +{ + if (env == nullptr) { + EVENT_LOGE("GetAniStringByString fail, env is nullptr"); + return ANI_INVALID_ARGS; + } + ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr); + if (status != ANI_OK) { + EVENT_LOGE("String_NewUTF8 failed %{public}d", status); + return status; + } + return status; +} + void AniCommonEventUtils::GetStdStringArrayClass(ani_env* env, ani_object arrayObj, std::vector& strings) { ani_double length; @@ -99,6 +114,36 @@ bool AniCommonEventUtils::GetStringOrUndefined(ani_env* env, ani_object param, c return true; } +bool AniCommonEventUtils::GetDoubleOrUndefined(ani_env* env, ani_object param, const char* name, int32_t& res) +{ + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + + if ((status = env->Object_GetPropertyByName_Ref(param, name, &obj)) != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + return false; + } + if (isUndefined) { + EVENT_LOGW("%{public}s : undefined", name); + return false; + } + + ani_double result = 0; + if ((status = env->Object_CallMethodByName_Double(reinterpret_cast(obj), "unboxed", nullptr, &result)) + != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + return false; + } + + res = static_cast(result); + return true; +} + bool AniCommonEventUtils::GetIntOrUndefined(ani_env* env, ani_object param, const char* name, int32_t& res) { ani_ref obj = nullptr; @@ -119,7 +164,7 @@ bool AniCommonEventUtils::GetIntOrUndefined(ani_env* env, ani_object param, cons } ani_int result = 0; - if ((status = env->Object_CallMethodByName_Int(reinterpret_cast(obj), "intValue", nullptr, &result)) != + if ((status = env->Object_CallMethodByName_Int(reinterpret_cast(obj), "unboxed", nullptr, &result)) != ANI_OK) { EVENT_LOGE("status : %{public}d", status); return false; @@ -183,12 +228,39 @@ bool AniCommonEventUtils::GetStringArrayOrUndefined( return true; } +bool AniCommonEventUtils::GetWantParamsOrUndefined( + ani_env* env, ani_object param, const char* name, AAFwk::WantParams& wantParams) +{ + ani_ref obj = nullptr; + ani_boolean isUndefined = true; + ani_status status = ANI_ERROR; + if ((status = env->Object_GetPropertyByName_Ref(param, name, &obj)) != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + return false; + } + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + EVENT_LOGE("status : %{public}d", status); + return false; + } + if (isUndefined) { + EVENT_LOGW("%{public}s : undefined", name); + return false; + } + + if (!UnwrapWantParams(env, obj, wantParams)) { + EVENT_LOGE("GetWantParamsOrUndefined UnwrapWantParams error."); + return false; + } + + return true; +} + void AniCommonEventUtils::ConvertCommonEventPublishData(ani_env* env, ani_object optionsObject, Want& want, CommonEventData &commonEventData, CommonEventPublishInfo &commonEventPublishInfo) { // Get the code. int32_t code; - if (GetIntOrUndefined(env, optionsObject, "code", code)) { + if (GetDoubleOrUndefined(env, optionsObject, "code", code)) { EVENT_LOGI("ConvertCommonEventPublishData code: %{public}d.", code); commonEventData.SetCode(code); } else { @@ -241,6 +313,13 @@ void AniCommonEventUtils::ConvertCommonEventPublishData(ani_env* env, ani_object } // Get the parameters [Record] + AAFwk::WantParams wantParams; + if (GetWantParamsOrUndefined(env, optionsObject, "parameters", wantParams)) { + EVENT_LOGI("ConvertCommonEventPublishData parameters success."); + want.SetParams(wantParams); + } else { + EVENT_LOGI("ConvertCommonEventPublishData parameters not exit"); + } } void AniCommonEventUtils::ConvertCommonEventSubscribeInfo( @@ -289,7 +368,7 @@ void AniCommonEventUtils::ConvertCommonEventSubscribeInfo( // Get the userId. int32_t userId; - if (GetIntOrUndefined(env, infoObject, "userId", userId)) { + if (GetDoubleOrUndefined(env, infoObject, "userId", userId)) { EVENT_LOGI("ConvertCommonEventPublishData userId: %{public}d.", userId); commonEventSubscribeInfo.SetUserId(userId); } else { @@ -298,7 +377,7 @@ void AniCommonEventUtils::ConvertCommonEventSubscribeInfo( // Get the priority. int32_t priority; - if (GetIntOrUndefined(env, infoObject, "priority", priority)) { + if (GetDoubleOrUndefined(env, infoObject, "priority", priority)) { EVENT_LOGI("ConvertCommonEventPublishData priority: %{public}d.", priority); commonEventSubscribeInfo.SetPriority(priority); } else { @@ -308,6 +387,110 @@ void AniCommonEventUtils::ConvertCommonEventSubscribeInfo( subscribeInfo = commonEventSubscribeInfo; } +void AniCommonEventUtils::GetCommonEventSubscribeInfoToEts( + ani_env* env, std::shared_ptr subscriber, ani_object &infoObject) +{ + ani_class cls = nullptr; + ani_status status = ANI_ERROR; + CreateNewObjectByClass(env, "LcommonEvent/commonEventSubscribeInfo/CommonEventSubscribeInfoImpl;", cls, infoObject); + if ((infoObject == nullptr) || (cls == nullptr)) { + EVENT_LOGE("CommonEventSubscribeInfoToAni infoObject or cls is null."); + return; + } + if (subscriber == nullptr) { + EVENT_LOGE("subscriber is null."); + return; + } + + // set events [Array] + ani_object eventsParamRef = GetAniStringArray(env, subscriber->GetSubscribeInfo().GetMatchingSkills().GetEvents()); + CallSetter(env, cls, infoObject, SETTER_METHOD_NAME(events), eventsParamRef); + + ani_string string = nullptr; + // set publisherPermission [string] + status = env->String_NewUTF8( + subscriber->GetSubscribeInfo().GetPermission().c_str(), + subscriber->GetSubscribeInfo().GetPermission().size(), &string); + CallSetter(env, cls, infoObject, SETTER_METHOD_NAME(publisherPermission), string); + + // set publisherDeviceId [string] + status = env->String_NewUTF8( + subscriber->GetSubscribeInfo().GetDeviceId().c_str(), + subscriber->GetSubscribeInfo().GetDeviceId().size(), &string); + CallSetter(env, cls, infoObject, SETTER_METHOD_NAME(publisherDeviceId), string); + + // set publisherBundleName [string] + status = env->String_NewUTF8( + subscriber->GetSubscribeInfo().GetPublisherBundleName().c_str(), + subscriber->GetSubscribeInfo().GetPublisherBundleName().size(), &string); + CallSetter(env, cls, infoObject, SETTER_METHOD_NAME(publisherBundleName), string); + + // set userId [number] + ani_object userIdObject; + CreateAniDoubleObject(env, userIdObject, static_cast(subscriber->GetSubscribeInfo().GetUserId())); + CallSetter(env, cls, infoObject, SETTER_METHOD_NAME(userId), userIdObject); + + // set priority [number] + ani_object priorityObject; + CreateAniDoubleObject(env, priorityObject, static_cast(subscriber->GetSubscribeInfo().GetPriority())); + CallSetter(env, cls, infoObject, SETTER_METHOD_NAME(priority), priorityObject); +} + +ani_object AniCommonEventUtils::GetAniStringArray(ani_env *env, std::vector strs) +{ + if (env == nullptr) { + EVENT_LOGE("GetAniStringArray fail, env is nullptr or strs is empty"); + return nullptr; + } + int length = strs.size(); + ani_object arrayObj = newArrayClass(env, length); + if (arrayObj == nullptr) { + return nullptr; + } + ani_size i = 0; + for (auto &str : strs) { + EVENT_LOGI("GetAniStringArray: %{public}s", str.c_str()); + ani_string aniStr; + if ((env->String_NewUTF8(str.c_str(), str.size(), &aniStr) != ANI_OK) || aniStr == nullptr) { + EVENT_LOGE("String_NewUTF8 faild"); + return nullptr; + } + ani_status status = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", i, aniStr); + if (status != ANI_OK) { + EVENT_LOGE("Object_CallMethodByName_Void failed %{public}d", status); + return nullptr; + } + i++; + } + return arrayObj; +} + +ani_object AniCommonEventUtils::newArrayClass(ani_env *env, int length) +{ + EVENT_LOGD("newArrayClass call"); + if (env == nullptr || length < 0) { + EVENT_LOGE("CreateDouble fail, env is nullptr or length is less than zero"); + return nullptr; + } + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + EVENT_LOGE("FindClass Lescompat/Array; Failed"); + return nullptr; + } + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) { + EVENT_LOGE("Class_FindMethod Failed"); + return nullptr; + } + ani_object arrayObj = nullptr; + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, length)) { + EVENT_LOGE("Object_New Array Faild"); + return nullptr; + } + EVENT_LOGD("newArrayClass end"); + return arrayObj; +} + void AniCommonEventUtils::CreateNewObjectByClass( ani_env* env, const char* className, ani_class& cls, ani_object& ani_data) { @@ -444,6 +627,8 @@ void AniCommonEventUtils::ConvertCommonEventDataToEts( CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(code), codeObject); // set parameters [Record] + ani_ref wantParamRef = WrapWantParams(env, commonEventData.GetWant().GetParams()); + CallSetter(env, cls, ani_data, SETTER_METHOD_NAME(parameters), wantParamRef); } } // namespace EventManagerFwkAni diff --git a/interfaces/kits/napi/napi_common_event/BUILD.gn b/interfaces/kits/napi/napi_common_event/BUILD.gn index 95cd3563d7f77df00900b8b6eb7132291344b051..a44c3d0b535b64279b718114ad910c8634a0184a 100644 --- a/interfaces/kits/napi/napi_common_event/BUILD.gn +++ b/interfaces/kits/napi/napi_common_event/BUILD.gn @@ -28,14 +28,17 @@ cflags = [ config("native_module_config") { visibility = [ ":*" ] - include_dirs = [] + include_dirs = [ + "${interfaces_path}/kits/napi/napi_common_event/include", + "${interfaces_path}/kits/napi/support/include", + ] if (target_cpu == "arm") { cflags += [ "-DBINDER_IPC_32BIT" ] } } -ohos_shared_library("commoneventmanager") { +ohos_shared_library("napi_commoneventmanager") { sanitize = { integer_overflow = true ubsan = true @@ -51,13 +54,12 @@ ohos_shared_library("commoneventmanager") { "${interfaces_path}/kits/napi/support/include", ] - configs = [ ":native_module_config" ] + public_configs = [ ":native_module_config" ] sources = [ "${interfaces_path}/kits/napi/support/src/support.cpp", "src/common_event_parse.cpp", "src/common_event_set_param.cpp", - "src/init.cpp", "src/napi_common_event.cpp", ] @@ -74,6 +76,40 @@ ohos_shared_library("commoneventmanager") { "napi:ace_napi", ] + subsystem_name = "notification" + part_name = "common_event_service" +} + +ohos_shared_library("commoneventmanager") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + sources = [ + "src/init.cpp", + ] + + deps = [ + ":napi_commoneventmanager", + "${ces_native_path}:cesfwk_innerkits", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:abilitykit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "c_utils:utils", + "hilog:libhilog", + "napi:ace_napi", + ] + relative_install_dir = "module" subsystem_name = "notification" part_name = "common_event_service" diff --git a/interfaces/kits/napi/napi_common_event/include/napi_common_event.h b/interfaces/kits/napi/napi_common_event/include/napi_common_event.h index d4754ebcc528a563d053a9d548291e3a358ee1eb..029ff03a707d3014af1f102059be2ed39f4b277c 100644 --- a/interfaces/kits/napi/napi_common_event/include/napi_common_event.h +++ b/interfaces/kits/napi/napi_common_event/include/napi_common_event.h @@ -222,6 +222,10 @@ struct AsyncCallbackRemoveSticky { CallbackPromiseInfo info; }; +typedef int32_t (*AniSubscriberCallback)(const std::shared_ptr &subscriber); +typedef void (*AniAsyncResultCloneCallback)(const std::shared_ptr &subscriber, + const std::shared_ptr result); + class SubscriberInstance : public CommonEventSubscriber, public std::enable_shared_from_this { public: SubscriberInstance(const CommonEventSubscribeInfo &sp); @@ -238,6 +242,15 @@ public: unsigned long long GetID(); napi_env GetEnv(); napi_ref GetCallbackRef(); + void SetAniUnsubscribeCallback(AniSubscriberCallback callback); + void SetAniAsyncResultCloneCallback(AniAsyncResultCloneCallback callback); + void SetAniGcCallback(AniSubscriberCallback callback); + void SetAniSubscribeCallback(AniSubscriberCallback callback); + AniAsyncResultCloneCallback GetAniAsyncResultCloneCallback(); + AniSubscriberCallback GetAniUnsubscribeCallback(); + AniSubscriberCallback GetAniGcCallback(); + AniSubscriberCallback GetAniSubscribeCallback(); + private: napi_env env_ = nullptr; napi_ref ref_ = nullptr; @@ -247,6 +260,10 @@ private: napi_threadsafe_function tsfn_ = nullptr; std::mutex envMutex_; std::mutex refMutex_; + AniAsyncResultCloneCallback asyncResultCloneCallback_ = nullptr; + AniSubscriberCallback unsubscribeCallback_ = nullptr; + AniSubscriberCallback gcCallback_ = nullptr; + AniSubscriberCallback subscribeCallback_ = nullptr; }; struct CommonEventDataWorker { @@ -309,6 +326,8 @@ void PaddingNapiCreateAsyncWorkCallbackInfo(AsyncCallbackInfoSubscribeInfo *&asy void SetNapiResult(const napi_env &env, const AsyncCallbackInfoSubscribeInfo *asynccallbackinfo, napi_value &result); +void SetNapiResult(const napi_env &env, const CommonEventSubscribeInfo &subscribeInfo, napi_value &result); + napi_value GetSubscribeInfo(napi_env env, napi_callback_info info); napi_value ParseParametersByIsOrderedCommonEvent( @@ -463,6 +482,15 @@ napi_value GetPublisherBundleNameByCreateSubscriber( napi_value CommonEventSubscriberConstructor(napi_env env, napi_callback_info info); +napi_value TransferedCommonEventSubscriberConstructor(napi_env env, const CommonEventSubscribeInfo &info); + +int32_t UnsubscribeAndRemoveInstance(const napi_env &env, std::shared_ptr &subscriber); + +std::shared_ptr GetAsyncCommonEventResult( + const std::shared_ptr &subscriber); +void SetAsyncCommonEventResult(const std::shared_ptr &subscriber, + std::shared_ptr asyncCommonEventResult); + napi_value CommonEventSubscriberInit(napi_env env, napi_value exports); napi_value CommonEventManagerInit(napi_env env, napi_value exports); diff --git a/interfaces/kits/napi/napi_common_event/src/common_event_set_param.cpp b/interfaces/kits/napi/napi_common_event/src/common_event_set_param.cpp index db27c96cfb58e0616bdc55b6e472c7a5ec00f397..fe8af10f0289bfb55cd5804880b60df8072cff13 100644 --- a/interfaces/kits/napi/napi_common_event/src/common_event_set_param.cpp +++ b/interfaces/kits/napi/napi_common_event/src/common_event_set_param.cpp @@ -118,6 +118,18 @@ void SetNapiResult(const napi_env &env, const AsyncCallbackInfoSubscribeInfo *as SetPublisherBundleNameResult(env, asyncCallbackInfo->publisherBundleName, result); } +void SetNapiResult(const napi_env &env, const CommonEventSubscribeInfo &subscribeInfo, napi_value &result) +{ + EVENT_LOGD("SetNapiResult start"); + + SetEventsResult(env, subscribeInfo.GetMatchingSkills().GetEvents(), result); + SetPublisherPermissionResult(env, subscribeInfo.GetPermission(), result); + SetPublisherDeviceIdResult(env, subscribeInfo.GetDeviceId(), result); + SetPublisherUserIdResult(env, subscribeInfo.GetUserId(), result); + SetPublisherPriorityResult(env, subscribeInfo.GetPriority(), result); + SetPublisherBundleNameResult(env, subscribeInfo.GetPublisherBundleName(), result); +} + napi_value SetCode(napi_env env, napi_callback_info info) { EVENT_LOGD("SetCode excute"); diff --git a/interfaces/kits/napi/napi_common_event/src/napi_common_event.cpp b/interfaces/kits/napi/napi_common_event/src/napi_common_event.cpp index ca6dcba0f3111a9926a7b4f02e9cd8f54c75112f..41889cd8e0cee0526369a85f5ecb02ab51c1ddd4 100644 --- a/interfaces/kits/napi/napi_common_event/src/napi_common_event.cpp +++ b/interfaces/kits/napi/napi_common_event/src/napi_common_event.cpp @@ -20,6 +20,7 @@ #include #include "ces_inner_error_code.h" +#include "common_event_manager.h" #include "event_log_wrapper.h" #include "napi_common.h" #include "node_api.h" @@ -263,6 +264,46 @@ napi_ref SubscriberInstance::GetCallbackRef() return ref_; } +void SubscriberInstance::SetAniAsyncResultCloneCallback(AniAsyncResultCloneCallback callback) +{ + asyncResultCloneCallback_ = callback; +} + +AniAsyncResultCloneCallback SubscriberInstance::GetAniAsyncResultCloneCallback() +{ + return asyncResultCloneCallback_; +} + +void SubscriberInstance::SetAniUnsubscribeCallback(AniSubscriberCallback callback) +{ + unsubscribeCallback_ = callback; +} + +AniSubscriberCallback SubscriberInstance::GetAniUnsubscribeCallback() +{ + return unsubscribeCallback_; +} + +void SubscriberInstance::SetAniGcCallback(AniSubscriberCallback callback) +{ + gcCallback_ = callback; +} + +AniSubscriberCallback SubscriberInstance::GetAniGcCallback() +{ + return gcCallback_; +} + +void SubscriberInstance::SetAniSubscribeCallback(AniSubscriberCallback callback) +{ + subscribeCallback_ = callback; +} + +AniSubscriberCallback SubscriberInstance::GetAniSubscribeCallback() +{ + return subscribeCallback_; +} + void SubscriberInstance::SetThreadSafeFunction(const napi_threadsafe_function &tsfn) { tsfn_ = tsfn; @@ -286,7 +327,11 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData &data) std::lock_guard lock(subscriberInsMutex); for (auto subscriberInstance : subscriberInstances) { if (subscriberInstance.first.get() == this) { - subscriberInstances[subscriberInstance.first].commonEventResult = GoAsyncCommonEvent(); + auto result = GoAsyncCommonEvent(); + subscriberInstances[subscriberInstance.first].commonEventResult = result; + if (asyncResultCloneCallback_ != nullptr) { + (*asyncResultCloneCallback_)(subscriberInstance.first, result); + } break; } } @@ -495,6 +540,12 @@ void AsyncExecuteCallbackSubscribe(napi_env env, void *data) EVENT_LOGD("Subscribe napi_create_async_work excute"); AsyncCallbackInfoSubscribe *asyncCallbackInfo = static_cast(data); if (asyncCallbackInfo) { + auto aniSubscribeCallback = asyncCallbackInfo->subscriber->GetAniSubscribeCallback(); + if (aniSubscribeCallback != nullptr) { + asyncCallbackInfo->errorCode = (*aniSubscribeCallback)(asyncCallbackInfo->subscriber); + return; + } + EVENT_LOGI("no transfer subscribe 1.1 subscriber"); asyncCallbackInfo->errorCode = CommonEventManager::NewSubscribeCommonEvent( asyncCallbackInfo->subscriber); } @@ -841,6 +892,17 @@ void NapiDeleteSubscribe(const napi_env &env, std::shared_ptr &subscriber) +{ + EVENT_LOGD("unsubscribe 1.1 subscriber"); + auto result = CommonEventManager::NewUnSubscribeCommonEvent(subscriber); + if (result != ERR_OK) { + EVENT_LOGE("unsubscribe failed result: %{public}d.", result); + return result; + } + NapiDeleteSubscribe(env, subscriber); + return result; +} napi_value Unsubscribe(napi_env env, napi_callback_info info) { @@ -901,6 +963,12 @@ napi_value Unsubscribe(napi_env env, napi_callback_info info) EVENT_LOGD("Unsubscribe napi_create_async_work start"); AsyncCallbackInfoUnsubscribe *asyncCallbackInfo = static_cast(data); if (asyncCallbackInfo) { + auto aniUnsubscribeCallback = asyncCallbackInfo->subscriber->GetAniUnsubscribeCallback(); + if (aniUnsubscribeCallback != nullptr) { + asyncCallbackInfo->errorCode = (*aniUnsubscribeCallback)(asyncCallbackInfo->subscriber); + return; + } + EVENT_LOGI("no transfer unsubscribe 1.1 subscriber"); asyncCallbackInfo->errorCode = CommonEventManager::NewUnSubscribeCommonEvent( asyncCallbackInfo->subscriber); } @@ -1012,7 +1080,12 @@ napi_value CommonEventSubscriberConstructor(napi_env env, napi_callback_info inf EVENT_LOGD("Constructor destroy"); auto subscriber = GetSubscriberByWrapper(wrapper); if (subscriber != nullptr) { - CommonEventManager::UnSubscribeCommonEvent(subscriber); + auto gcCallback = subscriber->GetAniGcCallback(); + if (gcCallback != nullptr) { + (*gcCallback)(subscriber); + } else { + CommonEventManager::UnSubscribeCommonEvent(subscriber); + } NapiDeleteSubscribe(env, subscriber); } delete wrapper; @@ -1025,16 +1098,41 @@ napi_value CommonEventSubscriberConstructor(napi_env env, napi_callback_info inf return thisVar; } -void SetNapiResult(const napi_env &env, const CommonEventSubscribeInfo &subscribeInfo, napi_value &result) +napi_value TransferedCommonEventSubscriberConstructor(napi_env env, const CommonEventSubscribeInfo &info) +{ + napi_value subscribeInfoValue = nullptr; + napi_create_object(env, &subscribeInfoValue); + SetNapiResult(env, info, subscribeInfoValue); + napi_value constructor = nullptr; + napi_get_reference_value(env, g_CommonEventSubscriber, &constructor); + napi_value thisVar = nullptr; + napi_new_instance(env, constructor, 1, &subscribeInfoValue, &thisVar); + return thisVar; +} + +std::shared_ptr GetAsyncCommonEventResult(const std::shared_ptr &subscriber) { - EVENT_LOGD("SetNapiResult start"); + std::lock_guard lock(subscriberInsMutex); + for (auto subscriberInstance : subscriberInstances) { + if (subscriberInstance.first.get() == subscriber.get()) { + return subscriberInstance.second.commonEventResult; + } + } + return nullptr; +} - SetEventsResult(env, subscribeInfo.GetMatchingSkills().GetEvents(), result); - SetPublisherPermissionResult(env, subscribeInfo.GetPermission(), result); - SetPublisherDeviceIdResult(env, subscribeInfo.GetDeviceId(), result); - SetPublisherUserIdResult(env, subscribeInfo.GetUserId(), result); - SetPublisherPriorityResult(env, subscribeInfo.GetPriority(), result); - SetPublisherBundleNameResult(env, subscribeInfo.GetPublisherBundleName(), result); +void SetAsyncCommonEventResult(const std::shared_ptr &subscriber, + std::shared_ptr asyncCommonEventResult) +{ + std::lock_guard lock(subscriberInsMutex); + for (const auto &subscriberInstance : subscriberInstances) { + if (subscriberInstance.first.get() == subscriber.get()) { + subscriberInstances[subscriberInstance.first].commonEventResult = asyncCommonEventResult; + return; + } + } + subscriberInstances[subscriber].commonEventResult = asyncCommonEventResult; + return; } napi_value GetSubscribeInfoSync(napi_env env, napi_callback_info info) @@ -1060,7 +1158,7 @@ napi_value GetSubscribeInfoSync(napi_env env, napi_callback_info info) napi_value IsOrderedCommonEventSync(napi_env env, napi_callback_info info) { - EVENT_LOGD("isOrderedCommonEventSync start"); + EVENT_LOGI("isOrderedCommonEventSync start"); size_t argc = 0; napi_value thisVar = nullptr; @@ -1088,7 +1186,7 @@ napi_value IsOrderedCommonEventSync(napi_env env, napi_callback_info info) napi_value GetCodeSync(napi_env env, napi_callback_info info) { - EVENT_LOGD("getCodeSync start"); + EVENT_LOGI("getCodeSync start"); size_t argc = 1; napi_value thisVar = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, &thisVar, NULL));