From ee6afbf824eaed06d08a10a9e71a91fa63aaa7c8 Mon Sep 17 00:00:00 2001 From: "zhangyafei.echo" Date: Tue, 17 Jun 2025 23:34:56 +0800 Subject: [PATCH] Description:add abilitystagecontext applicationcontext context transfter Sig:SIG_ApplicationFramework Feature or BugFix: Feature Binary Source: No Signed-off-by: zhangyafei.echo Change-Id: I03ae6b16d51395b372752cf5ab5a8738faa726d9 Description:add context transfer dynamic Sig:SIG_ApplicationFramework Feature or BugFix: Feature Binary Source: No Signed-off-by: zhangyafei.echo Change-Id: I60311120b492a947ab91a7035e304e55669c7988 Description:context transfer bugfix. Sig:SIG_ApplicationFramework Feature or BugFix: Feature Binary Source: No Signed-off-by: zhangyafei.echo Change-Id: Iff2ffa198547d51805ca09dbf977ecaa31d92d38 --- frameworks/ets/ani/BUILD.gn | 1 - frameworks/ets/ani/ani_common/BUILD.gn | 1 + .../ani/ani_common/include/ani_common_util.h | 2 + .../ani/ani_common/include/context_transfer.h | 56 +++ .../ani/ani_common/include/ets_error_utils.h | 1 + .../ani/ani_common/src/ani_common_util.cpp | 39 +- .../ani/ani_common/src/context_transfer.cpp | 81 ++++ .../src/ets_application_context_utils.cpp | 7 + .../ani/ani_common/src/ets_error_utils.cpp | 8 + .../ets/ani/app/ability_context/BUILD.gn | 72 ---- .../include/ets_ability_context_module.h | 52 --- .../src/ets_ability_context_module.cpp | 387 ------------------ .../ets/ets/application/UIAbilityContext.ets | 19 - .../ability_runtime/ability_context_impl.cpp | 12 +- .../ability_runtime/js_ability_context.cpp | 3 + .../native/ability/native/ui_ability.cpp | 8 +- frameworks/native/appkit/BUILD.gn | 1 + .../ability_runtime/app/ets_ability_stage.cpp | 9 + .../app/ets_ability_stage_context.cpp | 23 +- .../app/js_ability_stage_context.cpp | 4 + .../context/bindable_sub_thread.cpp | 121 ++++++ .../ability_runtime/context/context_impl.cpp | 6 + .../context/js_application_context_utils.cpp | 4 + .../context/js_context_utils.cpp | 4 + .../ability_runtime/ability_context_impl.h | 2 +- .../ability_runtime/app/ets_ability_stage.h | 2 +- .../appkit/ability_runtime/context/bindable.h | 59 +++ .../context/bindable_sub_thread.h | 54 +++ .../appkit/ability_runtime/context/context.h | 3 +- .../ability_runtime/context/context_impl.h | 2 +- .../BUILD.gn | 5 + .../context_impl_test.cpp | 40 ++ 32 files changed, 535 insertions(+), 553 deletions(-) create mode 100755 frameworks/ets/ani/ani_common/include/context_transfer.h create mode 100755 frameworks/ets/ani/ani_common/src/context_transfer.cpp delete mode 100644 frameworks/ets/ani/app/ability_context/BUILD.gn delete mode 100644 frameworks/ets/ani/app/ability_context/include/ets_ability_context_module.h delete mode 100644 frameworks/ets/ani/app/ability_context/src/ets_ability_context_module.cpp create mode 100755 frameworks/native/appkit/ability_runtime/context/bindable_sub_thread.cpp create mode 100755 interfaces/kits/native/appkit/ability_runtime/context/bindable_sub_thread.h diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn index a0063fbc25..7bc7dddc53 100644 --- a/frameworks/ets/ani/BUILD.gn +++ b/frameworks/ets/ani/BUILD.gn @@ -22,7 +22,6 @@ group("ani_packages") { "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", "${ability_runtime_path}/frameworks/ets/ani/app_manager:app_manager_ani", "${ability_runtime_path}/frameworks/ets/ani/application:application_ani", - "${ability_runtime_path}/frameworks/ets/ani/app/ability_context:ability_context_ani_kit", "${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/uri_permission_manager:uri_permission_manager_ani_kit", diff --git a/frameworks/ets/ani/ani_common/BUILD.gn b/frameworks/ets/ani/ani_common/BUILD.gn index 6078f8d6e4..12fe1f08f4 100644 --- a/frameworks/ets/ani/ani_common/BUILD.gn +++ b/frameworks/ets/ani/ani_common/BUILD.gn @@ -49,6 +49,7 @@ ohos_shared_library("ani_common") { "src/ani_common_start_options.cpp", "src/ani_common_util.cpp", "src/ani_common_want.cpp", + "src/context_transfer.cpp", "src/ets_application_context_utils.cpp", "src/ets_context_utils.cpp", "src/ets_data_struct_converter.cpp", 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 02d3c64b66..7475d48f30 100644 --- a/frameworks/ets/ani/ani_common/include/ani_common_util.h +++ b/frameworks/ets/ani/ani_common/include/ani_common_util.h @@ -74,6 +74,8 @@ bool SetDoublePropertyObject(ani_env *env, ani_object param, const char *name, d bool SetDoublePropertyValue(ani_env *env, ani_object param, const char *name, double value); bool SetStringArrayProperty(ani_env *env, ani_object param, const char *name, const std::vector &values); bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref value); + +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 diff --git a/frameworks/ets/ani/ani_common/include/context_transfer.h b/frameworks/ets/ani/ani_common/include/context_transfer.h new file mode 100755 index 0000000000..692dcbb77a --- /dev/null +++ b/frameworks/ets/ani/ani_common/include/context_transfer.h @@ -0,0 +1,56 @@ +/* +* 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 "ani.h" +#include "context.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); + + bool IsStaticCreatorExist(const std::string &contextType); + bool IsDynamicCreatorExist(const std::string &contextType); + +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 diff --git a/frameworks/ets/ani/ani_common/include/ets_error_utils.h b/frameworks/ets/ani/ani_common/include/ets_error_utils.h index 607350d0c3..97ebfc0bf4 100644 --- a/frameworks/ets/ani/ani_common/include/ets_error_utils.h +++ b/frameworks/ets/ani/ani_common/include/ets_error_utils.h @@ -34,6 +34,7 @@ public: static void ThrowInvalidParamError(ani_env *env, const std::string &message); static void ThrowErrorByNativeErr(ani_env *env, int32_t err); static void ThrowNotSystemAppError(ani_env *env); + static void ThrowEtsTransferClassError(ani_env *env); static ani_object CreateError(ani_env *env, const AbilityErrorCode &err); static ani_object CreateError(ani_env *env, ani_int code, const std::string &msg); 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 47ca889610..b199cdbe31 100644 --- a/frameworks/ets/ani/ani_common/src/ani_common_util.cpp +++ b/frameworks/ets/ani/ani_common/src/ani_common_util.cpp @@ -558,7 +558,7 @@ bool GetStringOrUndefined(ani_env *env, ani_object param, const char *name, std: ani_ref obj = nullptr; ani_boolean isUndefined = true; ani_status status = ANI_ERROR; - + if (env == nullptr || param == nullptr || name == nullptr) { TAG_LOGE(AAFwkTag::ANI, "null env or param or name"); return false; @@ -1181,5 +1181,42 @@ bool SetRefProperty(ani_env *env, ani_object param, const char *name, ani_ref va } return true; } + +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/ani_common/src/context_transfer.cpp b/frameworks/ets/ani/ani_common/src/context_transfer.cpp new file mode 100755 index 0000000000..408ccd7ec0 --- /dev/null +++ b/frameworks/ets/ani/ani_common/src/context_transfer.cpp @@ -0,0 +1,81 @@ +/* + * 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; +} + +bool ContextTransfer::IsStaticCreatorExist(const std::string &contextType) +{ + std::lock_guard lock(creatorMutex_); + auto it = staticCreators_.find(contextType); + return it != staticCreators_.end(); +} + +bool ContextTransfer::IsDynamicCreatorExist(const std::string &contextType) +{ + std::lock_guard lock(creatorMutex_); + auto it = dynamicCreators_.find(contextType); + return it != dynamicCreators_.end(); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp b/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp index e158c752f5..505acd70b1 100644 --- a/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_application_context_utils.cpp @@ -559,6 +559,13 @@ ani_object EtsApplicationContextUtils::CreateEtsApplicationContext(ani_env* aniE return nullptr; } ContextUtil::CreateEtsBaseContext(aniEnv, applicationContextClass, applicationContextObject, applicationContext); + ani_ref* contextGlobalRef = new (std::nothrow) ani_ref; + if ((status = aniEnv->GlobalReference_Create(applicationContextObject, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "GlobalReference_Create failed status: %{public}d", status); + delete contextGlobalRef; + return nullptr; + } + applicationContext->Bind(contextGlobalRef); return applicationContextObject; } } // namespace AbilityRuntime diff --git a/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp b/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp index 26811755eb..bd7b64b251 100644 --- a/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp +++ b/frameworks/ets/ani/ani_common/src/ets_error_utils.cpp @@ -26,6 +26,8 @@ constexpr const char *ERR_MSG_INVALID_NUM_PARAMS = "Parameter error. The number constexpr const char *NOT_SYSTEM_APP = "The application is not system-app, can not use system-api."; constexpr const char *BUSINESS_ERROR_CLASS = "L@ohos/base/BusinessError;"; constexpr const char *ERROR_CLASS_NAME = "Lescompat/Error;"; +constexpr const char* ERROR_MSG_TRANSFER_CLASS_NOT_FOUND = "Unable to find the class for transferring."; +constexpr int32_t ERROR_CODE_TRANSFER_CLASS_NOT_FOUND = 10200067; } // namespace void EtsErrorUtil::ThrowError(ani_env *env, ani_object err) @@ -106,6 +108,12 @@ void EtsErrorUtil::ThrowNotSystemAppError(ani_env *env) env, static_cast(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP), NOT_SYSTEM_APP)); } +void EtsErrorUtil::ThrowEtsTransferClassError(ani_env *env) +{ + EtsErrorUtil::ThrowError(env, EtsErrorUtil::CreateError( + env, static_cast(ERROR_CODE_TRANSFER_CLASS_NOT_FOUND), ERROR_MSG_TRANSFER_CLASS_NOT_FOUND)); +} + void EtsErrorUtil::ThrowInvalidParamError(ani_env *env, const std::string &message) { if (env == nullptr) { diff --git a/frameworks/ets/ani/app/ability_context/BUILD.gn b/frameworks/ets/ani/app/ability_context/BUILD.gn deleted file mode 100644 index 5eb598fce0..0000000000 --- a/frameworks/ets/ani/app/ability_context/BUILD.gn +++ /dev/null @@ -1,72 +0,0 @@ -# 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("//build/config/components/ets_frontend/ets2abc_config.gni") -import("//build/ohos.gni") -import("//foundation/ability/ability_runtime/ability_runtime.gni") - -ohos_shared_library("ability_context_ani_kit") { - branch_protector_ret = "pac_ret" - sanitize = { - cfi = true - cfi_cross_dso = true - cfi_vcall_icall_only = true - debug = false - } - - include_dirs = [ - "./include", - "${ability_runtime_path}/interfaces/inner_api", - "${ability_runtime_path}/interfaces/kits/native/appkit", - "${ability_runtime_path}/interfaces/kits/native/ability/native/ability_runtime", - "${ability_runtime_services_path}/common/include", - "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", - "${ability_runtime_path}/frameworks/ets/ani/ui_ability/include", - ] - - configs = [] - - public_configs = [] - - sources = [ "./src/ets_ability_context_module.cpp" ] - - cflags = [] - if (target_cpu == "arm") { - cflags += [ "-DBINDER_IPC_32BIT" ] - } - - deps = [ - "${ability_runtime_innerkits_path}/ani_base_context:ani_base_context", - "${ability_runtime_innerkits_path}/runtime:runtime", - "${ability_runtime_native_path}/ability/native:abilitykit_native", - "${ability_runtime_native_path}/ability/native:ui_ability_ani", - "${ability_runtime_native_path}/ability:ability_context_native", - "${ability_runtime_native_path}/appkit:app_context", - "${ability_runtime_native_path}/appkit:app_context_utils", - "${ability_runtime_native_path}/appkit:appkit_native", - "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "hitrace:hitrace_meter", - "napi:ace_napi", - "runtime_core:ani", - "runtime_core:ani_helpers", - ] - - innerapi_tags = [ "platformsdk" ] - subsystem_name = "ability" - part_name = "ability_runtime" -} diff --git a/frameworks/ets/ani/app/ability_context/include/ets_ability_context_module.h b/frameworks/ets/ani/app/ability_context/include/ets_ability_context_module.h deleted file mode 100644 index 46d7f78c5e..0000000000 --- a/frameworks/ets/ani/app/ability_context/include/ets_ability_context_module.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* 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_ETS_ABILITY_CONTEXT_MODULE_H -#define OHOS_ABILITY_RUNTIME_ETS_ABILITY_CONTEXT_MODULE_H - -#include -#include "ability_context.h" -#include "ani.h" -#include "native_engine/native_engine.h" - -namespace OHOS { -namespace AbilityRuntime { -class EtsAbilityContextModule { -public: - EtsAbilityContextModule() = default; - ~EtsAbilityContextModule() = default; - - EtsAbilityContextModule(const EtsAbilityContextModule&) = delete; - EtsAbilityContextModule(EtsAbilityContextModule&&) = delete; - EtsAbilityContextModule& operator=(const EtsAbilityContextModule&) = delete; - EtsAbilityContextModule& operator=(EtsAbilityContextModule&&) = delete; - - 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 napi_value GetOrCreateDynamicObject(napi_env napiEnv, - std::shared_ptr abilityContext); - -private: - static bool IsInstanceOf(ani_env *aniEnv, ani_object aniObj); - static std::unique_ptr CreateNativeReference(napi_env napiEnv, - std::shared_ptr abilityContext); - static ani_object CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, - std::shared_ptr abilityContext); -}; - -void EtsAbilityContextModuleInit(ani_env *aniEnv); -} // namespace AbilityRuntime -} // namespace OHOS -#endif // OHOS_ABILITY_RUNTIME_ETS_ABILITY_CONTEXT_MODULE_H diff --git a/frameworks/ets/ani/app/ability_context/src/ets_ability_context_module.cpp b/frameworks/ets/ani/app/ability_context/src/ets_ability_context_module.cpp deleted file mode 100644 index 638c9a786b..0000000000 --- a/frameworks/ets/ani/app/ability_context/src/ets_ability_context_module.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/* - * 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 "ets_ability_context_module.h" - -#include -#include -#include -#include "ability_context.h" -#include "ani_base_context.h" -#include "ani_common_util.h" -#include "context_transfer.h" -#include "ets_ability_context.h" -#include "ets_error_utils.h" -#include "hilog_tag_wrapper.h" -#include "hitrace_meter.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_context.h" -#include "js_runtime_utils.h" -#include "native_engine/native_engine.h" - -namespace OHOS { -namespace AbilityRuntime { -namespace { -constexpr const char *ETS_ABILITY_CONTEXT_CLASS_NAME = "Lapplication/UIAbilityContext/UIAbilityContext;"; -} // namespace - -ani_object EtsAbilityContextModule::NativeTransferStatic(ani_env *aniEnv, ani_object, ani_object input, - ani_object type) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - TAG_LOGD(AAFwkTag::CONTEXT, "transfer static AbilityContext"); - if (aniEnv == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); - return nullptr; - } - - void *unwrapResult = nullptr; - bool success = arkts_esvalue_unwrap(aniEnv, input, &unwrapResult); - if (!success) { - TAG_LOGE(AAFwkTag::CONTEXT, "failed to unwrap"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - if (unwrapResult == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null unwrapResult"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - auto context = reinterpret_cast *>(unwrapResult)->lock(); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null AbilityContext"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - auto abilityContext = Context::ConvertTo(context); - if (abilityContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityContext"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - auto &bindingObj = abilityContext->GetBindingObject(); - if (bindingObj == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - auto staticContext = bindingObj->Get(); - if (staticContext != nullptr) { - TAG_LOGI(AAFwkTag::CONTEXT, "there exist a staticContext"); - return reinterpret_cast(*staticContext); - } - - // if not exist, create a new one - std::string contextType; - if (!AppExecFwk::GetStdString(aniEnv, reinterpret_cast(type), contextType)) { - TAG_LOGE(AAFwkTag::JSNAPI, "GetStdString failed"); - EtsErrorUtil::ThrowEtsTransferClassError(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 abilityContext failed"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - return newContext; -} - -std::unique_ptr EtsAbilityContextModule::CreateNativeReference(napi_env napiEnv, - std::shared_ptr abilityContext) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - if (napiEnv == nullptr || abilityContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null param"); - return nullptr; - } - - auto value = CreateJsAbilityContext(napiEnv, abilityContext); - auto systemModule = JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.AbilityContext", &value, 1); - if (systemModule == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null systemModule"); - return nullptr; - } - - napi_value object = systemModule->GetNapiValue(); - if (!CheckTypeForNapiValue(napiEnv, object, napi_object)) { - TAG_LOGE(AAFwkTag::CONTEXT, "check type failed"); - return nullptr; - } - - auto workContext = new (std::nothrow) std::weak_ptr(abilityContext); - if (workContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null workContext"); - return nullptr; - } - auto status = napi_coerce_to_native_binding_object(napiEnv, object, DetachCallbackFunc, AttachJsUIAbilityContext, - workContext, nullptr); - if (status != napi_ok) { - TAG_LOGE(AAFwkTag::CONTEXT, "coerce AbilityContext failed: %{public}d", status); - delete workContext; - return nullptr; - } - - status = napi_wrap(napiEnv, object, workContext, - [](napi_env, void *data, void *) { - TAG_LOGD(AAFwkTag::CONTEXT, "finalizer for weak_ptr AbilityContext"); - delete static_cast *>(data); - }, nullptr, nullptr); - if (status != napi_ok) { - TAG_LOGE(AAFwkTag::CONTEXT, "wrap failed: %{public}d", status); - delete workContext; - return nullptr; - } - - return systemModule; -} - -napi_value EtsAbilityContextModule::GetOrCreateDynamicObject(napi_env napiEnv, - std::shared_ptr abilityContext) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - if (napiEnv == nullptr || abilityContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null param"); - return nullptr; - } - - // if sub-thread, create a new abilityContext and return - if (getpid() != syscall(SYS_gettid)) { - auto subThreadObj = static_cast( - abilityContext->GetSubThreadObject(static_cast(napiEnv))); - if (subThreadObj != nullptr) { - return subThreadObj->Get(); - } - auto subThreadRef = CreateNativeReference(napiEnv, abilityContext); - if (subThreadRef == nullptr) { - return nullptr; - } - auto newObject = subThreadRef->Get(); - abilityContext->BindSubThreadObject( - static_cast(napiEnv), static_cast(subThreadRef.release())); - return newObject; - } - - // if main-thread, get bindingObj firstly - auto &bindingObj = abilityContext->GetBindingObject(); - if (bindingObj == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null bindingObj"); - return nullptr; - } - - // if main-thread bindingObj exist, return it directly - auto dynamicContext = bindingObj->Get(); - if (dynamicContext != nullptr) { - TAG_LOGI(AAFwkTag::UIABILITY, "there exist a dynamicContext"); - return dynamicContext->Get(); - } - - // if main-thread bindingObj didn't exist, return null - return nullptr; -} - -ani_object EtsAbilityContextModule::NativeTransferDynamic(ani_env *aniEnv, ani_class aniCls, ani_object input) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - TAG_LOGD(AAFwkTag::CONTEXT, "transfer dynamic AbilityContext"); - if (!IsInstanceOf(aniEnv, input)) { - TAG_LOGE(AAFwkTag::CONTEXT, "not AbilityContext"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - auto context = AbilityRuntime::GetStageModeContext(aniEnv, input); - if (context == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null context"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - std::shared_ptr abilityContext = Context::ConvertTo(context); - if (abilityContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityContext"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - ani_object object = CreateDynamicObject(aniEnv, aniCls, abilityContext); - if (object == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "invalid object"); - EtsErrorUtil::ThrowEtsTransferClassError(aniEnv); - return nullptr; - } - - return object; -} - -ani_object EtsAbilityContextModule::CreateDynamicObject(ani_env *aniEnv, ani_class aniCls, - std::shared_ptr abilityContext) -{ - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - 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 ability context - auto contextObj = ContextTransfer::GetInstance().GetDynamicObject(contextType, napiEnv, abilityContext); - if (contextObj == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "create AbilityContext failed"); - arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr); - 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"); - arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr); - return nullptr; - } - - ani_object result = nullptr; - success = hybridgref_get_esvalue(aniEnv, ref, &result); - if (!success) { - TAG_LOGE(AAFwkTag::CONTEXT, "hybridgref_get_esvalue failed"); - hybridgref_delete_from_napi(napiEnv, ref); - arkts_napi_scope_close_n(napiEnv, 0, nullptr, nullptr); - 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 EtsAbilityContextModule::IsInstanceOf(ani_env *aniEnv, ani_object aniObj) -{ - ani_class cls {}; - ani_status status = ANI_ERROR; - if (aniEnv == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null aniEnv"); - return false; - } - if ((status = aniEnv->FindClass(ETS_ABILITY_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "FindClass status: %{public}d", status); - return false; - } - ani_boolean isInstanceOf = false; - if ((status = aniEnv->Object_InstanceOf(aniObj, cls, &isInstanceOf)) != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "Object_InstanceOf status: %{public}d", status); - return false; - } - return isInstanceOf; -} - -void EtsAbilityContextModuleInit(ani_env *aniEnv) -{ - TAG_LOGD(AAFwkTag::CONTEXT, "Init AbilityContext kit"); - if (aniEnv == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null ani env"); - return; - } - - ani_class abilityContextCls = nullptr; - auto status = aniEnv->FindClass(ETS_ABILITY_CONTEXT_CLASS_NAME, &abilityContextCls); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "FindClass AbilityContext failed status: %{public}d", status); - return; - } - - std::array nativeFuncs = { - ani_native_function { "nativeTransferStatic", "Lstd/interop/ESValue;Lstd/core/String;:Lstd/core/Object;", - reinterpret_cast(EtsAbilityContextModule::NativeTransferStatic) }, - ani_native_function { "nativeTransferDynamic", "Lstd/core/Object;:Lstd/interop/ESValue;", - reinterpret_cast(EtsAbilityContextModule::NativeTransferDynamic) }, - }; - status = aniEnv->Class_BindNativeMethods(abilityContextCls, nativeFuncs.data(), nativeFuncs.size()); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::APPKIT, "Class_BindNativeMethods failed status: %{public}d", status); - return; - } - - ContextTransfer::GetInstance().RegisterStaticObjectCreator("UIAbilityContext", - [](ani_env *aniEnv, std::shared_ptr context) -> ani_object { - TAG_LOGE(AAFwkTag::APPKIT, "AbilityContext should be created during ability startup"); - return nullptr; - }); - - ContextTransfer::GetInstance().RegisterDynamicObjectCreator("UIAbilityContext", - [](napi_env napiEnv, std::shared_ptr context) -> napi_value { - auto abilityContext = Context::ConvertTo(context); - if (abilityContext == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "invalid abilityContext"); - return nullptr; - } - - auto object = EtsAbilityContextModule::GetOrCreateDynamicObject(napiEnv, abilityContext); - if (object == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "get or create object failed"); - return nullptr; - } - return object; - }); - - TAG_LOGD(AAFwkTag::CONTEXT, "Init AbilityContext kit end"); -} - -extern "C" { -ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) -{ - TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor"); - if (vm == nullptr) { - TAG_LOGE(AAFwkTag::CONTEXT, "null vm"); - return ANI_ERROR; - } - - ani_env *aniEnv = nullptr; - ani_status status = vm->GetEnv(ANI_VERSION_1, &aniEnv); - if (status != ANI_OK) { - TAG_LOGE(AAFwkTag::CONTEXT, "GetEnv failed status: %{public}d", status); - return ANI_NOT_FOUND; - } - - EtsAbilityContextModuleInit(aniEnv); - *result = ANI_VERSION_1; - TAG_LOGD(AAFwkTag::CONTEXT, "ANI_Constructor finish"); - return ANI_OK; -} -} -} // namespace AbilityRuntime -} // namespace OHOS diff --git a/frameworks/ets/ets/application/UIAbilityContext.ets b/frameworks/ets/ets/application/UIAbilityContext.ets index 1ae948f2ac..9a916d88ef 100644 --- a/frameworks/ets/ets/application/UIAbilityContext.ets +++ b/frameworks/ets/ets/application/UIAbilityContext.ets @@ -45,7 +45,6 @@ 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; @@ -81,24 +80,6 @@ export default class UIAbilityContext extends Context { destroyRegister.unregister(unregisterToken); } - private static native nativeTransferStatic(input: ESValue, type: string): Object; - private static native nativeTransferDynamic(input: Object): ESValue; - private static contextType: string = 'UIAbilityContext'; - - 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 UIAbilityContext.nativeTransferStatic(ESValue.wrap(input), type); - } - static transferDynamic(input: Object): Any { - return UIAbilityContext.nativeTransferDynamic(input).unwrap(); - } - private native nativeStartAbilitySync(want: Want, callback: AsyncCallbackWrapper): void; private native nativeStartAbilitySync(want: Want, options: StartOptions, callback: AsyncCallbackWrapper): void; diff --git a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp index 44ae430b71..27602e8e9d 100644 --- a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp +++ b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp @@ -18,11 +18,14 @@ #include #include "ability_manager_client.h" -#include "hitrace_meter.h" +#include "application_configuration_manager.h" +#include "configuration_convertor.h" +#include "bindable_sub_thread.h" #include "connection_manager.h" #include "dialog_request_callback_impl.h" #include "dialog_ui_extension_callback.h" #include "hilog_tag_wrapper.h" +#include "hitrace_meter.h" #include "json_utils.h" #include "remote_object_wrapper.h" #include "request_constants.h" @@ -34,8 +37,6 @@ #include "ui_content.h" #endif // SUPPORT_SCREEN #include "want_params_wrapper.h" -#include "configuration_convertor.h" -#include "application_configuration_manager.h" namespace OHOS { namespace AbilityRuntime { @@ -55,6 +56,11 @@ struct RequestResult { RequestDialogResultTask task; }; +AbilityContextImpl::AbilityContextImpl() +{ + subThreadObject_ = std::make_unique(); +} + Global::Resource::DeviceType AbilityContextImpl::GetDeviceType() const { return (stageContext_ != nullptr) ? stageContext_->GetDeviceType() : Global::Resource::DeviceType::DEVICE_PHONE; 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 c5bf91d698..30803158a2 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp @@ -2223,6 +2223,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/ability/native/ui_ability.cpp b/frameworks/native/ability/native/ui_ability.cpp index eb03be3a04..bc2defb23d 100644 --- a/frameworks/native/ability/native/ui_ability.cpp +++ b/frameworks/native/ability/native/ui_ability.cpp @@ -704,7 +704,7 @@ void UIAbility::BindHybridContext(const std::shared_ptrcodeLanguage != AppExecFwk::Constants::CODE_LANGUAGE_HYBRID) { + if (appInfo->arkTSMode != AppExecFwk::Constants::ARKTS_MODE_HYBRID) { TAG_LOGD(AAFwkTag::UIABILITY, "not hybrid app, no need to create hybrid context"); return; } @@ -714,12 +714,12 @@ void UIAbility::BindHybridContext(const std::shared_ptrcodeLanguage == AppExecFwk::Constants::CODE_LANGUAGE_1_1) { + if (abilityInfo->arkTSMode == AppExecFwk::Constants::ARKTS_MODE_DYNAMIC) { BindEtsContext(application, record); - } else if (abilityInfo->codeLanguage == AppExecFwk::Constants::CODE_LANGUAGE_1_2) { + } else if (abilityInfo->arkTSMode == AppExecFwk::Constants::ARKTS_MODE_STATIC) { BindJsContext(application, record); } else { - TAG_LOGE(AAFwkTag::UIABILITY, "unknown codeLanguage"); + TAG_LOGE(AAFwkTag::UIABILITY, "unknown arkTSMode"); } } diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index 22f5534f3b..797f152348 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -453,6 +453,7 @@ 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/environment_callback.cpp", "${ability_runtime_native_path}/appkit/app/overlay_event_subscriber.cpp", diff --git a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp index e5c81ec068..6fe5166f8b 100644 --- a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp +++ b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage.cpp @@ -79,6 +79,15 @@ ETSAbilityStage::ETSAbilityStage( : etsRuntime_(etsRuntime), etsAbilityStageObj_(std::move(etsAbilityStageObj)) {} +ETSAbilityStage::~ETSAbilityStage() +{ + TAG_LOGI(AAFwkTag::APPKIT, "destructor"); + auto context = GetContext(); + if (context != nullptr) { + context->Unbind(); + } +} + void ETSAbilityStage::Init(const std::shared_ptr &context, const std::weak_ptr application) { diff --git a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp index 3ad856a706..66e6b56f12 100644 --- a/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp +++ b/frameworks/native/appkit/ability_runtime/app/ets_ability_stage_context.cpp @@ -36,21 +36,18 @@ ani_object ETSAbilityStageContext::CreateEtsAbilityStageContext(ani_env *env, st ani_status status = ANI_OK; ani_class abilityStageCtxCls; - status = env->FindClass(ETS_ABILITY_STAGE_CONTEXT_CLASS_NAME, &abilityStageCtxCls); - if (status != ANI_OK) { + if ((status = env->FindClass(ETS_ABILITY_STAGE_CONTEXT_CLASS_NAME, &abilityStageCtxCls)) != ANI_OK) { TAG_LOGE(AAFwkTag::ABILITY, "call FindClass LAbilityStageContext failed, status:%{public}d", status); return nullptr; } ani_method method = nullptr; - status = env->Class_FindMethod(abilityStageCtxCls, "", ":V", &method); - if (status != ANI_OK) { + if ((status = env->Class_FindMethod(abilityStageCtxCls, "", ":V", &method)) != ANI_OK) { TAG_LOGE(AAFwkTag::ABILITY, "call Class_FindMethod ctor failed"); return nullptr; } ani_object obj = nullptr; - status = env->Object_New(abilityStageCtxCls, method, &obj); - if (status != ANI_OK) { + if ((status = env->Object_New(abilityStageCtxCls, method, &obj)) != ANI_OK) { TAG_LOGE(AAFwkTag::ABILITY, "call Object_New abilityStageCtxCls failed"); return nullptr; } @@ -63,13 +60,11 @@ ani_object ETSAbilityStageContext::CreateEtsAbilityStageContext(ani_env *env, st return nullptr; } ani_field contextField; - status = env->Class_FindField(abilityStageCtxCls, "nativeContext", &contextField); - if (status != ANI_OK) { + if ((status = env->Class_FindField(abilityStageCtxCls, "nativeContext", &contextField)) != ANI_OK) { TAG_LOGE(AAFwkTag::ABILITY, "call Class_FindField nativeContext failed"); } ani_long nativeContextLong = (ani_long)workContext; - status = env->Object_SetField_Long(obj, contextField, nativeContextLong); - if (status != ANI_OK) { + if ((status = env->Object_SetField_Long(obj, contextField, nativeContextLong)) != ANI_OK) { TAG_LOGE(AAFwkTag::ABILITY, "call Object_SetField_Long contextField failed"); delete workContext; return nullptr; @@ -77,6 +72,14 @@ ani_object ETSAbilityStageContext::CreateEtsAbilityStageContext(ani_env *env, st ContextUtil::CreateEtsBaseContext(env, abilityStageCtxCls, obj, context); SetConfiguration(env, abilityStageCtxCls, obj, context); + ani_ref* contextGlobalRef = new (std::nothrow) ani_ref; + if ((status = env->GlobalReference_Create(obj, contextGlobalRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::ABILITY, "GlobalReference_Create failed status: %{public}d", status); + delete contextGlobalRef; + delete workContext; + return nullptr; + } + context->Bind(contextGlobalRef); return obj; } 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 89ac493101..72ad146be4 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 @@ -84,6 +84,10 @@ napi_value CreateJsAbilityStageContext(napi_env env, std::shared_ptr instance; + napi_env env = nullptr; +}; +} // namespace + +BindableSubThread::~BindableSubThread() +{ + TAG_LOGD(AAFwkTag::CONTEXT, "destructor"); +} + +void BindableSubThread::BindSubThreadObject(void* napiEnv, void* object) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "bind sub thread object"); + uintptr_t key = reinterpret_cast(napiEnv); + std::lock_guard guard(objectsMutex_); + auto it = objects_.find(key); + if (it != objects_.end()) { + TAG_LOGD(AAFwkTag::CONTEXT, "object has bound"); + return; + } + + napi_env acutalEnv = static_cast(napiEnv); + HookData* data = new (std::nothrow) HookData { weak_from_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, + [](void* ptr) { + TAG_LOGD(AAFwkTag::CONTEXT, "delete sub thread ptr"); + delete static_cast(ptr); + }); + objects_.emplace(key, std::move(obj)); +} + +void* BindableSubThread::GetSubThreadObject(void* napiEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "get sub thread object"); + uintptr_t key = reinterpret_cast(napiEnv); + std::lock_guard guard(objectsMutex_); + const auto& iter = objects_.find(key); + if (iter == objects_.end()) { + TAG_LOGD(AAFwkTag::CONTEXT, "not found target object"); + return nullptr; + } + return static_cast(iter->second.get()); +} + +void BindableSubThread::RemoveSubThreadObject(void* napiEnv) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "remove sub thread object"); + uintptr_t key = reinterpret_cast(napiEnv); + std::lock_guard guard(objectsMutex_); + const auto& iter = objects_.find(key); + if (iter == objects_.end()) { + TAG_LOGW(AAFwkTag::CONTEXT, "not found target object"); + return; + } + objects_.erase(key); +} + +void BindableSubThread::RemoveAllObject() +{ + TAG_LOGD(AAFwkTag::CONTEXT, "remove all object"); + std::lock_guard guard(objectsMutex_); + objects_.clear(); +} + +void BindableSubThread::StaticRemoveSubThreadObject(void* arg) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "remove sub thread object"); + HookData* data = static_cast(arg); + if (data == nullptr) { + return; + } + + std::shared_ptr instance = data->instance.lock(); + if (instance == nullptr) { + TAG_LOGW(AAFwkTag::CONTEXT, "instance nullptr"); + delete data; + return; + } + + instance->RemoveSubThreadObject(data->env); + delete data; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/ability_runtime/context/context_impl.cpp b/frameworks/native/appkit/ability_runtime/context/context_impl.cpp index fd846ca59d..48f7491f38 100644 --- a/frameworks/native/appkit/ability_runtime/context/context_impl.cpp +++ b/frameworks/native/appkit/ability_runtime/context/context_impl.cpp @@ -21,6 +21,7 @@ #include "ability_manager_client.h" #include "app_mgr_client.h" #include "application_context.h" +#include "bindable_sub_thread.h" #include "bundle_mgr_helper.h" #include "bundle_mgr_proxy.h" #include "common_event_manager.h" @@ -91,6 +92,11 @@ const int AREA2 = 2; const int AREA3 = 3; const int AREA4 = 4; +ContextImpl::ContextImpl() +{ + subThreadObject_ = std::make_unique(); +} + ContextImpl::~ContextImpl() { UnsubscribeToOverlayEvents(); 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 c507ba81c4..ef38cf8078 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 @@ -1757,6 +1757,10 @@ napi_value JsApplicationContextUtils::CreateJsApplicationContext(napi_env env) return nullptr; } napi_set_named_property(env, object, "index", applicationContextValue); + + 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 4f586acde7..b1d2a20d5b 100644 --- a/frameworks/native/appkit/ability_runtime/context/js_context_utils.cpp +++ b/frameworks/native/appkit/ability_runtime/context/js_context_utils.cpp @@ -1000,6 +1000,10 @@ napi_value CreateJsBaseContext(napi_env env, std::shared_ptr context, b return nullptr; } napi_set_named_property(env, object, "index", contextValue); + + 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/ability/ability_runtime/ability_context_impl.h b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h index 2425e49b44..124e9fc1da 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h @@ -30,7 +30,7 @@ namespace OHOS { namespace AbilityRuntime { class AbilityContextImpl : public AbilityContext { public: - AbilityContextImpl() = default; + AbilityContextImpl(); virtual ~AbilityContextImpl() = default; Global::Resource::DeviceType GetDeviceType() const override; diff --git a/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h b/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h index f293b5eba2..c8f6cde637 100644 --- a/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h +++ b/interfaces/kits/native/appkit/ability_runtime/app/ets_ability_stage.h @@ -35,7 +35,7 @@ public: const std::unique_ptr& runtime, const AppExecFwk::HapModuleInfo& hapModuleInfo); ETSAbilityStage(ETSRuntime &etsRuntime, std::unique_ptr &&ETSAbilityStageObj); - ~ETSAbilityStage() override {} + ~ETSAbilityStage() override; void Init(const std::shared_ptr &context, const std::weak_ptr application) override; diff --git a/interfaces/kits/native/appkit/ability_runtime/context/bindable.h b/interfaces/kits/native/appkit/ability_runtime/context/bindable.h index 8fb38e80cd..aeb356820b 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/bindable.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/bindable.h @@ -40,6 +40,16 @@ public: objects_.emplace(typeName, std::move(obj)); } + template + void Bind(T* object) + { + static_assert(IsValidType(), "T must be ani_ref or NativeReference"); + const std::string typeName = GetTypeString(); + std::lock_guard guard(objectsMutex_); + std::unique_ptr obj(object, SimpleRelease); + objects_.emplace(typeName, std::move(obj)); + } + template T* Get() { @@ -105,6 +115,23 @@ private: std::mutex objectsMutex_; }; +class BindingObjectSubThread { +public: + BindingObjectSubThread() = default; + virtual ~BindingObjectSubThread() = default; + + virtual void BindSubThreadObject(void* napiEnv, void* object); + virtual void* GetSubThreadObject(void* napiEnv); + virtual void RemoveSubThreadObject(void* napiEnv); + virtual void RemoveAllObject(); + +private: + BindingObjectSubThread(const BindingObjectSubThread&) = delete; + BindingObjectSubThread(BindingObjectSubThread&&) = delete; + BindingObjectSubThread& operator=(const BindingObjectSubThread&) = delete; + BindingObjectSubThread& operator=(BindingObjectSubThread&&) = delete; +}; + class Bindable { public: virtual ~Bindable() = default; @@ -117,11 +144,23 @@ public: } } + template + void Bind(T* object) + { + if (object_) { + object_->Bind(object); + } + } + void Unbind() const { if (object_) { object_->Unbind(); } + + if (subThreadObject_) { + subThreadObject_->RemoveAllObject(); + } } template @@ -130,6 +169,10 @@ public: if (object_) { object_->Unbind(); } + + if (subThreadObject_) { + subThreadObject_->RemoveAllObject(); + } } const std::unique_ptr& GetBindingObject() const @@ -137,8 +180,24 @@ public: return object_; } + void BindSubThreadObject(void* napiEnv, void* object) + { + if (subThreadObject_) { + subThreadObject_->BindSubThreadObject(napiEnv, object); + } + } + + void* GetSubThreadObject(void* napiEnv) + { + if (subThreadObject_) { + return subThreadObject_->GetSubThreadObject(napiEnv); + } + return nullptr; + } + protected: Bindable() = default; + std::unique_ptr subThreadObject_ = nullptr; private: std::unique_ptr object_ = std::make_unique(); 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 0000000000..553d7a2d0c --- /dev/null +++ b/interfaces/kits/native/appkit/ability_runtime/context/bindable_sub_thread.h @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_ABILITY_RUNTIME_BINDABLE_SUB_THREAD_H +#define OHOS_ABILITY_RUNTIME_BINDABLE_SUB_THREAD_H + +#include +#include +#include + +#include "bindable.h" + +namespace OHOS { +namespace AbilityRuntime { +class BindableSubThread : public BindingObjectSubThread, + public std::enable_shared_from_this { +public: + BindableSubThread() = default; + virtual ~BindableSubThread(); + + void BindSubThreadObject(void* napiEnv, void* object) override; + + void* GetSubThreadObject(void* napiEnv) override; + + void RemoveSubThreadObject(void* napiEnv) override; + + void RemoveAllObject() override; + + 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 8ca92ecb14..de30b97f25 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/context.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/context.h @@ -40,7 +40,8 @@ class Configuration; namespace AbilityRuntime { class ApplicationContext; -class Context : public Bindable, public std::enable_shared_from_this { +class Context : public Bindable, + public std::enable_shared_from_this { public: Context() = default; ~Context() override = default; diff --git a/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h b/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h index 3e61977f84..52a48ac299 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h @@ -36,7 +36,7 @@ using GetDisplayConfigCallback = std::functionGetHapModuleInfo(), nullptr); GTEST_LOG_(INFO) << "AppExecFwk_ContextImpl_InitPluginHapModuleInfo_003 end"; } + +/** + * @tc.number: AppExecFwk_ContextImpl_Bind_001 + * @tc.name: AppExecFwk_ContextImpl_Bind_001 + * @tc.desc: test Bind and UnBind function. + * @tc.type: FUNC + */ +HWTEST_F(ContextImplTest, AppExecFwk_ContextImpl_Bind_001, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "ContextImpl_Bind_001 start"); + auto context = std::make_shared(); + ASSERT_NE(context, nullptr); + + std::shared_ptr jsEnv = nullptr; + Options options; + auto errCode = AbilityRuntime::JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv); + EXPECT_NE(jsEnv, nullptr); + napi_env napiEnv = reinterpret_cast(jsEnv->GetNativeEngine()); + EXPECT_NE(napiEnv, nullptr); + + auto value = AbilityRuntime::CreateJsBaseContext(napiEnv, context); + auto systemModule = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(napiEnv, "application.Context", &value, 1); + EXPECT_NE(systemModule, nullptr); + context->Bind(systemModule.get()); + + auto &bindingObj = context->GetBindingObject(); + ASSERT_NE(bindingObj, nullptr); + + auto dynamicContext = bindingObj->Get(); + EXPECT_NE(dynamicContext, nullptr); + EXPECT_EQ(dynamicContext, systemModule.get()); + context->Unbind(); + + TAG_LOGI(AAFwkTag::TEST, "ContextImpl_Bind_001 end"); +} } // namespace AppExecFwk }