diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn index fa7be48e090d9f7cdb982c1ec43eb14bbddffddf..959c8c508c103a3dd37cc8f5f6f1790df2d69873 100644 --- a/frameworks/ets/ani/BUILD.gn +++ b/frameworks/ets/ani/BUILD.gn @@ -28,9 +28,9 @@ group("ani_packages") { "${ability_runtime_path}/frameworks/ets/ani/app/application_context:application_context_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/app/context:context_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/caller_complex:caller_complex_ani", + "${ability_runtime_path}/frameworks/ets/ani/event_hub:event_hub_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/featureAbility:featureability_ani", "${ability_runtime_path}/frameworks/ets/ani/insight_intent/insight_intent_driver:insight_intent_driver_ani_kit", - "${ability_runtime_path}/frameworks/ets/ani/native_constructor:context_ani", "${ability_runtime_path}/frameworks/ets/ani/ui_extension_callback:ani_ui_extension_callback", "${ability_runtime_path}/frameworks/ets/ani/uri_permission_manager:uri_permission_manager_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/wantagent:aniwantagent", diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn index ef5d7d7e1f0682344276f995ae0dc77f0eeefaa6..0a6e36105193cd7af603b92a5a38680c4d2b04f7 100644 --- a/frameworks/ets/ani/ani_common/BUILD.gn +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -32,6 +32,7 @@ ohos_shared_library("ani_common") { "./include", "${ability_runtime_innerkits_path}/app_manager/include/appmgr", "${ability_runtime_path}/frameworks/ets/ani/enum_convert", + "${ability_runtime_path}/frameworks/ets/ani/event_hub/include", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", "${ability_runtime_path}/interfaces/kits/native/ability/native", @@ -79,6 +80,7 @@ ohos_shared_library("ani_common") { "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/appkit:app_context", "${ability_runtime_native_path}/appkit:application_context_manager", + "${ability_runtime_path}/frameworks/ets/ani/event_hub:event_hub_ani_kit", ] external_deps = [ diff --git a/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp b/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp index 20642a066e5497ffa001cdb9e1cdb3bcd19f1554..481a88af279150645d094d7d388f6ad7865da104 100644 --- a/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_context_utils.cpp @@ -24,6 +24,7 @@ #include "ets_application_context_utils.h" #include "ets_error_utils.h" #include "ets_native_reference.h" +#include "event_hub.h" #include "hilog_tag_wrapper.h" #include "ipc_skeleton.h" #include "resourceManager.h" @@ -342,6 +343,21 @@ void CreateEtsBaseContext(ani_env *aniEnv, ani_class contextClass, ani_object co } BindParentProperty(aniEnv, contextClass, contextObj, context); BindNativeFunction(aniEnv); + // set eventHub context + ani_ref eventHubRef = nullptr; + ani_status status = ANI_OK; + if ((status = aniEnv->Object_GetFieldByName_Ref(contextObj, "eventHub", &eventHubRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_GetFieldByName_Ref failed status: %{public}d", status); + return; + } + + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "workContext null"); + return; + } + ani_long nativeContextLong = (ani_long)workContext; + AbilityRuntime::EventHub::SetEventHubContext(aniEnv, eventHubRef, nativeContextLong); } std::shared_ptr GetBaseContext(ani_env *env, ani_object aniObj) diff --git a/frameworks/ets/ani/app/context/BUILD.gn b/frameworks/ets/ani/app/context/BUILD.gn index 81a953ec41cd53931d93da593226beca56d154a2..b467541ef58dadc75debee1560a3269af4020623 100755 --- a/frameworks/ets/ani/app/context/BUILD.gn +++ b/frameworks/ets/ani/app/context/BUILD.gn @@ -29,6 +29,7 @@ ohos_shared_library("context_ani_kit") { "${ability_runtime_napi_path}/ability_auto_startup_callback", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/frameworks/ets/ani/event_hub/include", ] configs = [] @@ -53,6 +54,7 @@ ohos_shared_library("context_ani_kit") { "${ability_runtime_native_path}/appkit:appkit_native", "${ability_runtime_native_path}/appkit:application_context_manager", "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + "${ability_runtime_path}/frameworks/ets/ani/event_hub:event_hub_ani_kit", ] external_deps = [ diff --git a/frameworks/ets/ani/app/context/src/ets_context_module.cpp b/frameworks/ets/ani/app/context/src/ets_context_module.cpp index 6fbecb0340e875839f09f856efcdecdc09dadfc2..86c5298c8e41bd1befab42e44f951a9628583d6b 100755 --- a/frameworks/ets/ani/app/context/src/ets_context_module.cpp +++ b/frameworks/ets/ani/app/context/src/ets_context_module.cpp @@ -27,6 +27,7 @@ #include "ets_application_context_utils.h" #include "ets_context_utils.h" #include "ets_error_utils.h" +#include "event_hub.h" #include "hilog_tag_wrapper.h" #include "hitrace_meter.h" #include "interop_js/arkts_esvalue.h" @@ -408,6 +409,7 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) } EtsContextModuleInit(aniEnv); + AbilityRuntime::EventHub::InitAniEventHub(aniEnv); *result = ANI_VERSION_1; TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor finish"); return ANI_OK; diff --git a/frameworks/ets/ani/native_constructor/BUILD.gn b/frameworks/ets/ani/event_hub/BUILD.gn similarity index 61% rename from frameworks/ets/ani/native_constructor/BUILD.gn rename to frameworks/ets/ani/event_hub/BUILD.gn index 546c6ab0408918cabfd4b311f2005ba04c486b7c..3f66bcc418719ddaf50cc2ee19c753edfb42d5f4 100644 --- a/frameworks/ets/ani/native_constructor/BUILD.gn +++ b/frameworks/ets/ani/event_hub/BUILD.gn @@ -10,11 +10,12 @@ # 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("//build/config/components/ets_frontend/ets2abc_config.gni") import("//build/ohos.gni") import("//foundation/ability/ability_runtime/ability_runtime.gni") - -ohos_shared_library("context_ani") { + +ohos_shared_library("event_hub_ani_kit") { branch_protector_ret = "pac_ret" sanitize = { cfi = true @@ -22,20 +23,38 @@ ohos_shared_library("context_ani") { cfi_vcall_icall_only = true debug = false } - + + include_dirs = [ + "${ability_runtime_path}/frameworks/ets/ani/event_hub/include", + ] + configs = [] + + public_configs = [] + sources = [ - "context_native_constructor.cpp", + "./src/event_hub.cpp", ] - - include_dirs = [ - "${ability_runtime_services_path}/common/include", + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_napi_path}/inner/napi_common:napi_common", ] - + external_deps = [ "hilog:libhilog", + "napi:ace_napi", "runtime_core:ani", + "runtime_core:ani_helpers", ] + + public_external_deps = [ "ability_base:configuration" ] + + innerapi_tags = [ "platformsdk" ] subsystem_name = "ability" part_name = "ability_runtime" - output_extension = "so" } \ No newline at end of file diff --git a/frameworks/ets/ani/event_hub/include/event_hub.h b/frameworks/ets/ani/event_hub/include/event_hub.h new file mode 100644 index 0000000000000000000000000000000000000000..d9d8e1c979c661ffd76d565b3545b811ad3ffad5 --- /dev/null +++ b/frameworks/ets/ani/event_hub/include/event_hub.h @@ -0,0 +1,44 @@ +/* + * 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 OHOS_ABILITY_RUNTIME_EVENT_HUB_H +#define OHOS_ABILITY_RUNTIME_EVENT_HUB_H + +#include +#include "ability_context.h" +#include "hilog_tag_wrapper.h" +#include "js_runtime_utils.h" +#include "ets_runtime.h" +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { + +class EventHub { +public: + static ani_object GetDynamicContextEventHub(ani_env *env, ani_object aniObj); + static void InitAniEventHub(ani_env *aniEnv); + static void SetEventHubContext(ani_env *aniEnv, ani_ref eventHubRef, ani_long nativeContextLong); + +private: + static std::shared_ptr GetAbilityContext(ani_env *env, ani_object aniObj); + static bool CallNapiSetNativeEventHubRefFn(ani_env *aniEnv, ani_object aniObj, napi_env napiEnv, + napi_value eventHub); +}; + +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_EVENT_HUB_H \ No newline at end of file diff --git a/frameworks/ets/ani/event_hub/src/event_hub.cpp b/frameworks/ets/ani/event_hub/src/event_hub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb85643f9bb5dbae691ce29d9fe0104dacd43842 --- /dev/null +++ b/frameworks/ets/ani/event_hub/src/event_hub.cpp @@ -0,0 +1,195 @@ +/* + * 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 "event_hub.h" + +#include "interop_js/arkts_esvalue.h" +#include "interop_js/arkts_interop_js_api.h" +#include "interop_js/hybridgref_ani.h" +#include "interop_js/hybridgref_napi.h" +#include "js_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* ETS_EVENT_HUB_CLASS_NAME = "Lapplication/EventHub/EventHub;"; +} + +std::shared_ptr EventHub::GetAbilityContext(ani_env *env, ani_object aniObj) +{ + ani_long nativeContextLong = 0; + ani_class cls {}; + ani_field contextField = nullptr; + ani_status status = ANI_ERROR; + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return nullptr; + } + if ((status = env->FindClass(ETS_EVENT_HUB_CLASS_NAME, &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_GetField_Long(aniObj, contextField, &nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status); + return nullptr; + } + auto weakContext = reinterpret_cast*>(nativeContextLong); + return weakContext != nullptr ? weakContext->lock() : nullptr; +} + +ani_object EventHub::GetDynamicContextEventHub(ani_env *aniEnv, ani_object aniObj) +{ + TAG_LOGI(AAFwkTag::APPKIT, "GetDynamicContextEventHub called"); + if (aniEnv == nullptr || aniObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "aniEnv or aniObj is null"); + return nullptr; + } + auto context = GetAbilityContext(aniEnv, aniObj); + if (context == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + return nullptr; + } + auto &bindingObj = context->GetBindingObject(); + if (bindingObj == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null bindingObj"); + return nullptr; + } + auto dynamicContext = bindingObj->Get(); + if (dynamicContext == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null dynamicContext"); + return nullptr; + } + ani_object staticResult = nullptr; + { + napi_env napiEnv = {}; + if (!arkts_napi_scope_open(aniEnv, &napiEnv)) { + TAG_LOGE(AAFwkTag::APPKIT, "arkts_napi_scope_open failed"); + return nullptr; + } + napi_value eventHub = nullptr; + if (napi_get_named_property(napiEnv, dynamicContext->Get(), "eventHub", &eventHub) != napi_ok) { + TAG_LOGE(AAFwkTag::APPKIT, "napi_get_named_property failed"); + return nullptr; + } + if (eventHub == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "napi_get_named_property failed, eventHub nullptr"); + return nullptr; + } + if (!CallNapiSetNativeEventHubRefFn(aniEnv, aniObj, napiEnv, eventHub)) { + TAG_LOGE(AAFwkTag::APPKIT, "CallNapiSetNativeEventHubRefFn failed"); + return nullptr; + } + hybridgref dynamicHybrigRef = nullptr; + if (!hybridgref_create_from_napi(napiEnv, dynamicContext->Get(), &dynamicHybrigRef)) { + TAG_LOGE(AAFwkTag::APPKIT, "hybridgref_create_from_napi failed"); + return nullptr; + } + if (!hybridgref_get_esvalue(aniEnv, dynamicHybrigRef, &staticResult)) { + TAG_LOGE(AAFwkTag::APPKIT, "hybridgref_get_esvalue failed"); + hybridgref_delete_from_napi(napiEnv, dynamicHybrigRef); + return nullptr; + } + hybridgref_delete_from_napi(napiEnv, dynamicHybrigRef); + if (!arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr)) { + TAG_LOGE(AAFwkTag::APPKIT, "arkts_napi_scope_close_n failed"); + return nullptr; + } + } + return staticResult; +} + +bool EventHub::CallNapiSetNativeEventHubRefFn(ani_env *aniEnv, ani_object aniObj, napi_env napiEnv, + napi_value eventHub) +{ + napi_value setNativeEventHubRefFn = nullptr; + if (napi_get_named_property(napiEnv, eventHub, "setNativeEventHubRef", &setNativeEventHubRefFn) != napi_ok) { + TAG_LOGE(AAFwkTag::APPKIT, "napi_get_named_property failed"); + return false; + } + if (setNativeEventHubRefFn == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null method: setNativeEventHubRef"); + return false; + } + hybridgref nativeHybrigRef = nullptr; + if (!hybridgref_create_from_ani(aniEnv, static_cast(aniObj), &nativeHybrigRef)) { + TAG_LOGE(AAFwkTag::APPKIT, "hybridgref_create_from_ani failed"); + return false; + } + napi_value nativeEventHubRef {}; + if (!hybridgref_get_napi_value(napiEnv, nativeHybrigRef, &nativeEventHubRef)) { + TAG_LOGE(AAFwkTag::APPKIT, "hybridgref_get_napi_value failed"); + hybridgref_delete_from_ani(aniEnv, nativeHybrigRef); + return false; + } + hybridgref_delete_from_ani(aniEnv, nativeHybrigRef); + napi_value dynamicResult; + if (napi_call_function(napiEnv, eventHub, setNativeEventHubRefFn, 1, &nativeEventHubRef, + &dynamicResult) != napi_ok) { + TAG_LOGE(AAFwkTag::APPKIT, "napi_call_function failed"); + return false; + } + return true; +} + +void EventHub::InitAniEventHub(ani_env *aniEnv) +{ + TAG_LOGI(AAFwkTag::APPKIT, "called"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_class contextCls = nullptr; + if (aniEnv->FindClass(ETS_EVENT_HUB_CLASS_NAME, &contextCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed"); + return; + } + std::array contextFunctions = { + ani_native_function {"getDynamicContextEventHub", ":Lstd/interop/ESValue;", + reinterpret_cast(GetDynamicContextEventHub)}, + }; + aniEnv->Class_BindNativeMethods(contextCls, contextFunctions.data(), + contextFunctions.size()); +} + +void EventHub::SetEventHubContext(ani_env *aniEnv, ani_ref eventHubRef, ani_long nativeContextLong) +{ + TAG_LOGD(AAFwkTag::APPKIT, "called"); + if (aniEnv == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return; + } + ani_status status = ANI_ERROR; + ani_class contextCls = nullptr; + if (aniEnv->FindClass(ETS_EVENT_HUB_CLASS_NAME, &contextCls) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "FindClass Context failed"); + return; + } + ani_field contextField; + if ((status = aniEnv->Class_FindField(contextCls, "nativeContext", &contextField)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Class_FindField failed status: %{public}d", status); + return; + } + if ((status = aniEnv->Object_SetField_Long(static_cast(eventHubRef), contextField, + nativeContextLong)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Object_SetField_Long failed status: %{public}d", status); + return; + } +} +} +} \ No newline at end of file diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index def8a993939e9bdd8f0449cee0fa65ee812f1e0a..efa1a659ad3f98ab041fa7a17a09a4533ca3ae5c 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -1176,6 +1176,23 @@ ohos_prebuilt_etc("application_state_observer_abc_etc") { deps = [ ":application_state_observer_abc" ] } +generate_static_abc("ability_runtime_event_hub_abc") { + base_url = "./" + files = [ "./application/EventHub.ets" ] + + is_boot_abc = "True" + device_dst_file ="/system/framework/ability_runtime_event_hub_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_event_hub_abc_etc") { + source = "$target_out_dir/ability_runtime_event_hub_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_event_hub_abc" ] +} + + group("ets_packages") { deps = [ ":ability_application_abc_etc", @@ -1217,6 +1234,7 @@ group("ets_packages") { ":ability_runtime_data_uri_utils_abc_etc", ":ability_runtime_environment_callback_abc_etc", ":ability_runtime_error_code_abc_etc", + ":ability_runtime_event_hub_abc_etc", ":ability_runtime_extension_ability_abc_etc", ":ability_runtime_extension_context_abc_etc", ":ability_runtime_extension_running_info_abc_etc", diff --git a/frameworks/ets/ets/application/AbilityStageContext.ets b/frameworks/ets/ets/application/AbilityStageContext.ets index 1bbdab8ae8aaca49c37d5810d2f2c75db3a1bbd3..cec359860ec95dfd57cd92342f407d4574531f0e 100644 --- a/frameworks/ets/ets/application/AbilityStageContext.ets +++ b/frameworks/ets/ets/application/AbilityStageContext.ets @@ -19,16 +19,10 @@ import { HapModuleInfo } from 'bundleManager.HapModuleInfo' export default class AbilityStageContext extends Context { static { - loadLibrary("context_ani"); loadLibrary("ability_stage_context_ani_kit.z"); } config?: Configuration; - currentHapModuleInfo: HapModuleInfo; - native constructor(); - constructor(currentHapModuleInfo: HapModuleInfo) { - super(); - this.currentHapModuleInfo = currentHapModuleInfo; - } + currentHapModuleInfo!: HapModuleInfo; private static native nativeTransferStatic(input: ESValue, type: string): Object; private static native nativeTransferDynamic(input: Object): ESValue; diff --git a/frameworks/ets/ets/application/Context.ets b/frameworks/ets/ets/application/Context.ets index b3394932abd268068a09813a41f7af0a6be84522..e285cb169afb91b147fbd4f64299068b6bf07f99 100644 --- a/frameworks/ets/ets/application/Context.ets +++ b/frameworks/ets/ets/application/Context.ets @@ -14,6 +14,7 @@ */ import BaseContext from 'application.BaseContext' +import EventHub from 'application.EventHub'; import ApplicationContext from 'application.ApplicationContext' import AsyncCallbackWrapper from '../utils/AbilityUtils'; import { AsyncCallback } from '@ohos.base'; @@ -37,7 +38,6 @@ let unregisterToken = new object(); export class Context extends BaseContext { static { - loadLibrary("context_ani"); loadLibrary("context_ani_kit.z"); } @@ -52,15 +52,16 @@ export class Context extends BaseContext { distributedFilesDir: string = ""; bundleCodeDir: string = ""; resourceDir: string = ""; - applicationInfo: ApplicationInfo; - resourceManager: resmgr.ResourceManager; processName: string = ""; - native constructor(); - constructor(applicationInfo: ApplicationInfo, resourceManager: resmgr.ResourceManager) { - super(); - this.applicationInfo = applicationInfo; - this.resourceManager = resourceManager; + applicationInfo!: ApplicationInfo; + resourceManager!: resmgr.ResourceManager; + eventHub: EventHub = new EventHub(); + constructor() { + if (this.eventHub == null) { + this.eventHub = new EventHub(); + } } + private setEtsContextPtr(ptr: long) { if (this.etsContextPtr == 0) { this.etsContextPtr = ptr; diff --git a/frameworks/ets/ets/application/EventHub.ets b/frameworks/ets/ets/application/EventHub.ets new file mode 100644 index 0000000000000000000000000000000000000000..4a85ee9b96c46130cb8703543efd68efb7609fb8 --- /dev/null +++ b/frameworks/ets/ets/application/EventHub.ets @@ -0,0 +1,127 @@ +/* + * 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. + */ + +export type ESValueArgs = ESValue | Object | null | undefined +export type FixedArgs = Object | null | undefined + +export default class EventHub { + private nativeContext: long = 0; + private eventMap: Map = new Map(); + private dynamicContextEventHub?: ESValue; + private native getDynamicContextEventHub(): ESValue; + + on(event: string, callback: Function): void { + if (!this.eventMap.has(event)) { + this.eventMap.set(event, []); + } + const callbacks = this.eventMap.get(event)!; + let foundIndex = -1; + for (let i = 0; i < callbacks.length; i++) { + if (callbacks[i] == callback) { + foundIndex = i; + break; + } + } + if (foundIndex == -1) { + callbacks.push(callback); + } + if (!this.dynamicContextEventHub) { + this.dynamicContextEventHub = this.getDynamicContextEventHub(); + } + } + + offByNativeContext(event: string, callback?: Function): void { + if (!this.eventMap.has(event)) { + return; + } + if (!callback) { + this.eventMap.delete(event); + } else { + const callbacks = this.eventMap.get(event)!; + let foundIndex = -1; + for (let i = 0; i < callbacks.length; i++) { + if (callbacks[i] == callback) { + foundIndex = i; + break; + } + } + if (foundIndex > -1) { + callbacks.splice(foundIndex, 1); + } + if (callbacks.length === 0) { + this.eventMap.delete(event); + } + } + } + + off(event: string, callback: Function): void { + this.offByNativeContext(event, callback); + if (!this.dynamicContextEventHub) { + this.dynamicContextEventHub = this.getDynamicContextEventHub(); + } + this.dynamicContextEventHub!.getProperty("eventHub").invokeMethod("offByNativeContext", ESValue.wrap(event), ESValue.wrap(callback)); + } + + offByDynamicContext(event: string, callback: Function): void { + this.offByNativeContext(event, callback); + } + + off(event: string): void { + this.offByNativeContext(event, undefined); + if (!this.dynamicContextEventHub) { + this.dynamicContextEventHub = this.getDynamicContextEventHub(); + } + this.dynamicContextEventHub!.getProperty("eventHub").invokeMethod("offByNativeContext", ESValue.wrap(event)); + } + + offByDynamicContext(event: string): void { + this.offByNativeContext(event, undefined); + } + + private emitByStaticContext(event: string, ...args: FixedArray<(Object|null|undefined)>): void { + if (!this.eventMap.has(event)) { + return; + } + const callbacks = [...this.eventMap.get(event)!]; + callbacks.forEach(callback => { + try { + callback.unsafeCall(...args); + } catch (err) { + console.error(`Error '${event}'`, err); + } + }); + } + + emit(event: string, ...args: (Object|null|undefined)[]): void { + let fixedArgs: FixedArray<(Object|null|undefined)> = new FixedArgs[args.length]; + for (let i = 0; i < args.length; i++) { + fixedArgs[i] = args[i]; + } + this.emitByStaticContext(event, ...fixedArgs); + if (!this.dynamicContextEventHub) { + this.dynamicContextEventHub = this.getDynamicContextEventHub(); + } + let params: FixedArray = new ESValueArgs[args.length + 1]; + params[0] = ESValue.wrap(event); + for (let i = 0; i < args.length; i++) { + params[i + 1] = ESValue.wrap(args[i]); + } + this.dynamicContextEventHub!.getProperty("eventHub").invokeMethod("emitByNativeContext", ...params); + } + + emitByDynamicContext(event: string, ...args: FixedArray<(Object|null|undefined)>): void { + this.emitByStaticContext(event, ...args); + } +} \ No newline at end of file diff --git a/frameworks/ets/ets/application/ExtensionContext.ets b/frameworks/ets/ets/application/ExtensionContext.ets index df825c771b6d2c3ae2ba37643bbedeb85a3b575c..f8c788f81607c6c22d8101b23053f2409f07a760 100644 --- a/frameworks/ets/ets/application/ExtensionContext.ets +++ b/frameworks/ets/ets/application/ExtensionContext.ets @@ -14,22 +14,12 @@ */ import Context from 'application.Context' -import {ExtensionAbilityInfo} from 'bundleManager.ExtensionAbilityInfo' +import { ExtensionAbilityInfo } from 'bundleManager.ExtensionAbilityInfo' import { Configuration } from '@ohos.app.ability.Configuration' import { HapModuleInfo } from 'bundleManager.HapModuleInfo' export default class ExtensionContext extends Context { - static { - loadLibrary("context_ani"); - } - extensionAbilityInfo: ExtensionAbilityInfo; - config: Configuration; - currentHapModuleInfo: HapModuleInfo; - native constructor(); - constructor(config: Configuration, extensionAbilityInfo: ExtensionAbilityInfo, currentHapModuleInfo: HapModuleInfo) { - super(); - this.config = config; - this.extensionAbilityInfo = extensionAbilityInfo; - this.currentHapModuleInfo = currentHapModuleInfo; - } + extensionAbilityInfo!: ExtensionAbilityInfo; + config!: Configuration; + currentHapModuleInfo!: HapModuleInfo; } \ No newline at end of file diff --git a/frameworks/ets/ets/application/FormExtensionContext.ets b/frameworks/ets/ets/application/FormExtensionContext.ets index 63fcfbf217efef67388aabe9fc2599deea196200..d99bc13c81cf2d246ce9ef1a790cd0935aab03ed 100644 --- a/frameworks/ets/ets/application/FormExtensionContext.ets +++ b/frameworks/ets/ets/application/FormExtensionContext.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import ExtensionContext from './ExtensionContext'; +import ExtensionContext from 'application.ExtensionContext'; export default class FormExtensionContext extends ExtensionContext { diff --git a/frameworks/ets/ets/application/UIAbilityContext.ets b/frameworks/ets/ets/application/UIAbilityContext.ets index 2335e6fff012071acd34df404f394afbcede7831..4be5cc5c242fe2446d165fe76303de52f4b82d27 100644 --- a/frameworks/ets/ets/application/UIAbilityContext.ets +++ b/frameworks/ets/ets/application/UIAbilityContext.ets @@ -49,26 +49,15 @@ let unregisterToken = new object(); export default class UIAbilityContext extends Context { static { - loadLibrary("context_ani"); loadLibrary("ability_context_ani_kit.z"); } private cleaner: Cleaner | null = null; etsAbilityContextPtr: long = 0; - config: Configuration; - abilityInfo: AbilityInfo; - windowStage: window.WindowStage; - currentHapModuleInfo: HapModuleInfo; - - native constructor(); - - constructor(config: Configuration, abilityInfo: AbilityInfo, windowStage: window.WindowStage, currentHapModuleInfo: HapModuleInfo) { - super(); - this.config = config; - this.abilityInfo = abilityInfo; - this.windowStage = windowStage; - this.currentHapModuleInfo = currentHapModuleInfo; - } + config!: Configuration; + abilityInfo!: AbilityInfo; + windowStage!: window.WindowStage; + currentHapModuleInfo!: HapModuleInfo; private setEtsAbilityContextPtr(ptr: long) { if (this.etsAbilityContextPtr == 0) { diff --git a/frameworks/js/napi/app/context/context.js b/frameworks/js/napi/app/context/context.js index 0c922fcefdd89394c3b80c8d1a9fdc1f17a07d1e..29f1120177aaa1bcab5e54470e2f68d6d2ee0316 100644 --- a/frameworks/js/napi/app/context/context.js +++ b/frameworks/js/napi/app/context/context.js @@ -16,11 +16,16 @@ class EventHub { constructor() { this.eventMap = {}; + this.nativeEventHubRef = null; this.contextIndex = -1; this.emitMultiThreadingEnabled = false; this.emitter = undefined; } + setNativeEventHubRef(ref) { + this.nativeEventHubRef = ref; + } + onEmitterFunction(eventData = {'data':{}}) { let eventName = eventData.data[`arg${0}`]; let arrays = Object.keys(eventData.data); @@ -91,6 +96,26 @@ class EventHub { } } + offByNativeContext(event, callback) { + if (typeof (event) !== 'string') { + return; + } + if (this.eventMap[event]) { + if (callback) { + let cbArray = this.eventMap[event]; + let index = cbArray.indexOf(callback); + if (index > -1) { + for (; index + 1 < cbArray.length; index++) { + cbArray[index] = cbArray[index + 1]; + } + cbArray.pop(); + } + } else { + delete this.eventMap[event]; + } + } + } + off(event, callback) { if (typeof (event) !== 'string') { return; @@ -109,6 +134,14 @@ class EventHub { delete this.eventMap[event]; } } + if (this.nativeEventHubRef != null) { + // call native eventHub off + if (callback) { + this.nativeEventHubRef.offByDynamicContext(event, callback); + } else { + this.nativeEventHubRef.offByDynamicContext(event); + } + } if (this.emitMultiThreadingEnabled === true && this.emitter !== undefined) { let array = this.eventMap[event]; if (array === null || array === undefined) { @@ -139,6 +172,22 @@ class EventHub { cloneArray[i].apply(this, args); } } + if (this.nativeEventHubRef != null) { + this.nativeEventHubRef.emitByDynamicContext(event, ...args); + } + } + + emitByNativeContext(event, ...args) { + if (typeof (event) !== 'string') { + return; + } + if (this.eventMap[event]) { + const cloneArray = [...this.eventMap[event]]; + const len = cloneArray.length; + for (let i = 0; i < len; ++i) { + cloneArray[i].apply(this, args); + } + } } }