diff --git a/frameworks/native/ability/native/extension.cpp b/frameworks/native/ability/native/extension.cpp index 4d9445623a7b9a5d8cd525965a164139576d361f..a29abed0ccfb2477b23e72076ade9a6ef9daa20b 100644 --- a/frameworks/native/ability/native/extension.cpp +++ b/frameworks/native/ability/native/extension.cpp @@ -59,6 +59,16 @@ void Extension::OnStop() HILOG_DEBUG("extension:%{public}s.", abilityInfo_->name.c_str()); } +void Extension::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ + isAsyncCallback = false; + OnStop(); +} + +void Extension::OnStopCallBack() +{ +} + sptr Extension::OnConnect(const AAFwk::Want &want) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/frameworks/native/ability/native/extension_impl.cpp b/frameworks/native/ability/native/extension_impl.cpp index 4cccd5e70af460ae906156f2d8a4fa4fc15ed86f..a123ebcaa41a667ba8cceab83aec266aefb53895 100644 --- a/frameworks/native/ability/native/extension_impl.cpp +++ b/frameworks/native/ability/native/extension_impl.cpp @@ -74,8 +74,12 @@ void ExtensionImpl::HandleExtensionTransaction(const Want &want, const AAFwk::Li switch (targetState.state) { case AAFwk::ABILITY_STATE_INITIAL: { + bool isAsyncCallback = false; if (lifecycleState_ != AAFwk::ABILITY_STATE_INITIAL) { - Stop(); + Stop(isAsyncCallback); + } + if (isAsyncCallback) { + ret = false; } break; } @@ -176,6 +180,50 @@ void ExtensionImpl::Stop() HILOG_INFO("ok"); } +void ExtensionImpl::Stop(bool &isAsyncCallback) +{ + HILOG_INFO("call"); + if (extension_ == nullptr) { + HILOG_ERROR("ExtensionImpl::Stop extension_ is nullptr"); + isAsyncCallback = false; + return; + } + + auto *callbackInfo = AppExecFwk::AbilityTransactionCallbackInfo<>::Create(); + if (callbackInfo == nullptr) { + extension_->OnStop(); + lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + isAsyncCallback = false; + return; + } + std::weak_ptr weakPtr = shared_from_this(); + auto asyncCallback = [ExtensionImplWeakPtr = weakPtr, state = AAFwk::ABILITY_STATE_INITIAL]() { + auto extensionImpl = ExtensionImplWeakPtr.lock(); + if (extensionImpl == nullptr) { + HILOG_ERROR("extensionImpl is nullptr."); + return; + } + extensionImpl->lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + extensionImpl->AbilityTransactionCallback(state); + }; + callbackInfo->Push(asyncCallback); + + extension_->OnStop(callbackInfo, isAsyncCallback); + if (!isAsyncCallback) { + lifecycleState_ = AAFwk::ABILITY_STATE_INITIAL; + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); + } + // else: callbackInfo will be destroyed after the async callback + HILOG_DEBUG("%{public}s end.", __func__); +} + +void ExtensionImpl::AbilityTransactionCallback(const AAFwk::AbilityLifeCycleState &state) +{ + HILOG_INFO("call abilityms"); + AAFwk::PacMap restoreData; + AAFwk::AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, state, restoreData); +} + /** * @brief Connect the extension. and Calling information back to Extension. * diff --git a/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp b/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp index f420e388372bdf3ea30b8913d509e11f06b5900f..8aa48db9edb666d8f861632b6f3d1060e8de54e3 100755 --- a/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp +++ b/frameworks/native/ability/native/ui_extension_ability/js_ui_extension.cpp @@ -14,9 +14,13 @@ */ #include "js_ui_extension.h" - +#include "ability_context.h" +#include "ability_delegator_registry.h" #include "ability_info.h" #include "ability_manager_client.h" +#include "ability_start_setting.h" +#include "connection_manager.h" +#include "context.h" #include "hitrace_meter.h" #include "hilog_wrapper.h" #include "js_extension_common.h" @@ -217,8 +221,110 @@ void JsUIExtension::OnStop() HILOG_DEBUG("JsUIExtension OnStop begin."); HandleScope handleScope(jsRuntime_); CallObjectMethod("onDestroy"); + OnStopCallBack(); HILOG_DEBUG("JsUIExtension OnStop end."); } +void JsUIExtension::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) +{ + if (callbackInfo == nullptr) { + isAsyncCallback = false; + OnStop(); + return; + } + HILOG_DEBUG("OnStop begin."); + UIExtension::OnStop(); + HandleScope handleScope(jsRuntime_); + NativeValue *result = CallObjectMethod("onDestroy", nullptr, 0, true); + if (!CheckPromise(result)) { + OnStopCallBack(); + isAsyncCallback = false; + return; + } + + std::weak_ptr weakPtr = shared_from_this(); + auto asyncCallback = [extensionWeakPtr = weakPtr]() { + auto jsUIExtension = extensionWeakPtr.lock(); + if (jsUIExtension == nullptr) { + HILOG_ERROR("extension is nullptr."); + return; + } + jsUIExtension->OnStopCallBack(); + }; + callbackInfo->Push(asyncCallback); + isAsyncCallback = CallPromise(result, callbackInfo); + if (!isAsyncCallback) { + HILOG_ERROR("Failed to call promise."); + OnStopCallBack(); + } + HILOG_DEBUG("OnStop end."); +} + +void JsUIExtension::OnStopCallBack() +{ + bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken()); + if (ret) { + ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid()); + HILOG_DEBUG("The service connection is not disconnected."); + } + + auto applicationContext = Context::GetApplicationContext(); + if (applicationContext != nullptr) { + std::shared_ptr sharedJsObj = std::move(jsObj_); + applicationContext->DispatchOnAbilityDestroy(sharedJsObj); + } +} + +bool JsUIExtension::CheckPromise(NativeValue *result) +{ + if (result == nullptr) { + HILOG_DEBUG("result is null, no need to call promise."); + return false; + } + if (!result->IsPromise()) { + HILOG_DEBUG("result is not promise, no need to call promise."); + return false; + } + return true; +} + +NativeValue *PromiseCallback(NativeEngine *engine, NativeCallbackInfo *info) +{ + if (info == nullptr || info->functionInfo == nullptr || info->functionInfo->data == nullptr) { + HILOG_ERROR("Invalid input info."); + return nullptr; + } + void *data = info->functionInfo->data; + auto *callbackInfo = static_cast *>(data); + callbackInfo->Call(); + AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo); + info->functionInfo->data = nullptr; + return nullptr; +} + +bool JsUIExtension::CallPromise(NativeValue *result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo) +{ + auto *retObj = ConvertNativeValueTo(result); + if (retObj == nullptr) { + HILOG_ERROR("Failed to convert native value to NativeObject."); + return false; + } + NativeValue *then = retObj->GetProperty("then"); + if (then == nullptr) { + HILOG_ERROR("Failed to get property: then."); + return false; + } + if (!then->IsCallable()) { + HILOG_ERROR("property then is not callable."); + return false; + } + HandleScope handleScope(jsRuntime_); + auto &nativeEngine = jsRuntime_.GetNativeEngine(); + auto promiseCallback = nativeEngine.CreateFunction("promiseCallback", strlen("promiseCallback"), PromiseCallback, + callbackInfo); + NativeValue *argv[1] = { promiseCallback }; + nativeEngine.CallFunction(result, then, argv, 1); + return true; +} sptr JsUIExtension::OnConnect(const AAFwk::Want &want) { @@ -418,7 +524,7 @@ void JsUIExtension::DestroyWindow(const sptr &sessionInfo) HILOG_DEBUG("end."); } -NativeValue* JsUIExtension::CallObjectMethod(const char* name, NativeValue* const* argv, size_t argc) +NativeValue *JsUIExtension::CallObjectMethod(const char *name, NativeValue *const *argv, size_t argc, bool withResult) { HILOG_DEBUG("JsUIExtension CallObjectMethod(%{public}s), begin", name); @@ -427,21 +533,27 @@ NativeValue* JsUIExtension::CallObjectMethod(const char* name, NativeValue* cons return nullptr; } - auto& nativeEngine = jsRuntime_.GetNativeEngine(); - NativeValue* value = jsObj_->Get(); - NativeObject* obj = ConvertNativeValueTo(value); + HandleEscape handleEscape(jsRuntime_); + auto &nativeEngine = jsRuntime_.GetNativeEngine(); + + NativeValue *value = jsObj_->Get(); + NativeObject *obj = ConvertNativeValueTo(value); if (obj == nullptr) { HILOG_ERROR("Failed to get UIExtension object"); return nullptr; } - NativeValue* method = obj->GetProperty(name); - if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) { + NativeValue *methodOnCreate = obj->GetProperty(name); + if (methodOnCreate == nullptr || methodOnCreate->TypeOf() != NATIVE_FUNCTION) { HILOG_ERROR("Failed to get '%{public}s' from UIExtension object", name); return nullptr; } + if (withResult) { + return handleEscape.Escape(nativeEngine.CallFunction(value, methodOnCreate, argv, argc)); + } HILOG_DEBUG("JsUIExtension CallFunction(%{public}s), success", name); - return nativeEngine.CallFunction(value, method, argv, argc); + nativeEngine.CallFunction(value, methodOnCreate, argv, argc); + return nullptr; } NativeValue *JsUIExtension::CallOnConnect(const AAFwk::Want &want) diff --git a/interfaces/kits/native/ability/native/extension.h b/interfaces/kits/native/ability/native/extension.h index a97343e3eb8e92d34b41aeda0e57ac67e3f7c04c..40ac0fb0cc4993763220837cedbd7a9e7a4d6f58 100644 --- a/interfaces/kits/native/ability/native/extension.h +++ b/interfaces/kits/native/ability/native/extension.h @@ -165,12 +165,28 @@ public: * You can override this function to implement your own processing logic. */ virtual void OnStop(); + /** + * @brief Called when this extension enters the STATE_STOP state. + * + * The ability in the STATE_STOP is being destroyed. + * You can override this function to implement your own processing logic. + * + * @param callbackInfo Indicates the lifecycle transaction callback information + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + */ + virtual void OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback); /** * @brief Called when the system configuration is updated. * * @param configuration Indicates the updated configuration information. */ + + /** + * @brief The callback of OnStop. + */ + virtual void OnStopCallBack(); + virtual void OnConfigurationUpdated(const AppExecFwk::Configuration& configuration); /** diff --git a/interfaces/kits/native/ability/native/extension_impl.h b/interfaces/kits/native/ability/native/extension_impl.h index da545ecc7983e77ce14768d94417ba3bca731c54..475dcc483df7b0da7565f211549b720b597afd80 100644 --- a/interfaces/kits/native/ability/native/extension_impl.h +++ b/interfaces/kits/native/ability/native/extension_impl.h @@ -161,6 +161,13 @@ protected: * */ void Stop(); + /** + * @brief Toggles the lifecycle status of Extension to AAFwk::ABILITY_STATE_INITIAL. And notifies the application + * that it belongs to of the lifecycle status. + * @param isAsyncCallback Indicates whether it is an asynchronous lifecycle callback + */ + void Stop(bool &isAsyncCallback); + void AbilityTransactionCallback(const AAFwk::AbilityLifeCycleState &state); /** * @brief Toggles the lifecycle status of Extension to AAFwk::ABILITY_STATE_INACTIVE. And notifies the application diff --git a/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h b/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h index 93c456c934cbecc3a8952c1475c82b859038aaaa..6496aece293ae62676dfac9c1c3c14107da94689 100755 --- a/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h +++ b/interfaces/kits/native/ability/native/ui_extension_ability/js_ui_extension.h @@ -53,7 +53,7 @@ private: std::map, std::shared_ptr> listeners_; }; -class JsUIExtension : public UIExtension, public std::enable_shared_from_this { +class JsUIExtension : public UIExtension { public: explicit JsUIExtension(JsRuntime& jsRuntime); virtual ~JsUIExtension() override; @@ -133,6 +133,11 @@ public: * You can override this function to implement your own processing logic. */ virtual void OnStop() override; + virtual void OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback) override; + /** + * @brief The callback of OnStop. + */ + virtual void OnStopCallBack() override; /** * @brief Called when the system configuration is updated. @@ -182,7 +187,10 @@ public: private: virtual void BindContext(NativeEngine& engine, NativeObject* obj); - NativeValue* CallObjectMethod(const char* name, NativeValue* const *argv = nullptr, size_t argc = 0); + NativeValue *CallObjectMethod(const char *name, NativeValue *const *argv = nullptr, size_t argc = 0, + bool withResult = false); + bool CheckPromise(NativeValue* result); + bool CallPromise(NativeValue* result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo); NativeValue* CallOnConnect(const AAFwk::Want &want); diff --git a/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h b/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h index 30fce0248df2165d5560c3023fb398ac208c77e0..5f14369e4d6d99aef78663546121de36ab9465fc 100755 --- a/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h +++ b/interfaces/kits/native/ability/native/ui_extension_ability/ui_extension.h @@ -25,8 +25,7 @@ class Runtime; /** * @brief Basic ui extension components. */ -class UIExtension : public ExtensionBase, - public std::enable_shared_from_this { +class UIExtension : public ExtensionBase { public: UIExtension() = default; virtual ~UIExtension() = default;