From 12d3aaad37f1056e6a4bbbc3757e28901e7e9356 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Tue, 8 Jul 2025 22:45:48 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Wang --- frameworks/extension/BUILD.gn | 20 +- .../include/ani_common_event_utils.h | 39 ++ .../include/ani_static_subscriber_extension.h | 77 +++ .../ani_static_subscriber_extension_context.h | 37 ++ .../include/static_subscriber_stub_impl.h | 7 +- .../extension/src/ani_common_event_utils.cpp | 131 +++++ .../src/ani_static_subscriber_extension.cpp | 233 ++++++++ ...ni_static_subscriber_extension_context.cpp | 162 ++++++ .../src/static_subscriber_extension.cpp | 3 + .../static_subscriber_stub_imp_test.cpp | 5 +- interfaces/kits/ani/BUILD.gn | 2 + interfaces/kits/ani/common_event/BUILD.gn | 31 ++ ...ation.StaticSubscriberExtensionAbility.ets | 26 + ...ation.StaticSubscriberExtensionContext.ets | 52 ++ .../ets/@ohos.commonEventManager.ets | 357 +++++++++++- .../commonEvent/commonEventSubscribeInfo.ets | 9 + .../ets/commonEvent/commonEventSubscriber.ets | 470 +++++++++++++++- .../common_event/include/ani_common_event.h | 3 + .../include/ani_common_event_utils.h | 9 + .../ani/common_event/src/ani_common_event.cpp | 516 ++++++++++++++++-- .../src/ani_common_event_utils.cpp | 193 ++++++- 21 files changed, 2301 insertions(+), 81 deletions(-) create mode 100644 frameworks/extension/include/ani_common_event_utils.h create mode 100644 frameworks/extension/include/ani_static_subscriber_extension.h create mode 100644 frameworks/extension/include/ani_static_subscriber_extension_context.h create mode 100644 frameworks/extension/src/ani_common_event_utils.cpp create mode 100644 frameworks/extension/src/ani_static_subscriber_extension.cpp create mode 100644 frameworks/extension/src/ani_static_subscriber_extension_context.cpp create mode 100644 interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets create mode 100644 interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets diff --git a/frameworks/extension/BUILD.gn b/frameworks/extension/BUILD.gn index 220a2421..1bf63cbd 100644 --- a/frameworks/extension/BUILD.gn +++ b/frameworks/extension/BUILD.gn @@ -80,9 +80,15 @@ ohos_shared_library("static_subscriber_extension") { } branch_protector_ret = "pac_ret" - include_dirs = [] + include_dirs = [ + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + ] sources = [ + "${ces_extension_path}/src/ani_common_event_utils.cpp", + "${ces_extension_path}/src/ani_static_subscriber_extension.cpp", + "${ces_extension_path}/src/ani_static_subscriber_extension_context.cpp", "${ces_extension_path}/src/js_static_subscriber_extension.cpp", "${ces_extension_path}/src/js_static_subscriber_extension_context.cpp", "${ces_extension_path}/src/static_subscriber_extension.cpp", @@ -102,6 +108,7 @@ 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", @@ -112,8 +119,8 @@ ohos_shared_library("static_subscriber_extension") { "eventhandler:libeventhandler", "hilog:libhilog", "ipc:ipc_core", - "ipc:ipc_napi", "napi:ace_napi", + "runtime_core:ani", ] subsystem_name = "notification" @@ -137,7 +144,13 @@ ohos_shared_library("static_subscriber_extension_module") { } branch_protector_ret = "pac_ret" - include_dirs = [ "${ces_core_path}/include" ] + include_dirs = [ + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${ability_runtime_services_path}/common/include", + "${ces_core_path}/include", + ] sources = [ "${ces_extension_path}/src/loader/static_subscriber_extension_module_loader.cpp" ] @@ -157,7 +170,6 @@ ohos_shared_library("static_subscriber_extension_module") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", - "ipc:ipc_napi", "napi:ace_napi", ] diff --git a/frameworks/extension/include/ani_common_event_utils.h b/frameworks/extension/include/ani_common_event_utils.h new file mode 100644 index 00000000..2781a935 --- /dev/null +++ b/frameworks/extension/include/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_static_subscriber_extension.h b/frameworks/extension/include/ani_static_subscriber_extension.h new file mode 100644 index 00000000..ec70b94c --- /dev/null +++ b/frameworks/extension/include/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 "ani_static_subscriber_extension_context.h" +#include "ability_handler.h" +#include "common_event_data.h" +#include "common_event_manager.h" +#include "static_subscriber_extension.h" +#include "static_subscriber_extension_context.h" +#include "sts_runtime.h" + +class STSNativeReference; + +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::STSRuntime &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); + ani_object CreateSTSContext(ani_env *env, std::shared_ptr context, + const std::shared_ptr &application); + std::map> contentSessions_; + AbilityRuntime::STSRuntime& 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_static_subscriber_extension_context.h b/frameworks/extension/include/ani_static_subscriber_extension_context.h new file mode 100644 index 00000000..61294bc7 --- /dev/null +++ b/frameworks/extension/include/ani_static_subscriber_extension_context.h @@ -0,0 +1,37 @@ +/* + * 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; + +ani_object CreateStaticSubscriberExtensionContext(ani_env *env, + std::shared_ptr context, + const std::shared_ptr &application); +} // 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/static_subscriber_stub_impl.h b/frameworks/extension/include/static_subscriber_stub_impl.h index 0de820ee..d7f1d51a 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_common_event_utils.cpp b/frameworks/extension/src/ani_common_event_utils.cpp new file mode 100644 index 00000000..12f267d5 --- /dev/null +++ b/frameworks/extension/src/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_static_subscriber_extension.cpp b/frameworks/extension/src/ani_static_subscriber_extension.cpp new file mode 100644 index 00000000..b692af0b --- /dev/null +++ b/frameworks/extension/src/ani_static_subscriber_extension.cpp @@ -0,0 +1,233 @@ +/* + * 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 "ani_common_want.h" +#include "ani_common_event_utils.h" +#include "application_context.h" +#include "context.h" +#include "connection_manager.h" +#include "event_log_wrapper.h" +#include "static_subscriber_stub_impl.h" + +namespace OHOS { +namespace EventManagerFwkAni { +using namespace OHOS::AppExecFwk; +using namespace OHOS::AbilityRuntime; +using namespace OHOS::EventFwk; +using namespace OHOS::EventManagerFwkAni; + +StsStaticSubscriberExtension* StsStaticSubscriberExtension::Create(const std::unique_ptr& runtime) +{ + return new StsStaticSubscriberExtension(static_cast(*runtime)); +} +StsStaticSubscriberExtension::StsStaticSubscriberExtension(STSRuntime &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; +} + +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 = CreateSTSContext(env, context, application); + 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"); + ResetEnv(env); + } +} + +ani_object StsStaticSubscriberExtension::CreateSTSContext(ani_env* env, + std::shared_ptr context, + const std::shared_ptr &application) +{ + ani_object STSContext = CreateStaticSubscriberExtensionContext(env, context, application); + return STSContext; +} + +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_static_subscriber_extension_context.cpp b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp new file mode 100644 index 00000000..3c227698 --- /dev/null +++ b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp @@ -0,0 +1,162 @@ +/* + * 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 "ets_extension_context.h" +#include "event_log_wrapper.h" +#include "native_engine/native_engine.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace EventManagerFwkAni { +namespace { +using namespace OHOS::EventFwk; +using namespace OHOS::AbilityRuntime; + +class StsStaticSubscriberExtensionContext final { +public: + static StsStaticSubscriberExtensionContext& GetInstance() + { + static StsStaticSubscriberExtensionContext instance; + return instance; + } + + void StartAbilityInner([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call); + static StaticSubscriberExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); + +private: + explicit StsStaticSubscriberExtensionContext() = default; + ~StsStaticSubscriberExtensionContext() = default; +}; + +constexpr const char* STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME = + "L@ohos/application/StaticSubscriberExtensionContext/StaticSubscriberExtensionContext;"; +} + +static void StartAbility([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call) +{ + EVENT_LOGD("StartAbility"); + StsStaticSubscriberExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, call); +} + +void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call) +{ + EVENT_LOGD("StartAbilityInner"); + AAFwk::Want want; + ani_object aniObject = nullptr; + ErrCode innerErrCode = ERR_OK; + if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { + EVENT_LOGE("UnwrapWant filed"); + aniObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + auto context = StsStaticSubscriberExtensionContext::GetAbilityContext(env, aniObj); + if (context == nullptr) { + EVENT_LOGE("GetAbilityContext is nullptr"); + innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + aniObject = CreateStsError(env, static_cast(innerErrCode)); + AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + return; + } + innerErrCode = context->StartAbility(want); +} + +StaticSubscriberExtensionContext* StsStaticSubscriberExtensionContext::GetAbilityContext(ani_env *env, ani_object obj) +{ + EVENT_LOGD("GetAbilityContext"); + ani_class cls = nullptr; + ani_long nativeContextLong; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + EVENT_LOGD("null env"); + return nullptr; + } + if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + EVENT_LOGD("GetAbilityContext find class status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeStaticSubscriberExtensionContext", &contextField)) != ANI_OK) { + EVENT_LOGD("GetAbilityContext find field status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { + EVENT_LOGD("GetAbilityContext get filed status: %{public}d", status); + return nullptr; + } + return (StaticSubscriberExtensionContext*)nativeContextLong; +} + +ani_object CreateStaticSubscriberExtensionContext(ani_env *env, + std::shared_ptr context, + const std::shared_ptr &application) +{ + if (env == nullptr) { + EVENT_LOGE("null env"); + return nullptr; + } + std::shared_ptr abilityInfo = nullptr; + if (context) { + abilityInfo = context->GetAbilityInfo(); + } + ani_class cls = nullptr; + ani_object contextObj = nullptr; + ani_field field = nullptr; + ani_method method = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + EVENT_LOGE("find class status : %{public}d", status); + return nullptr; + } + std::array functions = { + ani_native_function { "nativeStartAbilitySync", "L@ohos/app/ability/Want/Want;:V", + reinterpret_cast(StartAbility) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + EVENT_LOGE("bind method status : %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + EVENT_LOGE("find Method status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + EVENT_LOGE("new Object status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeStaticSubscriberExtensionContext", &field)) != ANI_OK) { + EVENT_LOGE("find field status: %{public}d", status); + return nullptr; + } + ani_long nativeContextLong = (ani_long)context.get(); + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + EVENT_LOGE("set field status: %{public}d", status); + return nullptr; + } + if (application == nullptr) { + EVENT_LOGE("application null"); + return nullptr; + } + OHOS::AbilityRuntime::CreatEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} +} // EventManagerFwkAni +} // OHOS \ No newline at end of file diff --git a/frameworks/extension/src/static_subscriber_extension.cpp b/frameworks/extension/src/static_subscriber_extension.cpp index 1263419c..fb8fb7b5 100644 --- a/frameworks/extension/src/static_subscriber_extension.cpp +++ b/frameworks/extension/src/static_subscriber_extension.cpp @@ -15,6 +15,7 @@ #include "static_subscriber_extension.h" +#include "ani_static_subscriber_extension.h" #include "event_log_wrapper.h" #include "js_static_subscriber_extension.h" #include "runtime.h" @@ -33,6 +34,8 @@ StaticSubscriberExtension* StaticSubscriberExtension::Create(const std::unique_p switch (runtime->GetLanguage()) { case AbilityRuntime::Runtime::Language::JS: return JsStaticSubscriberExtension::Create(runtime); + case AbilityRuntime::Runtime::Language::STS: + return EventManagerFwkAni::StsStaticSubscriberExtension::Create(runtime); default: return new (std::nothrow) StaticSubscriberExtension(); } 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 b20ba208..f82b4666 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/interfaces/kits/ani/BUILD.gn b/interfaces/kits/ani/BUILD.gn index e1e037fa..a2f1cf5f 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_context_abc_etc", + "${interfaces_path}/kits/ani/common_event:static_subscriber_extension_ability_abc_etc", ] } diff --git a/interfaces/kits/ani/common_event/BUILD.gn b/interfaces/kits/ani/common_event/BUILD.gn index 50df3f17..b51bfc2d 100644 --- a/interfaces/kits/ani/common_event/BUILD.gn +++ b/interfaces/kits/ani/common_event/BUILD.gn @@ -63,6 +63,7 @@ ohos_shared_library("ani_commoneventmanager") { external_deps = [ "ability_base:want", + "ability_runtime:ani_common", "c_utils:utils", "hilog:libhilog", "runtime_core:ani", @@ -146,3 +147,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 00000000..6dc94e0e --- /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 = {} as 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 00000000..6fec4793 --- /dev/null +++ b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets @@ -0,0 +1,52 @@ +/* + * 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'; + +type ResolveCallback = (data: T) => void; +type RejectCallback = (err: Error) => void; + +loadLibrary("ani_commoneventmanager.z"); +export class StaticSubscriberExtensionContext extends ExtensionContext { + nativeStaticSubscriberExtensionContext: long = 0; + native nativeStartAbilitySync(want: Want): void; + + 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; + } +} \ 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 30688c11..c03eb615 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -21,14 +21,26 @@ 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: Error) => 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 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,8 +48,12 @@ 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); + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } }, (err:Object): void => { hilog.error(0x0000, TAG, 'publish error.'); }); @@ -49,13 +65,50 @@ 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); + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } }, (err:Object): void => { hilog.error(0x0000, TAG, 'publish with option error.'); }); } + 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); + } + }, (err:Object): void => { + hilog.error(0xD001202, TAG, 'publishAsUser error.'); + }); + } + + 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); + } + }, (err:Object): void => { + hilog.error(0xD001202, TAG, 'publishAsUser with option error.'); + }); + } + export function createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback): void { hilog.info(0x0000, TAG, 'createSubscriber callback call.'); @@ -63,8 +116,7 @@ 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); + callback(null, result); }, (err:Object): void => { hilog.error(0x0000, TAG, 'createSubscriber error.'); }); @@ -72,14 +124,13 @@ namespace commonEventManager { 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) => { + let p = new Promise((resolve: (v: CommonEventSubscriber) => 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'); }); }); @@ -113,26 +164,302 @@ namespace commonEventManager { 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); + let resultCode: Int = e as Int; + if (resultCode == 0) { + callback(null, undefined); + } else { + let r: BusinessError = { code: resultCode.intValue(), data: undefined }; + callback(r, undefined); + } } }, (err:Object): void => { hilog.error(0x0000, TAG, 'unsubscribe error'); }); } + export function removeStickyCommonEvent(event: string, callback: AsyncCallback): void { + if (event == undefined) { + throw errorParamInvalid; + } + let task = taskpool.execute(commonEventManager.removeStickyCommonEventExecute, event); + task.then((e: NullishType)=>{ + callback(null, 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((data: NullishType): void => { + resolve(undefined); + }, (error: Error): 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)=>{ + callback(null, 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 => { + resolve(undefined); + }, (error: Error): 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 => { + resolve(undefined); + }, (error: Error): 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 1f6d0914..77b8886e 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 fa4607b2..5590d1ab 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets @@ -13,14 +13,480 @@ * 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")} + public native 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; + + 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 4c6b5b13..cb266d94 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event.h @@ -32,6 +32,7 @@ public: void SetEnv(ani_env* env); void SetVm(ani_vm* etsVm); void SetCallback(const ani_object& callback); + ani_object GetCallback(); void ClearEnv(); private: @@ -58,6 +59,8 @@ struct subscriberInstanceInfo { std::shared_ptr commonEventResult = nullptr; }; +std::shared_ptr GetSubscriber(ani_env* env, ani_ref subscribeRef); +std::shared_ptr GetAsyncCommonEventResult (ani_env* env, ani_ref subscribeRef); std::shared_ptr GetSubscriberByWrapper(SubscriberInstanceWrapper* wrapper); } // namespace EventManagerFwkAni 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 0a4002e1..b24e577a 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 13dda4b7..50acba51 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -16,6 +16,7 @@ #include "ani_common_event.h" #include "ani_common_event_utils.h" +#include "ces_inner_error_code.h" #include "event_log_wrapper.h" namespace OHOS { namespace EventManagerFwkAni { @@ -53,62 +54,92 @@ 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 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; +} + 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 ret = ANI_OK; auto wrapper = new (std::nothrow) SubscriberInstanceWrapper(subscribeInfo); + if (wrapper == nullptr) { + return nullptr; + } ani_class cls; ret = env->FindClass("LcommonEvent/commonEventSubscriber/CommonEventSubscriberInner;", &cls); if (ret != ANI_OK) { EVENT_LOGE("createSubscriberExecute FindClass error. result: %{public}d.", ret); + delete wrapper; + wrapper = nullptr; 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); + delete wrapper; + wrapper = nullptr; return nullptr; } ani_object subscriberObj; - ret = env->Object_New(cls, ctor, &subscriberObj); + ret = env->Object_New(cls, ctor, &subscriberObj, reinterpret_cast(wrapper)); if (ret != ANI_OK) { EVENT_LOGE("createSubscriberExecute Object_New error. result: %{public}d.", ret); + delete wrapper; + wrapper = nullptr; return nullptr; } - 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); - 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); - return nullptr; - } EVENT_LOGI("createSubscriberExecute end."); - return resultRef; + return subscriberObj; } static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object callback) @@ -156,11 +187,36 @@ static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object } subscriberInstance->SetVm(etsVm); auto result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); - + if (result == ANI_OK) { + EVENT_LOGD("result is ANI_OK"); + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); + } else { + subscriberInstance = nullptr; + } EVENT_LOGI("subscribeExecute result: %{public}d.", result); return result; } +static int32_t removeSubscriberInstance(ani_env* env, SubscriberInstanceWrapper* wrapper) +{ + int32_t result = ERR_OK; + std::lock_guard lock(subscriberInsMutex); + for (auto iter = subscriberInstances.begin(); iter != subscriberInstances.end();) { + if (iter->first.get() == wrapper->GetSubscriber().get()) { + result = CommonEventManager::NewUnSubscribeCommonEvent(iter->first); + ani_ref callbackRef = static_cast(iter->first->GetCallback()); + if (result == ANI_OK && callbackRef != nullptr) { + env->GlobalReference_Delete(callbackRef); + } + iter = subscriberInstances.erase(iter); + } else { + ++iter; + } + } + return result; +} + static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) { EVENT_LOGI("unsubscribeExecute call."); @@ -186,11 +242,78 @@ static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) EVENT_LOGE("subscriberInstance is null."); return ANI_INVALID_ARGS; } - auto result = CommonEventManager::NewUnSubscribeCommonEvent(subscriberInstance); + auto result = removeSubscriberInstance(env, wrapper); EVENT_LOGI("unsubscribeExecute result: %{public}d.", result); 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 {}; + 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); + return nullptr; + } + + SubscriberInstanceWrapper* wrapper = nullptr; + wrapper = reinterpret_cast(wrapper_long); + if (wrapper == nullptr) { + EVENT_LOGE("unsubscribeExecute wrapper is null."); + return nullptr; + } + return GetSubscriberByWrapper(wrapper); +} + std::shared_ptr GetSubscriberByWrapper(SubscriberInstanceWrapper* wrapper) { if (wrapper->GetSubscriber() == nullptr) { @@ -215,6 +338,9 @@ SubscriberInstance::SubscriberInstance(const CommonEventSubscribeInfo& sp) : Com SubscriberInstance::~SubscriberInstance() { EVENT_LOGI("destroy SubscriberInstance"); + if (env_ != nullptr && callback_ != nullptr) { + env_->GlobalReference_Delete(callback_); + } } void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) @@ -231,13 +357,13 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) } 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 +373,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; @@ -259,13 +385,6 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) 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; } } @@ -293,6 +412,12 @@ void SubscriberInstance::SetCallback(const ani_object& callback) callback_ = callback; } +ani_object SubscriberInstance::GetCallback() +{ + std::lock_guard lockRef(callbackMutex_); + return callback_; +} + void SubscriberInstance::ClearEnv() { EVENT_LOGD("Env expired, clear SubscriberInstance env"); @@ -321,30 +446,261 @@ std::shared_ptr SubscriberInstanceWrapper::GetSubscriber() return subscriber; } -extern "C" { -ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) +static void clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) { - 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_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 result = removeSubscriberInstance(env, wrapper); + EVENT_LOGD("clean result: %{public}d.", result); + return; +} - ani_namespace kitNs; - status = env->FindNamespace("L@ohos/commonEventManager/commonEventManager;", &kitNs); - if (status != ANI_OK) { - EVENT_LOGE("Not found L@ohos/commonEventManager/commonEventManager."); - return ANI_INVALID_ARGS; +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; + } + if (subscriberInstances.size() == 0) { + EVENT_LOGE("subscriberInstances is null."); + return nullptr; + } + std::lock_guard lock(subscriberInsMutex); + for (auto subscriberRes : subscriberInstances) { + if (subscriberRes.first.get() == subscriberInstance.get()) { + return subscriberInstances[subscriberRes.first]; + } + } + return nullptr; +} + +static ani_double getCode(ani_env *env, ani_object object) +{ + EVENT_LOGD("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_status init(ani_env *env, ani_namespace kitNs) +{ + ani_status status = ANI_ERROR; 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 { "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;", @@ -353,6 +709,12 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) "subscribeExecute", nullptr, reinterpret_cast(OHOS::EventManagerFwkAni::subscribeExecute) }, 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) }, }; status = env->Namespace_BindNativeFunctions(kitNs, methods.data(), methods.size()); @@ -360,7 +722,59 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) EVENT_LOGE("Cannot bind native methods to L@ohos/event/common_event_manager/commonEventManager"); return ANI_INVALID_TYPE; } + return status; +} +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_namespace kitNs; + status = env->FindNamespace("L@ohos/commonEventManager/commonEventManager;", &kitNs); + if (status != ANI_OK) { + EVENT_LOGE("Not found L@ohos/commonEventManager/commonEventManager."); + return ANI_INVALID_ARGS; + } + status = init(env, kitNs); + if (status != ANI_OK) { + 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; + } + + 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; + } *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 496552f9..e683d11d 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 -- Gitee From a12cbb8f958904a6dd5b9ce18d28a07620759a3d Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Tue, 8 Jul 2025 22:51:48 +0800 Subject: [PATCH 02/14] modify Signed-off-by: Michael Wang --- .../@ohos.application.StaticSubscriberExtensionAbility.ets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets index 6dc94e0e..fce78ebf 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets @@ -18,9 +18,9 @@ import StaticSubscriberExtensionContext from '@ohos.application.StaticSubscriber export default class StaticSubscriberExtensionAbility { - context: StaticSubscriberExtensionContext = {} as StaticSubscriberExtensionContext; + context: StaticSubscriberExtensionContext = {}; onReceiveEvent(event: CommonEventData): void { console.log("StsonReceiveEvent, event:" + event.code); } -} \ No newline at end of file +} -- Gitee From fdd0c880fd8f345f3958efc0bb78440d86491545 Mon Sep 17 00:00:00 2001 From: Martin Sajti Date: Mon, 19 May 2025 15:53:33 +0200 Subject: [PATCH 03/14] Fix invlid code after primitive type refactor Change-Id: I0615ceabceb8503b09b036dbbb595fe63eda1bc7 Signed-off-by: Martin Sajti --- .../kits/ani/common_event/ets/@ohos.commonEventManager.ets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets index 30688c11..8b321008 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -73,13 +73,13 @@ namespace commonEventManager { 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'); }); }); -- Gitee From 0151e2ec47111ffd0db24ec157cd3f4d44613eef Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 10 Jul 2025 10:04:25 +0800 Subject: [PATCH 04/14] modify Signed-off-by: Michael Wang --- frameworks/extension/BUILD.gn | 1 + ...ni_static_subscriber_extension_context.cpp | 22 +++++++++---------- .../static_subscriber_proxy_test/BUILD.gn | 0 .../static_subscriber_stub_imp_test/BUILD.gn | 0 .../test/static_subscriber_stub_test/BUILD.gn | 0 interfaces/kits/ani/BUILD.gn | 2 +- .../ets/@ohos.commonEventManager.ets | 14 +++++++----- 7 files changed, 22 insertions(+), 17 deletions(-) mode change 100755 => 100644 frameworks/extension/test/static_subscriber_proxy_test/BUILD.gn mode change 100755 => 100644 frameworks/extension/test/static_subscriber_stub_imp_test/BUILD.gn mode change 100755 => 100644 frameworks/extension/test/static_subscriber_stub_test/BUILD.gn diff --git a/frameworks/extension/BUILD.gn b/frameworks/extension/BUILD.gn index 1bf63cbd..a1fa17aa 100644 --- a/frameworks/extension/BUILD.gn +++ b/frameworks/extension/BUILD.gn @@ -83,6 +83,7 @@ ohos_shared_library("static_subscriber_extension") { include_dirs = [ "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "${interfaces_path}/kits/ani/common_event/include", ] sources = [ diff --git a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp index 3c227698..88a52735 100644 --- a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp +++ b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp @@ -36,7 +36,7 @@ public: } void StartAbilityInner([[maybe_unused]] ani_env *env, - [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call); + [[maybe_unused]] ani_object aniObj, ani_object wantObj); static StaticSubscriberExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); private: @@ -49,34 +49,34 @@ constexpr const char* STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME = } static void StartAbility([[maybe_unused]] ani_env *env, - [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call) + [[maybe_unused]] ani_object aniObj, ani_object wantObj) { EVENT_LOGD("StartAbility"); - StsStaticSubscriberExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj, call); + StsStaticSubscriberExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj); } void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, - [[maybe_unused]] ani_object aniObj, ani_object wantObj, ani_object call) + [[maybe_unused]] ani_object aniObj, ani_object wantObj) { EVENT_LOGD("StartAbilityInner"); AAFwk::Want want; - ani_object aniObject = nullptr; ErrCode innerErrCode = ERR_OK; if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { EVENT_LOGE("UnwrapWant filed"); - aniObject = CreateStsInvalidParamError(env, "UnwrapWant filed"); - AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); return; } auto context = StsStaticSubscriberExtensionContext::GetAbilityContext(env, aniObj); if (context == nullptr) { EVENT_LOGE("GetAbilityContext is nullptr"); - innerErrCode = static_cast(AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); - aniObject = CreateStsError(env, static_cast(innerErrCode)); - AppExecFwk::AsyncCallback(env, call, aniObject, nullptr); + ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); return; } - innerErrCode = context->StartAbility(want); + innerErrCode = context->StartAbility(want); + if (innerErrCode != ERR_OK) { + EVENT_LOGE("StartAbility failed, code = %{public}d", innerErrCode); + ThrowStsErrorByNativeErr(env, innerErrCode); + } } StaticSubscriberExtensionContext* StsStaticSubscriberExtensionContext::GetAbilityContext(ani_env *env, ani_object obj) 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_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 a2f1cf5f..effea0b8 100644 --- a/interfaces/kits/ani/BUILD.gn +++ b/interfaces/kits/ani/BUILD.gn @@ -22,7 +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_context_abc_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/ets/@ohos.commonEventManager.ets b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets index c03eb615..f15a2695 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -149,12 +149,13 @@ 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); }); } @@ -165,7 +166,6 @@ namespace commonEventManager { let resultCode: Int = e as Int; hilog.info(0x0000, TAG, 'unsubscribe result:%{public}d.', resultCode.intValue()); if (callback != undefined) { - let resultCode: Int = e as Int; if (resultCode == 0) { callback(null, undefined); } else { @@ -173,8 +173,12 @@ namespace commonEventManager { 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); + } }); } -- Gitee From 58016a25a89dabbed4a5d46c805f99c137648734 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 10 Jul 2025 21:55:06 +0800 Subject: [PATCH 05/14] modify Signed-off-by: Michael Wang --- frameworks/extension/BUILD.gn | 8 ++------ .../include/ani_static_subscriber_extension.h | 16 +++++++++------- .../src/ani_static_subscriber_extension.cpp | 9 +++++++-- .../ani_static_subscriber_extension_context.cpp | 13 ++++++++----- .../src/static_subscriber_extension.cpp | 2 +- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/frameworks/extension/BUILD.gn b/frameworks/extension/BUILD.gn index a1fa17aa..dc03aa25 100644 --- a/frameworks/extension/BUILD.gn +++ b/frameworks/extension/BUILD.gn @@ -81,8 +81,6 @@ ohos_shared_library("static_subscriber_extension") { branch_protector_ret = "pac_ret" include_dirs = [ - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", "${interfaces_path}/kits/ani/common_event/include", ] @@ -120,6 +118,7 @@ ohos_shared_library("static_subscriber_extension") { "eventhandler:libeventhandler", "hilog:libhilog", "ipc:ipc_core", + "ipc:ipc_napi", "napi:ace_napi", "runtime_core:ani", ] @@ -146,10 +145,6 @@ ohos_shared_library("static_subscriber_extension_module") { branch_protector_ret = "pac_ret" include_dirs = [ - "${ability_runtime_path}/interfaces/kits/native/ability/native", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime", - "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", - "${ability_runtime_services_path}/common/include", "${ces_core_path}/include", ] @@ -171,6 +166,7 @@ ohos_shared_library("static_subscriber_extension_module") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "ipc:ipc_napi", "napi:ace_napi", ] diff --git a/frameworks/extension/include/ani_static_subscriber_extension.h b/frameworks/extension/include/ani_static_subscriber_extension.h index ec70b94c..6958dd61 100644 --- a/frameworks/extension/include/ani_static_subscriber_extension.h +++ b/frameworks/extension/include/ani_static_subscriber_extension.h @@ -18,16 +18,19 @@ #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 "sts_runtime.h" - -class STSNativeReference; +#include "ets_runtime.h" +#include "ets_native_reference.h" namespace OHOS { namespace EventManagerFwkAni { @@ -38,7 +41,7 @@ using CommonEventData = OHOS::EventFwk::CommonEventData; class StsStaticSubscriberExtension : public StaticSubscriberExtension { public: - explicit StsStaticSubscriberExtension(AbilityRuntime::STSRuntime &stsRuntime); + explicit StsStaticSubscriberExtension(AbilityRuntime::ETSRuntime &stsRuntime); virtual ~StsStaticSubscriberExtension() override; static StsStaticSubscriberExtension* Create(const std::unique_ptr& stsRuntime); @@ -68,9 +71,8 @@ private: void BindContext(ani_env *env, const std::shared_ptr &application); ani_object CreateSTSContext(ani_env *env, std::shared_ptr context, const std::shared_ptr &application); - std::map> contentSessions_; - AbilityRuntime::STSRuntime& stsRuntime_; - std::unique_ptr stsObj_; + AbilityRuntime::ETSRuntime& stsRuntime_; + std::unique_ptr stsObj_; }; } // namespace EventManagerFwkAni } // namespace OHOS diff --git a/frameworks/extension/src/ani_static_subscriber_extension.cpp b/frameworks/extension/src/ani_static_subscriber_extension.cpp index b692af0b..2ad15a9b 100644 --- a/frameworks/extension/src/ani_static_subscriber_extension.cpp +++ b/frameworks/extension/src/ani_static_subscriber_extension.cpp @@ -15,12 +15,17 @@ #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 "native_engine/native_engine.h" +#include "ets_runtime.h" #include "static_subscriber_stub_impl.h" namespace OHOS { @@ -32,9 +37,9 @@ using namespace OHOS::EventManagerFwkAni; StsStaticSubscriberExtension* StsStaticSubscriberExtension::Create(const std::unique_ptr& runtime) { - return new StsStaticSubscriberExtension(static_cast(*runtime)); + return new StsStaticSubscriberExtension(static_cast(*runtime)); } -StsStaticSubscriberExtension::StsStaticSubscriberExtension(STSRuntime &stsRuntime) : stsRuntime_(stsRuntime) {} +StsStaticSubscriberExtension::StsStaticSubscriberExtension(ETSRuntime &stsRuntime) : stsRuntime_(stsRuntime) {} StsStaticSubscriberExtension::~StsStaticSubscriberExtension() { EVENT_LOGD("~StsStaticSubscriberExtension called"); diff --git a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp index 88a52735..c43198fd 100644 --- a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp +++ b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp @@ -15,11 +15,14 @@ #include "ani_static_subscriber_extension_context.h" #include "ability_manager_client.h" +#include "ani_common_event_throw_error.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" -#include "sts_error_utils.h" + namespace OHOS { namespace EventManagerFwkAni { @@ -63,19 +66,19 @@ void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani ErrCode innerErrCode = ERR_OK; if (!AppExecFwk::UnwrapWant(env, wantObj, want)) { EVENT_LOGE("UnwrapWant filed"); - ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); return; } auto context = StsStaticSubscriberExtensionContext::GetAbilityContext(env, aniObj); if (context == nullptr) { EVENT_LOGE("GetAbilityContext is nullptr"); - ThrowStsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + 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); - ThrowStsErrorByNativeErr(env, innerErrCode); + EtsErrorUtil::ThrowErrorByNativeErr(env, innerErrCode); } } @@ -155,7 +158,7 @@ ani_object CreateStaticSubscriberExtensionContext(ani_env *env, EVENT_LOGE("application null"); return nullptr; } - OHOS::AbilityRuntime::CreatEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); return contextObj; } } // EventManagerFwkAni diff --git a/frameworks/extension/src/static_subscriber_extension.cpp b/frameworks/extension/src/static_subscriber_extension.cpp index fb8fb7b5..63df0b88 100644 --- a/frameworks/extension/src/static_subscriber_extension.cpp +++ b/frameworks/extension/src/static_subscriber_extension.cpp @@ -34,7 +34,7 @@ StaticSubscriberExtension* StaticSubscriberExtension::Create(const std::unique_p switch (runtime->GetLanguage()) { case AbilityRuntime::Runtime::Language::JS: return JsStaticSubscriberExtension::Create(runtime); - case AbilityRuntime::Runtime::Language::STS: + case AbilityRuntime::Runtime::Language::ETS: return EventManagerFwkAni::StsStaticSubscriberExtension::Create(runtime); default: return new (std::nothrow) StaticSubscriberExtension(); -- Gitee From 656e7c1146990f702634081760553cc80c35adcc Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 10 Jul 2025 22:07:12 +0800 Subject: [PATCH 06/14] modify Signed-off-by: Michael Wang --- .../extension/src/ani_static_subscriber_extension_context.cpp | 1 - interfaces/kits/ani/common_event/BUILD.gn | 2 ++ .../kits/ani/common_event/ets/commonEvent/commonEventData.ets | 2 +- .../ani/common_event/ets/commonEvent/commonEventSubscriber.ets | 3 +-- interfaces/kits/ani/common_event/src/ani_common_event.cpp | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp index c43198fd..9a78244c 100644 --- a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp +++ b/frameworks/extension/src/ani_static_subscriber_extension_context.cpp @@ -15,7 +15,6 @@ #include "ani_static_subscriber_extension_context.h" #include "ability_manager_client.h" -#include "ani_common_event_throw_error.h" #include "ani_common_want.h" #include "ani_common_start_options.h" #include "ets_error_utils.h" diff --git a/interfaces/kits/ani/common_event/BUILD.gn b/interfaces/kits/ani/common_event/BUILD.gn index b51bfc2d..fb0af135 100644 --- a/interfaces/kits/ani/common_event/BUILD.gn +++ b/interfaces/kits/ani/common_event/BUILD.gn @@ -64,8 +64,10 @@ ohos_shared_library("ani_commoneventmanager") { external_deps = [ "ability_base:want", "ability_runtime:ani_common", + "ability_runtime:runtime", "c_utils:utils", "hilog:libhilog", + "napi:ace_napi", "runtime_core:ani", ] diff --git a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets index 7b09c843..75306dd8 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets @@ -22,7 +22,7 @@ export interface CommonEventData { } class CommonEventDataImpl implements CommonEventData { - public event: string = ''; + public event: string = ""; public bundleName?: string | undefined; public code?: number | undefined; public data?: string | undefined; diff --git a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets index 5590d1ab..b2677323 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets @@ -36,7 +36,6 @@ 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; @@ -76,7 +75,7 @@ export interface CommonEventSubscriber { class CommonEventSubscriberInner implements CommonEventSubscriber { static {loadLibrary("ani_commoneventmanager.z")} - public native subscriberInstanceWrapper: long = 0; + private subscriberInstanceWrapper: long = 0; public native nativeGetCode(): number; public native nativeSetCode(code: int): int; 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 50acba51..19625f3e 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -18,6 +18,7 @@ #include "ani_common_event_utils.h" #include "ces_inner_error_code.h" #include "event_log_wrapper.h" + namespace OHOS { namespace EventManagerFwkAni { -- Gitee From e03d343a6d67ff0f582ec759f6dc887ecdb98b45 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 10 Jul 2025 22:15:34 +0800 Subject: [PATCH 07/14] modify Signed-off-by: Michael Wang --- .../kits/ani/common_event/ets/commonEvent/commonEventData.ets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets index 75306dd8..711585e9 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets @@ -22,9 +22,9 @@ export interface CommonEventData { } class CommonEventDataImpl implements CommonEventData { - public event: string = ""; + public event: string = ''; public bundleName?: string | undefined; public code?: number | undefined; public data?: string | undefined; public parameters?: Record | undefined; -} \ No newline at end of file +} -- Gitee From d9ce54ac13418d47f4c6f111edde17201aaaa802 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 10 Jul 2025 23:09:51 +0800 Subject: [PATCH 08/14] modify ets Signed-off-by: Michael Wang --- ...ation.StaticSubscriberExtensionAbility.ets | 2 +- .../ets/@ohos.commonEventManager.ets | 38 ++++++++++++------- .../ets/commonEvent/commonEventData.ets | 2 +- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets index fce78ebf..7ecf2941 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionAbility.ets @@ -23,4 +23,4 @@ export default class StaticSubscriberExtensionAbility { 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.commonEventManager.ets b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets index f15a2695..fc05b504 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -25,7 +25,7 @@ const ERROR_PARAM_INVALID = 401; const errorParamInvalid: BusinessError = {code: ERROR_PARAM_INVALID, data: "Invalid parameter"}; type ResolveCallback = (data: T) => void; -type RejectCallback = (err: Error) => void; +type RejectCallback = (err: Object) => void; namespace commonEventManager { loadLibrary("ani_commoneventmanager.z"); @@ -54,8 +54,10 @@ namespace commonEventManager { let r: BusinessError = { code: resultCode.intValue(), data: undefined }; callback(r, undefined); } - }, (err:Object): void => { + }, (error:Object): void => { hilog.error(0x0000, TAG, 'publish error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } @@ -71,13 +73,15 @@ namespace commonEventManager { let r: BusinessError = { code: resultCode.intValue(), data: undefined }; callback(r, undefined); } - }, (err:Object): void => { + }, (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 publishAsUserId: Int = userId as Int; let task = taskpool.execute(commonEventManager.publishAsUserExecute, event, publishAsUserId); task.then((e: NullishType)=>{ let resultCode: Int = e as Int; @@ -87,8 +91,10 @@ namespace commonEventManager { let r: BusinessError = { code: resultCode.intValue(), data: undefined }; callback(r, undefined); } - }, (err:Object): void => { + }, (error:Object): void => { hilog.error(0xD001202, TAG, 'publishAsUser error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } @@ -104,8 +110,10 @@ namespace commonEventManager { let r: BusinessError = { code: resultCode.intValue(), data: undefined }; callback(r, undefined); } - }, (err:Object): void => { + }, (error:Object): void => { hilog.error(0xD001202, TAG, 'publishAsUser with option error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } @@ -117,8 +125,10 @@ namespace commonEventManager { let result: CommonEventSubscriber = e as CommonEventSubscriber; hilog.info(0x0000, TAG, 'createSubscriber result.'); callback(null, result); - }, (err:Object): void => { + }, (error: Object): void => { hilog.error(0x0000, TAG, 'createSubscriber error.'); + let err: BusinessError = error as BusinessError; + callback(err, undefined); }); } @@ -130,7 +140,7 @@ namespace commonEventManager { hilog.info(0x0000, TAG, 'createSubscriber Promise result.'); let result: CommonEventSubscriber = e as CommonEventSubscriber; resolve(result); - }, (err: Error): void => { + }, (err: Object): void => { hilog.error(0x0000, TAG, 'createSubscriber Promise error'); }); }); @@ -152,7 +162,7 @@ namespace commonEventManager { let r: BusinessError = { code: resultCode.intValue(), data: undefined }; callback(r, undefined); } - }, (error: Object): void => { + }, (error:Object): void => { hilog.error(0x0000, TAG, 'subscribe error'); let err: BusinessError = error as BusinessError; callback(err, undefined); @@ -173,7 +183,7 @@ namespace commonEventManager { callback(r, undefined); } } - }, (error: Object): void => { + }, (error:Object): void => { hilog.error(0x0000, TAG, 'unsubscribe error'); if (callback != undefined) { let err: BusinessError = error as BusinessError; @@ -203,7 +213,7 @@ namespace commonEventManager { let task = taskpool.execute(commonEventManager.removeStickyCommonEventExecute, event); task.then((data: NullishType): void => { resolve(undefined); - }, (error: Error): void => { + }, (error: Object): void => { hilog.error(0xD001202, TAG, 'removeStickyCommonEvent Promise error'); reject(error); }); @@ -226,7 +236,7 @@ namespace commonEventManager { let task = taskpool.execute(commonEventManager.setStaticSubscriberStateExecute, enable); task.then((e: NullishType): void => { resolve(undefined); - }, (error: Error): void => { + }, (error: Object): void => { hilog.error(0xD001202, TAG, 'setStaticSubscriberState Promise error'); reject(error); }); @@ -239,7 +249,7 @@ namespace commonEventManager { let task = taskpool.execute(commonEventManager.setStaticSubscriberStateWithEventsExecute, enable, events); task.then((e: NullishType): void => { resolve(undefined); - }, (error: Error): void => { + }, (error: Object): void => { hilog.error(0xD001202, TAG, 'setStaticSubscriberStateExecute Promise error.'); reject(error); }); @@ -459,7 +469,7 @@ namespace commonEventManager { 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_BUNDLE_RESOURCES_CHANGED = 'usual.event.BUNDLE_RESOURCES_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', diff --git a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets index 711585e9..7b09c843 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventData.ets @@ -27,4 +27,4 @@ class CommonEventDataImpl implements CommonEventData { public code?: number | undefined; public data?: string | undefined; public parameters?: Record | undefined; -} +} \ No newline at end of file -- Gitee From 602b8c84edd998100c65e0f2b777634b6837e27a Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Fri, 11 Jul 2025 11:45:36 +0800 Subject: [PATCH 09/14] add Signed-off-by: Michael Wang --- .../ets/@ohos.commonEventManager.ets | 57 ++++++++++++++----- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets index fc05b504..057229c1 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -198,7 +198,14 @@ namespace commonEventManager { } let task = taskpool.execute(commonEventManager.removeStickyCommonEventExecute, event); task.then((e: NullishType)=>{ - callback(null, undefined); + 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); @@ -211,8 +218,14 @@ namespace commonEventManager { } let p = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { let task = taskpool.execute(commonEventManager.removeStickyCommonEventExecute, event); - task.then((data: NullishType): void => { - resolve(undefined); + 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); @@ -224,7 +237,13 @@ namespace commonEventManager { export function setStaticSubscriberState(enable: boolean, callback: AsyncCallback): void { let task = taskpool.execute(commonEventManager.setStaticSubscriberStateExecute, enable); task.then((e: NullishType)=>{ - callback(null, undefined); + 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); @@ -235,7 +254,13 @@ namespace commonEventManager { let pPromise = new Promise((resolve: ResolveCallback, reject: RejectCallback): void => { let task = taskpool.execute(commonEventManager.setStaticSubscriberStateExecute, enable); task.then((e: NullishType): void => { - resolve(undefined); + 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); @@ -246,16 +271,22 @@ namespace commonEventManager { 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 => { - resolve(undefined); - }, (error: Object): void => { - hilog.error(0xD001202, TAG, 'setStaticSubscriberStateExecute Promise error.'); - reject(error); + 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', -- Gitee From f6994cee7202d4fbc552a961eaec7bfb05c7f2ec Mon Sep 17 00:00:00 2001 From: cheerful_ricky Date: Sun, 29 Jun 2025 11:38:29 +0800 Subject: [PATCH 10/14] add transfer logic Signed-off-by: cheerful_ricky --- frameworks/extension/BUILD.gn | 75 ++- .../{ => ani}/ani_common_event_utils.h | 0 .../ani_static_subscriber_extension.h | 2 - .../ani_static_subscriber_extension_context.h | 21 +- .../js_static_subscriber_extension_context.h | 19 + .../src/{ => ani}/ani_common_event_utils.cpp | 0 .../ani_static_subscriber_extension.cpp | 135 ++++- ...ni_static_subscriber_extension_context.cpp | 103 +--- ...js_static_subscriber_extension_context.cpp | 23 +- ...tic_subscriber_extension_module_loader.cpp | 51 +- .../src/static_subscriber_extension.cpp | 15 +- interfaces/kits/ani/common_event/BUILD.gn | 9 +- ...ation.StaticSubscriberExtensionContext.ets | 73 ++- .../ets/commonEvent/commonEventSubscriber.ets | 10 + .../common_event/include/ani_common_event.h | 38 +- .../ani/common_event/src/ani_common_event.cpp | 521 +++++++++++++----- .../kits/napi/napi_common_event/BUILD.gn | 44 +- .../include/napi_common_event.h | 28 + .../src/common_event_set_param.cpp | 12 + .../src/napi_common_event.cpp | 122 +++- 20 files changed, 994 insertions(+), 307 deletions(-) rename frameworks/extension/include/{ => ani}/ani_common_event_utils.h (100%) rename frameworks/extension/include/{ => ani}/ani_static_subscriber_extension.h (94%) rename frameworks/extension/include/{ => ani}/ani_static_subscriber_extension_context.h (64%) rename frameworks/extension/src/{ => ani}/ani_common_event_utils.cpp (100%) rename frameworks/extension/src/{ => ani}/ani_static_subscriber_extension.cpp (61%) rename frameworks/extension/src/{ => ani}/ani_static_subscriber_extension_context.cpp (48%) diff --git a/frameworks/extension/BUILD.gn b/frameworks/extension/BUILD.gn index dc03aa25..03d2b7bc 100644 --- a/frameworks/extension/BUILD.gn +++ b/frameworks/extension/BUILD.gn @@ -80,14 +80,9 @@ ohos_shared_library("static_subscriber_extension") { } branch_protector_ret = "pac_ret" - include_dirs = [ - "${interfaces_path}/kits/ani/common_event/include", - ] + include_dirs = [] sources = [ - "${ces_extension_path}/src/ani_common_event_utils.cpp", - "${ces_extension_path}/src/ani_static_subscriber_extension.cpp", - "${ces_extension_path}/src/ani_static_subscriber_extension_context.cpp", "${ces_extension_path}/src/js_static_subscriber_extension.cpp", "${ces_extension_path}/src/js_static_subscriber_extension_context.cpp", "${ces_extension_path}/src/static_subscriber_extension.cpp", @@ -103,6 +98,68 @@ ohos_shared_library("static_subscriber_extension") { "${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", + "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", @@ -121,6 +178,7 @@ ohos_shared_library("static_subscriber_extension") { "ipc:ipc_napi", "napi:ace_napi", "runtime_core:ani", + "runtime_core:ani_helpers", ] subsystem_name = "notification" @@ -144,9 +202,7 @@ ohos_shared_library("static_subscriber_extension_module") { } branch_protector_ret = "pac_ret" - include_dirs = [ - "${ces_core_path}/include", - ] + include_dirs = [ "${ces_core_path}/include" ] sources = [ "${ces_extension_path}/src/loader/static_subscriber_extension_module_loader.cpp" ] @@ -178,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_common_event_utils.h b/frameworks/extension/include/ani/ani_common_event_utils.h similarity index 100% rename from frameworks/extension/include/ani_common_event_utils.h rename to frameworks/extension/include/ani/ani_common_event_utils.h diff --git a/frameworks/extension/include/ani_static_subscriber_extension.h b/frameworks/extension/include/ani/ani_static_subscriber_extension.h similarity index 94% rename from frameworks/extension/include/ani_static_subscriber_extension.h rename to frameworks/extension/include/ani/ani_static_subscriber_extension.h index 6958dd61..502f0f1f 100644 --- a/frameworks/extension/include/ani_static_subscriber_extension.h +++ b/frameworks/extension/include/ani/ani_static_subscriber_extension.h @@ -69,8 +69,6 @@ public: private: void BindContext(ani_env *env, const std::shared_ptr &application); - ani_object CreateSTSContext(ani_env *env, std::shared_ptr context, - const std::shared_ptr &application); AbilityRuntime::ETSRuntime& stsRuntime_; std::unique_ptr stsObj_; }; diff --git a/frameworks/extension/include/ani_static_subscriber_extension_context.h b/frameworks/extension/include/ani/ani_static_subscriber_extension_context.h similarity index 64% rename from frameworks/extension/include/ani_static_subscriber_extension_context.h rename to frameworks/extension/include/ani/ani_static_subscriber_extension_context.h index 61294bc7..580433c3 100644 --- a/frameworks/extension/include/ani_static_subscriber_extension_context.h +++ b/frameworks/extension/include/ani/ani_static_subscriber_extension_context.h @@ -28,10 +28,27 @@ 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, - const std::shared_ptr &application); + 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 f0eab5a7..6ac0e3eb 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/src/ani_common_event_utils.cpp b/frameworks/extension/src/ani/ani_common_event_utils.cpp similarity index 100% rename from frameworks/extension/src/ani_common_event_utils.cpp rename to frameworks/extension/src/ani/ani_common_event_utils.cpp diff --git a/frameworks/extension/src/ani_static_subscriber_extension.cpp b/frameworks/extension/src/ani/ani_static_subscriber_extension.cpp similarity index 61% rename from frameworks/extension/src/ani_static_subscriber_extension.cpp rename to frameworks/extension/src/ani/ani_static_subscriber_extension.cpp index 2ad15a9b..2d25b2b7 100644 --- a/frameworks/extension/src/ani_static_subscriber_extension.cpp +++ b/frameworks/extension/src/ani/ani_static_subscriber_extension.cpp @@ -24,10 +24,17 @@ #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; @@ -35,6 +42,12 @@ 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)); @@ -84,6 +97,117 @@ void StsStaticSubscriberExtension::Init(const std::shared_ptrStartAbilityInner(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"); @@ -93,7 +217,7 @@ void StsStaticSubscriberExtension::BindContext(ani_env* env, const std::shared_p return; } - ani_object contextObj = CreateSTSContext(env, context, application); + ani_object contextObj = CreateStaticSubscriberExtensionContext(env, context); if (contextObj == nullptr) { EVENT_LOGE("null contextObj"); return; @@ -113,18 +237,11 @@ void StsStaticSubscriberExtension::BindContext(ani_env* env, const std::shared_p } if (env->Object_SetField_Ref(stsObj_->aniObj, contextField, contextRef) != ANI_OK) { EVENT_LOGE("Object_SetField_Ref contextObj failed"); + env->GlobalReference_Delete(contextRef); ResetEnv(env); } } -ani_object StsStaticSubscriberExtension::CreateSTSContext(ani_env* env, - std::shared_ptr context, - const std::shared_ptr &application) -{ - ani_object STSContext = CreateStaticSubscriberExtensionContext(env, context, application); - return STSContext; -} - std::weak_ptr StsStaticSubscriberExtension::GetWeakPtr() { return std::static_pointer_cast(shared_from_this()); diff --git a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp b/frameworks/extension/src/ani/ani_static_subscriber_extension_context.cpp similarity index 48% rename from frameworks/extension/src/ani_static_subscriber_extension_context.cpp rename to frameworks/extension/src/ani/ani_static_subscriber_extension_context.cpp index 9a78244c..2e330fcf 100644 --- a/frameworks/extension/src/ani_static_subscriber_extension_context.cpp +++ b/frameworks/extension/src/ani/ani_static_subscriber_extension_context.cpp @@ -25,38 +25,8 @@ namespace OHOS { namespace EventManagerFwkAni { -namespace { -using namespace OHOS::EventFwk; using namespace OHOS::AbilityRuntime; -class StsStaticSubscriberExtensionContext final { -public: - static StsStaticSubscriberExtensionContext& GetInstance() - { - static StsStaticSubscriberExtensionContext instance; - return instance; - } - - void StartAbilityInner([[maybe_unused]] ani_env *env, - [[maybe_unused]] ani_object aniObj, ani_object wantObj); - static StaticSubscriberExtensionContext* GetAbilityContext(ani_env *env, ani_object obj); - -private: - explicit StsStaticSubscriberExtensionContext() = default; - ~StsStaticSubscriberExtensionContext() = default; -}; - -constexpr const char* STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME = - "L@ohos/application/StaticSubscriberExtensionContext/StaticSubscriberExtensionContext;"; -} - -static void StartAbility([[maybe_unused]] ani_env *env, - [[maybe_unused]] ani_object aniObj, ani_object wantObj) -{ - EVENT_LOGD("StartAbility"); - StsStaticSubscriberExtensionContext::GetInstance().StartAbilityInner(env, aniObj, wantObj); -} - void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object aniObj, ani_object wantObj) { @@ -68,7 +38,7 @@ void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); return; } - auto context = StsStaticSubscriberExtensionContext::GetAbilityContext(env, aniObj); + auto context = GetAbilityContext(); if (context == nullptr) { EVENT_LOGE("GetAbilityContext is nullptr"); EtsErrorUtil::ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); @@ -81,35 +51,35 @@ void StsStaticSubscriberExtensionContext::StartAbilityInner([[maybe_unused]] ani } } -StaticSubscriberExtensionContext* StsStaticSubscriberExtensionContext::GetAbilityContext(ani_env *env, ani_object obj) +std::shared_ptr StsStaticSubscriberExtensionContext::GetAbilityContext() +{ + return context_.lock(); +} + +StsStaticSubscriberExtensionContext* StsStaticSubscriberExtensionContext::GetAbilityContext(ani_env *env, + ani_object obj) { - EVENT_LOGD("GetAbilityContext"); - ani_class cls = nullptr; ani_long nativeContextLong; - ani_field contextField = nullptr; ani_status status = ANI_ERROR; if (env == nullptr) { EVENT_LOGD("null env"); return nullptr; } - if ((status = env->FindClass(STATIC_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { - EVENT_LOGD("GetAbilityContext find class status: %{public}d", status); - return nullptr; - } - if ((status = env->Class_FindField(cls, "nativeStaticSubscriberExtensionContext", &contextField)) != ANI_OK) { - EVENT_LOGD("GetAbilityContext find field status: %{public}d", status); + + status = env->Object_GetFieldByName_Long(obj, "nativeStaticSubscriberExtensionContext", &nativeContextLong); + if (status != ANI_OK) { + EVENT_LOGE("get property status: %{public}d", status); return nullptr; } - if ((status = env->Object_GetField_Long(obj, contextField, &nativeContextLong)) != ANI_OK) { - EVENT_LOGD("GetAbilityContext get filed status: %{public}d", status); + if (nativeContextLong == 0) { + EVENT_LOGE("nativeContextLong is zero"); return nullptr; } - return (StaticSubscriberExtensionContext*)nativeContextLong; + return reinterpret_cast(nativeContextLong); } ani_object CreateStaticSubscriberExtensionContext(ani_env *env, - std::shared_ptr context, - const std::shared_ptr &application) + std::shared_ptr context) { if (env == nullptr) { EVENT_LOGE("null env"); @@ -119,45 +89,32 @@ ani_object CreateStaticSubscriberExtensionContext(ani_env *env, if (context) { abilityInfo = context->GetAbilityInfo(); } - ani_class cls = nullptr; + auto stsStaticSubscriberExtensionContext = new (std::nothrow) StsStaticSubscriberExtensionContext(context); + if (stsStaticSubscriberExtensionContext == nullptr) { + EVENT_LOGE("null sts context"); + return nullptr; + } ani_object contextObj = nullptr; - ani_field field = nullptr; - ani_method method = 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; } - std::array functions = { - ani_native_function { "nativeStartAbilitySync", "L@ohos/app/ability/Want/Want;:V", - reinterpret_cast(StartAbility) }, - }; - if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { - EVENT_LOGE("bind method status : %{public}d", status); - return nullptr; - } - if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + if ((status = env->Class_FindMethod(cls, "", "J:V", &method)) != ANI_OK) { EVENT_LOGE("find Method status: %{public}d", status); + delete stsStaticSubscriberExtensionContext; return nullptr; } - if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + 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; } - if ((status = env->Class_FindField(cls, "nativeStaticSubscriberExtensionContext", &field)) != ANI_OK) { - EVENT_LOGE("find field status: %{public}d", status); - return nullptr; - } - ani_long nativeContextLong = (ani_long)context.get(); - if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { - EVENT_LOGE("set field status: %{public}d", status); - return nullptr; - } - if (application == nullptr) { - EVENT_LOGE("application null"); - return nullptr; - } - OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, abilityInfo); return contextObj; } } // EventManagerFwkAni diff --git a/frameworks/extension/src/js_static_subscriber_extension_context.cpp b/frameworks/extension/src/js_static_subscriber_extension_context.cpp index 9a5f1ea8..65e575a7 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 e3174a91..b9cd694e 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 63df0b88..edfce6e6 100644 --- a/frameworks/extension/src/static_subscriber_extension.cpp +++ b/frameworks/extension/src/static_subscriber_extension.cpp @@ -15,7 +15,6 @@ #include "static_subscriber_extension.h" -#include "ani_static_subscriber_extension.h" #include "event_log_wrapper.h" #include "js_static_subscriber_extension.h" #include "runtime.h" @@ -26,19 +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); - case AbilityRuntime::Runtime::Language::ETS: - return EventManagerFwkAni::StsStaticSubscriberExtension::Create(runtime); - default: - return new (std::nothrow) StaticSubscriberExtension(); - } + return new (std::nothrow) StaticSubscriberExtension(); } void StaticSubscriberExtension::Init(const std::shared_ptr& record, diff --git a/interfaces/kits/ani/common_event/BUILD.gn b/interfaces/kits/ani/common_event/BUILD.gn index fb0af135..10e534d2 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,16 +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" diff --git a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets index 6fec4793..8f7eaaab 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.application.StaticSubscriberExtensionContext.ets @@ -19,34 +19,71 @@ 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; -loadLibrary("ani_commoneventmanager.z"); export class StaticSubscriberExtensionContext extends ExtensionContext { - nativeStaticSubscriberExtensionContext: long = 0; + 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); - }); + 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; - } + 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/commonEvent/commonEventSubscriber.ets b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets index b2677323..846546e2 100644 --- a/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets +++ b/interfaces/kits/ani/common_event/ets/commonEvent/commonEventSubscriber.ets @@ -90,6 +90,16 @@ class CommonEventSubscriberInner implements CommonEventSubscriber { 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 => { 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 cb266d94..c039ff16 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event.h @@ -20,24 +20,30 @@ #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 ClearEnv(); private: - std::mutex envMutex_; - std::mutex callbackMutex_; + ffrt::mutex envMutex_; + ffrt::mutex callbackMutex_; ani_env* env_ = nullptr; ani_object callback_ = nullptr; std::atomic_ullong id_; @@ -59,10 +65,30 @@ struct subscriberInstanceInfo { std::shared_ptr commonEventResult = nullptr; }; +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(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/src/ani_common_event.cpp b/interfaces/kits/ani/common_event/src/ani_common_event.cpp index 19625f3e..eee5523c 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -19,14 +19,19 @@ #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) { @@ -103,83 +108,66 @@ static uint32_t publishAsUserWithOptionsExecute(ani_env* env, ani_string eventId return errorCode; } -static ani_ref createSubscriberExecute(ani_env* env, ani_object infoObject) +ani_ref CreateSubscriberRef(ani_env* env, SubscriberInstanceWrapper *subscriberWrapper) { - EVENT_LOGI("createSubscriberExecute call."); - CommonEventSubscribeInfo subscribeInfo; - AniCommonEventUtils::ConvertCommonEventSubscribeInfo(env, infoObject, subscribeInfo); - subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::ThreadMode::HANDLER); - auto ret = ANI_OK; - auto wrapper = new (std::nothrow) SubscriberInstanceWrapper(subscribeInfo); - if (wrapper == nullptr) { - return nullptr; - } 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); - delete wrapper; - wrapper = nullptr; return nullptr; } ani_method ctor; ret = env->Class_FindMethod(cls, "", "J:V", &ctor); if (ret != ANI_OK) { EVENT_LOGE("createSubscriberExecute Class_FindMethod error. result: %{public}d.", ret); - delete wrapper; - wrapper = nullptr; return nullptr; } ani_object subscriberObj; - ret = env->Object_New(cls, ctor, &subscriberObj, reinterpret_cast(wrapper)); + 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; +} + +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 subscriberObj = CreateSubscriberRef(env, wrapper); + if (subscriberObj == nullptr) { delete wrapper; wrapper = nullptr; return nullptr; } - EVENT_LOGI("createSubscriberExecute end."); 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); - return ANI_INVALID_ARGS; - } - - SubscriberInstanceWrapper* wrapper = nullptr; - wrapper = reinterpret_cast(wrapper_long); - if (wrapper == nullptr) { - EVENT_LOGE("subscribeExecute wrapper is null."); - return ANI_INVALID_ARGS; - } - auto subscriberInstance = GetSubscriberByWrapper(wrapper); + EVENT_LOGD("subscribeExecute 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) { + 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; } - if (resultRef == nullptr) { - EVENT_LOGE("subscribeExecute resultRef is null."); - } - subscriberInstance->SetEnv(env); subscriberInstance->SetCallback(static_cast(resultRef)); - ani_vm* etsVm; ret = env->GetVM(&etsVm); if (ret != ANI_OK) { @@ -187,33 +175,49 @@ static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object return ANI_INVALID_ARGS; } subscriberInstance->SetVm(etsVm); - auto result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); - if (result == ANI_OK) { - EVENT_LOGD("result is ANI_OK"); - std::lock_guard lock(subscriberInsMutex); + 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(); - } else { - subscriberInstance = nullptr; } - EVENT_LOGI("subscribeExecute result: %{public}d.", result); + EVENT_LOGI("subscribe result: %{public}d", result); return result; } -static int32_t removeSubscriberInstance(ani_env* env, SubscriberInstanceWrapper* wrapper) +int32_t UnsubscribeAndRemoveInstance(ani_env* env, const std::shared_ptr &subscriber) { - int32_t result = ERR_OK; - std::lock_guard lock(subscriberInsMutex); - for (auto iter = subscriberInstances.begin(); iter != subscriberInstances.end();) { - if (iter->first.get() == wrapper->GetSubscriber().get()) { - result = CommonEventManager::NewUnSubscribeCommonEvent(iter->first); - ani_ref callbackRef = static_cast(iter->first->GetCallback()); - if (result == ANI_OK && callbackRef != nullptr) { - env->GlobalReference_Delete(callbackRef); - } - iter = subscriberInstances.erase(iter); - } else { - ++iter; + 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; } @@ -221,30 +225,27 @@ static int32_t removeSubscriberInstance(ani_env* env, SubscriberInstanceWrapper* static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) { EVENT_LOGI("unsubscribeExecute 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); - return ANI_INVALID_ARGS; - } - - 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); + auto subscriberInstance = GetSubscriber(env, subscribeRef); if (subscriberInstance == nullptr) { EVENT_LOGE("subscriberInstance is null."); return ANI_INVALID_ARGS; } - auto result = removeSubscriberInstance(env, wrapper); - EVENT_LOGI("unsubscribeExecute result: %{public}d.", result); + 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; } @@ -321,39 +322,37 @@ 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"); - if (env_ != nullptr && callback_ != nullptr) { - env_->GlobalReference_Delete(callback_); - } -} +{} 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; } } @@ -394,38 +393,29 @@ 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; } ani_object SubscriberInstance::GetCallback() { - std::lock_guard lockRef(callbackMutex_); + std::lock_guard lockRef(callbackMutex_); return callback_; } -void SubscriberInstance::ClearEnv() -{ - EVENT_LOGD("Env expired, clear SubscriberInstance env"); - std::lock_guard lock(envMutex_); - env_ = nullptr; -} - SubscriberInstanceWrapper::SubscriberInstanceWrapper(const CommonEventSubscribeInfo& info) { auto objectInfo = new (std::nothrow) SubscriberInstance(info); @@ -447,6 +437,218 @@ 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; @@ -459,8 +661,38 @@ static void clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj EVENT_LOGE("clean wrapper is null."); return; } - auto result = removeSubscriberInstance(env, wrapper); - EVENT_LOGD("clean result: %{public}d.", result); + 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; } @@ -472,14 +704,23 @@ std::shared_ptr GetAsyncCommonEventResult(ani_env* env, 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); + std::lock_guard lock(subscriberInsMutex); for (auto subscriberRes : subscriberInstances) { - if (subscriberRes.first.get() == subscriberInstance.get()) { - return subscriberInstances[subscriberRes.first]; + if (subscriberRes.first.get() == subscriber.get()) { + return subscriberRes.second; } } return nullptr; @@ -487,7 +728,7 @@ std::shared_ptr GetAsyncCommonEventResult(ani_env* env, static ani_double getCode(ani_env *env, ani_object object) { - EVENT_LOGD("subscriberInstance getCode."); + EVENT_LOGI("subscriberInstance getCode."); auto subscriberRes = GetAsyncCommonEventResult(env, object); int32_t code = 0; if (subscriberRes != nullptr) { @@ -686,6 +927,10 @@ static std::array commonEventSubscriberFunctions = { 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)}, }; ani_status init(ani_env *env, ani_namespace kitNs) @@ -723,6 +968,20 @@ ani_status init(ani_env *env, ani_namespace kitNs) 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; } @@ -762,20 +1021,6 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result) EVENT_LOGE("Cannot bind native methods to LcommonEvent/commonEventSubscriber/Cleaner"); 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; - } *result = ANI_VERSION_1; return ANI_OK; } diff --git a/interfaces/kits/napi/napi_common_event/BUILD.gn b/interfaces/kits/napi/napi_common_event/BUILD.gn index 95cd3563..a44c3d0b 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 d4754ebc..029ff03a 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 db27c96c..fe8af10f 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 ca6dcba0..41889cd8 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)); -- Gitee From cbbcfad1678d279be71ddc4059475450f11e3487 Mon Sep 17 00:00:00 2001 From: cheerful_ricky Date: Tue, 15 Jul 2025 17:15:31 +0800 Subject: [PATCH 11/14] subscriber transfer support multi-transfer Signed-off-by: cheerful_ricky --- .../common_event/include/ani_common_event.h | 11 +- .../ani/common_event/src/ani_common_event.cpp | 133 +++++++++++------- 2 files changed, 84 insertions(+), 60 deletions(-) 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 c039ff16..a6ff360b 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event.h @@ -65,18 +65,11 @@ struct subscriberInstanceInfo { std::shared_ptr commonEventResult = nullptr; }; -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::vector> aniSubscribers_; + std::vector> napiSubscribers_; 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_; }; 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 eee5523c..5be01972 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -179,10 +179,10 @@ static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object int32_t result = ERR_OK; if (relation != nullptr) { std::lock_guard lock(relation->relationMutex_); - if (relation->subscribeEnv_ == DO_NOT_SUBSCRIBE) { + if (!relation->aniSubscriber_ && !relation->napiSubscriber_) { result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); if (result == ERR_OK) { - relation->subscribeEnv_ = SUBSCRIBE_IN_ANI_ENV; + relation->aniSubscriber_ = subscriberInstance; std::lock_guard lock(subscriberInsMutex); subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); } @@ -237,15 +237,16 @@ static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) return UnsubscribeAndRemoveInstance(env, subscriberInstance); } std::lock_guard lock(relation->relationMutex_); - if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + if (relation->napiSubscriber_) { result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + relation->napiSubscriber_ = nullptr; + } else if (relation->aniSubscriber_) { result = UnsubscribeAndRemoveInstance(env, relation->aniSubscriber_); + relation->aniSubscriber_ = nullptr; } else { EVENT_LOGD("transfered no subscribe"); } - relation->subscribeEnv_ = DO_NOT_SUBSCRIBE; return result; } @@ -347,7 +348,10 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) auto asyncCommonEvent = GoAsyncCommonEvent(); auto relation = GetTransferRelation(subscriber, nullptr); if (relation != nullptr) { - EventManagerFwkNapi::SetAsyncCommonEventResult(relation->napiSubscriber_, asyncCommonEvent); + std::lock_guard lock(relation->relationMutex_); + for (const auto &subscriber : relation->napiSubscribers_) { + EventManagerFwkNapi::SetAsyncCommonEventResult(subscriber, asyncCommonEvent); + } } std::lock_guard lock(subscriberInsMutex); auto item = subscriberInstances.find(subscriber); @@ -378,8 +382,6 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) EVENT_LOGE("subscribeCallbackThreadFunciton fnObject is null."); return; } - - EVENT_LOGI("FunctionalObject_Call."); std::vector args = { nullObject, reinterpret_cast(ani_data) }; ani_ref result; aniResult = etsEnv->FunctionalObject_Call(fnObject, args.size(), args.data(), &result); @@ -442,9 +444,18 @@ std::shared_ptr GetTransferRelation(std::shared_ { 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; + if (napiSubscriber != nullptr) { + auto subscriberItem = std::find(item->napiSubscribers_.begin(), item->napiSubscribers_.end(), + napiSubscriber); + if (subscriberItem != item->napiSubscribers_.end()) { + return item; + } + } else if (aniSubscriber != nullptr) { + auto subscriberItem = std::find(item->aniSubscribers_.begin(), item->aniSubscribers_.end(), + aniSubscriber); + if (subscriberItem != item->aniSubscribers_.end()) { + return item; + } } } return nullptr; @@ -461,11 +472,6 @@ static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_cla 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"); @@ -477,14 +483,23 @@ static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_cla aniWrapper = nullptr; return undefinedRef; } + SetNapiSubscriberCallback(napiSubscriber); auto asyncCommonEventResult = EventManagerFwkNapi::GetAsyncCommonEventResult(napiSubscriber); + + auto relation = GetTransferRelation(nullptr, napiSubscriber); + if (relation != nullptr) { + relation->aniSubscribers_.push_back(aniWrapper->GetSubscriber()); + if (asyncCommonEventResult != nullptr || napiSubscriber->GetCallbackRef() != nullptr) { + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[aniWrapper->GetSubscriber()] = asyncCommonEventResult; + } + return subscriberObj; + } relation = std::make_shared(); - relation->aniSubscriber_ = aniWrapper->GetSubscriber(); - relation->napiSubscriber_ = napiSubscriber; - relation->aniSubscriberRef_ = subscriberObj; - relation->napiSubscriberRef_ = static_cast(input); + relation->aniSubscribers_.push_back(aniWrapper->GetSubscriber()); + relation->napiSubscribers_.push_back(napiSubscriber); if (asyncCommonEventResult != nullptr || napiSubscriber->GetCallbackRef() != nullptr) { - relation->subscribeEnv_ = SUBSCRIBE_IN_NAPI_ENV; + relation->napiSubscriber_ = napiSubscriber; std::lock_guard lock(subscriberInsMutex); subscriberInstances[aniWrapper->GetSubscriber()] = asyncCommonEventResult; } @@ -492,7 +507,6 @@ static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_cla std::lock_guard lock(transferRelationMutex); transferRelations.push_back(relation); } - SetNapiSubscriberCallback(napiSubscriber); return subscriberObj; } @@ -505,10 +519,11 @@ static int32_t unsubscribeCallback(const std::shared_ptr lock(relation->relationMutex_); - if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + if (relation->napiSubscriber_ != nullptr) { result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + relation->napiSubscriber_ = nullptr; + } else if (relation->aniSubscriber_ != nullptr) { ani_env* etsEnv; ani_status aniResult = ANI_OK; ani_options aniArgs {0, nullptr}; @@ -519,8 +534,8 @@ static int32_t unsubscribeCallback(const std::shared_ptraniSubscriber_); relation->aniSubscriber_->GetVm()->DetachCurrentThread(); + relation->aniSubscriber_ = nullptr; } - relation->subscribeEnv_ = DO_NOT_SUBSCRIBE; return result; } @@ -532,13 +547,13 @@ static int32_t subscribeCallback(const std::shared_ptr lock(relation->relationMutex_); - if (relation->subscribeEnv_ != DO_NOT_SUBSCRIBE) { - EVENT_LOGW("transfered subscriber already subscribed in 1.%{public}d context", relation->subscribeEnv_); + if (relation->napiSubscriber_ || relation->aniSubscriber_) { + EVENT_LOGW("transfered subscriber already subscribed"); return ERR_OK; } auto result = CommonEventManager::NewSubscribeCommonEvent(napiSubscriber); if (result == ERR_OK) { - relation->subscribeEnv_ = SUBSCRIBE_IN_NAPI_ENV; + relation->napiSubscriber_ = napiSubscriber; } return result; }; @@ -554,12 +569,17 @@ static int32_t gcCallback(const std::shared_ptr lock(relation->relationMutex_); - relation->napiSubscriberDestroyed_ = true; - if (relation->aniSubscriberDestroyed_) { - if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + auto subscriberItem = std::find(relation->napiSubscribers_.begin(), relation->napiSubscribers_.end(), + napiSubscriber); + if (subscriberItem != relation->napiSubscribers_.end()) { + relation->napiSubscribers_.erase(subscriberItem); + } + if (relation->aniSubscribers_.empty() && relation->napiSubscribers_.empty()) { + if (relation->napiSubscriber_) { result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + relation->napiSubscriber_ = nullptr; + } else if (relation->aniSubscriber_) { ani_env* etsEnv; ani_status aniResult = ANI_OK; ani_options aniArgs {0, nullptr}; @@ -570,6 +590,7 @@ static int32_t gcCallback(const std::shared_ptraniSubscriber_); relation->aniSubscriber_->GetVm()->DetachCurrentThread(); + relation->aniSubscriber_ = nullptr; } allDestroyed = true; } @@ -593,8 +614,11 @@ static void asyncResultCloneCallback(const std::shared_ptr lock(subscriberInsMutex); - subscriberInstances[relation->aniSubscriber_] = result; + std::lock_guard lock(relation->relationMutex_); + for (const auto &subscriber : relation->aniSubscribers_) { + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[subscriber] = result; + } return; }; @@ -609,11 +633,6 @@ static ani_ref transferToDynamicSubscriber(ani_env *env, [[maybe_unused]] ani_cl 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) { @@ -621,23 +640,31 @@ static ani_ref transferToDynamicSubscriber(ani_env *env, [[maybe_unused]] ani_cl return undefinedRef; } ani_ref result {}; + arkts_napi_scope_close_n(jsEnv, 1, &napiSubscriberValue, &result); + auto napiSubscriber = EventManagerFwkNapi::GetSubscriber(jsEnv, napiSubscriberValue); + SetNapiSubscriberCallback(napiSubscriber); + auto asyncResult = GetAsyncCommonEventResult(aniSubscriber); + + auto relation = GetTransferRelation(aniSubscriber, nullptr); + if (relation != nullptr) { + relation->napiSubscribers_.push_back(napiSubscriber); + if (asyncResult != nullptr || aniSubscriber->GetCallback() != nullptr) { + EventManagerFwkNapi::SetAsyncCommonEventResult(napiSubscriber, asyncResult); + } + return result; + } relation = std::make_shared(); - relation->aniSubscriber_ = aniSubscriber; - relation->napiSubscriber_ = napiSubscriber; - relation->aniSubscriberRef_ = static_cast(input); - relation->napiSubscriberRef_ = result; - std::shared_ptr asyncResult = GetAsyncCommonEventResult(aniSubscriber); + relation->aniSubscribers_.push_back(aniSubscriber); + relation->napiSubscribers_.push_back(napiSubscriber); if (asyncResult != nullptr || aniSubscriber->GetCallback() != nullptr) { - relation->subscribeEnv_ = SUBSCRIBE_IN_ANI_ENV; + relation->aniSubscriber_ = aniSubscriber; 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; } @@ -675,12 +702,16 @@ static void clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj bool allDestroyed = false; { std::lock_guard lock(relation->relationMutex_); - relation->aniSubscriberDestroyed_ = true; - if (relation->napiSubscriberDestroyed_) { - if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { + auto subscriberItem = std::find(relation->aniSubscribers_.begin(), relation->aniSubscribers_.end(), + subscriberInstance); + if (subscriberItem != relation->aniSubscribers_.end()) { + relation->aniSubscribers_.erase(subscriberItem); + } + if (relation->aniSubscribers_.empty() && relation->napiSubscribers_.empty()) { + if (relation->napiSubscriber_ != nullptr) { EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { + } else if (relation->aniSubscriber_ != nullptr) { UnsubscribeAndRemoveInstance(env, relation->aniSubscriber_); } allDestroyed = true; -- Gitee From 8e2bf27991a0068f8ba7def30324153724e2eea8 Mon Sep 17 00:00:00 2001 From: heguokai <275503077@qq.com> Date: Tue, 15 Jul 2025 19:03:11 +0800 Subject: [PATCH 12/14] ani subscribeToEvent impl Signed-off-by: heguokai <275503077@qq.com> --- .../ets/@ohos.commonEventManager.ets | 25 ++++++- .../common_event/include/ani_common_event.h | 4 ++ .../ani/common_event/src/ani_common_event.cpp | 68 +++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets index 2105d466..e78c2f89 100644 --- a/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets +++ b/interfaces/kits/ani/common_event/ets/@ohos.commonEventManager.ets @@ -14,7 +14,7 @@ */ 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'; @@ -37,6 +37,8 @@ namespace commonEventManager { 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; @@ -170,6 +172,27 @@ namespace commonEventManager { }); } + 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); 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 c039ff16..a4968fea 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event.h @@ -39,13 +39,17 @@ public: ani_vm* GetVm(); void SetCallback(const ani_object& callback); ani_object GetCallback(); + void SetIsToEvent(bool isToEvent); + bool GetIsToEvent(); void ClearEnv(); private: 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; 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 eee5523c..f492291e 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -201,6 +201,56 @@ static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object 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; + 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; + } + subscriberInstance->SetCallback(static_cast(resultRef)); + subscriberInstance->SetIsToEvent(true); + 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("subscribeToEventExecute result: %{public}d", result); + return result; +} + int32_t UnsubscribeAndRemoveInstance(ani_env* env, const std::shared_ptr &subscriber) { EVENT_LOGD("unsubscribe 1.2 subscriber"); @@ -381,6 +431,9 @@ 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) { @@ -416,6 +469,18 @@ ani_object SubscriberInstance::GetCallback() 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) { auto objectInfo = new (std::nothrow) SubscriberInstance(info); @@ -953,6 +1018,9 @@ ani_status init(ani_env *env, ani_namespace kitNs) 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", -- Gitee From fde352a29b616fb8acff056380fadbaab8f918b1 Mon Sep 17 00:00:00 2001 From: heguokai <275503077@qq.com> Date: Tue, 15 Jul 2025 20:08:16 +0800 Subject: [PATCH 13/14] modify init func Signed-off-by: heguokai <275503077@qq.com> --- .../ani/common_event/src/ani_common_event.cpp | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) 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 f492291e..fe643c8f 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -998,40 +998,42 @@ static std::array commonEventSubscriberFunctions = { 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; - 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 { "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) }, - }; - - status = env->Namespace_BindNativeFunctions(kitNs, methods.data(), methods.size()); + 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; -- Gitee From 7aff41850045f9cd1c650a8c078a45f614f0bc5f Mon Sep 17 00:00:00 2001 From: oh_ci Date: Wed, 16 Jul 2025 11:13:45 +0000 Subject: [PATCH 14/14] =?UTF-8?q?=E5=9B=9E=E9=80=80=20'Pull=20Request=20!1?= =?UTF-8?q?418=20:=20subscriber=20transfer=20support=20multi-transfer'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common_event/include/ani_common_event.h | 11 +- .../ani/common_event/src/ani_common_event.cpp | 133 +++++++----------- 2 files changed, 60 insertions(+), 84 deletions(-) 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 7c25c71f..a4968fea 100644 --- a/interfaces/kits/ani/common_event/include/ani_common_event.h +++ b/interfaces/kits/ani/common_event/include/ani_common_event.h @@ -69,11 +69,18 @@ struct subscriberInstanceInfo { std::shared_ptr commonEventResult = nullptr; }; +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::vector> aniSubscribers_; - std::vector> napiSubscribers_; 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_; }; 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 11e40fc2..fe643c8f 100644 --- a/interfaces/kits/ani/common_event/src/ani_common_event.cpp +++ b/interfaces/kits/ani/common_event/src/ani_common_event.cpp @@ -179,10 +179,10 @@ static uint32_t subscribeExecute(ani_env* env, ani_ref subscribeRef, ani_object int32_t result = ERR_OK; if (relation != nullptr) { std::lock_guard lock(relation->relationMutex_); - if (!relation->aniSubscriber_ && !relation->napiSubscriber_) { + if (relation->subscribeEnv_ == DO_NOT_SUBSCRIBE) { result = CommonEventManager::NewSubscribeCommonEvent(subscriberInstance); if (result == ERR_OK) { - relation->aniSubscriber_ = subscriberInstance; + relation->subscribeEnv_ = SUBSCRIBE_IN_ANI_ENV; std::lock_guard lock(subscriberInsMutex); subscriberInstances[subscriberInstance] = subscriberInstance->GoAsyncCommonEvent(); } @@ -287,16 +287,15 @@ static uint32_t unsubscribeExecute(ani_env* env, ani_ref subscribeRef) return UnsubscribeAndRemoveInstance(env, subscriberInstance); } std::lock_guard lock(relation->relationMutex_); - if (relation->napiSubscriber_) { + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - relation->napiSubscriber_ = nullptr; - } else if (relation->aniSubscriber_) { + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { result = UnsubscribeAndRemoveInstance(env, relation->aniSubscriber_); - relation->aniSubscriber_ = nullptr; } else { EVENT_LOGD("transfered no subscribe"); } + relation->subscribeEnv_ = DO_NOT_SUBSCRIBE; return result; } @@ -398,10 +397,7 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) auto asyncCommonEvent = GoAsyncCommonEvent(); auto relation = GetTransferRelation(subscriber, nullptr); if (relation != nullptr) { - std::lock_guard lock(relation->relationMutex_); - for (const auto &subscriber : relation->napiSubscribers_) { - EventManagerFwkNapi::SetAsyncCommonEventResult(subscriber, asyncCommonEvent); - } + EventManagerFwkNapi::SetAsyncCommonEventResult(relation->napiSubscriber_, asyncCommonEvent); } std::lock_guard lock(subscriberInsMutex); auto item = subscriberInstances.find(subscriber); @@ -432,6 +428,8 @@ void SubscriberInstance::OnReceiveEvent(const CommonEventData& data) EVENT_LOGE("subscribeCallbackThreadFunciton fnObject is null."); return; } + + EVENT_LOGI("FunctionalObject_Call."); std::vector args = { nullObject, reinterpret_cast(ani_data) }; if (GetIsToEvent()) { args.erase(args.begin()); @@ -509,18 +507,9 @@ std::shared_ptr GetTransferRelation(std::shared_ { std::lock_guard lock(transferRelationMutex); for (auto const &item : transferRelations) { - if (napiSubscriber != nullptr) { - auto subscriberItem = std::find(item->napiSubscribers_.begin(), item->napiSubscribers_.end(), - napiSubscriber); - if (subscriberItem != item->napiSubscribers_.end()) { - return item; - } - } else if (aniSubscriber != nullptr) { - auto subscriberItem = std::find(item->aniSubscribers_.begin(), item->aniSubscribers_.end(), - aniSubscriber); - if (subscriberItem != item->aniSubscribers_.end()) { - return item; - } + if ((napiSubscriber != nullptr && item->napiSubscriber_.get() == napiSubscriber.get()) || + (aniSubscriber != nullptr && item->aniSubscriber_.get() == aniSubscriber.get())) { + return item; } } return nullptr; @@ -537,6 +526,11 @@ static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_cla 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"); @@ -548,23 +542,14 @@ static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_cla aniWrapper = nullptr; return undefinedRef; } - SetNapiSubscriberCallback(napiSubscriber); auto asyncCommonEventResult = EventManagerFwkNapi::GetAsyncCommonEventResult(napiSubscriber); - - auto relation = GetTransferRelation(nullptr, napiSubscriber); - if (relation != nullptr) { - relation->aniSubscribers_.push_back(aniWrapper->GetSubscriber()); - if (asyncCommonEventResult != nullptr || napiSubscriber->GetCallbackRef() != nullptr) { - std::lock_guard lock(subscriberInsMutex); - subscriberInstances[aniWrapper->GetSubscriber()] = asyncCommonEventResult; - } - return subscriberObj; - } relation = std::make_shared(); - relation->aniSubscribers_.push_back(aniWrapper->GetSubscriber()); - relation->napiSubscribers_.push_back(napiSubscriber); + relation->aniSubscriber_ = aniWrapper->GetSubscriber(); + relation->napiSubscriber_ = napiSubscriber; + relation->aniSubscriberRef_ = subscriberObj; + relation->napiSubscriberRef_ = static_cast(input); if (asyncCommonEventResult != nullptr || napiSubscriber->GetCallbackRef() != nullptr) { - relation->napiSubscriber_ = napiSubscriber; + relation->subscribeEnv_ = SUBSCRIBE_IN_NAPI_ENV; std::lock_guard lock(subscriberInsMutex); subscriberInstances[aniWrapper->GetSubscriber()] = asyncCommonEventResult; } @@ -572,6 +557,7 @@ static ani_ref transferToStaticSubscriber(ani_env *env, [[maybe_unused]] ani_cla std::lock_guard lock(transferRelationMutex); transferRelations.push_back(relation); } + SetNapiSubscriberCallback(napiSubscriber); return subscriberObj; } @@ -584,11 +570,10 @@ static int32_t unsubscribeCallback(const std::shared_ptr lock(relation->relationMutex_); - if (relation->napiSubscriber_ != nullptr) { + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - relation->napiSubscriber_ = nullptr; - } else if (relation->aniSubscriber_ != nullptr) { + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { ani_env* etsEnv; ani_status aniResult = ANI_OK; ani_options aniArgs {0, nullptr}; @@ -599,8 +584,8 @@ static int32_t unsubscribeCallback(const std::shared_ptraniSubscriber_); relation->aniSubscriber_->GetVm()->DetachCurrentThread(); - relation->aniSubscriber_ = nullptr; } + relation->subscribeEnv_ = DO_NOT_SUBSCRIBE; return result; } @@ -612,13 +597,13 @@ static int32_t subscribeCallback(const std::shared_ptr lock(relation->relationMutex_); - if (relation->napiSubscriber_ || relation->aniSubscriber_) { - EVENT_LOGW("transfered subscriber already subscribed"); + 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->napiSubscriber_ = napiSubscriber; + relation->subscribeEnv_ = SUBSCRIBE_IN_NAPI_ENV; } return result; }; @@ -634,17 +619,12 @@ static int32_t gcCallback(const std::shared_ptr lock(relation->relationMutex_); - auto subscriberItem = std::find(relation->napiSubscribers_.begin(), relation->napiSubscribers_.end(), - napiSubscriber); - if (subscriberItem != relation->napiSubscribers_.end()) { - relation->napiSubscribers_.erase(subscriberItem); - } - if (relation->aniSubscribers_.empty() && relation->napiSubscribers_.empty()) { - if (relation->napiSubscriber_) { + relation->napiSubscriberDestroyed_ = true; + if (relation->aniSubscriberDestroyed_) { + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { result = EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - relation->napiSubscriber_ = nullptr; - } else if (relation->aniSubscriber_) { + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { ani_env* etsEnv; ani_status aniResult = ANI_OK; ani_options aniArgs {0, nullptr}; @@ -655,7 +635,6 @@ static int32_t gcCallback(const std::shared_ptraniSubscriber_); relation->aniSubscriber_->GetVm()->DetachCurrentThread(); - relation->aniSubscriber_ = nullptr; } allDestroyed = true; } @@ -679,11 +658,8 @@ static void asyncResultCloneCallback(const std::shared_ptr lock(relation->relationMutex_); - for (const auto &subscriber : relation->aniSubscribers_) { - std::lock_guard lock(subscriberInsMutex); - subscriberInstances[subscriber] = result; - } + std::lock_guard lock(subscriberInsMutex); + subscriberInstances[relation->aniSubscriber_] = result; return; }; @@ -698,6 +674,11 @@ static ani_ref transferToDynamicSubscriber(ani_env *env, [[maybe_unused]] ani_cl 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) { @@ -705,31 +686,23 @@ static ani_ref transferToDynamicSubscriber(ani_env *env, [[maybe_unused]] ani_cl return undefinedRef; } ani_ref result {}; - arkts_napi_scope_close_n(jsEnv, 1, &napiSubscriberValue, &result); - auto napiSubscriber = EventManagerFwkNapi::GetSubscriber(jsEnv, napiSubscriberValue); - SetNapiSubscriberCallback(napiSubscriber); - auto asyncResult = GetAsyncCommonEventResult(aniSubscriber); - - auto relation = GetTransferRelation(aniSubscriber, nullptr); - if (relation != nullptr) { - relation->napiSubscribers_.push_back(napiSubscriber); - if (asyncResult != nullptr || aniSubscriber->GetCallback() != nullptr) { - EventManagerFwkNapi::SetAsyncCommonEventResult(napiSubscriber, asyncResult); - } - return result; - } relation = std::make_shared(); - relation->aniSubscribers_.push_back(aniSubscriber); - relation->napiSubscribers_.push_back(napiSubscriber); + 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->aniSubscriber_ = aniSubscriber; + 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; } @@ -767,16 +740,12 @@ static void clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj bool allDestroyed = false; { std::lock_guard lock(relation->relationMutex_); - auto subscriberItem = std::find(relation->aniSubscribers_.begin(), relation->aniSubscribers_.end(), - subscriberInstance); - if (subscriberItem != relation->aniSubscribers_.end()) { - relation->aniSubscribers_.erase(subscriberItem); - } - if (relation->aniSubscribers_.empty() && relation->napiSubscribers_.empty()) { - if (relation->napiSubscriber_ != nullptr) { + relation->aniSubscriberDestroyed_ = true; + if (relation->napiSubscriberDestroyed_) { + if (relation->subscribeEnv_ == SUBSCRIBE_IN_NAPI_ENV) { EventManagerFwkNapi::UnsubscribeAndRemoveInstance(relation->napiSubscriber_->GetEnv(), relation->napiSubscriber_); - } else if (relation->aniSubscriber_ != nullptr) { + } else if (relation->subscribeEnv_ == SUBSCRIBE_IN_ANI_ENV) { UnsubscribeAndRemoveInstance(env, relation->aniSubscriber_); } allDestroyed = true; -- Gitee