From 31124371e0dcbc2545ddaeb5a9925c4920976af1 Mon Sep 17 00:00:00 2001 From: zhanghang Date: Fri, 30 May 2025 20:08:54 +0800 Subject: [PATCH] feat:Preview UEC Signed-off-by: zhanghang --- .../pattern/ui_extension/BUILD.gn | 2 + .../preview_ui_extension_adapter.h | 162 +++ .../preview_session_wrapper_impl.cpp | 955 ++++++++++++++++++ .../preview_session_wrapper_impl.h | 139 +++ .../preview_ui_extension_pattern.cpp | 314 ++++++ .../preview_ui_extension_pattern.h | 38 + .../security_ui_extension_pattern.h | 18 +- .../pattern/ui_extension/session_wrapper.h | 2 + .../ui_extension/session_wrapper_factory.cpp | 9 +- .../core/pattern/ui_extension/BUILD.gn | 6 + .../ui_extension/dynamic_component/BUILD.gn | 2 + .../ui_extension_component/BUILD.gn | 2 + 12 files changed, 1639 insertions(+), 10 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/ui_extension/preview_ui_extension_adapter.h create mode 100644 frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp create mode 100644 frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.h create mode 100644 frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp create mode 100644 frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h diff --git a/frameworks/core/components_ng/pattern/ui_extension/BUILD.gn b/frameworks/core/components_ng/pattern/ui_extension/BUILD.gn index 6c677ea4394..8d99a1fe8b3 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/BUILD.gn +++ b/frameworks/core/components_ng/pattern/ui_extension/BUILD.gn @@ -31,6 +31,8 @@ build_component_ng("ui_extension_pattern_ng") { # security_ui_extension_component sources += [ + "security_ui_extension_component/preview_session_wrapper_impl.cpp", + "security_ui_extension_component/preview_ui_extension_pattern.cpp", "security_ui_extension_component/security_session_wrapper_impl.cpp", "security_ui_extension_component/security_ui_extension_pattern.cpp", "security_ui_extension_component/security_ui_extension_proxy.cpp", diff --git a/frameworks/core/components_ng/pattern/ui_extension/preview_ui_extension_adapter.h b/frameworks/core/components_ng/pattern/ui_extension/preview_ui_extension_adapter.h new file mode 100644 index 00000000000..64648fbe807 --- /dev/null +++ b/frameworks/core/components_ng/pattern/ui_extension/preview_ui_extension_adapter.h @@ -0,0 +1,162 @@ +/* +* Copyright (c) 2023-2024 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 FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_PREVIEW_UI_EXTENSION_ADAPTER_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_PREVIEW_UI_EXTENSION_ADAPTER_H + +#include +#include + +#include "core/components_ng/base/frame_node.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_model.h" +#include "core/components_ng/pattern/ui_extension/dynamic_component/dynamic_node.h" +#include "core/components_ng/pattern/ui_extension/dynamic_component/dynamic_pattern.h" +#include "core/components_ng/pattern/ui_extension/isolated_component/isolated_pattern.h" +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h" +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_hub.h" +#include "core/pipeline_ng/pipeline_context.h" +namespace OHOS::Ace { +struct ModalUIExtensionCallbacks; +} // namespace OHOS::Ace + +namespace OHOS::Ace::NG { +class ACE_EXPORT PreViewUIExtensionAdapter { +public: + static PreViewUIExtensionAdapter* GetInstance(); + ~PreViewUIExtensionAdapter() = default; + + void Create(const NG::UIExtensionConfig& config) + { + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode(V2::UI_EXTENSION_COMPONENT_ETS_TAG, nodeId, + []() { return AceType::MakeRefPtr(); }); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->Initialize(config); + pattern->SetPlaceholderNode(config.placeholderNode); + pattern->UpdateWant(config.wantWrap); + pattern->SetDensityDpi(config.densityDpi); + stack->Push(frameNode); + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + pipeline->AddWindowStateChangedCallback(nodeId); + auto dragDropManager = pipeline->GetDragDropManager(); + CHECK_NULL_VOID(dragDropManager); + dragDropManager->AddDragFrameNode(nodeId, AceType::WeakClaim(AceType::RawPtr(frameNode))); + } + + RefPtr CreatePreviewUIExtensionNode(const NG::UIExtensionConfig& config) + { + auto* stack = ViewStackProcessor::GetInstance(); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = FrameNode::GetOrCreateFrameNode(V2::UI_EXTENSION_COMPONENT_ETS_TAG, nodeId, + []() { return AceType::MakeRefPtr(); }); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_RETURN(pattern, nullptr); + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(pipeline, nullptr); + pipeline->AddWindowStateChangedCallback(nodeId); + auto dragDropManager = pipeline->GetDragDropManager(); + CHECK_NULL_RETURN(dragDropManager, nullptr); + dragDropManager->AddDragFrameNode(nodeId, AceType::WeakClaim(AceType::RawPtr(frameNode))); + return frameNode; + } + + void UpdatePreviewUIExtensionConfig(const RefPtr& pattern, + const NG::UIExtensionConfig& config) + { + pattern->Initialize(config); + pattern->SetPlaceholderNode(config.placeholderNode); + pattern->UpdateWant(config.wantWrap); + pattern->SetDensityDpi(config.densityDpi); + } + + void SetWant(const RefPtr& wantWrap) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->UpdateWant(wantWrap); + } + + void SetAdaptiveWidth(bool state) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->SetAdaptiveWidth(state); + } + + void SetAdaptiveHeight(bool state) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->SetAdaptiveHeight(state); + } + + std::string GetUiExtensionType(NG::SessionType sessionType) + { + return ""; + } + + void SetOnRemoteReady(std::function&)>&& onRemoteReady) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetOrCreateEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnRemoteReadyCallback(std::move(onRemoteReady)); + return; + } + + void SetOnTerminated( + std::function&)>&& onTerminated) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetOrCreateEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnTerminatedCallback(std::move(onTerminated)); + } + + void SetOnReceive( + std::function&& onReceive) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto eventHub = frameNode->GetOrCreateEventHub(); + CHECK_NULL_VOID(eventHub); + eventHub->SetOnReceiveCallback(std::move(onReceive)); + } + + void SetOnError( + std::function&& onError) + { + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto pattern = frameNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->SetOnErrorCallback(std::move(onError)); + } +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_UI_EXTENSION_MODEL_NG_H diff --git a/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp new file mode 100644 index 00000000000..70fa15dcb2c --- /dev/null +++ b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp @@ -0,0 +1,955 @@ +/* +* Copyright (c) 2024-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 "core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.h" +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h" + +#include +#include + +#include "accessibility_event_info.h" +#include "extension/extension_business_info.h" +#include "refbase.h" +#include "session_manager/include/extension_session_manager.h" +#include "transaction/rs_sync_transaction_controller.h" +#include "transaction/rs_transaction.h" +#include "want_params.h" +#include "want_params_wrapper.h" +#include "wm/wm_common.h" +#include "wm/data_handler_interface.h" + +#include "adapter/ohos/entrance/ace_container.h" +#include "adapter/ohos/osal/want_wrap_ohos.h" +#include "base/error/error_code.h" +#include "base/utils/utils.h" +#include "core/common/container.h" +#include "core/common/container_scope.h" +#include "core/components_ng/pattern/ui_extension/session_wrapper.h" +#include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h" +#include "core/components_ng/pattern/window_scene/scene/system_window_scene.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { +namespace { +constexpr char START_FAIL_NAME[] = "start_ability_fail"; +constexpr char START_FAIL_MESSAGE[] = "Start ui extension ability failed, please check the want of UIextensionAbility."; +constexpr char BACKGROUND_FAIL_NAME[] = "background_fail"; +constexpr char BACKGROUND_FAIL_MESSAGE[] = "background ui extension ability failed, please check AMS log."; +constexpr char TERMINATE_FAIL_NAME[] = "terminate_fail"; +constexpr char TERMINATE_FAIL_MESSAGE[] = "terminate ui extension ability failed, please check AMS log."; +constexpr char EXIT_ABNORMALLY_NAME[] = "extension_exit_abnormally"; +constexpr char EXIT_ABNORMALLY_MESSAGE[] = "the extension ability exited abnormally, please check AMS log."; +constexpr char EXTENSION_TRANSPARENT_NAME[] = "extension_node_transparent"; +constexpr char EXTENSION_TRANSPARENT_MESSAGE[] = "the extension ability has transparent node."; +constexpr char LIFECYCLE_TIMEOUT_NAME[] = "extension_lifecycle_timeout"; +constexpr char LIFECYCLE_TIMEOUT_MESSAGE[] = "the lifecycle of extension ability is timeout, please check AMS log."; +constexpr char OCCUPIED_AREA_CHANGE_KEY[] = "ability.want.params.IsNotifyOccupiedAreaChange"; +constexpr const char* const UIEXTENSION_CONFIG_FIELD = "ohos.system.window.uiextension.params"; +} // namespace + +static bool IsDispatchExtensionDataToHostWindow(uint32_t customId) +{ + auto businessCode = static_cast(customId); + return (businessCode >= UIContentBusinessCode::WINDOW_CODE_BEGIN && + businessCode <= UIContentBusinessCode::WINDOW_CODE_END); +} + +class PreViewUIExtensionLifecycleListener : public Rosen::ILifecycleListener { +public: + explicit PreViewUIExtensionLifecycleListener(const WeakPtr& sessionWrapper) + : sessionWrapper_(sessionWrapper) {} + virtual ~PreViewUIExtensionLifecycleListener() = default; + + void OnActivation() override {} + void OnForeground() override {} + void OnBackground() override {} + + void OnConnect() override + { + auto sessionWrapper = sessionWrapper_.Upgrade(); + CHECK_NULL_VOID(sessionWrapper); + sessionWrapper->OnConnect(); + } + + void OnDisconnect() override + { + auto sessionWrapper = sessionWrapper_.Upgrade(); + CHECK_NULL_VOID(sessionWrapper); + sessionWrapper->OnDisconnect(false); + } + + void OnExtensionDied() override + { + auto sessionWrapper = sessionWrapper_.Upgrade(); + CHECK_NULL_VOID(sessionWrapper); + sessionWrapper->OnDisconnect(true); + } + + void OnExtensionTimeout(int32_t errorCode) override + { + auto sessionWrapper = sessionWrapper_.Upgrade(); + CHECK_NULL_VOID(sessionWrapper); + sessionWrapper->OnExtensionTimeout(errorCode); + } + + void OnExtensionDetachToDisplay() override + { + auto sessionWrapper = sessionWrapper_.Upgrade(); + CHECK_NULL_VOID(sessionWrapper); + sessionWrapper->OnExtensionDetachToDisplay(); + } + + void OnAccessibilityEvent( + const Accessibility::AccessibilityEventInfo& info, int64_t uiExtensionOffset) override + { + auto sessionWrapper = sessionWrapper_.Upgrade(); + CHECK_NULL_VOID(sessionWrapper); + sessionWrapper->OnAccessibilityEvent(info, uiExtensionOffset); + } + +private: + WeakPtr sessionWrapper_; +}; + +/********************* Begin: Initialization *************************/ +PreviewSessionWrapperImpl::PreviewSessionWrapperImpl( + const WeakPtr& hostPattern, + int32_t instanceId, bool isTransferringCaller, SessionType sessionType) + : hostPattern_(hostPattern), instanceId_(instanceId), isTransferringCaller_(isTransferringCaller), + sessionType_(sessionType) +{ + auto pattern = hostPattern.Upgrade(); + platformId_ = pattern ? pattern->GetUiExtensionId() : 0; + taskExecutor_ = Container::CurrentTaskExecutor(); +} + +PreviewSessionWrapperImpl::~PreviewSessionWrapperImpl() {} + +void PreviewSessionWrapperImpl::InitAllCallback() +{ + CHECK_NULL_VOID(session_); + int32_t callSessionId = GetSessionId(); + if (!taskExecutor_) { + LOGE("PreviewUIExtension Get taskExecutor_ is nullptr, the sessionid = %{public}d", callSessionId); + return; + } + auto sessionCallbacks = session_->GetExtensionSessionEventCallback(); + foregroundCallback_ = + [weak = hostPattern_, taskExecutor = taskExecutor_, callSessionId](OHOS::Rosen::WSError errcode) { + if (errcode != OHOS::Rosen::WSError::WS_OK) { + taskExecutor->PostTask( + [weak, callSessionId] { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]foregroundCallback:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireOnErrorCallback( + ERROR_CODE_UIEXTENSION_FOREGROUND_FAILED, START_FAIL_NAME, START_FAIL_MESSAGE); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionForegroundError"); + } + }; + backgroundCallback_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId](OHOS::Rosen::WSError errcode) { + if (errcode != OHOS::Rosen::WSError::WS_OK) { + taskExecutor->PostTask( + [weak, callSessionId] { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]backgroundCallback:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireOnErrorCallback(ERROR_CODE_UIEXTENSION_BACKGROUND_FAILED, + BACKGROUND_FAIL_NAME, BACKGROUND_FAIL_MESSAGE); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionBackgroundError"); + } + }; + destructionCallback_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId](OHOS::Rosen::WSError errcode) { + if (errcode != OHOS::Rosen::WSError::WS_OK) { + taskExecutor->PostTask( + [weak, callSessionId] { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]destructCallback:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireOnErrorCallback(ERROR_CODE_UIEXTENSION_DESTRUCTION_FAILED, + TERMINATE_FAIL_NAME, TERMINATE_FAIL_MESSAGE); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionDestructionError"); + } + }; + sessionCallbacks->transferAbilityResultFunc_ = [weak = hostPattern_, taskExecutor = taskExecutor_, + callSessionId](int32_t code, const AAFwk::Want& want) { + taskExecutor->PostTask( + [weak, code, want, callSessionId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]transferAbilityResult:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireOnTerminatedCallback(code, MakeRefPtr(want)); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionTransferAbilityResult"); + }; + sessionCallbacks->transferExtensionDataFunc_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId](const AAFwk::WantParams& params) { + taskExecutor->PostTask( + [weak, params, callSessionId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]transferExtensionData:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireOnReceiveCallback(params); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionReceiveCallback"); + }; + sessionCallbacks->notifyRemoteReadyFunc_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId]() { + taskExecutor->PostTask( + [weak, callSessionId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]notifyRemoteReadyFunc:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireOnRemoteReadyCallback(); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionRemoteReadyCallback"); + }; + sessionCallbacks->notifySyncOnFunc_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId]() { + taskExecutor->PostTask( + [weak, callSessionId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]notifySyncOnFunc:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireSyncCallbacks(); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionSyncCallbacks"); + }; + sessionCallbacks->notifyAsyncOnFunc_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId]() { + taskExecutor->PostTask( + [weak, callSessionId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]notifyAsyncOnFunc:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireAsyncCallbacks(); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionAsyncCallbacks"); + }; + sessionCallbacks->notifyBindModalFunc_ = [weak = hostPattern_, + taskExecutor = taskExecutor_, callSessionId]() { + taskExecutor->PostSyncTask( + [weak, callSessionId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]notifyBindModalFunc:" + "The callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->FireBindModalCallback(); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionBindModalCallback"); + }; + sessionCallbacks->notifyGetAvoidAreaByTypeFunc_ = + [instanceId = instanceId_](Rosen::AvoidAreaType type, int32_t apiVersion) -> Rosen::AvoidArea { + Rosen::AvoidArea avoidArea; + auto container = Platform::AceContainer::GetContainer(instanceId); + CHECK_NULL_RETURN(container, avoidArea); + avoidArea = container->GetAvoidAreaByType(type, apiVersion); + return avoidArea; + }; + sessionCallbacks->notifyExtensionEventFunc_ = + [weak = hostPattern_, taskExecutor = taskExecutor_, callSessionId](uint32_t eventId) { + taskExecutor->PostTask( + [weak, callSessionId, eventId]() { + auto pattern = AceType::DynamicCast(weak.Upgrade()); + CHECK_NULL_VOID(pattern); + if (callSessionId != pattern->GetSessionId()) { + TAG_LOGW(AceLogTag::ACE_SECURITYUIEXTENSION, + "notifyBindModalFunc_: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, pattern->GetSessionId()); + return; + } + pattern->OnExtensionEvent(static_cast(eventId)); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionEventCallback"); + }; +} +/*********************** End: Initialization *************************************/ + +/*********************** Begin: About session ************************************/ +void PreviewSessionWrapperImpl::CreateSession(const AAFwk::Want& want, const SessionConfig& config) +{ + PLATFORM_LOGI("PreviewUIExtension The session is created with bundle = %{public}s, ability = %{public}s", + want.GetElement().GetBundleName().c_str(), want.GetElement().GetAbilityName().c_str()); + auto container = Platform::AceContainer::GetContainer(instanceId_); + CHECK_NULL_VOID(container); + customWant_ = std::make_shared(want); + auto wantPtr = std::make_shared(want); + UpdateWantPtr(wantPtr); + isNotifyOccupiedAreaChange_ = want.GetBoolParam(OCCUPIED_AREA_CHANGE_KEY, true); + uint32_t parentWindowType = 0; + if (container->IsUIExtensionWindow()) { + parentWindowType = container->GetParentWindowType(); + } else { + parentWindowType = container->GetWindowType(); + } + PLATFORM_LOGI("PreviewUIExtension isNotifyOccupiedAreaChange is %{public}d, parentWindowType: %{public}u", + isNotifyOccupiedAreaChange_, parentWindowType); + auto callerToken = container->GetToken(); + auto parentToken = container->GetParentToken(); + Rosen::SessionInfo extensionSessionInfo; + extensionSessionInfo.bundleName_ = want.GetElement().GetBundleName(); + extensionSessionInfo.abilityName_ = want.GetElement().GetAbilityName(); + extensionSessionInfo.callerToken_ = callerToken; + extensionSessionInfo.rootToken_ = (isTransferringCaller_ && parentToken) ? parentToken : callerToken; + extensionSessionInfo.want = wantPtr; + extensionSessionInfo.parentWindowType_ = parentWindowType; + extensionSessionInfo.uiExtensionUsage_ = static_cast(config.uiExtensionUsage); + extensionSessionInfo.isAsyncModalBinding_ = config.isAsyncModalBinding; + session_ = Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSession(extensionSessionInfo); + CHECK_NULL_VOID(session_); + lifecycleListener_ = std::make_shared( + AceType::WeakClaim(this)); + session_->RegisterLifecycleListener(lifecycleListener_); + InitAllCallback(); + RegisterDataConsumer(); +} + +void PreviewSessionWrapperImpl::DestroySession() +{ + CHECK_NULL_VOID(session_); + session_->UnregisterLifecycleListener(lifecycleListener_); + auto dataHandler = session_->GetExtensionDataHandler(); + if (dataHandler) { + dataHandler->UnregisterDataConsumer(subSystemId_); + } + customWant_ = nullptr; + session_ = nullptr; +} + +void PreviewSessionWrapperImpl::UpdateWantPtr(std::shared_ptr& wantPtr) +{ + CHECK_NULL_VOID(wantPtr); + AAFwk::WantParams configParam; + auto container = Platform::AceContainer::GetContainer(GetInstanceIdFromHost()); + CHECK_NULL_VOID(container); + container->GetExtensionConfig(configParam); + AAFwk::WantParams wantParam(wantPtr->GetParams()); + wantParam.SetParam(UIEXTENSION_CONFIG_FIELD, AAFwk::WantParamWrapper::Box(configParam)); + wantPtr->SetParams(wantParam); +} + +void PreviewSessionWrapperImpl::ReDispatchWantParams() +{ + CHECK_NULL_VOID(session_); + auto dataHandler = session_->GetExtensionDataHandler(); + CHECK_NULL_VOID(dataHandler); + AAFwk::WantParams configParam; + auto container = Platform::AceContainer::GetContainer(GetInstanceIdFromHost()); + CHECK_NULL_VOID(container); + container->GetExtensionConfig(configParam); + AAFwk::WantParams wantParam(customWant_->GetParams()); + wantParam.SetParam(UIEXTENSION_CONFIG_FIELD, AAFwk::WantParamWrapper::Box(configParam)); + AAFwk::Want dataToSend; + dataToSend.SetParams(wantParam); + dataHandler->SendDataAsync(Rosen::SubSystemId::WM_UIEXT, + static_cast(OHOS::Rosen::Extension::Businesscode::SYNC_WANT_PARAMS), dataToSend); +} + +bool PreviewSessionWrapperImpl::IsSessionValid() +{ + return session_ != nullptr; +} + +int32_t PreviewSessionWrapperImpl::GetSessionId() const +{ + if (session_) { + LOGI("PreviewSessionWrapperImpl::GetSessionId"); + return session_->GetPersistentId(); + } + LOGI("PreviewSessionWrapperImpl::GetSessionId session_ is NULL return 0."); + return 0; +} + +const std::shared_ptr PreviewSessionWrapperImpl::GetWant() +{ + return session_ ? customWant_ : nullptr; +} +/******************************* End: About session ***************************************/ + +/******************************* Begin: Synchronous interface for event notify ************/ +bool PreviewSessionWrapperImpl::NotifyFocusEventSync(bool isFocus) +{ + return false; +} +bool PreviewSessionWrapperImpl::NotifyFocusStateSync(bool focusState) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyBackPressedSync() +{ + CHECK_NULL_RETURN(session_, false); + bool isConsumed = false; + session_->TransferBackPressedEventForConsumed(isConsumed); + PLATFORM_LOGI("PreviewUIExtension BackPress, persistentid = %{public}d and %{public}s consumed.", + GetSessionId(), isConsumed ? "is" : "is not"); + return isConsumed; +} + +bool PreviewSessionWrapperImpl::NotifyPointerEventSync( + const std::shared_ptr& pointerEvent) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyKeyEventSync( + const std::shared_ptr& keyEvent, bool isPreIme) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyKeyEventAsync( + const std::shared_ptr& keyEvent, bool isPreIme) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyAxisEventSync( + const std::shared_ptr& axisEvent) +{ + return false; +} +/*************************** End: Synchronous interface for event notify *************************/ + +/*************************** Begin: Asynchronous interface for event notify **********************/ +bool PreviewSessionWrapperImpl::NotifyFocusEventAsync(bool isFocus) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyFocusStateAsync(bool focusState) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyBackPressedAsync() +{ + return false; +} +bool PreviewSessionWrapperImpl::NotifyPointerEventAsync( + const std::shared_ptr& pointerEvent) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyKeyEventAsync( + const std::shared_ptr& keyEvent) +{ + return false; +} + +bool PreviewSessionWrapperImpl::NotifyAxisEventAsync( + const std::shared_ptr& axisEvent) +{ + return false; +} + +void PreviewSessionWrapperImpl::NotifyCreate() {} + +void PreviewSessionWrapperImpl::NotifyForeground() +{ + ContainerScope scope(instanceId_); + CHECK_NULL_VOID(session_); + auto pipeline = PipelineBase::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto hostWindowId = pipeline->GetFocusWindowId(); + auto wantPtr = session_->EditSessionInfo().want; + UpdateWantPtr(wantPtr); + Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionActivation( + session_, hostWindowId, std::move(foregroundCallback_)); +} + +void PreviewSessionWrapperImpl::NotifyBackground(bool isHandleError) +{ + CHECK_NULL_VOID(session_); + Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionBackground( + session_, std::move(backgroundCallback_)); +} +void PreviewSessionWrapperImpl::NotifyDestroy(bool isHandleError) +{ + CHECK_NULL_VOID(session_); + Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionDestruction( + session_, std::move(destructionCallback_)); +} + +void PreviewSessionWrapperImpl::NotifyConfigurationUpdate() {} + +void PreviewSessionWrapperImpl::OnConnect() +{ + int32_t callSessionId = GetSessionId(); + taskExecutor_->PostTask( + [weak = hostPattern_, wrapperWeak = WeakClaim(this), callSessionId]() { + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]Connect: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + preViewPattern->OnConnect(); + auto wrapper = wrapperWeak.Upgrade(); + CHECK_NULL_VOID(wrapper && wrapper->session_); + ContainerScope scope(wrapper->instanceId_); + if (auto hostWindowNode = WindowSceneHelper::FindWindowScene(preViewPattern->GetHost())) { + auto hostNode = AceType::DynamicCast(hostWindowNode); + CHECK_NULL_VOID(hostNode); + auto hostPattern = hostNode->GetPattern(); + CHECK_NULL_VOID(hostPattern); + wrapper->session_->SetParentSession(hostPattern->GetSession()); + } + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionSessionConnect"); +} + +void PreviewSessionWrapperImpl::OnDisconnect(bool isAbnormal) +{ + int32_t callSessionId = GetSessionId(); + taskExecutor_->PostTask( + [weak = hostPattern_, isAbnormal, callSessionId]() { + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]OnDisconnect: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + preViewPattern->OnDisconnect(isAbnormal); + if (isAbnormal) { + LOGI("PreviewUIExtension OnDisconnect Abnormal."); + preViewPattern->FireOnErrorCallback(ERROR_CODE_UIEXTENSION_EXITED_ABNORMALLY, + EXIT_ABNORMALLY_NAME, EXIT_ABNORMALLY_MESSAGE); + } else { + preViewPattern->FireOnTerminatedCallback(0, nullptr); + } + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionSessionDisconnect"); +} + +void PreviewSessionWrapperImpl::OnExtensionDetachToDisplay() +{ + PLATFORM_LOGI("PreviewUIExtension OnExtensionDetachToDisplay"); + int32_t callSessionId = GetSessionId(); + taskExecutor_->PostTask( + [weak = hostPattern_, callSessionId]() { + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]OnExtensionDetachToDisplay:: The " + "callSessionId(%{public}d) is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + + preViewPattern->OnExtensionDetachToDisplay(); + }, + TaskExecutor::TaskType::UI, "ArkUISecurityUIExtensionOnExtensionDetachToDisplay"); +} + +void PreviewSessionWrapperImpl::OnExtensionTimeout(int32_t errorCode) +{ + int32_t callSessionId = GetSessionId(); + taskExecutor_->PostTask( + [weak = hostPattern_, callSessionId, errorCode]() { + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + LOGW("PreviewUIExtension [AcePreviewUIExtension]OnExtensionTimeout: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + bool isTransparent = errorCode == ERROR_CODE_UIEXTENSION_TRANSPARENT; + preViewPattern->FireOnErrorCallback( + isTransparent ? errorCode : ERROR_CODE_UIEXTENSION_LIFECYCLE_TIMEOUT, + isTransparent ? EXTENSION_TRANSPARENT_NAME : LIFECYCLE_TIMEOUT_NAME, + isTransparent ? EXTENSION_TRANSPARENT_MESSAGE : LIFECYCLE_TIMEOUT_MESSAGE); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionTimeout"); +} + +void PreviewSessionWrapperImpl::OnAccessibilityEvent( + const Accessibility::AccessibilityEventInfo& info, int64_t offset) +{} + +void PreviewSessionWrapperImpl::TransferAccessibilityHoverEvent(float pointX, + float pointY, int32_t sourceType, int32_t eventType, int64_t timeMs) +{ + CHECK_NULL_VOID(session_); + session_->TransferAccessibilityHoverEvent(pointX, pointY, sourceType, eventType, timeMs); +} + +void PreviewSessionWrapperImpl::TransferAccessibilityChildTreeRegister( + uint32_t windowId, int32_t treeId, int64_t accessibilityId) +{ + CHECK_NULL_VOID(session_); + session_->TransferAccessibilityChildTreeRegister(windowId, treeId, accessibilityId); +} + +void PreviewSessionWrapperImpl::TransferAccessibilityChildTreeDeregister() +{ + CHECK_NULL_VOID(session_); + session_->TransferAccessibilityChildTreeUnregister(); +} + +void PreviewSessionWrapperImpl::TransferAccessibilityDumpChildInfo( + const std::vector& params, std::vector& info) +{ + CHECK_NULL_VOID(session_); + session_->TransferAccessibilityDumpChildInfo(params, info); +} +/************************ End: The interface about the accessibility **************************/ + +/********** Begin: The interface to control the display area and the avoid area ***************/ +std::shared_ptr PreviewSessionWrapperImpl::GetSurfaceNode() const +{ + return session_ ? session_->GetSurfaceNode() : nullptr; +} + +void PreviewSessionWrapperImpl::NotifyDisplayArea(const RectF& displayArea) +{ + CHECK_NULL_VOID(session_); + ContainerScope scope(instanceId_); + auto pipeline = PipelineBase::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto curWindow = pipeline->GetCurrentWindowRect(); + displayArea_ = displayArea + OffsetF(curWindow.Left(), curWindow.Top()); + std::shared_ptr transaction; + auto parentSession = session_->GetParentSession(); + auto reason = parentSession ? parentSession->GetSizeChangeReason() : session_->GetSizeChangeReason(); + reason_ = (uint32_t)reason; + auto persistentId = parentSession ? parentSession->GetPersistentId() : session_->GetPersistentId(); + ACE_SCOPED_TRACE("NotifyDisplayArea id: %d, reason [%d]", persistentId, reason); + PLATFORM_LOGI("PreviewUIExtension DisplayArea: %{public}s, persistentId: %{public}d, reason: %{public}d", + displayArea_.ToString().c_str(), persistentId, reason); + if (reason == Rosen::SizeChangeReason::ROTATION) { + if (auto temp = transaction_.lock()) { + transaction = temp; + transaction_.reset(); + } else if (auto transactionController = Rosen::RSSyncTransactionController::GetInstance()) { + transaction = transactionController->GetRSTransaction(); + } + if (transaction && parentSession) { + transaction->SetDuration(pipeline->GetSyncAnimationOption().GetDuration()); + } + } + session_->UpdateRect({ std::round(displayArea_.Left()), std::round(displayArea_.Top()), + std::round(displayArea_.Width()), std::round(displayArea_.Height()) }, + reason, "NotifyDisplayArea", transaction); +} + +void PreviewSessionWrapperImpl::NotifySizeChangeReason( + WindowSizeChangeReason type, const std::shared_ptr& rsTransaction) +{ + CHECK_NULL_VOID(session_); + auto reason = static_cast(type); + session_->UpdateSizeChangeReason(reason); + if (rsTransaction && (type == WindowSizeChangeReason::ROTATION)) { + transaction_ = rsTransaction; + } +} + +void PreviewSessionWrapperImpl::NotifyOriginAvoidArea( + const Rosen::AvoidArea& avoidArea, uint32_t type) const +{ + CHECK_NULL_VOID(session_); + PLATFORM_LOGI("PreviewUIExtension The avoid area is notified to the provider."); + session_->UpdateAvoidArea( + sptr::MakeSptr(avoidArea), static_cast(type)); +} + +bool PreviewSessionWrapperImpl::NotifyOccupiedAreaChangeInfo( + sptr info, bool needWaitLayout) +{ + CHECK_NULL_RETURN(session_, false); + CHECK_NULL_RETURN(info, false); + CHECK_NULL_RETURN(isNotifyOccupiedAreaChange_, false); + int32_t keyboardHeight = static_cast(info->rect_.height_); + if (keyboardHeight > 0) { + ContainerScope scope(instanceId_); + auto pipeline = PipelineBase::GetCurrentContext(); + CHECK_NULL_RETURN(pipeline, false); + auto curWindow = pipeline->GetCurrentWindowRect(); + int32_t spaceWindow = std::max(curWindow.Bottom() - displayArea_.Bottom(), .0); + keyboardHeight = static_cast(std::max(keyboardHeight - spaceWindow, 0)); + } + sptr newInfo = new Rosen::OccupiedAreaChangeInfo( + info->type_, info->rect_, info->safeHeight_, info->textFieldPositionY_, info->textFieldHeight_); + newInfo->rect_.height_ = static_cast(keyboardHeight); + PLATFORM_LOGI("PreviewUIExtension The occcupied area with 'keyboardHeight = %{public}d'" + "is notified to the provider.", keyboardHeight); + session_->NotifyOccupiedAreaChangeInfo(newInfo); + return true; +} + +void PreviewSessionWrapperImpl::SetDensityDpiImpl(bool isDensityDpi) +{ + CHECK_NULL_VOID(session_); + if (isDensityDpi) { + float density = PipelineBase::GetCurrentDensity(); + session_->NotifyDensityFollowHost(isDensityDpi, density); + } +} + +void PreviewSessionWrapperImpl::SendDataAsync(const AAFwk::WantParams& params) const +{ + PLATFORM_LOGD("The data is asynchronously send and the session is %{public}s", + session_ ? "valid" : "invalid"); + CHECK_NULL_VOID(session_); + session_->TransferComponentData(params); +} + +int32_t PreviewSessionWrapperImpl::SendDataSync( + const AAFwk::WantParams& wantParams, AAFwk::WantParams& reWantParams) const +{ + PLATFORM_LOGD("The data is synchronously send and the session is %{public}s", + session_ ? "valid" : "invalid"); + Rosen::WSErrorCode transferCode = Rosen::WSErrorCode::WS_ERROR_TRANSFER_DATA_FAILED; + if (session_) { + transferCode = session_->TransferComponentDataSync(wantParams, reWantParams); + } + return static_cast(transferCode); +} + +uint32_t PreviewSessionWrapperImpl::GetReasonDump() const +{ + return reason_; +} + +void PreviewSessionWrapperImpl::NotifyUieDump(const std::vector& params, std::vector& info) +{ + CHECK_NULL_VOID(session_); + session_->NotifyDumpInfo(params, info); +} + +bool PreviewSessionWrapperImpl::SendBusinessDataSyncReply( + UIContentBusinessCode code, const AAFwk::Want& data, AAFwk::Want& reply, RSSubsystemId subSystemId) +{ + if (code == UIContentBusinessCode::UNDEFINED) { + return false; + } + CHECK_NULL_RETURN(session_, false); + auto dataHandler = session_->GetExtensionDataHandler(); + CHECK_NULL_RETURN(dataHandler, false); + auto result = dataHandler->SendDataSync(static_cast(subSystemId), + static_cast(code), data, reply); + if (result != Rosen::DataHandlerErr::OK) { + PLATFORM_LOGW("PreviewUIExtension SendBusinessDataSyncReply Fail, businessCode=%{public}u, " + "result=%{public}u, subSystemId=%{public}hhu.", code, result, subSystemId); + return false; + } + PLATFORM_LOGI("PreviewUIExtension SendBusinessDataSyncReply Success," + "businessCode=%{public}u, subSystemId=%{public}hhu.", code, subSystemId); + return true; +} + +int32_t PreviewSessionWrapperImpl::GetInstanceIdFromHost() const +{ + auto pattern = hostPattern_.Upgrade(); + if (pattern == nullptr) { + PLATFORM_LOGW("PreviewUIExtension UIExtension pattern is null," + "session wrapper get instanceId from host return fail."); + return INSTANCE_ID_UNDEFINED; + } + auto instanceId = pattern->GetInstanceIdFromHost(); + if (instanceId != instanceId_) { + PLATFORM_LOGW("PreviewUIExtension SessionWrapper instanceId %{public}d" + "not equal frame node instanceId %{public}d", instanceId_, instanceId); + } + return instanceId; +} + +bool PreviewSessionWrapperImpl::SendBusinessData( + UIContentBusinessCode code, const AAFwk::Want& data, BusinessDataSendType type, RSSubsystemId subSystemId) +{ + if (code == UIContentBusinessCode::UNDEFINED) { + return false; + } + CHECK_NULL_RETURN(session_, false); + auto dataHandler = session_->GetExtensionDataHandler(); + CHECK_NULL_RETURN(dataHandler, false); + if (type == BusinessDataSendType::ASYNC) { + dataHandler->SendDataAsync(static_cast(subSystemId), + static_cast(code), data); + PLATFORM_LOGD("SendBusinessData ASYNC Success, businessCode=%{public}u, subSystemId=%{public}hhu.", + code, subSystemId); + return true; + } + auto result = dataHandler->SendDataSync(static_cast(subSystemId), + static_cast(code), data); + if (result != Rosen::DataHandlerErr::OK) { + PLATFORM_LOGD("SendBusinessData SYNC Fail, businessCode=%{public}u, " + "result=%{public}u, subSystemId=%{public}hhu.", code, result, subSystemId); + return false; + } + PLATFORM_LOGD("SendBusinessData SYNC Success, businessCode=%{public}u, subSystemId=%{public}hhu.", + code, subSystemId); + return true; +} + +void PreviewSessionWrapperImpl::DispatchExtensionDataToHostWindow(uint32_t customId, const AAFwk::Want& data) +{ + int32_t callSessionId = GetSessionId(); + CHECK_NULL_VOID(taskExecutor_); + auto instanceId = GetInstanceIdFromHost(); + taskExecutor_->PostTask( + [instanceId, weak = hostPattern_, customId, data, callSessionId]() { + ContainerScope scope(instanceId); + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT, + "Sec DispatchExtensionDataToHostWindow: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + auto container = Platform::AceContainer::GetContainer(instanceId); + CHECK_NULL_VOID(container); + container->DispatchExtensionDataToHostWindow(customId, data, callSessionId); + }, + TaskExecutor::TaskType::UI, "ArkUIDispatchExtensionSecDataToHostWindow"); +} + +void PreviewSessionWrapperImpl::PostBusinessDataConsumeAsync(uint32_t customId, const AAFwk::Want& data) +{ + PLATFORM_LOGI("PreviewUIExtension PostBusinessDataConsumeAsync, businessCode=%{public}u.", customId); + int32_t callSessionId = GetSessionId(); + CHECK_NULL_VOID(taskExecutor_); + auto instanceId = GetInstanceIdFromHost(); + taskExecutor_->PostTask( + [instanceId, weak = hostPattern_, customId, data, callSessionId]() { + ContainerScope scope(instanceId); + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + LOGW("PreviewUIExtension BusinessDataConsumeAsync: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + preViewPattern->OnUIExtBusinessReceive(static_cast(customId), data); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionBusinessDataConsumeAsync"); +} +void PreviewSessionWrapperImpl::PostBusinessDataConsumeSyncReply( + uint32_t customId, const AAFwk::Want& data, std::optional& reply) +{ + PLATFORM_LOGI("PreviewUIExtension PostBusinessDataConsumeSyncReply, businessCode=%{public}u.", customId); + int32_t callSessionId = GetSessionId(); + CHECK_NULL_VOID(taskExecutor_); + auto instanceId = GetInstanceIdFromHost(); + taskExecutor_->PostSyncTask( + [instanceId, weak = hostPattern_, customId, data, &reply, callSessionId]() { + ContainerScope scope(instanceId); + auto preViewPattern = weak.Upgrade(); + CHECK_NULL_VOID(preViewPattern); + if (callSessionId != preViewPattern->GetSessionId()) { + LOGW("PreviewUIExtension BusinessDataConsumeSyncReply: The callSessionId(%{public}d)" + " is inconsistent with the curSession(%{public}d)", + callSessionId, preViewPattern->GetSessionId()); + return; + } + preViewPattern->OnUIExtBusinessReceiveReply( + static_cast(customId), data, reply); + }, + TaskExecutor::TaskType::UI, "ArkUIUIExtensionBusinessDataConsumeSyncReply"); +} + +bool PreviewSessionWrapperImpl::RegisterDataConsumer() +{ + CHECK_NULL_RETURN(session_, false); + auto dataHandler = session_->GetExtensionDataHandler(); + CHECK_NULL_RETURN(dataHandler, false); + auto subSystemId = subSystemId_; + auto callback = [wrapperWeak = WeakClaim(this), subSystemId] + (Rosen::SubSystemId id, uint32_t customId, AAFwk::Want&& data, std::optional& reply) ->int32_t { + auto sessionWrapper = wrapperWeak.Upgrade(); + CHECK_NULL_RETURN(sessionWrapper, false); + auto instanceId = sessionWrapper->GetInstanceIdFromHost(); + ContainerScope scope(instanceId); + if (id != subSystemId) { + return false; + } + if (IsDispatchExtensionDataToHostWindow(customId)) { + sessionWrapper->DispatchExtensionDataToHostWindow(customId, data); + return true; + } + if (reply.has_value()) { + sessionWrapper->PostBusinessDataConsumeSyncReply(customId, data, reply); + } else { + sessionWrapper->PostBusinessDataConsumeAsync(customId, data); + } + return false; + }; + auto result = dataHandler->RegisterDataConsumer(subSystemId, std::move(callback)); + if (result != Rosen::DataHandlerErr::OK) { + PLATFORM_LOGW("PreviewUIExtension RegisterDataConsumer Fail, result=%{public}u", result); + return false; + } + return true; +} +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.h b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.h new file mode 100644 index 00000000000..48ae6b45342 --- /dev/null +++ b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.h @@ -0,0 +1,139 @@ +/* +* 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 FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_SUEC_PREVIEW_SESSION_WRAPPER_IMPL_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_SUEC_PREVIEW_SESSION_WRAPPER_IMPL_H + +#include + +#include "session/host/include/extension_session.h" +#include "want.h" + +#include "base/geometry/ng/rect_t.h" +#include "base/memory/referenced.h" +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/security_session_wrapper_impl.h" +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h" +#include "core/components_ng/pattern/ui_extension/session_wrapper.h" + +namespace OHOS::Ace::NG { +class PreviewSessionWrapperImpl : public SessionWrapper { + DECLARE_ACE_TYPE(PreviewSessionWrapperImpl, SessionWrapper); + +public: + PreviewSessionWrapperImpl( + const WeakPtr& hostPattern, + int32_t instanceId, + bool isTransferringCaller, + SessionType sessionType); + ~PreviewSessionWrapperImpl() override; + + // About session + void CreateSession(const AAFwk::Want& want, const SessionConfig& config) override; + void DestroySession() override; + bool IsSessionValid() override; + int32_t GetSessionId() const override; + const std::shared_ptr GetWant() override; + + // Synchronous interface for event notify + bool NotifyFocusEventSync(bool isFocus) override; + bool NotifyFocusStateSync(bool focusState) override; + bool NotifyBackPressedSync() override; + bool NotifyPointerEventSync(const std::shared_ptr& pointerEvent) override; + bool NotifyKeyEventSync(const std::shared_ptr& keyEvent, bool isPreIme) override; + bool NotifyKeyEventAsync(const std::shared_ptr& keyEvent, bool isPreIme) override; + bool NotifyAxisEventSync(const std::shared_ptr& axisEvent) override; + + // Asynchronous interface for event notify + bool NotifyFocusEventAsync(bool isFocus) override; + bool NotifyFocusStateAsync(bool focusState) override; + bool NotifyBackPressedAsync() override; + bool NotifyPointerEventAsync(const std::shared_ptr& pointerEvent) override; + bool NotifyKeyEventAsync(const std::shared_ptr& keyEvent) override; + bool NotifyAxisEventAsync(const std::shared_ptr& axisEvent) override; + + // The lifecycle interface + void NotifyCreate() override; + void NotifyForeground() override; + void NotifyBackground(bool isHandleError) override; + void NotifyDestroy(bool isHandleError = true) override; + void NotifyConfigurationUpdate() override; + + // The interface for responsing provider + void OnConnect() override; + void OnDisconnect(bool isAbnormal) override; + void OnExtensionTimeout(int32_t errorCode) override; + void OnExtensionDetachToDisplay() override; + void OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info, int64_t offset) override; + + void TransferAccessibilityHoverEvent(float pointX, float pointY, int32_t sourceType, int32_t eventType, + int64_t timeMs) override; + void TransferAccessibilityChildTreeRegister(uint32_t windowId, int32_t treeId, int64_t accessibilityId) override; + void TransferAccessibilityChildTreeDeregister() override; + void TransferAccessibilityDumpChildInfo( + const std::vector& params, std::vector& info) override; + + // The interface to control the display area and the avoid area + std::shared_ptr GetSurfaceNode() const override; + void NotifyDisplayArea(const RectF& displayArea) override; + void NotifySizeChangeReason( + WindowSizeChangeReason type, const std::shared_ptr& rsTransaction) override; + void NotifyOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type) const override; + bool NotifyOccupiedAreaChangeInfo( + sptr info, bool needWaitLayout) override; + void SetDensityDpiImpl(bool isDensityDpi) override; + + // The interface to send the data for ArkTS + void SendDataAsync(const AAFwk::WantParams& params) const override; + int32_t SendDataSync(const AAFwk::WantParams& wantParams, AAFwk::WantParams& reWantParams) const override; + + // The interface for UEC dump + uint32_t GetReasonDump() const override; + void NotifyUieDump(const std::vector& params, std::vector& info) override; + int32_t GetInstanceIdFromHost() const; + bool SendBusinessDataSyncReply(UIContentBusinessCode code, const AAFwk::Want& data, AAFwk::Want& reply, + RSSubsystemId subSystemId = RSSubsystemId::ARKUI_UIEXT) override; + bool SendBusinessData(UIContentBusinessCode code, const AAFwk::Want& data, BusinessDataSendType type, + RSSubsystemId subSystemId = RSSubsystemId::ARKUI_UIEXT) override; + void ReDispatchWantParams() override; + +private: + void InitAllCallback(); + bool RegisterDataConsumer(); + void PostBusinessDataConsumeAsync(uint32_t customId, const AAFwk::Want& data); + void PostBusinessDataConsumeSyncReply( + uint32_t customId, const AAFwk::Want& data, std::optional& reply); + void DispatchExtensionDataToHostWindow(uint32_t customId, const AAFwk::Want& data); + void UpdateWantPtr(std::shared_ptr& wantPtr); + AceLogTag tag_ = AceLogTag::ACE_SECURITYUIEXTENSION; + WeakPtr hostPattern_; + RefPtr taskExecutor_; + int32_t instanceId_; + bool isTransferringCaller_ = false; + SessionType sessionType_ = SessionType::UI_EXTENSION_ABILITY; + int32_t platformId_ = 0; + sptr session_; + bool isNotifyOccupiedAreaChange_ = true; + RectF displayArea_; + uint32_t reason_ = (uint32_t)Rosen::SizeChangeReason::UNDEFINED; + std::shared_ptr lifecycleListener_; + std::function foregroundCallback_; + std::function backgroundCallback_; + std::function destructionCallback_; + std::weak_ptr transaction_; + std::shared_ptr customWant_; + OHOS::Rosen::SubSystemId subSystemId_ = OHOS::Rosen::SubSystemId::ARKUI_UIEXT; +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_SUEC_SECURITY_SESSION_WRAPPER_IMPL_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp new file mode 100644 index 00000000000..23f4b4fb1e7 --- /dev/null +++ b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp @@ -0,0 +1,314 @@ +/* + * 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 "core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h" + +#include + +#include "core/event/key_event.h" +#include "core/event/pointer_event.h" +#include "session/host/include/extension_session.h" +#include "session/host/include/session.h" +#include "ui/rs_surface_node.h" + +#include "adapter/ohos/entrance/ace_container.h" +#include "adapter/ohos/entrance/ace_extra_input_data.h" +#include "adapter/ohos/entrance/mmi_event_convertor.h" +#include "adapter/ohos/osal/want_wrap_ohos.h" +#include "base/error/error_code.h" +#include "base/geometry/offset.h" +#include "base/log/dump_log.h" +#include "base/utils/utils.h" +#include "core/common/container.h" +#include "core/components_ng/event/event_hub.h" +#include "core/components_ng/pattern/pattern.h" +#include "core/components_ng/pattern/text_field/text_field_manager.h" +#include "core/components_ng/pattern/ui_extension/session_wrapper.h" +#include "core/components_ng/pattern/ui_extension/session_wrapper_factory.h" +#include "core/components_ng/pattern/ui_extension/preview_ui_extension_adapter.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_component/modal_ui_extension_proxy_impl.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_component/session_wrapper_impl.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_proxy.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_layout_algorithm.h" +#include "core/components_ng/pattern/window_scene/scene/window_pattern.h" +#include "core/components_ng/render/adapter/rosen_render_context.h" +#include "core/components_ng/render/adapter/rosen_window.h" +#include "core/event/ace_events.h" +#include "core/event/mouse_event.h" +#include "core/event/touch_event.h" +#include "core/pipeline/pipeline_context.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { +namespace { +constexpr char UI_EXTENSION_TYPE_KEY[] = "ability.want.params.uiExtensionType"; +} + +PreviewUIExtensionPattern::PreviewUIExtensionPattern(): SecurityUIExtensionPattern::SecurityUIExtensionPattern() +{ + PLATFORM_LOGI("The Preview UIExtension is created."); +} + +PreviewUIExtensionPattern::~PreviewUIExtensionPattern() +{ + PLATFORM_LOGI("PreviewUIExtension The Security UIExtension is destroyed."); +} + +void PreviewUIExtensionPattern::Initialize(const NG::UIExtensionConfig& config) +{ + if (sessionWrapper_ != nullptr) { + return; + } + sessionType_ = config.sessionType; + SessionCreateParam sessionCreateParam; + sessionCreateParam.hostPattern = WeakClaim(this); + sessionCreateParam.instanceId = instanceId_; + sessionCreateParam.isTransferringCaller = config.transferringCaller; + sessionWrapper_ = SessionWrapperFactory::CreateSessionWrapper( + config.sessionType, sessionCreateParam); + accessibilitySessionAdapter_ = + AceType::MakeRefPtr(sessionWrapper_); +} + +void PreviewUIExtensionPattern::UpdateWant(const RefPtr& wantWrap) +{ + if (!wantWrap) { + PLATFORM_LOGW("wantWrap is nullptr"); + return; + } + auto wantWrapOhos = AceType::DynamicCast(wantWrap); + if (!wantWrapOhos) { + PLATFORM_LOGW("DynamicCast failed, wantWrapOhos is nullptr"); + return; + } + auto want = wantWrapOhos->GetWant(); + UpdateWant(want); +} + +void PreviewUIExtensionPattern::UpdateWant(const AAFwk::Want& want) +{ + uiExtensionType_ = want.GetStringParam(UI_EXTENSION_TYPE_KEY); + if (!CheckConstraint()) { + PLATFORM_LOGE("PreviewUIExtension Check constraint failed."); + return; + } + + CHECK_NULL_VOID(sessionWrapper_); + PLATFORM_LOGI("PreviewUIExtension The current state is '%{public}s' when UpdateWant.", ToString(state_)); + bool isBackground = state_ == AbilityState::BACKGROUND; + // Prohibit rebuilding the session unless the Want is updated. + if (sessionWrapper_->IsSessionValid()) { + auto sessionWant = sessionWrapper_->GetWant(); + if (sessionWant == nullptr) { + PLATFORM_LOGW("PreviewUIExtension The sessionWrapper want is nulllptr."); + return; + } + if (sessionWant->IsEquals(want)) { + return; + } + PLATFORM_LOGI("PreviewUIExtension The old want bundle = %{public}s, ability = %{public}s", + sessionWant->GetElement().GetBundleName().c_str(), sessionWant->GetElement().GetAbilityName().c_str()); + auto host = GetHost(); + CHECK_NULL_VOID(host); + host->RemoveChild(contentNode_); + host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); + NotifyDestroy(); + // reset callback, in order to register childtree call back again when onConnect to new ability + ResetAccessibilityChildTreeCallback(); + } + + MountPlaceholderNode(); + SessionConfig config; + config.uiExtensionUsage = UIExtensionUsage::EMBEDDED; + sessionWrapper_->CreateSession(want, config); + if (isBackground) { + PLATFORM_LOGW("PreviewUIExtension Unable to StartUiextensionAbility while in the background."); + return; + } + NotifyForeground(); +} + +void PreviewUIExtensionPattern::OnConnect() +{ + CHECK_RUN_ON(UI); + CHECK_NULL_VOID(sessionWrapper_); + PLATFORM_LOGI("PreviewUIExtension The session is connected and the current state is '%{public}s'.", + ToString(state_)); + ContainerScope scope(instanceId_); + contentNode_ = FrameNode::CreateFrameNode(V2::UI_EXTENSION_SURFACE_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr()); + contentNode_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT); + contentNode_->SetHitTestMode(HitTestMode::HTMNONE); + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto&& opts = host->GetLayoutProperty()->GetSafeAreaExpandOpts(); + if (opts && opts->Expansive()) { + contentNode_->GetLayoutProperty()->UpdateSafeAreaExpandOpts(*opts); + contentNode_->MarkModifyDone(); + } + auto context = AceType::DynamicCast(contentNode_->GetRenderContext()); + CHECK_NULL_VOID(context); + auto surfaceNode = sessionWrapper_->GetSurfaceNode(); + if (!surfaceNode) { + PLATFORM_LOGE("PreviewUIExtension Get surfaceNode from session is null."); + return; + } + context->SetRSNode(surfaceNode); + RemovePlaceholderNode(); + host->AddChild(contentNode_, 0); + host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); + surfaceNode->CreateNodeInRenderThread(); + FireOnRemoteReadyCallback(); + auto focusHub = host->GetFocusHub(); + bool isFocused = focusHub && focusHub->IsCurrentFocus(); + RegisterVisibleAreaChange(); + DispatchFocusState(isFocused); + DispatchFollowHostDensity(GetDensityDpi()); + auto pipeline = host->GetContextRefPtr(); + CHECK_NULL_VOID(pipeline); + auto uiExtensionManager = pipeline->GetUIExtensionManager(); + auto weakSecurityUIExtension = AceType::WeakClaim(this); + uiExtensionManager->AddAliveUIExtension(host->GetId(), weakSecurityUIExtension); + if (isFocused) { + uiExtensionManager->RegisterSecurityUIExtensionInFocus( + WeakClaim(this), sessionWrapper_); + } + ReDispatchWantParams(); + InitializeAccessibility(); + InitBusinessDataHandleCallback(); +} + +class PreviewUECAccessibilitySAObserverCallback : public AccessibilitySAObserverCallback { + public: + PreviewUECAccessibilitySAObserverCallback( + const WeakPtr &weakPattern, int64_t accessibilityId) + : AccessibilitySAObserverCallback(accessibilityId), weakUECPattern_(weakPattern) + {} + + ~PreviewUECAccessibilitySAObserverCallback() override = default; + + bool OnState(bool state) override + { + auto pattern = weakUECPattern_.Upgrade(); + CHECK_NULL_RETURN(pattern, false); + if (state) { + pattern->TransferAccessibilityRectInfo(true); + } + return true; + } +private: + WeakPtr weakUECPattern_; +}; + +void PreviewUIExtensionPattern::OnAttachToFrameNode() +{ + ContainerScope scope(instanceId_); + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto pipeline = host->GetContextRefPtr(); + CHECK_NULL_VOID(pipeline); + auto eventHub = host->GetEventHub(); + CHECK_NULL_VOID(eventHub); + OnAreaChangedFunc onAreaChangedFunc = [weak = WeakClaim(this)]( + const RectF& oldRect, + const OffsetF& oldOrigin, + const RectF& rect, + const OffsetF& origin) { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + pattern->DispatchDisplayArea(); + }; + eventHub->AddInnerOnAreaChangedCallback(host->GetId(), std::move(onAreaChangedFunc)); + pipeline->AddOnAreaChangeNode(host->GetId()); + callbackId_ = pipeline->RegisterSurfacePositionChangedCallback( + [weak = WeakClaim(this)](int32_t, int32_t) { + auto pattern = weak.Upgrade(); + if (pattern) { + pattern->TransferAccessibilityRectInfo(); + pattern->DispatchDisplayArea(true); + } + }); + host->RegisterNodeChangeListener(); + accessibilitySAObserverCallback_ = std::make_shared( + WeakClaim(this), host->GetAccessibilityId()); + #ifndef ACE_UNITTEST + auto accessibilityManager = pipeline->GetAccessibilityManager(); + CHECK_NULL_VOID(accessibilityManager); + accessibilityManager->RegisterAccessibilitySAObserverCallback(host->GetAccessibilityId(), + accessibilitySAObserverCallback_); + #endif + PLATFORM_LOGI("PreviewUIExtension OnAttachToFrameNode"); +} + +void PreviewUIExtensionPattern::FireOnRemoteReadyCallback() +{ + PLATFORM_LOGI("PreviewUIExtension The current state is '%{public}s'.", ToString(state_)); + ContainerScope scope(instanceId_); + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto eventHub = host->GetEventHub(); + CHECK_NULL_VOID(eventHub); + auto weakSecurityUIExtension = AceType::WeakClaim(this); + auto suec = weakSecurityUIExtension.Upgrade(); + eventHub->FireOnRemoteReadyCallback( + MakeRefPtr(sessionWrapper_, suec)); +} + +void PreviewUIExtensionPattern::RegisterVisibleAreaChange() +{ + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto callback = [weak = WeakClaim(this)](bool visible, double ratio) { + auto uiExtension = weak.Upgrade(); + CHECK_NULL_VOID(uiExtension); + uiExtension->OnVisibleChange(visible); + }; + auto host = GetHost(); + CHECK_NULL_VOID(host); + std::vector ratioList = { 0.0 }; + pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false); +} + +void PreviewUIExtensionPattern::InitializeAccessibility() +{ + if (accessibilityChildTreeCallback_ != nullptr) { + return; + } + ContainerScope scope(instanceId_); + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto ngPipeline = host->GetContextRefPtr(); + CHECK_NULL_VOID(ngPipeline); + auto frontend = ngPipeline->GetFrontend(); + CHECK_NULL_VOID(frontend); + auto accessibilityManager = frontend->GetAccessibilityManager(); + CHECK_NULL_VOID(accessibilityManager); + auto frameNode = frameNode_.Upgrade(); + CHECK_NULL_VOID(frameNode); + int64_t accessibilityId = frameNode->GetAccessibilityId(); + accessibilityChildTreeCallback_ = std::make_shared( + WeakClaim(this), accessibilityId); + CHECK_NULL_VOID(accessibilityChildTreeCallback_); + auto realHostWindowId = ngPipeline->GetRealHostWindowId(); + if (accessibilityManager->IsRegister()) { + accessibilityChildTreeCallback_->OnRegister( + realHostWindowId, accessibilityManager->GetTreeId()); + } + UIEXT_LOGI("PreviewUIExtension SecurityUIExtension: %{public}" PRId64 + " register child tree, realHostWindowId: %{public}u", + accessibilityId, realHostWindowId); + accessibilityManager->RegisterAccessibilityChildTreeCallback(accessibilityId, accessibilityChildTreeCallback_); +} +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h new file mode 100644 index 00000000000..775d26e23cb --- /dev/null +++ b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.h @@ -0,0 +1,38 @@ +/* + * 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 FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_PREVIEW_UI_EXTENSION_PATTERN_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_PREVIEW_UI_EXTENSION_PATTERN_H + +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.h" +namespace OHOS::Ace::NG { +class PreviewUIExtensionPattern : public SecurityUIExtensionPattern { + DECLARE_ACE_TYPE(PreviewUIExtensionPattern, SecurityUIExtensionPattern); +public: + PreviewUIExtensionPattern(); + ~PreviewUIExtensionPattern() override; + void Initialize(const NG::UIExtensionConfig& config); + void UpdateWant(const RefPtr& wantWrap); + void UpdateWant(const AAFwk::Want& want); + void OnConnect(); + void OnAttachToFrameNode() override; + void FireOnRemoteReadyCallback() override; + void RegisterVisibleAreaChange(); + void InitializeAccessibility(); +private: + ACE_DISALLOW_COPY_AND_MOVE(PreviewUIExtensionPattern); +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_UI_EXTENSION_PREVIEW_UI_EXTENSION_PATTERN_H \ No newline at end of file diff --git a/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.h b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.h index dc925b38927..aa02c39a9b6 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.h +++ b/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.h @@ -102,16 +102,16 @@ public: void DumpInfo() override; void DumpInfo(std::unique_ptr& json) override; - void FireOnRemoteReadyCallback(); - void FireBindModalCallback(); - void FireOnTerminatedCallback(int32_t code, const RefPtr& wantWrap); - void FireOnReceiveCallback(const AAFwk::WantParams& params); - void SetSyncCallbacks( + virtual void FireOnRemoteReadyCallback(); + virtual void FireBindModalCallback(); + virtual void FireOnTerminatedCallback(int32_t code, const RefPtr& wantWrap); + virtual void FireOnReceiveCallback(const AAFwk::WantParams& params); + virtual void SetSyncCallbacks( const std::list&)>>&& callbackList); - void FireSyncCallbacks(); - void SetAsyncCallbacks( + virtual void FireSyncCallbacks(); + virtual void SetAsyncCallbacks( const std::list&)>>&& callbackList); - void FireAsyncCallbacks(); + virtual void FireAsyncCallbacks(); // Dpi void SetDensityDpi(bool densityDpi); @@ -140,7 +140,7 @@ public: void OnFrameNodeChanged(FrameNodeChangeInfoFlag flag) override; void UpdateWMSUIExtProperty(UIContentBusinessCode code, const AAFwk::Want& data, RSSubsystemId subSystemId); -private: +protected: void InitializeAccessibility(); bool HandleKeyEvent(const KeyEvent& event) override; void HandleFocusEvent() override; diff --git a/frameworks/core/components_ng/pattern/ui_extension/session_wrapper.h b/frameworks/core/components_ng/pattern/ui_extension/session_wrapper.h index 7b926df2f40..d0948547a31 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/session_wrapper.h +++ b/frameworks/core/components_ng/pattern/ui_extension/session_wrapper.h @@ -63,6 +63,7 @@ enum class SessionType : int32_t { SECURITY_UI_EXTENSION_ABILITY = 3, DYNAMIC_COMPONENT = 4, ISOLATED_COMPONENT = 5, + PREVIEW_UI_EXTENSION_ABILITY = 6, INVALID_TYPE = 100, }; @@ -70,6 +71,7 @@ enum class UIExtensionUsage : uint32_t { MODAL = 0, EMBEDDED = 1, CONSTRAINED_EMBEDDED = 2, + PREVIEW_EMBEDDED = 3, }; struct SessionConfig { diff --git a/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp b/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp index 7baefb33406..ebea60b6cea 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp +++ b/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp @@ -14,7 +14,7 @@ */ #include "core/components_ng/pattern/ui_extension/session_wrapper_factory.h" - +#include "core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.h" #include "core/components_ng/pattern/ui_extension/security_ui_extension_component/security_session_wrapper_impl.h" #include "core/components_ng/pattern/ui_extension/ui_extension_component/session_wrapper_impl.h" @@ -32,6 +32,13 @@ RefPtr SessionWrapperFactory::CreateSessionWrapper(SessionType s RefPtr SessionWrapperFactory::CreateSessionWrapper( SessionType sessionType, const SessionCreateParam& sessionCreateParam) { + if (sessionType == SessionType::UI_EXTENSION_ABILITY) { + TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "CreateSessionWrapper return PreviewSessionWrapperImpl"); + return AceType::MakeRefPtr( + AceType::DynamicCast(sessionCreateParam.hostPattern.Upgrade()), + sessionCreateParam.instanceId, + sessionCreateParam.isTransferringCaller, SessionType::UI_EXTENSION_ABILITY); + } if (sessionType == SessionType::SECURITY_UI_EXTENSION_ABILITY) { return AceType::MakeRefPtr( sessionCreateParam.hostPattern, sessionCreateParam.instanceId, diff --git a/test/unittest/core/pattern/ui_extension/BUILD.gn b/test/unittest/core/pattern/ui_extension/BUILD.gn index c389382f261..1597a4cf37a 100644 --- a/test/unittest/core/pattern/ui_extension/BUILD.gn +++ b/test/unittest/core/pattern/ui_extension/BUILD.gn @@ -33,6 +33,8 @@ ace_unittest("accessibility_session_adapter_ui_extension_test_ng") { "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_session_wrapper_impl.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_proxy.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/surface_proxy_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/modal_ui_extension_proxy_impl.cpp", @@ -426,6 +428,8 @@ ace_unittest("security_ui_extension_pattern_test") { "$ace_root/frameworks/core/components_ng/pattern/ui_extension/platform_utils.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_proxy.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/surface_proxy_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/modal_ui_extension_proxy_impl.cpp", @@ -646,6 +650,8 @@ ace_unittest("security_session_wrapper_impl_test_ng") { "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_session_wrapper_impl.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_proxy.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/surface_proxy_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/modal_ui_extension_proxy_impl.cpp", diff --git a/test/unittest/core/pattern/ui_extension/dynamic_component/BUILD.gn b/test/unittest/core/pattern/ui_extension/dynamic_component/BUILD.gn index c371de6edff..30e04a8ce39 100644 --- a/test/unittest/core/pattern/ui_extension/dynamic_component/BUILD.gn +++ b/test/unittest/core/pattern/ui_extension/dynamic_component/BUILD.gn @@ -37,6 +37,8 @@ ace_unittest("dynamic_pattern_test") { "$ace_root/frameworks/core/components_ng/pattern/ui_extension/platform_utils.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_proxy.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/surface_proxy_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/modal_ui_extension_proxy_impl.cpp", diff --git a/test/unittest/core/pattern/ui_extension/ui_extension_component/BUILD.gn b/test/unittest/core/pattern/ui_extension/ui_extension_component/BUILD.gn index e0cb6e4af28..edf6992316d 100644 --- a/test/unittest/core/pattern/ui_extension/ui_extension_component/BUILD.gn +++ b/test/unittest/core/pattern/ui_extension/ui_extension_component/BUILD.gn @@ -114,6 +114,8 @@ ace_unittest("ui_extension_pattern_test_ng") { "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_session_wrapper_impl.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/security_ui_extension_proxy.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_session_wrapper_impl.cpp", + "$ace_root/frameworks/core/components_ng/pattern/ui_extension/security_ui_extension_component/preview_ui_extension_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/session_wrapper_factory.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/surface_proxy_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/modal_ui_extension_proxy_impl.cpp", -- Gitee