From d34077d7ce33257c73f85b2df31c6a3f41782c58 Mon Sep 17 00:00:00 2001 From: liweifeng Date: Thu, 30 Mar 2023 15:32:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A7=BB=E5=8A=A8arkts?= =?UTF-8?q?=E5=8D=A1=E7=89=87=EF=BC=8C=E5=8D=A1=E7=89=87=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E8=BF=98=E5=8E=9F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liweifeng Change-Id: I4cf22aac1a7e5c4e0477b865a4023c4e76066dce --- adapter/ohos/entrance/ui_content_impl.h | 2 +- .../js_frontend/engine/jsi/ark_js_runtime.cpp | 31 ++++-- .../js_frontend/engine/jsi/ark_js_runtime.h | 7 +- .../form_render/include/form_renderer.h | 3 + .../form_renderer_delegate_interface.h | 22 ++++ .../include/form_renderer_delegate_proxy.h | 5 + .../include/form_renderer_delegate_stub.h | 2 + .../form_render/include/form_renderer_group.h | 23 ++-- .../form_render/src/form_renderer.cpp | 79 +++++++++++--- .../src/form_renderer_delegate_proxy.cpp | 75 ++++++++++++- .../src/form_renderer_delegate_stub.cpp | 64 ++++++++++- .../form_render/src/form_renderer_group.cpp | 101 +++++++++--------- .../arkuiformrendergroup_fuzzer.cpp | 3 - test/unittest/interfaces/form_render_test.cpp | 21 +--- 14 files changed, 322 insertions(+), 116 deletions(-) diff --git a/adapter/ohos/entrance/ui_content_impl.h b/adapter/ohos/entrance/ui_content_impl.h index 44ddac2b120..a629a6236f5 100644 --- a/adapter/ohos/entrance/ui_content_impl.h +++ b/adapter/ohos/entrance/ui_content_impl.h @@ -128,7 +128,7 @@ private: // ITouchOutsideListener is used for touching out of hot areas of window. OHOS::sptr touchOutsideListener_ = nullptr; - + // ArkTS Form bool isFormRender_ = false; bool isFormRenderInit_ = false; diff --git a/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.cpp b/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.cpp index c885851e28a..84ed5b68539 100644 --- a/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.cpp +++ b/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.cpp @@ -40,6 +40,14 @@ Local FunctionCallback(panda::JsiRuntimeCallInfo* info) return package->Callback(info); } +void FunctionDeleter(void *nativePointer, void *data) +{ + auto info = reinterpret_cast(data); + if (info != nullptr) { + delete info; + } +} + bool ArkJSRuntime::Initialize(const std::string& libraryPath, bool isDebugMode, int32_t instanceId) { RuntimeOption option; @@ -86,10 +94,6 @@ void ArkJSRuntime::Reset() vm_ = nullptr; } } - for (auto data : dataList_) { - delete data; - } - dataList_.clear(); #if defined(PREVIEW) previewComponents_.clear(); #endif @@ -235,8 +239,8 @@ shared_ptr ArkJSRuntime::NewFunction(RegisterFunctionType func) { LocalScope scope(vm_); auto data = new PandaFunctionData(shared_from_this(), func); - dataList_.emplace_back(data); - return std::make_shared(shared_from_this(), FunctionRef::New(vm_, FunctionCallback, nullptr, data)); + return std::make_shared(shared_from_this(), + FunctionRef::New(vm_, FunctionCallback, FunctionDeleter, data)); } shared_ptr ArkJSRuntime::NewNativePointer(void* ptr) @@ -312,19 +316,24 @@ void ArkJSRuntime::DumpHeapSnapshot(bool isPrivate) Local PandaFunctionData::Callback(panda::JsiRuntimeCallInfo* info) const { - EscapeLocalScope scope(runtime_->GetEcmaVm()); + auto runtime = runtime_.lock(); + if (runtime == nullptr) { + LOGE("runtime is nullptr"); + return Local(); + } + EscapeLocalScope scope(runtime->GetEcmaVm()); shared_ptr thisPtr = - std::static_pointer_cast(std::make_shared(runtime_, info->GetThisRef())); + std::static_pointer_cast(std::make_shared(runtime, info->GetThisRef())); std::vector> argv; int32_t length = info->GetArgsNumber(); argv.reserve(length); for (int32_t i = 0; i < length; ++i) { argv.emplace_back( - std::static_pointer_cast(std::make_shared(runtime_, info->GetCallArgRef(i)))); + std::static_pointer_cast(std::make_shared(runtime, info->GetCallArgRef(i)))); } - shared_ptr result = func_(runtime_, thisPtr, argv, length); - return scope.Escape(std::static_pointer_cast(result)->GetValue(runtime_)); + shared_ptr result = func_(runtime, thisPtr, argv, length); + return scope.Escape(std::static_pointer_cast(result)->GetValue(runtime)); } } // namespace OHOS::Ace::Framework diff --git a/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h b/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h index 62b0ff0a386..6705d48a08e 100644 --- a/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h +++ b/frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h @@ -197,7 +197,6 @@ public: private: EcmaVM* vm_ = nullptr; int32_t instanceId_ = 0; - std::vector dataList_; LOG_PRINT print_ { nullptr }; UncaughtExceptionCallback uncaughtErrorHandler_ { nullptr }; std::string libPath_ {}; @@ -215,8 +214,8 @@ private: class PandaFunctionData { public: - PandaFunctionData(shared_ptr runtime, RegisterFunctionType func) - : runtime_(std::move(runtime)), func_(std::move(func)) + PandaFunctionData(std::weak_ptr runtime, RegisterFunctionType func) + : runtime_(runtime), func_(std::move(func)) {} ~PandaFunctionData() = default; @@ -226,7 +225,7 @@ public: private: Local Callback(panda::JsiRuntimeCallInfo* info) const; - shared_ptr runtime_; + std::weak_ptr runtime_; RegisterFunctionType func_; friend Local FunctionCallback(panda::JsiRuntimeCallInfo* info); }; diff --git a/interfaces/inner_api/form_render/include/form_renderer.h b/interfaces/inner_api/form_render/include/form_renderer.h index b6c4f68a9b4..f00b0a33b3e 100644 --- a/interfaces/inner_api/form_render/include/form_renderer.h +++ b/interfaces/inner_api/form_render/include/form_renderer.h @@ -48,15 +48,18 @@ public: bool IsAllowUpdate(); void OnSurfaceCreate(const OHOS::AppExecFwk::FormJsInfo& formJsInfo); + void OnSurfaceReuse(const OHOS::AppExecFwk::FormJsInfo& formJsInfo); void OnActionEvent(const std::string& action); void OnError(const std::string& code, const std::string& msg); void OnSurfaceChange(float width, float height); void UpdateConfiguration(const std::shared_ptr& config); + void AttachForm(const OHOS::AAFwk::Want& want, const OHOS::AppExecFwk::FormJsInfo& formJsInfo); private: void InitUIContent(const OHOS::AppExecFwk::FormJsInfo& formJsInfo); void ParseWant(const OHOS::AAFwk::Want& want); void SetRenderDelegate(const sptr &renderRemoteObj); + void AttachUIContent(const OHOS::AppExecFwk::FormJsInfo& formJsInfo); bool allowUpdate_ = true; float width_ = 0.0f; diff --git a/interfaces/inner_api/form_render/include/form_renderer_delegate_interface.h b/interfaces/inner_api/form_render/include/form_renderer_delegate_interface.h index 50f958e1d94..56a52a2e8b8 100644 --- a/interfaces/inner_api/form_render/include/form_renderer_delegate_interface.h +++ b/interfaces/inner_api/form_render/include/form_renderer_delegate_interface.h @@ -47,6 +47,26 @@ public: const std::shared_ptr& surfaceNode, const OHOS::AppExecFwk::FormJsInfo& formJsInfo, const AAFwk::Want& want) = 0; + /** + * @brief OnSurfaceReuse. + * @param surfaceId The surfaceNode ID. + * @param formJsInfo The formJsInfo. + * @param want The want. + */ + virtual int32_t OnSurfaceReuse(uint64_t surfaceId, + const OHOS::AppExecFwk::FormJsInfo& formJsInfo, + const AAFwk::Want& want) + { + return ERR_OK; + } + /** + * @brief OnSurfaceRelease. + * @param surfaceId The surfaceNode ID. + */ + virtual int32_t OnSurfaceRelease(uint64_t surfaceId) + { + return ERR_OK; + } /** * @brief OnActionEvent. * @param action The action. @@ -67,6 +87,8 @@ public: enum Message : uint32_t { ON_SURFACE_CREATE = 1, + ON_SURFACE_REUSE, + ON_SURFACE_RELEASE, ON_ACTION_CREATE, ON_ERROR, ON_SURFACE_CHANGE, diff --git a/interfaces/inner_api/form_render/include/form_renderer_delegate_proxy.h b/interfaces/inner_api/form_render/include/form_renderer_delegate_proxy.h index 6338b0c4485..b15d12d1ed8 100644 --- a/interfaces/inner_api/form_render/include/form_renderer_delegate_proxy.h +++ b/interfaces/inner_api/form_render/include/form_renderer_delegate_proxy.h @@ -35,6 +35,11 @@ public: int32_t OnSurfaceCreate(const std::shared_ptr& surfaceNode, const OHOS::AppExecFwk::FormJsInfo& formJsInfo, const AAFwk::Want& want) override; + int32_t OnSurfaceReuse(uint64_t surfaceId, + const OHOS::AppExecFwk::FormJsInfo& formJsInfo, const AAFwk::Want& want) override; + + int32_t OnSurfaceRelease(uint64_t surfaceId) override; + int32_t OnActionEvent(const std::string& action) override; int32_t OnError(const std::string& code, const std::string& msg) override; diff --git a/interfaces/inner_api/form_render/include/form_renderer_delegate_stub.h b/interfaces/inner_api/form_render/include/form_renderer_delegate_stub.h index 09519d666ad..45b0d4d8bd8 100644 --- a/interfaces/inner_api/form_render/include/form_renderer_delegate_stub.h +++ b/interfaces/inner_api/form_render/include/form_renderer_delegate_stub.h @@ -46,6 +46,8 @@ public: private: int32_t HandleOnSurfaceCreate(MessageParcel &data, MessageParcel &reply); + int32_t HandleOnSurfaceReuse(MessageParcel &data, MessageParcel &reply); + int32_t HandleOnSurfaceRelease(MessageParcel &data, MessageParcel &reply); int32_t HandleOnActionEvent(MessageParcel &data, MessageParcel &reply); int32_t HandleOnError(MessageParcel &data, MessageParcel &reply); int32_t HandleOnSurfaceChange(MessageParcel &data, MessageParcel &reply); diff --git a/interfaces/inner_api/form_render/include/form_renderer_group.h b/interfaces/inner_api/form_render/include/form_renderer_group.h index c544a76e2ed..1debe4def25 100644 --- a/interfaces/inner_api/form_render/include/form_renderer_group.h +++ b/interfaces/inner_api/form_render/include/form_renderer_group.h @@ -16,9 +16,12 @@ #ifndef FOUNDATION_ACE_INTERFACE_INNERKITS_FORM_RENDERER_GROUP_H #define FOUNDATION_ACE_INTERFACE_INNERKITS_FORM_RENDERER_GROUP_H -#include #include #include +#include + +#include "form_js_info.h" +#include "want.h" namespace OHOS { namespace AbilityRuntime { @@ -26,12 +29,7 @@ class Context; class Runtime; } -namespace AAFwk { -class Want; -} - namespace AppExecFwk { -struct FormJsInfo; class Configuration; } @@ -46,7 +44,7 @@ class FormRenderer; * @class FormRendererGroup * FormRendererGroup interface is used to form renderer group. * Provider:FormRendererGroup:runtime = 1:1:1 - * FormRendererGroup:FormRenderer = 1:compId + * FormRendererGroup:FormRenderer = 1:1 */ class ACE_EXPORT FormRendererGroup { public: @@ -62,13 +60,18 @@ public: void DeleteForm(); void DeleteForm(const std::string& compId); void ReloadForm(); - bool IsEmpty(); void UpdateConfiguration(const std::shared_ptr& config); - private: + struct FormRequest { + std::string compId; + OHOS::AAFwk::Want want; + OHOS::AppExecFwk::FormJsInfo formJsInfo; + }; std::shared_ptr context_; std::shared_ptr runtime_; - std::unordered_map> rendererMap_; + std::shared_ptr formRenderer_; + std::vector formRequests_; + std::string currentCompId_; }; } // namespace Ace } // namespace OHOS diff --git a/interfaces/inner_api/form_render/src/form_renderer.cpp b/interfaces/inner_api/form_render/src/form_renderer.cpp index e03717c7f2d..8e4c28b300f 100644 --- a/interfaces/inner_api/form_render/src/form_renderer.cpp +++ b/interfaces/inner_api/form_render/src/form_renderer.cpp @@ -134,7 +134,6 @@ void FormRenderer::UpdateForm(const OHOS::AppExecFwk::FormJsInfo& formJsInfo) HILOG_ERROR("uiContent_ is null"); return; } - uiContent_->UpdateFormSharedImage(formJsInfo.imageDataMap); uiContent_->UpdateFormData(formJsInfo.formData); } @@ -142,6 +141,14 @@ void FormRenderer::UpdateForm(const OHOS::AppExecFwk::FormJsInfo& formJsInfo) void FormRenderer::Destroy() { HILOG_INFO("Destroy FormRenderer start."); + if (formRendererDelegate_ != nullptr) { + auto rsSurfaceNode = uiContent_->GetFormRootNode(); + if (rsSurfaceNode != nullptr) { + HILOG_INFO("Form OnSurfaceRelease!"); + formRendererDelegate_->OnSurfaceRelease(rsSurfaceNode->GetId()); + } + } + if (formRendererDelegate_ != nullptr && formRendererDelegate_->AsObject() != nullptr) { formRendererDelegate_->AsObject()->RemoveDeathRecipient(renderDelegateDeathRecipient_); } @@ -183,6 +190,27 @@ void FormRenderer::OnSurfaceCreate(const OHOS::AppExecFwk::FormJsInfo& formJsInf formRendererDelegate_->OnSurfaceCreate(rsSurfaceNode, formJsInfo, newWant); } +void FormRenderer::OnSurfaceReuse(const OHOS::AppExecFwk::FormJsInfo& formJsInfo) +{ + if (!formRendererDispatcherImpl_) { + HILOG_ERROR("form renderer dispatcher is null!"); + return; + } + if (!formRendererDelegate_) { + HILOG_ERROR("form renderer delegate is null!"); + return; + } + auto rsSurfaceNode = uiContent_->GetFormRootNode(); + if (rsSurfaceNode == nullptr) { + HILOG_ERROR("form renderer rsSurfaceNode is null!"); + return; + } + OHOS::AAFwk::Want newWant; + newWant.SetParam(FORM_RENDERER_DISPATCHER, formRendererDispatcherImpl_->AsObject()); + HILOG_INFO("Form OnSurfaceReuse."); + formRendererDelegate_->OnSurfaceReuse(rsSurfaceNode->GetId(), formJsInfo, newWant); +} + void FormRenderer::OnActionEvent(const std::string& action) { if (!formRendererDelegate_) { @@ -211,21 +239,19 @@ void FormRenderer::SetRenderDelegate(const sptr &remoteObj) HILOG_ERROR("renderRemoteObj is nullptr."); return; } - if (formRendererDelegate_ == nullptr) { - formRendererDelegate_ = renderRemoteObj; - } - if (renderDelegateDeathRecipient_) { - return; + formRendererDelegate_ = renderRemoteObj; + + if (renderDelegateDeathRecipient_ == nullptr) { + renderDelegateDeathRecipient_ = new FormRenderDelegateRecipient([weak = weak_from_this()]() { + auto formRender = weak.lock(); + if (!formRender) { + HILOG_ERROR("formRender is nullptr"); + return; + } + formRender->ResetRenderDelegate(); + }); } - renderDelegateDeathRecipient_ = new FormRenderDelegateRecipient([weak = weak_from_this()]() { - auto formRender = weak.lock(); - if (!formRender) { - HILOG_ERROR("formRender is nullptr"); - return; - } - formRender->ResetRenderDelegate(); - }); auto renderDelegate = formRendererDelegate_->AsObject(); if (renderDelegate == nullptr) { HILOG_ERROR("renderDelegate is nullptr, can not get obj from renderRemoteObj."); @@ -236,6 +262,7 @@ void FormRenderer::SetRenderDelegate(const sptr &remoteObj) void FormRenderer::ResetRenderDelegate() { + HILOG_INFO("ResetRenderDelegate."); formRendererDelegate_ = nullptr; } @@ -261,5 +288,29 @@ void FormRenderDelegateRecipient::OnRemoteDied(const wptr& remote handler_(); } } + +void FormRenderer::AttachForm(const OHOS::AAFwk::Want& want, const OHOS::AppExecFwk::FormJsInfo& formJsInfo) +{ + if (uiContent_ == nullptr) { + HILOG_ERROR("uiContent is null!"); + return; + } + ParseWant(want); + AttachUIContent(formJsInfo); + SetRenderDelegate(proxy_); + OnSurfaceReuse(formJsInfo); +} + +void FormRenderer::AttachUIContent(const OHOS::AppExecFwk::FormJsInfo& formJsInfo) +{ + HILOG_INFO("AttachUIContent width = %{public}f , height = %{public}f.", width_, height_); + SetAllowUpdate(allowUpdate_); + auto rsSurfaceNode = uiContent_->GetFormRootNode(); + if (rsSurfaceNode == nullptr) { + HILOG_ERROR("rsSurfaceNode is nullptr."); + return; + } + rsSurfaceNode->SetBounds(0.0f, 0.0f, width_, height_); +} } // namespace Ace } // namespace OHOS diff --git a/interfaces/inner_api/form_render/src/form_renderer_delegate_proxy.cpp b/interfaces/inner_api/form_render/src/form_renderer_delegate_proxy.cpp index d971ed11b5f..6019d1f53d1 100644 --- a/interfaces/inner_api/form_render/src/form_renderer_delegate_proxy.cpp +++ b/interfaces/inner_api/form_render/src/form_renderer_delegate_proxy.cpp @@ -32,27 +32,29 @@ int32_t FormRendererDelegateProxy::OnSurfaceCreate( HILOG_ERROR("%{public}s, failed to write interface token", __func__); return ERR_INVALID_VALUE; } - - if (surfaceNode == nullptr || !surfaceNode->Marshalling(data)) { + if (surfaceNode == nullptr) { + HILOG_ERROR("%{public}s fail, surfaceNode is nullptr", __func__); + return ERR_INVALID_VALUE; + } + if (!surfaceNode->Marshalling(data)) { HILOG_ERROR("%{public}s fail, write surfaceNode error", __func__); return ERR_INVALID_VALUE; } - if (!data.WriteParcelable(&formJsInfo)) { HILOG_ERROR("%{public}s fail, write formJsInfo error", __func__); return ERR_INVALID_VALUE; } - if (!data.WriteParcelable(&want)) { HILOG_ERROR("%{public}s fail, write want error", __func__); return ERR_INVALID_VALUE; } + HILOG_INFO("Proxy create surfaceNode:%{public}s", std::to_string(surfaceNode->GetId()).c_str()); MessageParcel reply; MessageOption option; auto remoteProxy = Remote(); if (!remoteProxy) { - HILOG_ERROR("Send surfaceNode failed, ipc remoteobj is null"); + HILOG_ERROR("Send surfaceNode failed, ipc remoteObj is null"); return IPC_PROXY_ERR; } int32_t error = remoteProxy->SendRequest( @@ -65,6 +67,69 @@ int32_t FormRendererDelegateProxy::OnSurfaceCreate( return reply.ReadInt32(); } +int32_t FormRendererDelegateProxy::OnSurfaceReuse(uint64_t surfaceId, + const OHOS::AppExecFwk::FormJsInfo& formJsInfo, const AAFwk::Want& want) +{ + MessageParcel data; + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("%{public}s, failed to write interface token", __func__); + return ERR_INVALID_VALUE; + } + data.WriteUint64(surfaceId); + if (!data.WriteParcelable(&formJsInfo)) { + HILOG_ERROR("%{public}s fail, write formJsInfo error", __func__); + return ERR_INVALID_VALUE; + } + if (!data.WriteParcelable(&want)) { + HILOG_ERROR("%{public}s fail, write want error", __func__); + return ERR_INVALID_VALUE; + } + HILOG_INFO("Proxy reuse surfaceNode:%{public}s", std::to_string(surfaceId).c_str()); + + MessageParcel reply; + MessageOption option; + auto remoteProxy = Remote(); + if (!remoteProxy) { + HILOG_ERROR("Send surfaceNode failed, ipc remoteObj is null"); + return IPC_PROXY_ERR; + } + int32_t error = remoteProxy->SendRequest( + static_cast(IFormRendererDelegate::Message::ON_SURFACE_REUSE), data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("%{public}s, failed to SendRequest: %{public}d", __func__, error); + return error; + } + + return reply.ReadInt32(); +} + +int32_t FormRendererDelegateProxy::OnSurfaceRelease(uint64_t surfaceId) +{ + MessageParcel data; + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("%{public}s, failed to write interface token", __func__); + return ERR_INVALID_VALUE; + } + data.WriteUint64(surfaceId); + HILOG_INFO("Proxy release surfaceNode:%{public}s", std::to_string(surfaceId).c_str()); + + MessageParcel reply; + MessageOption option; + auto remoteProxy = Remote(); + if (!remoteProxy) { + HILOG_ERROR("Send surfaceNode failed, ipc remoteObj is null"); + return IPC_PROXY_ERR; + } + int32_t error = remoteProxy->SendRequest( + static_cast(IFormRendererDelegate::Message::ON_SURFACE_RELEASE), data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("%{public}s, failed to SendRequest: %{public}d", __func__, error); + return error; + } + + return reply.ReadInt32(); +} + int32_t FormRendererDelegateProxy::OnActionEvent(const std::string& action) { MessageParcel data; diff --git a/interfaces/inner_api/form_render/src/form_renderer_delegate_stub.cpp b/interfaces/inner_api/form_render/src/form_renderer_delegate_stub.cpp index aaca5c04f53..3b86a4453af 100644 --- a/interfaces/inner_api/form_render/src/form_renderer_delegate_stub.cpp +++ b/interfaces/inner_api/form_render/src/form_renderer_delegate_stub.cpp @@ -18,10 +18,17 @@ namespace OHOS { namespace Ace { +static std::mutex g_surfaceNodeMutex_; +static std::map> g_surfaceNodeMap_; + FormRendererDelegateStub::FormRendererDelegateStub() { memberFuncMap_[static_cast(IFormRendererDelegate::Message::ON_SURFACE_CREATE)] = &FormRendererDelegateStub::HandleOnSurfaceCreate; + memberFuncMap_[static_cast(IFormRendererDelegate::Message::ON_SURFACE_REUSE)] = + &FormRendererDelegateStub::HandleOnSurfaceReuse; + memberFuncMap_[static_cast(IFormRendererDelegate::Message::ON_SURFACE_RELEASE)] = + &FormRendererDelegateStub::HandleOnSurfaceRelease; memberFuncMap_[static_cast(IFormRendererDelegate::Message::ON_ACTION_CREATE)] = &FormRendererDelegateStub::HandleOnActionEvent; memberFuncMap_[static_cast(IFormRendererDelegate::Message::ON_ERROR)] = @@ -60,12 +67,16 @@ int FormRendererDelegateStub::OnRemoteRequest( int FormRendererDelegateStub::HandleOnSurfaceCreate(MessageParcel &data, MessageParcel &reply) { - std::shared_ptr surfaceNode = Rosen::RSSurfaceNode::Unmarshalling(data); + auto surfaceNode = Rosen::RSSurfaceNode::Unmarshalling(data); if (surfaceNode == nullptr) { HILOG_ERROR("surfaceNode is nullptr"); return ERR_INVALID_VALUE; } - + { + std::lock_guard lock(g_surfaceNodeMutex_); + g_surfaceNodeMap_[surfaceNode->GetId()] = surfaceNode; + } + HILOG_INFO("Stub create surfaceNode:%{public}s", std::to_string(surfaceNode->GetId()).c_str()); std::unique_ptr formJsInfo(data.ReadParcelable()); if (formJsInfo == nullptr) { HILOG_ERROR("formJsInfo is nullptr"); @@ -83,6 +94,55 @@ int FormRendererDelegateStub::HandleOnSurfaceCreate(MessageParcel &data, Message return ERR_OK; } +int32_t FormRendererDelegateStub::HandleOnSurfaceReuse(MessageParcel &data, MessageParcel &reply) +{ + uint64_t id = UINT64_MAX; + data.ReadUint64(id); + std::shared_ptr surfaceNode; + { + std::lock_guard lock(g_surfaceNodeMutex_); + surfaceNode = g_surfaceNodeMap_[id]; + } + if (surfaceNode == nullptr) { + HILOG_ERROR("surfaceNode:%{public}s is nullptr", std::to_string(id).c_str()); + return ERR_INVALID_VALUE; + } + + HILOG_INFO("Stub reuse surfaceNode:%{public}s", std::to_string(id).c_str()); + std::unique_ptr formJsInfo(data.ReadParcelable()); + if (formJsInfo == nullptr) { + HILOG_ERROR("formJsInfo is nullptr"); + return ERR_INVALID_VALUE; + } + + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return ERR_INVALID_VALUE; + } + + int32_t errCode = OnSurfaceCreate(surfaceNode, *formJsInfo, *want); + reply.WriteInt32(errCode); + return ERR_OK; +} + +int32_t FormRendererDelegateStub::HandleOnSurfaceRelease(MessageParcel &data, MessageParcel &reply) +{ + uint64_t id = UINT64_MAX; + data.ReadUint64(id); + HILOG_INFO("Stub release surfaceNode:%{public}s start", std::to_string(id).c_str()); + { + std::lock_guard lock(g_surfaceNodeMutex_); + auto iter = g_surfaceNodeMap_.find(id); + if (iter != g_surfaceNodeMap_.end()) { + HILOG_INFO("Stub release surfaceNode:%{public}s finish", std::to_string(id).c_str()); + g_surfaceNodeMap_.erase(iter); + } + } + reply.WriteInt32(ERR_OK); + return ERR_OK; +} + int FormRendererDelegateStub::HandleOnActionEvent(MessageParcel &data, MessageParcel &reply) { std::string action = data.ReadString(); diff --git a/interfaces/inner_api/form_render/src/form_renderer_group.cpp b/interfaces/inner_api/form_render/src/form_renderer_group.cpp index 6b6c94cac20..f86b0d7c35f 100644 --- a/interfaces/inner_api/form_render/src/form_renderer_group.cpp +++ b/interfaces/inner_api/form_render/src/form_renderer_group.cpp @@ -16,7 +16,6 @@ #include "form_renderer_group.h" #include "configuration.h" -#include "form_js_info.h" #include "form_renderer.h" #include "form_renderer_hilog.h" @@ -40,76 +39,78 @@ FormRendererGroup::FormRendererGroup( void FormRendererGroup::AddForm(const OHOS::AAFwk::Want& want, const OHOS::AppExecFwk::FormJsInfo& formJsInfo) { auto compId = want.GetStringParam(FORM_RENDERER_COMP_ID); - HILOG_INFO("AddForm compId %{public}s.", compId.c_str()); - auto iter = rendererMap_.find(compId); - if (iter != rendererMap_.end()) { - HILOG_WARN("AddForm compId: %{public}s exist", compId.c_str()); - auto renderer = iter->second; - renderer->Destroy(); - rendererMap_.erase(iter); + currentCompId_ = compId; + FormRequest formRequest; + formRequest.compId = compId; + formRequest.want = want; + formRequest.formJsInfo = formJsInfo; + formRequests_.push_back(formRequest); + if (formRenderer_ == nullptr) { + formRenderer_ = std::make_shared(context_, runtime_); + if (!formRenderer_) { + HILOG_ERROR("AddForm create form render failed"); + return; + } + HILOG_INFO("AddForm compId is %{public}s. formId is %{public}s", compId.c_str(), + std::to_string(formJsInfo.formId).c_str()); + formRenderer_->AddForm(want, formJsInfo); + } else { + HILOG_INFO("AttachForm compId is %{public}s formRequests size is :%{public}s.", + compId.c_str(), std::to_string(formRequests_.size()).c_str()); + formRenderer_->AttachForm(want, formJsInfo); } - auto formRenderer = std::make_shared(context_, runtime_); - if (!formRenderer) { - HILOG_ERROR("AddForm create formrender failed"); - return; - } - rendererMap_.try_emplace(compId, formRenderer); - formRenderer->AddForm(want, formJsInfo); } void FormRendererGroup::ReloadForm() { - auto iter = rendererMap_.begin(); - while (iter != rendererMap_.end()) { - auto renderer = iter->second; - renderer->ReloadForm(); - iter++; + if (formRenderer_ == nullptr) { + HILOG_ERROR("ReloadForm failed, formRenderer is null"); + return; } + formRenderer_->ReloadForm(); } void FormRendererGroup::UpdateForm(const OHOS::AppExecFwk::FormJsInfo& formJsInfo) { HILOG_INFO("UpdateForm formId %{public}s.", std::to_string(formJsInfo.formId).c_str()); - auto iter = rendererMap_.begin(); - while (iter!= rendererMap_.end()) { - auto renderer = iter->second; - renderer->UpdateForm(formJsInfo); - iter++; + if (formRenderer_ == nullptr) { + HILOG_ERROR("UpdateForm failed, formRenderer is null"); + return; } + formRenderer_->UpdateForm(formJsInfo); } void FormRendererGroup::DeleteForm(const std::string& compId) { - HILOG_INFO("DeleteForm compId %{public}s.", compId.c_str()); - auto iter = rendererMap_.find(compId); - if (iter == rendererMap_.end()) { - return; + HILOG_INFO("DeleteForm compId is %{public}s, currentCompId is %{public}s, formRequests size is %{public}s.", + compId.c_str(), currentCompId_.c_str(), std::to_string(formRequests_.size()).c_str()); + + for (auto iter = formRequests_.begin(); iter != formRequests_.end(); ++iter) { + if (iter->compId == compId) { + formRequests_.erase(iter); + break; + } } - auto renderer = iter->second; - // should release the occupancy of resources of the context, runtime and ui content - if (!renderer) { - HILOG_ERROR("DeleteForm compId %{public}s renderer is null.", compId.c_str()); + + if (formRequests_.empty() || compId != currentCompId_) { return; } - renderer->Destroy(); - rendererMap_.erase(iter); + FormRequest request = formRequests_.back(); + currentCompId_ = request.compId; + HILOG_INFO("RestoreForm compId is %{public}s.", currentCompId_.c_str()); + formRenderer_->AttachForm(request.want, request.formJsInfo); } void FormRendererGroup::DeleteForm() { - HILOG_INFO("DeleteForm all compIds, size: %{public}zu", rendererMap_.size()); - for (const auto &iter : rendererMap_) { - HILOG_INFO("DeleteForm compId %{public}s.", iter.first.c_str()); - iter.second->Destroy(); + if (formRenderer_ == nullptr) { + HILOG_ERROR("DeleteForm failed, formRenderer is null"); + return; } - - rendererMap_.clear(); -} - -bool FormRendererGroup::IsEmpty() -{ - return rendererMap_.empty(); + formRenderer_->Destroy(); + formRenderer_ = nullptr; + formRequests_.clear(); } void FormRendererGroup::UpdateConfiguration( @@ -119,11 +120,11 @@ void FormRendererGroup::UpdateConfiguration( HILOG_ERROR("UpdateConfiguration config is null"); return; } - - HILOG_INFO("UpdateConfiguration all compIds, size: %{public}zu", rendererMap_.size()); - for (const auto& iter : rendererMap_) { - iter.second->UpdateConfiguration(config); + if (formRenderer_ == nullptr) { + HILOG_ERROR("UpdateConfiguration failed, formRenderer is null"); + return; } + formRenderer_->UpdateConfiguration(config); } } // namespace Ace } // namespace OHOS diff --git a/test/fuzztest/arkuiformrendergroup_fuzzer/arkuiformrendergroup_fuzzer.cpp b/test/fuzztest/arkuiformrendergroup_fuzzer/arkuiformrendergroup_fuzzer.cpp index ba86cbddd8a..ba4116639e7 100644 --- a/test/fuzztest/arkuiformrendergroup_fuzzer/arkuiformrendergroup_fuzzer.cpp +++ b/test/fuzztest/arkuiformrendergroup_fuzzer/arkuiformrendergroup_fuzzer.cpp @@ -36,9 +36,6 @@ bool FormRenderGroup(const std::string data, size_t size) fromGroup->ReloadForm(); auto id = size % u16m; fromGroup->DeleteForm(std::to_string(id)); - if (fromGroup->IsEmpty()) { - return false; - } return true; } } diff --git a/test/unittest/interfaces/form_render_test.cpp b/test/unittest/interfaces/form_render_test.cpp index 0a25d5e9fd5..25c6ffad3ce 100644 --- a/test/unittest/interfaces/form_render_test.cpp +++ b/test/unittest/interfaces/form_render_test.cpp @@ -67,19 +67,15 @@ HWTEST_F(FormRenderTest, FormRenderTest001, TestSize.Level1) * @tc.steps: step2. call AddForm * @tc.expected: step2. formRenderer is created successfully and added to the formRendererGroup */ - EXPECT_TRUE(formRendererGroup->IsEmpty()); // formRenderer->uiContent_ is null, so formRenderer->AddForm will not be called formRendererGroup->AddForm(want, formJsInfo); - EXPECT_FALSE(formRendererGroup->IsEmpty()); - auto renderMap = formRendererGroup->rendererMap_; - auto iter = renderMap.find(FORM_COMPONENT_ID_1); - EXPECT_TRUE(iter != renderMap.end()); + EXPECT_TRUE(formRendererGroup->formRenderer_ != nullptr); /** * @tc.steps: step3. call formRenderer's AddForm * @tc.expected: step3. uiContent's relevant methods are called & formRenderer's property are set */ - auto formRenderer = iter->second; + auto formRenderer = formRendererGroup->formRenderer_; EXPECT_TRUE(formRenderer); formRenderer->uiContent_ = UIContent::Create(nullptr, nullptr); EXPECT_TRUE(formRenderer->uiContent_); @@ -91,7 +87,7 @@ HWTEST_F(FormRenderTest, FormRenderTest001, TestSize.Level1) .WillOnce(Return()); EXPECT_CALL(*((MockUIContent*)(formRenderer->uiContent_.get())), SetActionEventHandler(_)).WillOnce(Return()); EXPECT_CALL(*((MockUIContent*)(formRenderer->uiContent_.get())), SetErrorEventHandler(_)).WillOnce(Return()); - EXPECT_CALL(*((MockUIContent*)(formRenderer->uiContent_.get())), GetFormRootNode()).WillOnce(Return(nullptr)); + EXPECT_CALL(*((MockUIContent*)(formRenderer->uiContent_.get())), GetFormRootNode()).Times(Exactly(2)); // call AddForm manually formRenderer->AddForm(want, formJsInfo); EXPECT_EQ(formRenderer->allowUpdate_, true); @@ -108,9 +104,7 @@ HWTEST_F(FormRenderTest, FormRenderTest001, TestSize.Level1) want2.SetParam(FORM_RENDERER_COMP_ID, FORM_COMPONENT_ID_2); want2.SetParam(FORM_RENDERER_ALLOW_UPDATE, true); formRendererGroup->AddForm(want2, formJsInfo); - EXPECT_EQ(static_cast(formRendererGroup->rendererMap_.size()), 2); - // call formRenderer2's events, nothing will happen for formRendererDelegate_ is null - auto formRenderer2 = formRendererGroup->rendererMap_.find(FORM_COMPONENT_ID_2)->second; + auto formRenderer2 = formRendererGroup->formRenderer_; formRenderer2->OnActionEvent(""); formRenderer2->OnError("", ""); formRenderer2->OnSurfaceChange(0.0f, 0.0f); @@ -135,7 +129,6 @@ HWTEST_F(FormRenderTest, FormRenderTest001, TestSize.Level1) * @tc.expected: step7. delete fail */ formRendererGroup->DeleteForm(FORM_COMPONENT_ID_3); - EXPECT_EQ(static_cast(formRendererGroup->rendererMap_.size()), 2); /** * @tc.steps: step8. delete formRenderer whose compId exists @@ -144,14 +137,12 @@ HWTEST_F(FormRenderTest, FormRenderTest001, TestSize.Level1) EXPECT_CALL(*((MockUIContent*)(formRenderer->uiContent_.get())), Destroy()).WillOnce(Return()); // delete formRenderer that compId exists formRendererGroup->DeleteForm(FORM_COMPONENT_ID_1); - EXPECT_EQ(static_cast(formRendererGroup->rendererMap_.size()), 1); /** * @tc.steps: step9. delete all formRenderers * @tc.expected: step9. delete successfully */ formRendererGroup->DeleteForm(); - EXPECT_TRUE(formRendererGroup->IsEmpty()); } /** @@ -175,9 +166,7 @@ HWTEST_F(FormRenderTest, FormRenderTest002, TestSize.Level1) want.SetParam(FORM_RENDERER_PROCESS_ON_ADD_SURFACE, renderDelegate->AsObject()); OHOS::AppExecFwk::FormJsInfo formJsInfo; formRendererGroup->AddForm(want, formJsInfo); - auto renderMap = formRendererGroup->rendererMap_; - auto iter = renderMap.find(FORM_COMPONENT_ID_1); - auto formRenderer = iter->second; + auto formRenderer = formRendererGroup->formRenderer_;; EXPECT_TRUE(formRenderer); formRenderer->uiContent_ = UIContent::Create(nullptr, nullptr); EXPECT_TRUE(formRenderer->uiContent_);