From 71585589de14539f249653d15a16a9b7d9ace6b2 Mon Sep 17 00:00:00 2001 From: sunbees Date: Wed, 4 Sep 2024 16:42:39 +0800 Subject: [PATCH] xcomponent add callback mode Signed-off-by: sunbees Change-Id: Ib94fec1d4e91b558cb0eee3db3e76a00dd4c7006 --- .../pattern/xcomponent/xcomponent_pattern.cpp | 68 ++++++++++++---- .../pattern/xcomponent/xcomponent_pattern.h | 12 +++ .../xcomponent_controller.cpp | 37 ++++++++- .../xcomponent_controller.h | 17 +++- .../xcomponent/xcomponent_testtwo_ng.cpp | 80 +++++++++++++++++++ 5 files changed, 194 insertions(+), 20 deletions(-) diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp index 6534ac09ccc..010cee085db 100644 --- a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp @@ -171,6 +171,7 @@ XComponentPattern::XComponentPattern(const std::optional& id, XComp if (!isTypedNode_) { InitNativeXComponent(); } + RegisterSurfaceCallbackModeEvent(); } void XComponentPattern::InitNativeXComponent() @@ -262,25 +263,15 @@ void XComponentPattern::Initialize() void XComponentPattern::OnAttachToMainTree() { - if (isTypedNode_) { - CHECK_NULL_VOID(renderSurface_); - renderSurface_->RegisterSurface(); - surfaceId_ = renderSurface_->GetUniqueId(); - CHECK_NULL_VOID(xcomponentController_); - xcomponentController_->SetSurfaceId(surfaceId_); - OnSurfaceCreated(); + if (isTypedNode_ && surfaceCallbackMode_ == SurfaceCallbackMode::DEFAULT) { + HandleSurfaceCreated(); } } void XComponentPattern::OnDetachFromMainTree() { - if (isTypedNode_) { - CHECK_NULL_VOID(renderSurface_); - renderSurface_->ReleaseSurfaceBuffers(); - renderSurface_->UnregisterSurface(); - CHECK_NULL_VOID(xcomponentController_); - OnSurfaceDestroyed(); - xcomponentController_->SetSurfaceId(""); + if (isTypedNode_ && surfaceCallbackMode_ == SurfaceCallbackMode::DEFAULT) { + HandleSurfaceDestroyed(); } } @@ -583,6 +574,9 @@ void XComponentPattern::OnDetachFromFrameNode(FrameNode* frameNode) CHECK_NULL_VOID(frameNode); UninitializeAccessibility(); if (isTypedNode_) { + if (surfaceCallbackMode_ == SurfaceCallbackMode::PIP) { + HandleSurfaceDestroyed(); + } if (isNativeXComponent_) { OnNativeUnload(frameNode); } @@ -1895,6 +1889,52 @@ void XComponentPattern::OnSurfaceDestroyed() } } +void XComponentPattern::RegisterSurfaceCallbackModeEvent() +{ + if (isTypedNode_ && !surfaceCallbackModeChangeEvent_) { + surfaceCallbackModeChangeEvent_ = [weak = WeakClaim(this)](SurfaceCallbackMode mode) { + auto xcPattern = weak.Upgrade(); + CHECK_NULL_VOID(xcPattern); + xcPattern->OnSurfaceCallbackModeChange(mode); + }; + } +} + +void XComponentPattern::OnSurfaceCallbackModeChange(SurfaceCallbackMode mode) +{ + CHECK_EQUAL_VOID(surfaceCallbackMode_, mode); + surfaceCallbackMode_ = mode; + auto host = GetHost(); + CHECK_NULL_VOID(host); + if (!host->IsOnMainTree()) { + if (surfaceCallbackMode_ == SurfaceCallbackMode::PIP) { + HandleSurfaceCreated(); + } else if (surfaceCallbackMode_ == SurfaceCallbackMode::DEFAULT) { + HandleSurfaceDestroyed(); + } + } +} + +void XComponentPattern::HandleSurfaceCreated() +{ + CHECK_NULL_VOID(renderSurface_); + renderSurface_->RegisterSurface(); + surfaceId_ = renderSurface_->GetUniqueId(); + CHECK_NULL_VOID(xcomponentController_); + xcomponentController_->SetSurfaceId(surfaceId_); + OnSurfaceCreated(); +} + +void XComponentPattern::HandleSurfaceDestroyed() +{ + CHECK_NULL_VOID(renderSurface_); + renderSurface_->ReleaseSurfaceBuffers(); + renderSurface_->UnregisterSurface(); + CHECK_NULL_VOID(xcomponentController_); + OnSurfaceDestroyed(); + xcomponentController_->SetSurfaceId(""); +} + void XComponentPattern::NativeSurfaceShow() { CHECK_RUN_ON(UI); diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h index 91ad7229f89..eea801213bc 100644 --- a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h @@ -323,6 +323,15 @@ public: float RoundValueToPixelGrid(float value, bool isRound, bool forceCeil, bool forceFloor); void OnSurfaceDestroyed(); void SetRenderFit(RenderFit renderFit); + void HandleSurfaceCreated(); + void HandleSurfaceDestroyed(); + void ChangeSurfaceCallbackMode(SurfaceCallbackMode mode) + { + if (surfaceCallbackModeChangeEvent_) { + surfaceCallbackModeChangeEvent_(mode); + } + } + void OnSurfaceCallbackModeChange(SurfaceCallbackMode mode); private: void OnAttachToFrameNode() override; @@ -391,6 +400,7 @@ private: void UpdateAnalyzerUIConfig(const RefPtr& geometryNode); void ReleaseImageAnalyzer(); void SetRotation(uint32_t rotation); + void RegisterSurfaceCallbackModeEvent(); #ifdef RENDER_EXTRACT_SUPPORTED RenderSurface::RenderSurfaceType CovertToRenderSurfaceType(const XComponentType& hostType); @@ -471,6 +481,8 @@ private: bool isTypedNode_ = false; bool isNativeXComponent_ = false; bool hasLoadNativeDone_ = false; + SurfaceCallbackMode surfaceCallbackMode_ = SurfaceCallbackMode::DEFAULT; + std::function surfaceCallbackModeChangeEvent_; }; } // namespace OHOS::Ace::NG diff --git a/interfaces/inner_api/xcomponent_controller/xcomponent_controller.cpp b/interfaces/inner_api/xcomponent_controller/xcomponent_controller.cpp index 3266eda0672..7c70b2c97b9 100644 --- a/interfaces/inner_api/xcomponent_controller/xcomponent_controller.cpp +++ b/interfaces/inner_api/xcomponent_controller/xcomponent_controller.cpp @@ -16,23 +16,52 @@ #include "xcomponent_controller.h" #include "js_native_api.h" + #include "bridge/declarative_frontend/jsview/js_xcomponent_controller.h" +#include "core/components_ng/pattern/xcomponent/xcomponent_pattern.h" namespace OHOS::Ace { +namespace { +const char* NODEPTR_OF_UINODE = "nodePtr_"; +} // namespace std::shared_ptr XComponentController::GetXComponentControllerFromNapiValue( napi_env env, napi_value napiValue) { - auto vm = reinterpret_cast(env)->GetEcmaVm(); + const auto* vm = reinterpret_cast(env)->GetEcmaVm(); auto localRef = NapiValueToLocalValue(napiValue); if (localRef->IsNull()) { return nullptr; } - auto* jsXComponentController = - static_cast(Local(localRef)->GetNativePointerField( - vm, 0)); + auto* jsXComponentController = static_cast( + Local(localRef)->GetNativePointerField(vm, 0)); if (!jsXComponentController) { return nullptr; } return jsXComponentController->GetController(); } + +XComponentControllerErrorCode XComponentController::SetSurfaceCallbackMode( + napi_env env, napi_value node, SurfaceCallbackMode mode) +{ + const auto* vm = reinterpret_cast(env)->GetEcmaVm(); + auto nodeRef = NapiValueToLocalValue(node); + if (nodeRef.IsEmpty() || !nodeRef->IsObject(vm)) { + return XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_BAD_PARAMETER; + } + auto nodeObj = nodeRef->ToObject(vm); + panda::Local nodePtr = nodeObj->Get(vm, panda::StringRef::NewFromUtf8(vm, NODEPTR_OF_UINODE)); + if (nodePtr.IsEmpty() || nodePtr->IsNull() || nodePtr->IsUndefined()) { + return XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_BAD_PARAMETER; + } + auto* frameNode = reinterpret_cast(nodePtr->ToNativePointer(vm)->Value()); + if (!frameNode) { + return XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_BAD_PARAMETER; + } + auto* xcPattern = frameNode->GetPatternPtr(); + if (!xcPattern) { + return XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_BAD_PARAMETER; + } + xcPattern->ChangeSurfaceCallbackMode(mode); + return XComponentControllerErrorCode::XCOMPONENT_CONTROLLER_NO_ERROR; +} } // namespace OHOS::Ace diff --git a/interfaces/inner_api/xcomponent_controller/xcomponent_controller.h b/interfaces/inner_api/xcomponent_controller/xcomponent_controller.h index 49b44f1c4af..46df05038ef 100644 --- a/interfaces/inner_api/xcomponent_controller/xcomponent_controller.h +++ b/interfaces/inner_api/xcomponent_controller/xcomponent_controller.h @@ -34,6 +34,11 @@ enum XComponentControllerErrorCode { XCOMPONENT_CONTROLLER_RESET_ERROR, }; +enum class SurfaceCallbackMode : char { + DEFAULT = 0, + PIP, +}; + /** * @class XComponentController * XComponentController interface is used to control xcomponent. @@ -45,8 +50,16 @@ public: * @brief Get xcomponentController from napiValue converted by jsXComponentController * */ - static std::shared_ptr GetXComponentControllerFromNapiValue(napi_env env, - napi_value napiValue); + static std::shared_ptr GetXComponentControllerFromNapiValue( + napi_env env, napi_value napiValue); + + /** + * @brief set typedNode.XComponent's SurfaceCallbackMode + * + */ + static XComponentControllerErrorCode SetSurfaceCallbackMode( + napi_env env, napi_value node, SurfaceCallbackMode mode); + XComponentController() = default; virtual ~XComponentController() = default; diff --git a/test/unittest/core/pattern/xcomponent/xcomponent_testtwo_ng.cpp b/test/unittest/core/pattern/xcomponent/xcomponent_testtwo_ng.cpp index c89a57555c5..a860cdaa224 100644 --- a/test/unittest/core/pattern/xcomponent/xcomponent_testtwo_ng.cpp +++ b/test/unittest/core/pattern/xcomponent/xcomponent_testtwo_ng.cpp @@ -525,4 +525,84 @@ HWTEST_F(XComponentTestTwoNg, XComponentTestTwoNg015, TestSize.Level1) ASSERT_FALSE(pattern->IsSupportImageAnalyzerFeature()); SystemProperties::extSurfaceEnabled_ = extSurfaceEnabled; } + +/** + * @tc.name: XComponentTestTwoNg016 + * @tc.desc: Test ChangeSurfaceCallbackMode. + * @tc.type: FUNC + */ +HWTEST_F(XComponentTestTwoNg, XComponentTestTwoNg016, TestSize.Level1) +{ + /** + * @tc.steps: step1. set surface life cycle callback, set id&libraryname to null and create XComponent + * @tc.expected: xcomponent frameNode create successfully + */ + g_testProperty.xcType = XCOMPONENT_SURFACE_TYPE_VALUE; + g_testProperty.xcId = std::nullopt; + g_testProperty.libraryName = std::nullopt; + int32_t onSurfaceCreatedSurfaceCount = 0; + int32_t onSurfaceDestroyedSurfaceCount = 0; + auto onSurfaceCreated = [&onSurfaceCreatedSurfaceCount]( + const std::string& surfaceId) { ++onSurfaceCreatedSurfaceCount; }; + auto onSurfaceDestroyed = [&onSurfaceDestroyedSurfaceCount]( + const std::string& surfaceId) { ++onSurfaceDestroyedSurfaceCount; }; + g_testProperty.surfaceCreatedEvent = std::move(onSurfaceCreated); + g_testProperty.surfaceDestroyedEvent = std::move(onSurfaceDestroyed); + auto frameNode = CreateXComponentNode(g_testProperty); + ASSERT_TRUE(frameNode); + auto pattern = frameNode->GetPattern(); + ASSERT_TRUE(pattern); + pattern->isTypedNode_ = true; + pattern->RegisterSurfaceCallbackModeEvent(); + EXPECT_EQ(pattern->surfaceCallbackMode_, SurfaceCallbackMode::DEFAULT); + + /** + * @tc.steps: step2. attachTo&detachFrom main tree in DEFAULT mode + * @tc.expected: DEFAULT mode attach to(detach from) main tree will call onSurfaceCreated(onSurfaceDestroyed) once + */ + frameNode->AttachToMainTree(false); + EXPECT_EQ(onSurfaceCreatedSurfaceCount, 1); + frameNode->DetachFromMainTree(); + EXPECT_EQ(onSurfaceDestroyedSurfaceCount, 1); + + /** + * @tc.steps: step3. detachFromFrameNode(in frameNode's destructor) in DEFAULT mode + * @tc.expected: will not call onSurfaceDestroyed + */ + pattern->OnDetachFromFrameNode(AceType::RawPtr(frameNode)); + EXPECT_EQ(onSurfaceDestroyedSurfaceCount, 1); + + /** + * @tc.steps: step4. ChangeSurfaceCallbackMode to PIP not in main tree + * @tc.expected: not in main tree change to pip will call onSurfaceCreated once + */ + pattern->ChangeSurfaceCallbackMode(SurfaceCallbackMode::PIP); + EXPECT_EQ(onSurfaceCreatedSurfaceCount, 2); + + /** + * @tc.steps: step5. attachTo&detachFrom main tree in PIP mode + * @tc.expected: PIP mode attach to(detach from) main tree will not call onSurfaceCreated(onSurfaceDestroyed) + */ + frameNode->AttachToMainTree(false); + EXPECT_EQ(onSurfaceCreatedSurfaceCount, 2); + frameNode->DetachFromMainTree(); + EXPECT_EQ(onSurfaceDestroyedSurfaceCount, 1); + + /** + * @tc.steps: step6. detachFromFrameNode(in frameNode's destructor) in PIP mode + * @tc.expected: call onSurfaceDestroyed once + */ + pattern->OnDetachFromFrameNode(AceType::RawPtr(frameNode)); + EXPECT_EQ(onSurfaceDestroyedSurfaceCount, 2); + + /** + * @tc.steps: step7. ChangeSurfaceCallbackMode in main tree + * @tc.expected: will not call onSurfaceCreated(onSurfaceDestroyed) + */ + frameNode->AttachToMainTree(false); + pattern->ChangeSurfaceCallbackMode(SurfaceCallbackMode::DEFAULT); + EXPECT_EQ(onSurfaceDestroyedSurfaceCount, 2); + pattern->ChangeSurfaceCallbackMode(SurfaceCallbackMode::PIP); + EXPECT_EQ(onSurfaceCreatedSurfaceCount, 2); +} } // namespace OHOS::Ace::NG -- Gitee