diff --git a/frameworks/ets/ani/caller_complex/include/ets_caller_complex.h b/frameworks/ets/ani/caller_complex/include/ets_caller_complex.h index fa3ac766510f32f6b95b2092e9db21467645f55a..dc748e4bb329bfb7555d2a61c27b795201540c6c 100644 --- a/frameworks/ets/ani/caller_complex/include/ets_caller_complex.h +++ b/frameworks/ets/ani/caller_complex/include/ets_caller_complex.h @@ -24,6 +24,16 @@ namespace OHOS { namespace AbilityRuntime { +struct EtsRefWrap { + EtsRefWrap(ani_env *env, ani_object srcObj); + EtsRefWrap(EtsRefWrap &) = delete; + void operator=(EtsRefWrap &) = delete; + ~EtsRefWrap(); + + ani_vm *aniVM = nullptr; + ani_ref objectRef = nullptr; +}; + class EtsCallerComplex { public: EtsCallerComplex(ReleaseCallFunc releaseCallFunc, std::shared_ptr callerCallBack, @@ -43,23 +53,23 @@ public: static ani_object NativeTransferDynamic(ani_env *env, ani_object, ani_object input); static bool IsInstanceOf(ani_env *env, ani_object aniObj); static ani_object CreateDynamicCaller(ani_env *env, sptr remoteObj); + static void TransferFinalizeCallback(uintptr_t jsPtr); protected: void ReleaseCallInner(ani_env *env); private: ReleaseCallFunc releaseCallFunc_; std::shared_ptr callerCallback_; wptr remoteObj_; + + static std::mutex staticTransferRecordMutex_; + static std::unordered_map> staticTransferRecords_; }; -struct CallbackWrap { +struct CallbackWrap: public EtsRefWrap { CallbackWrap(ani_env *env, ani_object callerObj, const std::string &callbackName); - CallbackWrap(CallbackWrap &) = delete; - void operator=(CallbackWrap &) = delete; - ~CallbackWrap(); + ~CallbackWrap() = default; void Invoke(const std::string &msg) const; private: - ani_vm *aniVM = nullptr; - ani_ref callbackRef = nullptr; std::string name; }; } // namespace AbilityRuntime diff --git a/frameworks/ets/ani/caller_complex/src/ets_caller_complex.cpp b/frameworks/ets/ani/caller_complex/src/ets_caller_complex.cpp index b50bc60bbc26bc214b605a7a0fa6a4dae17f7cff..16983755c594c7acd6308a4c360e7d80d18f85aa 100644 --- a/frameworks/ets/ani/caller_complex/src/ets_caller_complex.cpp +++ b/frameworks/ets/ani/caller_complex/src/ets_caller_complex.cpp @@ -39,6 +39,9 @@ void ReleaseNativeRemote(ani_env *env, ani_ref aniObj) namespace OHOS { namespace AbilityRuntime { +std::mutex EtsCallerComplex::staticTransferRecordMutex_; +std::unordered_map> EtsCallerComplex::staticTransferRecords_; + EtsCallerComplex* EtsCallerComplex::GetComplexPtrFrom(ani_env *env, ani_object aniObj) { if (env == nullptr || aniObj == nullptr) { @@ -170,7 +173,9 @@ void EtsCallerComplex::SetCallerCallback(std::shared_ptr callbac ani_object EtsCallerComplex::NativeTransferStatic(ani_env *env, ani_object, ani_object input) { TAG_LOGI(AAFwkTag::UIABILITY, "transfer static caller"); + std::lock_guard lock(staticTransferRecordMutex_); ani_object output = nullptr; + uintptr_t srcPtr = 0; do { void *unwrapResult = nullptr; bool success = arkts_esvalue_unwrap(env, input, &unwrapResult); @@ -182,7 +187,12 @@ ani_object EtsCallerComplex::NativeTransferStatic(ani_env *env, ani_object, ani_ TAG_LOGE(AAFwkTag::UIABILITY, "null unwrapResult"); break; } - auto remoteObj = GetJsCallerRemoteObj(reinterpret_cast(unwrapResult)); + srcPtr = reinterpret_cast(unwrapResult); + auto recordItr = staticTransferRecords_.find(srcPtr); + if (recordItr != staticTransferRecords_.end()) { + return reinterpret_cast(recordItr->second->objectRef); + } + auto remoteObj = GetJsCallerRemoteObj(srcPtr); if (remoteObj == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "null remoteObj"); } @@ -198,6 +208,8 @@ ani_object EtsCallerComplex::NativeTransferStatic(ani_env *env, ani_object, ani_ if (output == nullptr) { TAG_LOGE(AAFwkTag::UIABILITY, "failed to create"); EtsErrorUtil::ThrowEtsTransferClassError(env); + } else { + staticTransferRecords_.emplace(srcPtr, std::make_shared(env, output)); } return output; } @@ -291,7 +303,13 @@ ani_object EtsCallerComplex::CreateDynamicCaller(ani_env *env, sptrGetVM(&aniVM) != ANI_OK) { TAG_LOGE(AAFwkTag::UIABILITY, "get aniVM failed"); @@ -299,16 +317,14 @@ CallbackWrap::CallbackWrap(ani_env *env, ani_object callerObj, const std::string } ani_status status = ANI_ERROR; - if ((status = env->GlobalReference_Create(callerObj, &callbackRef)) != ANI_OK) { - TAG_LOGE(AAFwkTag::UIABILITY, "callbackRef: %{public}d", status); - return; + if ((status = env->GlobalReference_Create(srcObj, &objectRef)) != ANI_OK) { + TAG_LOGE(AAFwkTag::UIABILITY, "create ref: %{public}d", status); } - name = callbackName; } -CallbackWrap::~CallbackWrap() +EtsRefWrap::~EtsRefWrap() { - if (callbackRef == nullptr) { + if (objectRef == nullptr) { return; } ani_status status = ANI_ERROR; @@ -317,14 +333,17 @@ CallbackWrap::~CallbackWrap() TAG_LOGE(AAFwkTag::UIABILITY, "GetEnv failed, status : %{public}d", status); return; } - aniEnv->GlobalReference_Delete(callbackRef); - callbackRef = nullptr; + aniEnv->GlobalReference_Delete(objectRef); + objectRef = nullptr; } +CallbackWrap::CallbackWrap(ani_env *env, ani_object callerObj, const std::string &callbackName) + : EtsRefWrap(env, callerObj), name(callbackName) {} + void CallbackWrap::Invoke(const std::string &msg) const { - if (callbackRef == nullptr) { - TAG_LOGE(AAFwkTag::UIABILITY, "callbackRef null"); + if (objectRef == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "objectRef null"); return; } ani_string aniMsg = nullptr; @@ -338,7 +357,7 @@ void CallbackWrap::Invoke(const std::string &msg) const TAG_LOGE(AAFwkTag::UIABILITY, "String_NewUTF8 failed %{public}d", status); return; } - status = aniEnv->Object_CallMethodByName_Void(reinterpret_cast(callbackRef), name.c_str(), + status = aniEnv->Object_CallMethodByName_Void(reinterpret_cast(objectRef), name.c_str(), "Lstd/core/String;:V", aniMsg); if (status != ANI_OK) { TAG_LOGE(AAFwkTag::UIABILITY, "%{public}s failed %{public}d", name.c_str(), status); @@ -379,6 +398,8 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) return status; } + SetFinalizeCallback(EtsCallerComplex::TransferFinalizeCallback); + *result = ANI_VERSION_1; return ANI_OK; } diff --git a/frameworks/native/ability/native/ability_runtime/js_caller_complex.cpp b/frameworks/native/ability/native/ability_runtime/js_caller_complex.cpp index ebe0844fdd2b3e978e9a1b656e281613681e7276..e3ddd5e8e99524da240dd8ddb3c6bd47c28a4615 100644 --- a/frameworks/native/ability/native/ability_runtime/js_caller_complex.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_caller_complex.cpp @@ -200,6 +200,9 @@ public: auto ret = ptr->ChangeCurrentState(state); TAG_LOGD(AAFwkTag::DEFAULT, "ChangeCurrentState ret:%{public}s", ret ? "true" : "false"); + if (finalizeCallback_) { + finalizeCallback_(reinterpret_cast(ptr)); + } return ret; } @@ -449,7 +452,8 @@ private: TAG_LOGD(AAFwkTag::DEFAULT, "end"); return CreateJsUndefined(env); } - +public: + static std::function finalizeCallback_; private: ReleaseCallFunc releaseCallFunc_; sptr callee_; @@ -470,6 +474,7 @@ private: std::set JsCallerComplex::jsCallerComplexManagerList; std::mutex JsCallerComplex::jsCallerComplexMutex; +std::function JsCallerComplex::finalizeCallback_; } // nameless napi_value CreateJsCallerComplex( @@ -527,5 +532,10 @@ sptr GetJsCallerRemoteObj(uintptr_t jsCallerComplex) } return callerPtr->GetRemoteObject(); } + +void SetFinalizeCallback(std::function finalizeCallback) +{ + JsCallerComplex::finalizeCallback_ = finalizeCallback; +} } // AbilityRuntime } // OHOS diff --git a/interfaces/kits/native/ability/native/ability_runtime/js_caller_complex.h b/interfaces/kits/native/ability/native/ability_runtime/js_caller_complex.h index 93d8e907b63b1f0fcdc6d13d22aba4e0705f5645..64b7c87b9f52b72802153a4d27c2219c25fb36b2 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/js_caller_complex.h +++ b/interfaces/kits/native/ability/native/ability_runtime/js_caller_complex.h @@ -30,6 +30,7 @@ napi_value CreateJsCallerComplex( napi_value CreateJsCalleeRemoteObject(napi_env env, sptr callee); sptr GetJsCallerRemoteObj(uintptr_t jsCallerComplex); +void SetFinalizeCallback(std::function finalizeCallback); } // AbilityRuntime } // OHOS #endif // OHOS_ABILITY_RUNTIME_JS_CALLER_COMPLEX_H