From edfedc61d630a4ed909a04569a6ec641ff1636d0 Mon Sep 17 00:00:00 2001 From: "zhangyafei.echo" Date: Tue, 8 Jul 2025 17:18:41 +0800 Subject: [PATCH] Description:add context transfer dynamic Sig:SIG_ApplicationFramework Feature or BugFix: Feature Binary Source: No Signed-off-by: zhangyafei.echo Change-Id: I60311120b492a947ab91a7035e304e55669c7988 --- .../ani/ani_common/include/ani_common_util.h | 3 +- .../ani/ani_common/src/ani_common_util.cpp | 37 +++++ .../ets_ability_stage_context_module.h | 10 +- .../src/ets_ability_stage_context_module.cpp | 119 ++++++++++++++-- .../include/ets_application_context_module.h | 10 +- .../src/ets_application_context_module.cpp | 130 ++++++++++++++++-- .../app/context/include/ets_context_module.h | 10 +- .../app/context/src/ets_context_module.cpp | 107 ++++++++++++-- .../ets/application/AbilityStageContext.ets | 32 +++-- .../ets/application/ApplicationContext.ets | 14 +- frameworks/ets/ets/application/Context.ets | 13 +- .../js/napi/application/js_application.cpp | 23 +++- .../ability_runtime/js_ability_context.cpp | 3 + frameworks/native/appkit/BUILD.gn | 2 + .../app/js_ability_stage_context.cpp | 4 + .../context/bindable_sub_thread.cpp | 84 +++++++++++ .../context/context_transfer.cpp | 67 +++++++++ .../context/js_application_context_utils.cpp | 3 + .../context/js_context_utils.cpp | 3 + .../context/bindable_sub_thread.h | 49 +++++++ .../appkit/ability_runtime/context/context.h | 5 +- .../context/context_transfer.h | 52 +++++++ 22 files changed, 717 insertions(+), 63 deletions(-) create mode 100755 frameworks/native/appkit/ability_runtime/context/bindable_sub_thread.cpp create mode 100755 frameworks/native/appkit/ability_runtime/context/context_transfer.cpp create mode 100755 interfaces/kits/native/appkit/ability_runtime/context/bindable_sub_thread.h create mode 100755 interfaces/kits/native/appkit/ability_runtime/context/context_transfer.h diff --git a/frameworks/ets/ani/ani_common/include/ani_common_util.h b/frameworks/ets/ani/ani_common/include/ani_common_util.h index b04d07660a1..99ac43b3221 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_util.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_util.h @@ -68,7 +68,8 @@ bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref va bool WrapArrayString(ani_env *env, ani_object &arrayObj, const std::vector &values); bool UnwrapArrayString(ani_env *env, const ani_object &arrayObj, std::vector &stringList); ani_object CreateEmptyArray(ani_env *env); + +bool GetStaticFieldString(ani_env *env, ani_class classObj, const char *fieldName, std::string &value); } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_ANI_COMMON_UTIL_H - \ No newline at end of file diff --git a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp index 613a23e926e..0f883c73474 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -1053,5 +1053,42 @@ ani_object CreateEmptyArray(ani_env *env) } return arrayObj; } + +bool GetStaticFieldString(ani_env *env, ani_class classObj, const char *fieldName, std::string &value) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::JSNAPI, "null env"); + return false; + } + + ani_status status = ANI_ERROR; + ani_static_field field {}; + if ((status = env->Class_FindStaticField(classObj, fieldName, &field)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Class_FindStaticField status: %{public}d", status); + return false; + } + + ani_ref obj = nullptr; + if ((status = env->Class_GetStaticField_Ref(classObj, field, &obj)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "Class_GetStaticField_Ref status: %{public}d", status); + return false; + } + + ani_boolean isUndefined = true; + if ((status = env->Reference_IsUndefined(obj, &isUndefined)) != ANI_OK) { + TAG_LOGE(AAFwkTag::JSNAPI, "status: %{public}d", status); + return false; + } + if (isUndefined) { + TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s : undefined", fieldName); + return false; + } + + if (!AppExecFwk::GetStdString(env, reinterpret_cast(obj), value)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); + return false; + } + return true; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h b/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h index e98ff1d9864..2ab52dfb83a 100755 --- a/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h +++ b/frameworks/ets/ani/app/ability_stage_context/include/ets_ability_stage_context_module.h @@ -33,15 +33,17 @@ public: EtsAbilityStageContextModule& operator=(const EtsAbilityStageContextModule&) = delete; EtsAbilityStageContextModule& operator=(EtsAbilityStageContextModule&&) = delete; - static ani_object NativeTransferStatic(ani_env *aniEnv, ani_object aniObj, ani_object input); - static ani_object NativeTransferDynamic(ani_env *aniEnv, ani_object aniObj, ani_object input); + static ani_object NativeTransferStatic(ani_env *aniEnv, ani_object aniObj, ani_object input, ani_object type); + static ani_object NativeTransferDynamic(ani_env *aniEnv, ani_class aniCls, ani_object input); + static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr abilityStageContext); private: static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); - static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, - std::shared_ptr abilityStageContext); static std::unique_ptr CreateNativeReference(napi_env napiEnv, std::shared_ptr abilityStageContext); + static ani_object CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, + std::shared_ptr abilityStageContext); }; void EtsAbilityStageContextModuleInit(ani_env *aniEnv); diff --git a/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp b/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp index 6f20b207845..41eed5694c6 100755 --- a/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp +++ b/frameworks/ets/ani/app/ability_stage_context/src/ets_ability_stage_context_module.cpp @@ -20,8 +20,11 @@ #include #include "ability_stage_context.h" #include "ani_base_context.h" +#include "ani_common_util.h" +#include "context_transfer.h" #include "hilog_tag_wrapper.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_ability_stage_context.h" @@ -36,7 +39,8 @@ namespace { constexpr const char *ETS_ABILITY_STAGE_CONTEXT_CLASS_NAME = "Lapplication/AbilityStageContext/AbilityStageContext;"; } // namespace -ani_object EtsAbilityStageContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input) +ani_object EtsAbilityStageContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input, + ani_object type) { TAG_LOGD(AAFwkTag::CONTEXT, "transfer static AbilityStageContext"); if (aniEnv == nullptr) { @@ -85,7 +89,15 @@ ani_object EtsAbilityStageContextModule::NativeTransferStatic(ani_env *aniEnv, a } // if not exist, create a new one - auto newContext = STSAbilityStageContext::CreateStsAbilityStageContext(aniEnv, abilityStageContext); + std::string contextType; + if (!AppExecFwk::GetStdString(aniEnv, reinterpret_cast(type), contextType)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + TAG_LOGD(AAFwkTag::CONTEXT, "contextType %{public}s", contextType.c_str()); + + auto newContext = ContextTransfer::GetInstance().GetStaticObject(contextType, aniEnv, context); if (newContext == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "create abilityStageContext failed"); ThrowStsTransferClassError(aniEnv); @@ -153,7 +165,17 @@ std::unique_ptr EtsAbilityStageContextModule::GetOrCreateNative // if sub-thread, create a new abilityStageContext and return if (getpid() != syscall(SYS_gettid)) { - return CreateNativeReference(napiEnv, abilityStageContext); + auto subThreadObj = static_cast( + abilityStageContext->GetSubThreadObject(static_cast(napiEnv))); + if (subThreadObj != nullptr) { + return std::unique_ptr(subThreadObj); + } + auto subThreadRef = CreateNativeReference(napiEnv, abilityStageContext); + if (subThreadRef == nullptr) { + return nullptr; + } + abilityStageContext->BindSubThreadObject(static_cast(napiEnv), static_cast(subThreadRef.get())); + return subThreadRef; } // if main-thread, get bindingObj firstly @@ -180,7 +202,7 @@ std::unique_ptr EtsAbilityStageContextModule::GetOrCreateNative return nativeRef; } -ani_object EtsAbilityStageContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, ani_object input) +ani_object EtsAbilityStageContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_class aniCls, ani_object input) { TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic AbilityStageContext"); if (!IsInstanceOf(aniEnv, input)) { @@ -196,16 +218,69 @@ ani_object EtsAbilityStageContextModule::NativeTransferDynamic(ani_env *aniEnv, return nullptr; } - auto abilityStageContext = Context::ConvertTo(context); + std::shared_ptr abilityStageContext = Context::ConvertTo(context); if (abilityStageContext == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityStageContext"); ThrowStsTransferClassError(aniEnv); return nullptr; } - // Not support yet - ThrowStsTransferClassError(aniEnv); - return nullptr; + ani_object object = CreateDynamicObject(aniEnv, aniCls, abilityStageContext); + if (object == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid object"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return object; +} + +ani_object EtsAbilityStageContextModule::CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, + std::shared_ptr abilityStageContext) +{ + std::string contextType; + if (!AppExecFwk::GetStaticFieldString(aniEnv, aniCls, "contextType", contextType)) { + TAG_LOGE(AAFwkTag::CONTEXT, "get context type failed"); + return nullptr; + } + TAG_LOGD(AAFwkTag::CONTEXT, "contextType %{public}s", contextType.c_str()); + + // get napiEnv from aniEnv + napi_env napiEnv = {}; + if (!arkts_napi_scope_open(aniEnv, &napiEnv)) { + TAG_LOGE(AAFwkTag::CONTEXT, "arkts_napi_scope_open failed"); + return nullptr; + } + + // create normal abilitystage context + auto contextObj = ContextTransfer::GetInstance().GetDynamicObject(contextType, napiEnv, abilityStageContext); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "create AbilityStageContext failed"); + return nullptr; + } + + hybridgref ref = nullptr; + bool success = hybridgref_create_from_napi(napiEnv, contextObj, &ref); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_create_from_napi failed"); + return nullptr; + } + + ani_object result = nullptr; + success = hybridgref_get_esvalue(aniEnv, ref, &result); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_get_esvalue failed"); + return nullptr; + } + + hybridgref_delete_from_napi(napiEnv, ref); + + if (!arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr)) { + TAG_LOGE(AAFwkTag::CONTEXT, "arkts_napi_scope_close_n failed"); + return nullptr; + } + + return result; } bool EtsAbilityStageContextModule::IsInstanceOf(ani_env *aniEnv, ani_object aniObj) @@ -244,7 +319,7 @@ void EtsAbilityStageContextModuleInit(ani_env *aniEnv) } std::array nativeFuncs = { - ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;Lstd/core/String;:Lstd/core/Object;", reinterpret_cast(EtsAbilityStageContextModule::NativeTransferStatic) }, ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", reinterpret_cast(EtsAbilityStageContextModule::NativeTransferDynamic) }, @@ -255,6 +330,32 @@ void EtsAbilityStageContextModuleInit(ani_env *aniEnv) return; } + ContextTransfer::GetInstance().RegisterStaticObjectCreator("AbilityStageContext", + [](ani_env *aniEnv, std::shared_ptr context) -> ani_object { + auto newContext = STSAbilityStageContext::CreateStsAbilityStageContext(aniEnv, context); + if (newContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "create abilityStageContext failed"); + return nullptr; + } + + return newContext; + }); + + ContextTransfer::GetInstance().RegisterDynamicObjectCreator("AbilityStageContext", + [](napi_env napiEnv, std::shared_ptr context) -> napi_value { + auto abilityStageContext = Context::ConvertTo(context); + if (abilityStageContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityStageContext"); + return nullptr; + } + + auto ref = EtsAbilityStageContextModule::GetOrCreateNativeReference(napiEnv, abilityStageContext); + if (ref == nullptr) { + return nullptr; + } + return ref->Get(); + }); + TAG_LOGD(AAFwkTag::CONTEXT, "Init AbilityStageContext kit end"); } diff --git a/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h b/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h index 5955f66d16e..208ae2c67e4 100755 --- a/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h +++ b/frameworks/ets/ani/app/application_context/include/ets_application_context_module.h @@ -33,15 +33,17 @@ public: EtsApplicationContextModule& operator=(const EtsApplicationContextModule&) = delete; EtsApplicationContextModule& operator=(EtsApplicationContextModule&&) = delete; - static ani_object NativeTransferStatic(ani_env *aniEnv, ani_object aniObj, ani_object input); - static ani_object NativeTransferDynamic(ani_env *aniEnv, ani_object aniObj, ani_object input); + static ani_object NativeTransferStatic(ani_env *aniEnv, ani_object aniObj, ani_object input, ani_object type); + static ani_object NativeTransferDynamic(ani_env *aniEnv, ani_class aniCls, ani_object input); + static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, + std::shared_ptr applicationContext); private: static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); - static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, - std::shared_ptr applicationContext); static std::unique_ptr CreateNativeReference(napi_env napiEnv, std::shared_ptr applicationContext); + static ani_object CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, + std::shared_ptr applicationContext); }; void EtsApplicationContextModuleInit(ani_env *aniEnv); diff --git a/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp b/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp index 958ed653ce8..2cc5e526b76 100755 --- a/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp +++ b/frameworks/ets/ani/app/application_context/src/ets_application_context_module.cpp @@ -19,10 +19,14 @@ #include #include #include "ani_base_context.h" +#include "ani_common_util.h" #include "application_context_manager.h" +#include "bindable_sub_thread.h" +#include "context_transfer.h" #include "ets_application_context_utils.h" #include "hilog_tag_wrapper.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_application_context_utils.h" @@ -37,7 +41,8 @@ namespace { constexpr const char *ETS_APPLICATION_CONTEXT_CLASS_NAME = "Lapplication/ApplicationContext/ApplicationContext;"; } // namespace -ani_object EtsApplicationContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input) +ani_object EtsApplicationContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object self, ani_object input, + ani_object type) { TAG_LOGD(AAFwkTag::CONTEXT, "transfer static ApplicationContext"); if (aniEnv == nullptr) { @@ -86,15 +91,22 @@ ani_object EtsApplicationContextModule::NativeTransferStatic(ani_env *aniEnv, an } // create a new one - EtsApplicationContextUtils::CreateEtsApplicationContext(aniEnv); - auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); - if (appContextObj == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "appContextObj is nullptr"); + std::string contextType; + if (!AppExecFwk::GetStdString(aniEnv, reinterpret_cast(type), contextType)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); ThrowStsTransferClassError(aniEnv); return nullptr; } + TAG_LOGD(AAFwkTag::CONTEXT, "contextType %{public}s", contextType.c_str()); - return appContextObj->aniObj; + auto contextObj = ContextTransfer::GetInstance().GetStaticObject(contextType, aniEnv, context); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "create object failed"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return contextObj; } std::unique_ptr EtsApplicationContextModule::CreateNativeReference(napi_env napiEnv, @@ -155,7 +167,17 @@ std::unique_ptr EtsApplicationContextModule::GetOrCreateNativeR // if sub-thread, create a new applicationContext and return if (getpid() != syscall(SYS_gettid)) { - return CreateNativeReference(napiEnv, applicationContext); + auto subThreadObj = static_cast( + applicationContext->GetSubThreadObject(static_cast(napiEnv))); + if (subThreadObj != nullptr) { + return std::unique_ptr(subThreadObj); + } + auto subThreadRef = CreateNativeReference(napiEnv, applicationContext); + if (subThreadRef == nullptr) { + return nullptr; + } + applicationContext->BindSubThreadObject(static_cast(napiEnv), static_cast(subThreadRef.get())); + return subThreadRef; } // if main-thread, get bindingObj firstly @@ -182,11 +204,11 @@ std::unique_ptr EtsApplicationContextModule::GetOrCreateNativeR return nativeRef; } -ani_object EtsApplicationContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, ani_object input) +ani_object EtsApplicationContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_class aniCls, ani_object input) { TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic ApplicationContext"); if (!IsInstanceOf(aniEnv, input)) { - TAG_LOGE(AAFwkTag::CONTEXT, "not AbilityStageContext"); + TAG_LOGE(AAFwkTag::CONTEXT, "not ApplicationContext"); ThrowStsTransferClassError(aniEnv); return nullptr; } @@ -198,16 +220,69 @@ ani_object EtsApplicationContextModule::NativeTransferDynamic(ani_env *aniEnv, a return nullptr; } - auto applicationContext = Context::ConvertTo(context); + std::shared_ptr applicationContext = Context::ConvertTo(context); if (applicationContext == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "invalid applicationContext"); ThrowStsTransferClassError(aniEnv); return nullptr; } - // Not support yet - ThrowStsTransferClassError(aniEnv); - return nullptr; + ani_object object = CreateDynamicObject(aniEnv, aniCls, applicationContext); + if (object == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid object"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return object; +} + +ani_object EtsApplicationContextModule::CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, + std::shared_ptr applicationContext) +{ + std::string contextType; + if (!AppExecFwk::GetStaticFieldString(aniEnv, aniCls, "contextType", contextType)) { + TAG_LOGE(AAFwkTag::CONTEXT, "get context type failed"); + return nullptr; + } + TAG_LOGD(AAFwkTag::CONTEXT, "contextType %{public}s", contextType.c_str()); + + // get napiEnv from aniEnv + napi_env napiEnv = {}; + if (!arkts_napi_scope_open(aniEnv, &napiEnv)) { + TAG_LOGE(AAFwkTag::CONTEXT, "arkts_napi_scope_open failed"); + return nullptr; + } + + // create normal application context + auto contextObj = ContextTransfer::GetInstance().GetDynamicObject(contextType, napiEnv, applicationContext); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "create ApplicationContext failed"); + return nullptr; + } + + hybridgref ref = nullptr; + bool success = hybridgref_create_from_napi(napiEnv, contextObj, &ref); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_create_from_napi failed"); + return nullptr; + } + + ani_object result = nullptr; + success = hybridgref_get_esvalue(aniEnv, ref, &result); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_get_esvalue failed"); + return nullptr; + } + + hybridgref_delete_from_napi(napiEnv, ref); + + if (!arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr)) { + TAG_LOGE(AAFwkTag::CONTEXT, "arkts_napi_scope_close_n failed"); + return nullptr; + } + + return result; } bool EtsApplicationContextModule::IsInstanceOf(ani_env *aniEnv, ani_object aniObj) @@ -246,7 +321,7 @@ void EtsApplicationContextModuleInit(ani_env *aniEnv) } std::array nativeFuncs = { - ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;Lstd/core/String;:Lstd/core/Object;", reinterpret_cast(EtsApplicationContextModule::NativeTransferStatic) }, ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", reinterpret_cast(EtsApplicationContextModule::NativeTransferDynamic) }, @@ -257,6 +332,33 @@ void EtsApplicationContextModuleInit(ani_env *aniEnv) return; } + ContextTransfer::GetInstance().RegisterStaticObjectCreator("ApplicationContext", + [](ani_env *aniEnv, std::shared_ptr context) -> ani_object { + EtsApplicationContextUtils::CreateEtsApplicationContext(aniEnv); + auto appContextObj = ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject(); + if (appContextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "appContextObj is nullptr"); + return nullptr; + } + + return appContextObj->aniObj; + }); + + ContextTransfer::GetInstance().RegisterDynamicObjectCreator("ApplicationContext", + [](napi_env napiEnv, std::shared_ptr context) -> napi_value { + auto applicationContext = Context::ConvertTo(context); + if (applicationContext == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid applicationContext"); + return nullptr; + } + + auto ref = EtsApplicationContextModule::GetOrCreateNativeReference(napiEnv, applicationContext); + if (ref == nullptr) { + return nullptr; + } + return ref->Get(); + }); + TAG_LOGD(AAFwkTag::CONTEXT, "Init application context kit end"); } diff --git a/frameworks/ets/ani/app/context/include/ets_context_module.h b/frameworks/ets/ani/app/context/include/ets_context_module.h index b4c60fc6705..acb1600dcf8 100755 --- a/frameworks/ets/ani/app/context/include/ets_context_module.h +++ b/frameworks/ets/ani/app/context/include/ets_context_module.h @@ -34,19 +34,21 @@ public: EtsContextModule& operator=(const EtsContextModule&) = delete; EtsContextModule& operator=(EtsContextModule&&) = delete; - static ani_object NativeTransferStatic(ani_env *env, ani_object aniObj, ani_object input); - static ani_object NativeTransferDynamic(ani_env *env, ani_object aniObj, ani_object input); - -private: + static ani_object NativeTransferStatic(ani_env *env, ani_object aniObj, ani_object input, ani_object type); + static ani_object NativeTransferDynamic(ani_env *env, ani_class aniCls, ani_object input); static ani_object GetOrCreateAniObject(ani_env *aniEnv, std::shared_ptr context); static std::unique_ptr GetOrCreateNativeReference(napi_env napiEnv, std::shared_ptr context); + +private: static std::unique_ptr CreateNativeReference(napi_env napiEnv, std::shared_ptr context); static std::unique_ptr CreateApplicationNativeReference(napi_env napiEnv, std::shared_ptr applicationContext); static std::unique_ptr CreateAbilityStageNativeReference(napi_env napiEnv, std::shared_ptr abilityStageContext); + static ani_object CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, + std::shared_ptr applicationContext); }; void EtsContextModuleInit(ani_env *aniEnv); 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 67cee0d992b..4a8d9c70a98 100755 --- a/frameworks/ets/ani/app/context/src/ets_context_module.cpp +++ b/frameworks/ets/ani/app/context/src/ets_context_module.cpp @@ -19,11 +19,14 @@ #include #include #include "ani_base_context.h" +#include "ani_common_util.h" #include "application_context_manager.h" +#include "context_transfer.h" #include "ets_application_context_utils.h" #include "event_hub.h" #include "hilog_tag_wrapper.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_ability_stage_context.h" @@ -32,6 +35,7 @@ #include "js_runtime_utils.h" #include "native_engine/native_engine.h" #include "sts_ability_stage_context.h" +#include "sts_context_utils.h" #include "sts_error_utils.h" namespace OHOS { @@ -40,7 +44,7 @@ namespace { constexpr const char *ETS_CONTEXT_CLASS_NAME = "Lapplication/Context/Context;"; } // namespace -ani_object EtsContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input) +ani_object EtsContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object self, ani_object input, ani_object type) { TAG_LOGD(AAFwkTag::CONTEXT, "transfer static Context"); if (aniEnv == nullptr) { @@ -80,6 +84,14 @@ ani_object EtsContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, a return reinterpret_cast(*staticContext); } + std::string contextType; + if (!AppExecFwk::GetStdString(aniEnv, reinterpret_cast(type), contextType)) { + TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + TAG_LOGD(AAFwkTag::CONTEXT, "contextType %{public}s", contextType.c_str()); + auto contextObj = GetOrCreateAniObject(aniEnv, context); if (contextObj == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "contextObj invalid"); @@ -115,7 +127,13 @@ ani_object EtsContextModule::GetOrCreateAniObject(ani_env *aniEnv, std::shared_p } } - return nullptr; + ani_class cls {}; + ani_status status = ANI_ERROR; + if ((status = aniEnv->FindClass("Lapplication/Context/Context;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return nullptr; + } + return ContextUtil::CreateContextObject(aniEnv, cls, context); } std::unique_ptr EtsContextModule::CreateNativeReference(napi_env napiEnv, @@ -313,7 +331,7 @@ std::unique_ptr EtsContextModule::GetOrCreateNativeReference(na return nativeRef; } -ani_object EtsContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, ani_object input) +ani_object EtsContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_class aniCls, ani_object input) { TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic Context"); if (aniEnv == nullptr) { @@ -328,16 +346,69 @@ ani_object EtsContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_object, return nullptr; } - auto contextPtr = Context::ConvertTo(context); + std::shared_ptr contextPtr = Context::ConvertTo(context); if (contextPtr == nullptr) { TAG_LOGE(AAFwkTag::CONTEXT, "invalid Context"); ThrowStsTransferClassError(aniEnv); return nullptr; } - // Not support yet - ThrowStsTransferClassError(aniEnv); - return nullptr; + ani_object object = CreateDynamicObject(aniEnv, aniCls, contextPtr); + if (object == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "invalid object"); + ThrowStsTransferClassError(aniEnv); + return nullptr; + } + + return object; +} + +ani_object EtsContextModule::CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, + std::shared_ptr contextPtr) +{ + std::string contextType; + if (!AppExecFwk::GetStaticFieldString(aniEnv, aniCls, "contextType", contextType)) { + TAG_LOGE(AAFwkTag::CONTEXT, "get context type failed"); + return nullptr; + } + TAG_LOGD(AAFwkTag::CONTEXT, "contextType %{public}s", contextType.c_str()); + + // get napiEnv from aniEnv + napi_env napiEnv = {}; + if (!arkts_napi_scope_open(aniEnv, &napiEnv)) { + TAG_LOGE(AAFwkTag::CONTEXT, "arkts_napi_scope_open failed"); + return nullptr; + } + + // create normal context + auto contextObj = ContextTransfer::GetInstance().GetDynamicObject(contextType, napiEnv, contextPtr); + if (contextObj == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "create Context failed"); + return nullptr; + } + + hybridgref ref = nullptr; + bool success = hybridgref_create_from_napi(napiEnv, contextObj, &ref); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_create_from_napi failed"); + return nullptr; + } + + ani_object result = nullptr; + success = hybridgref_get_esvalue(aniEnv, ref, &result); + if (!success) { + TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_get_esvalue failed"); + return nullptr; + } + + hybridgref_delete_from_napi(napiEnv, ref); + + if (!arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr)) { + TAG_LOGE(AAFwkTag::CONTEXT, "arkts_napi_scope_close_n failed"); + return nullptr; + } + + return result; } void EtsContextModuleInit(ani_env *aniEnv) @@ -356,7 +427,7 @@ void EtsContextModuleInit(ani_env *aniEnv) } std::array nativeFuncs = { - ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;:Lstd/core/Object;", + ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;Lstd/core/String;:Lstd/core/Object;", reinterpret_cast(EtsContextModule::NativeTransferStatic) }, ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", reinterpret_cast(EtsContextModule::NativeTransferDynamic) }, @@ -367,6 +438,26 @@ void EtsContextModuleInit(ani_env *aniEnv) return; } + ContextTransfer::GetInstance().RegisterStaticObjectCreator("Context", + [](ani_env *aniEnv, std::shared_ptr context) -> ani_object { + ani_class cls {}; + ani_status status = ANI_ERROR; + if ((status = aniEnv->FindClass("Lapplication/Context/Context;", &cls)) != ANI_OK) { + TAG_LOGE(AAFwkTag::CONTEXT, "status: %{public}d", status); + return nullptr; + } + return ContextUtil::CreateContextObject(aniEnv, cls, context); + }); + + ContextTransfer::GetInstance().RegisterDynamicObjectCreator("Context", + [](napi_env napiEnv, std::shared_ptr context) -> napi_value { + auto ref = EtsContextModule::GetOrCreateNativeReference(napiEnv, context); + if (ref == nullptr) { + return nullptr; + } + return ref->Get(); + }); + TAG_LOGD(AAFwkTag::CONTEXT, "Init Context kit end"); } diff --git a/frameworks/ets/ets/application/AbilityStageContext.ets b/frameworks/ets/ets/application/AbilityStageContext.ets index cf005f7343e..f6da2648953 100644 --- a/frameworks/ets/ets/application/AbilityStageContext.ets +++ b/frameworks/ets/ets/application/AbilityStageContext.ets @@ -18,20 +18,28 @@ import { Configuration } from '@ohos.app.ability.Configuration' import { HapModuleInfo } from 'bundleManager.HapModuleInfo'; export default class AbilityStageContext extends Context { - static { - loadLibrary("ability_stage_context_ani_kit.z"); - } - config?: Configuration; - currentHapModuleInfo!: HapModuleInfo; + static { + loadLibrary("ability_stage_context_ani_kit.z"); + } + config?: Configuration; + currentHapModuleInfo!: HapModuleInfo; - private static native nativeTransferStatic(input: ESValue): Object; - private static native nativeTransferDynamic(input: Object): ESValue; + private static native nativeTransferStatic(input: ESValue, type: string): Object; + private static native nativeTransferDynamic(input: Object): ESValue; + private static contextType: string = 'AbilityStageContext'; - static transferStatic(input: Any): Object { - return AbilityStageContext.nativeTransferStatic(ESValue.wrap(input)); + static transferStatic(input: Any): Object { + let type: string = ''; + try { + type = ESValue.wrap(input).getProperty('__context_impl__').getProperty('contextType').toString(); + } catch (err) { + console.log('transferStatic err: ' + err.toString()); } + console.log('transferStatic type: ' + type); + return AbilityStageContext.nativeTransferStatic(ESValue.wrap(input), type); + } - static transferDynamic(input: Object): Any { - return AbilityStageContext.nativeTransferDynamic(input).unwrap(); - } + static transferDynamic(input: Object): Any { + return AbilityStageContext.nativeTransferDynamic(input).unwrap(); + } } diff --git a/frameworks/ets/ets/application/ApplicationContext.ets b/frameworks/ets/ets/application/ApplicationContext.ets index 044b902ddb3..064d77ea73b 100644 --- a/frameworks/ets/ets/application/ApplicationContext.ets +++ b/frameworks/ets/ets/application/ApplicationContext.ets @@ -44,8 +44,9 @@ export default class ApplicationContext extends Context { public native nativeOffApplicationStateChangeSync(callback?: ApplicationStateChangeCallback): void; public native nativegetCurrentAppCloneIndex(): number; public native nativegetCurrentInstanceKey(): string; - private static native nativeTransferStatic(input: ESValue): Object; + private static native nativeTransferStatic(input: ESValue, type: string): Object; private static native nativeTransferDynamic(input: Object): ESValue; + private static contextType: string = 'ApplicationContext'; setSupportedProcessCache(isSupported: boolean): void { taskpool.execute((): void => { @@ -171,7 +172,7 @@ export default class ApplicationContext extends Context { }); return p; } - + getAllRunningInstanceKeys(): Promise> { let p = new Promise>((resolve: (data: Array) => void, reject: (err: BusinessError) => void): void => { @@ -245,7 +246,14 @@ export default class ApplicationContext extends Context { } static transferStatic(input: Any): Object { - return ApplicationContext.nativeTransferStatic(ESValue.wrap(input)); + let type: string = ''; + try { + type = ESValue.wrap(input).getProperty('__context_impl__').getProperty('contextType').toString(); + } catch (err) { + console.log('transferStatic err: ' + err.toString()); + } + console.log('transferStatic contextType: ' + type); + return ApplicationContext.nativeTransferStatic(ESValue.wrap(input), type); } static transferDynamic(input: Object): Any { diff --git a/frameworks/ets/ets/application/Context.ets b/frameworks/ets/ets/application/Context.ets index a8500ff198c..a5e84458c68 100644 --- a/frameworks/ets/ets/application/Context.ets +++ b/frameworks/ets/ets/application/Context.ets @@ -53,10 +53,12 @@ export class Context extends BaseContext { public native nativeGetGroupDir(dataGroupID: string, callback: AsyncCallbackWrapper): void; - private static native nativeTransferStatic(input: ESValue): Object; + private static native nativeTransferStatic(input: ESValue, type: string): Object; private static native nativeTransferDynamic(input: Object): ESValue; + private static contextType: string = 'Context'; + private native switchArea(mode: contextConstant.AreaMode): void; private native getArea(): contextConstant.AreaMode; @@ -98,7 +100,14 @@ export class Context extends BaseContext { } static transferStatic(input: Any): Object { - return Context.nativeTransferStatic(ESValue.wrap(input)); + let type: string = ''; + try { + type = ESValue.wrap(input).getProperty('__context_impl__').getProperty('contextType').toString(); + } catch (err) { + console.log('transferStatic err: ' + err.toString()); + } + console.log('transferStatic type: ' + type); + return Context.nativeTransferStatic(ESValue.wrap(input), type); } static transferDynamic(input: Object): Any { diff --git a/frameworks/js/napi/application/js_application.cpp b/frameworks/js/napi/application/js_application.cpp index fd4e3f9c394..e0595b63b73 100644 --- a/frameworks/js/napi/application/js_application.cpp +++ b/frameworks/js/napi/application/js_application.cpp @@ -60,6 +60,27 @@ napi_value JsApplication::OnGetApplicationContext(napi_env env, NapiCallbackInfo AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR); return CreateJsUndefined(env); } + + auto applicationContext = ApplicationContext::GetInstance(); + auto workContext = new (std::nothrow) std::weak_ptr(applicationContext); + napi_coerce_to_native_binding_object( + env, object, DetachCallbackFunc, AttachApplicationContext, workContext, nullptr); + if (workContext != nullptr) { + auto res = napi_wrap(env, object, workContext, + [](napi_env, void *data, void *) { + TAG_LOGD(AAFwkTag::APPKIT, "Finalizer for weak_ptr application context is called"); + delete static_cast *>(data); + data = nullptr; + }, + nullptr, nullptr); + if (res != napi_ok && workContext != nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "napi_wrap failed:%{public}d", res); + delete workContext; + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR); + return CreateJsUndefined(env); + } + } + return object; } @@ -260,7 +281,7 @@ void JsApplication::SetCreateCompleteCallback(std::shared_ptr(AbilityErrorCode::ERROR_CODE_INVALID_PARAM), "invalid param.")); return; } diff --git a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp index fdf67dfc956..74012914fd0 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp @@ -1982,6 +1982,9 @@ napi_value CreateJsAbilityContext(napi_env env, std::shared_ptr napi_set_named_property(env, object, "config", CreateJsConfiguration(env, *configuration)); } + std::string type = "UIAbilityContext"; + napi_set_named_property(env, object, "contextType", CreateJsValue(env, type)); + const char *moduleName = "JsAbilityContext"; BindNativeFunction(env, object, "startAbility", moduleName, JsAbilityContext::StartAbility); BindNativeFunction(env, object, "openLink", moduleName, JsAbilityContext::OpenLink); diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index 332c53e67c4..25d645547f9 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -343,7 +343,9 @@ ohos_shared_library("app_context") { "${ability_runtime_native_path}/appkit/ability_runtime/context/ability_stage_context.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/application_context.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/application_state_change_callback.cpp", + "${ability_runtime_native_path}/appkit/ability_runtime/context/bindable_sub_thread.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/context_impl.cpp", + "${ability_runtime_native_path}/appkit/ability_runtime/context/context_transfer.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/environment_callback.cpp", "${ability_runtime_native_path}/appkit/ability_runtime/context/ets_application_state_change_callback.cpp", "${ability_runtime_native_path}/appkit/app/overlay_event_subscriber.cpp", diff --git a/frameworks/native/appkit/ability_runtime/app/js_ability_stage_context.cpp b/frameworks/native/appkit/ability_runtime/app/js_ability_stage_context.cpp index 349241d864c..056f04383d3 100644 --- a/frameworks/native/appkit/ability_runtime/app/js_ability_stage_context.cpp +++ b/frameworks/native/appkit/ability_runtime/app/js_ability_stage_context.cpp @@ -64,6 +64,10 @@ napi_value CreateJsAbilityStageContext(napi_env env, std::shared_ptr(napiEnv); + HookData* data = new HookData { this, acutalEnv }; + if (data == nullptr) { + TAG_LOGE(AAFwkTag::CONTEXT, "data err"); + return; + } + + napi_status ret = napi_add_env_cleanup_hook(acutalEnv, + StaticRemoveSubThreadObject, data); + if (ret != napi_status::napi_ok) { + TAG_LOGE(AAFwkTag::CONTEXT, "add hook err"); + delete data; + return; + } + + std::unique_ptr obj(object, nullptr); + objects_.emplace(napiEnv, std::move(obj)); +} + +void* BindableSubThread::GetSubThreadObject(void* napiEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "get sub thread object"); + std::lock_guard guard(objectsMutex_); + const auto& iter = objects_.find(napiEnv); + if (iter == objects_.end()) { + return nullptr; + } + return static_cast(iter->second.get()); +} + +void BindableSubThread::RemoveSubThreadObject(void* napiEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "remove sub thread object"); + std::lock_guard guard(objectsMutex_); + objects_.erase(napiEnv); +} + +void BindableSubThread::StaticRemoveSubThreadObject(void* arg) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "remove sub thread object"); + HookData* data = static_cast(arg); + if (data) { + data->instance->RemoveSubThreadObject(data->env); + delete data; + } +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/context/context_transfer.cpp b/frameworks/native/appkit/ability_runtime/context/context_transfer.cpp new file mode 100755 index 00000000000..869742ee1f7 --- /dev/null +++ b/frameworks/native/appkit/ability_runtime/context/context_transfer.cpp @@ -0,0 +1,67 @@ +/* + * 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 "context_transfer.h" + +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +ContextTransfer &ContextTransfer::GetInstance() +{ + static ContextTransfer contextTransfer; + return contextTransfer; +} + +void ContextTransfer::RegisterStaticObjectCreator(const std::string &contextType, const CreateStaticObject &createFunc) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Reg static creator for %{public}s", contextType.c_str()); + std::lock_guard lock(creatorMutex_); + staticCreators_.emplace(contextType, createFunc); +} + +ani_object ContextTransfer::GetStaticObject(const std::string &contextType, ani_env *aniEnv, + std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Get static creator for %{public}s", contextType.c_str()); + std::lock_guard lock(creatorMutex_); + auto it = staticCreators_.find(contextType); + if (it != staticCreators_.end()) { + return it->second(aniEnv, context); + } + return nullptr; +} + +void ContextTransfer::RegisterDynamicObjectCreator(const std::string &contextType, + const CreateDynamicObject &createFunc) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Reg dynamic creator for %{public}s", contextType.c_str()); + std::lock_guard lock(creatorMutex_); + dynamicCreators_.emplace(contextType, createFunc); +} + +napi_value ContextTransfer::GetDynamicObject(const std::string &contextType, napi_env napiEnv, + std::shared_ptr context) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Get dynamic creator for %{public}s", contextType.c_str()); + std::lock_guard lock(creatorMutex_); + auto it = dynamicCreators_.find(contextType); + if (it != dynamicCreators_.end()) { + return it->second(napiEnv, context); + } + return nullptr; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp b/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp index 5eca238c7b3..f6592ffdc65 100644 --- a/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp +++ b/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp @@ -1748,6 +1748,9 @@ napi_value JsApplicationContextUtils::CreateJsApplicationContext(napi_env env) napi_set_named_property(env, object, "resourceManager", CreateJsResourceManager(env, resourceManager, context)); } + std::string type = "ApplicationContext"; + napi_set_named_property(env, object, "contextType", CreateJsValue(env, type)); + BindNativeApplicationContextOne(env, object); BindNativeApplicationContextTwo(env, object); return object; diff --git a/frameworks/native/appkit/ability_runtime/context/js_context_utils.cpp b/frameworks/native/appkit/ability_runtime/context/js_context_utils.cpp index d86eabcb229..18be206b9ad 100644 --- a/frameworks/native/appkit/ability_runtime/context/js_context_utils.cpp +++ b/frameworks/native/appkit/ability_runtime/context/js_context_utils.cpp @@ -986,6 +986,9 @@ napi_value CreateJsBaseContext(napi_env env, std::shared_ptr context, b } } + std::string type = "Context"; + napi_set_named_property(env, object, "contextType", CreateJsValue(env, type)); + const char *moduleName = "JsBaseContext"; BindPropertyAndFunction(env, object, moduleName); return object; diff --git a/interfaces/kits/native/appkit/ability_runtime/context/bindable_sub_thread.h b/interfaces/kits/native/appkit/ability_runtime/context/bindable_sub_thread.h new file mode 100755 index 00000000000..5d577c0d1d6 --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/bindable_sub_thread.h @@ -0,0 +1,49 @@ +/* +* 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_BINDABLE_SUB_THREAD_H +#define OHOS_ABILITY_RUNTIME_BINDABLE_SUB_THREAD_H + +#include +#include +#include + +namespace OHOS { +namespace AbilityRuntime { +class BindableSubThread { +public: + BindableSubThread() = default; + virtual ~BindableSubThread() = default; + + void BindSubThreadObject(void* napiEnv, void* object); + + void* GetSubThreadObject(void* napiEnv); + + void RemoveSubThreadObject(void* napiEnv); + + static void StaticRemoveSubThreadObject(void* arg); + +private: + BindableSubThread(const BindableSubThread&) = delete; + BindableSubThread(BindableSubThread&&) = delete; + BindableSubThread& operator=(const BindableSubThread&) = delete; + BindableSubThread& operator=(BindableSubThread&&) = delete; + + std::mutex objectsMutex_; + std::map> objects_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_BINDABLE_SUB_THREAD_H diff --git a/interfaces/kits/native/appkit/ability_runtime/context/context.h b/interfaces/kits/native/appkit/ability_runtime/context/context.h index 3e449b7a404..121bbcad643 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/context.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/context.h @@ -21,6 +21,7 @@ #include "application_info.h" #include "bindable.h" +#include "bindable_sub_thread.h" #include "hap_module_info.h" #include "iremote_object.h" #include "resource_manager.h" @@ -40,7 +41,9 @@ class Configuration; namespace AbilityRuntime { class ApplicationContext; -class Context : public Bindable, public std::enable_shared_from_this { +class Context : public Bindable, + public BindableSubThread, + public std::enable_shared_from_this { public: Context() = default; ~Context() override = default; diff --git a/interfaces/kits/native/appkit/ability_runtime/context/context_transfer.h b/interfaces/kits/native/appkit/ability_runtime/context/context_transfer.h new file mode 100755 index 00000000000..cfb2e959fce --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/context_transfer.h @@ -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. +*/ + +#ifndef OHOS_ABILITY_RUNTIME_CONTEXT_TRANSFER_H +#define OHOS_ABILITY_RUNTIME_CONTEXT_TRANSFER_H + +#include +#include "context.h" +#include "ani.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace AbilityRuntime { +using CreateStaticObject = std::function context)>; +using CreateDynamicObject = std::function context)>; +class ContextTransfer { +public: + static ContextTransfer &GetInstance(); + ContextTransfer() = default; + ~ContextTransfer() = default; + + void RegisterStaticObjectCreator(const std::string &contextType, const CreateStaticObject &createFunc); + ani_object GetStaticObject(const std::string &contextType, ani_env *aniEnv, std::shared_ptr context); + + void RegisterDynamicObjectCreator(const std::string &contextType, const CreateDynamicObject &createFunc); + napi_value GetDynamicObject(const std::string &contextType, napi_env napiEnv, std::shared_ptr context); + +private: + ContextTransfer(const ContextTransfer&) = delete; + ContextTransfer(ContextTransfer&&) = delete; + ContextTransfer& operator=(const ContextTransfer&) = delete; + ContextTransfer& operator=(ContextTransfer&&) = delete; + + std::mutex creatorMutex_; + std::unordered_map staticCreators_; + std::unordered_map dynamicCreators_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_CONTEXT_TRANSFER_H -- Gitee