From e19757ec47673249b87b0c16ee459a66739ffdf1 Mon Sep 17 00:00:00 2001 From: Alexey Khoraskin Date: Tue, 2 Sep 2025 08:52:39 +0300 Subject: [PATCH] Support Standalone Previewer. Signed-off-by: Alexey Khoraskin Change-Id: I6671639ca066fbcd66e0e8f120cb3256ac3015ba --- adapter/preview/entrance/ace_container.cpp | 158 ++++++++++-------- adapter/preview/entrance/ace_container.h | 2 + .../entrance/samples/event_adapter.cpp | 34 +++- adapter/preview/entrance/ui_content_impl.cpp | 27 +++ adapter/preview/entrance/ui_content_impl.h | 2 + .../preview/sdk/arkts_framework_modules.gni | 3 + adapter/preview/sdk/sharedlib_config.gni | 47 +++++- build/BUILD.gn | 27 +++ bundle.json | 16 +- frameworks/core/common/container.cpp | 4 +- frameworks/core/common/container_consts.h | 6 + frameworks/core/common/container_scope.cpp | 17 +- 12 files changed, 250 insertions(+), 93 deletions(-) diff --git a/adapter/preview/entrance/ace_container.cpp b/adapter/preview/entrance/ace_container.cpp index 0923933a936..f0a22682d44 100644 --- a/adapter/preview/entrance/ace_container.cpp +++ b/adapter/preview/entrance/ace_container.cpp @@ -18,6 +18,8 @@ #include #include "base/log/log.h" +#include "base/memory/referenced.h" +#include "core/pipeline/pipeline_base.h" #ifndef ENABLE_ROSEN_BACKEND #include "flutter/lib/ui/ui_dart_state.h" @@ -143,26 +145,32 @@ void AceContainer::Destroy() if (!taskExecutor_) { return; } - auto weak = AceType::WeakClaim(AceType::RawPtr(pipelineContext_)); - taskExecutor_->PostTask( - [weak]() { - auto context = weak.Upgrade(); - if (context == nullptr) { - return; - } - context->Destroy(); - }, - TaskExecutor::TaskType::UI, "ArkUIPipelineDestroy"); - + // 1. Destroy Pipeline on UI thread. + RefPtr context; + { + context.Swap(pipelineContext_); + } + auto uiTask = [context]() { context->Destroy(); }; + if (GetSettings().usePlatformAsUIThread) { + uiTask(); + } else { + taskExecutor_->PostTask(uiTask, TaskExecutor::TaskType::UI, "ArkUIPipelineDestroy"); + } + + // 2. Destroy Frontend on JS thread. RefPtr frontend; - frontend_.Swap(frontend); - if (frontend && taskExecutor_) { - taskExecutor_->PostTask( - [frontend]() { - frontend->UpdateState(Frontend::State::ON_DESTROY); - frontend->Destroy(); - }, - TaskExecutor::TaskType::JS, "ArkUIFrontendDestroy"); + { + frontend.Swap(frontend_); + } + auto jsTask = [frontend]() { + auto lock = frontend->GetLock(); + frontend->Destroy(); + }; + frontend->UpdateState(Frontend::State::ON_DESTROY); + if (GetSettings().usePlatformAsUIThread && GetSettings().useUIAsJSThread) { + jsTask(); + } else { + taskExecutor_->PostTask(jsTask, TaskExecutor::TaskType::JS, "ArkUIFrontendDestroy"); } messageBridge_.Reset(); @@ -535,8 +543,16 @@ void AceContainer::DestroyContainer(int32_t instanceId) taskExecutor->PostSyncTask([] { LOGI("Wait JS thread..."); }, TaskExecutor::TaskType::JS, "ArkUIWaitLog"); } container->DestroyView(); // Stop all threads(ui,gpu,io) for current ability. - EngineHelper::RemoveEngine(instanceId); - AceEngine::Get().RemoveContainer(instanceId); + auto removeContainerTask = [instanceId] { + LOGI("Remove on Platform thread..."); + EngineHelper::RemoveEngine(instanceId); + AceEngine::Get().RemoveContainer(instanceId); + }; + if (container->GetSettings().usePlatformAsUIThread) { + removeContainerTask(); + } else { + taskExecutor->PostTask(removeContainerTask, TaskExecutor::TaskType::PLATFORM, "ArkUIAceContainerRemove"); + } } UIContentErrorCode AceContainer::RunPage( @@ -963,6 +979,53 @@ void AceContainer::AttachView( AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_, GetSettings().useUIAsJSThread); } #else +void AceContainer::InitThemeManagerTask() +{ + // Only init global resource here, construct theme in UI thread + auto themeManager = AceType::MakeRefPtr(); + + if (SystemProperties::GetResourceDecoupling()) { + auto resourceAdapter = ResourceAdapter::Create(); + resourceAdapter->Init(resourceInfo_); + SaveResourceAdapter(bundleName_, moduleName_, instanceId_, resourceAdapter); + themeManager = AceType::MakeRefPtr(resourceAdapter); + } + + pipelineContext_->SetThemeManager(themeManager); + // Init resource, load theme map. + if (!SystemProperties::GetResourceDecoupling()) { + themeManager->InitResource(resourceInfo_); + } + themeManager->LoadSystemTheme(resourceInfo_.GetThemeId()); + auto themeTask = [themeManager, assetManager = assetManager_, colorScheme = colorScheme_, + pipelineContext = pipelineContext_]() { + themeManager->ParseSystemTheme(); + themeManager->SetColorScheme(colorScheme); + themeManager->LoadCustomTheme(assetManager); + // get background color from theme + pipelineContext->SetAppBgColor(themeManager->GetBackgroundColor()); + }; + if (GetSettings().usePlatformAsUIThread) { + themeTask(); + } else { + taskExecutor_->PostTask(themeTask, TaskExecutor::TaskType::UI, "ArkUISetBackgroundColor"); + } +} + +void AceContainer::InitEnvCallbackTask(UIEnvCallback callback) +{ + if (!useNewPipeline_) { + auto envCallbackTask = [context = pipelineContext_, callback]() { + CHECK_NULL_VOID(callback); + callback(AceType::DynamicCast(context)); + }; + if (GetSettings().usePlatformAsUIThread) { + envCallbackTask(); + } else { + taskExecutor_->PostTask(envCallbackTask, TaskExecutor::TaskType::UI, "ArkUIEnvCallback"); + } + } +} void AceContainer::AttachView(std::shared_ptr window, AceViewPreview* view, double density, int32_t width, int32_t height, UIEnvCallback callback) @@ -1031,53 +1094,16 @@ void AceContainer::AttachView(std::shared_ptr window, AceViewPreview* vi } ThemeConstants::InitDeviceType(); - // Only init global resource here, construct theme in UI thread - auto themeManager = AceType::MakeRefPtr(); + InitThemeManagerTask(); + InitEnvCallbackTask(callback); - if (SystemProperties::GetResourceDecoupling()) { - auto resourceAdapter = ResourceAdapter::Create(); - resourceAdapter->Init(resourceInfo_); - SaveResourceAdapter(bundleName_, moduleName_, instanceId_, resourceAdapter); - themeManager = AceType::MakeRefPtr(resourceAdapter); - } - - if (themeManager) { - pipelineContext_->SetThemeManager(themeManager); - // Init resource, load theme map. - if (!SystemProperties::GetResourceDecoupling()) { - themeManager->InitResource(resourceInfo_); - } - themeManager->LoadSystemTheme(resourceInfo_.GetThemeId()); - taskExecutor_->PostTask( - [themeManager, assetManager = assetManager_, colorScheme = colorScheme_, - pipelineContext = pipelineContext_]() { - themeManager->ParseSystemTheme(); - themeManager->SetColorScheme(colorScheme); - themeManager->LoadCustomTheme(assetManager); - // get background color from theme - pipelineContext->SetAppBgColor(themeManager->GetBackgroundColor()); - }, - TaskExecutor::TaskType::UI, "ArkUISetBackgroundColor"); - } - if (!useNewPipeline_) { - taskExecutor_->PostTask( - [context = pipelineContext_, callback]() { - CHECK_NULL_VOID(callback); - callback(AceType::DynamicCast(context)); - }, - TaskExecutor::TaskType::UI, "ArkUIEnvCallback"); + auto setupRootElementTask = [context = pipelineContext_]() { context->SetupRootElement(); }; + if (GetSettings().usePlatformAsUIThread) { + setupRootElementTask(); + } else { + taskExecutor_->PostTask(setupRootElementTask, TaskExecutor::TaskType::UI, "ArkUISetupRootElement"); } - auto weak = AceType::WeakClaim(AceType::RawPtr(pipelineContext_)); - taskExecutor_->PostTask( - [weak]() { - auto context = weak.Upgrade(); - if (context == nullptr) { - return; - } - context->SetupRootElement(); - }, - TaskExecutor::TaskType::UI, "ArkUISetupRootElement"); aceView_->Launch(); frontend_->AttachPipelineContext(pipelineContext_); @@ -1085,7 +1111,7 @@ void AceContainer::AttachView(std::shared_ptr window, AceViewPreview* vi if (cardFronted) { cardFronted->SetDensity(static_cast(density)); taskExecutor_->PostTask( - [weak, width, height]() { + [weak = WeakPtr(pipelineContext_), width, height]() { auto context = weak.Upgrade(); if (context == nullptr) { return; diff --git a/adapter/preview/entrance/ace_container.h b/adapter/preview/entrance/ace_container.h index f1f589d0a44..4a18f2b16ea 100644 --- a/adapter/preview/entrance/ace_container.h +++ b/adapter/preview/entrance/ace_container.h @@ -343,6 +343,8 @@ private: #else void AttachView(std::shared_ptr window, AceViewPreview* view, double density, int32_t width, int32_t height, UIEnvCallback callback); + void InitThemeManagerTask(); + void InitEnvCallbackTask(UIEnvCallback callback); #endif RefPtr aceView_ = nullptr; diff --git a/adapter/preview/entrance/samples/event_adapter.cpp b/adapter/preview/entrance/samples/event_adapter.cpp index 80370f125be..33c11213aaf 100644 --- a/adapter/preview/entrance/samples/event_adapter.cpp +++ b/adapter/preview/entrance/samples/event_adapter.cpp @@ -20,7 +20,13 @@ #include #include "base/utils/utils.h" -#include "frameworks/base/log/log.h" + +#ifdef __linux__ +#include +#endif +#ifdef __APPLE__ +#include +#endif namespace OHOS::Ace::Sample { @@ -81,8 +87,6 @@ void EventAdapter::Initialize(std::shared_ptr& glfwRenderCont } if (keyEventCallback_ && RecognizeKeyEvent(key, action, mods)) { keyEventCallback_(keyEvent_); - } else { - LOGW("Unrecognized key type."); } }; glfwRenderContext->OnKey(keyboardCbk); @@ -175,6 +179,28 @@ bool EventAdapter::RecognizeKeyEvent(int key, int action, int mods) return true; } +OHOS::MMI::TimeStamp GetExactTime() +{ +#ifdef __linux__ + timespec ts; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + + return std::chrono::system_clock::time_point( + std::chrono::system_clock::duration(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); +#elif defined(__APPLE__) + static mach_timebase_info_data_t info; + static std::once_flag flag; + std::call_once(flag, [] { mach_timebase_info(&info); }); + + auto nanos = (mach_absolute_time() * info.numer) / info.denom; + + return std::chrono::steady_clock::time_point( + std::chrono::duration_cast(std::chrono::nanoseconds(nanos))); +#else + return std::chrono::high_resolution_clock::now(); +#endif +} + void EventAdapter::RecognizePointerEvent(const TouchType type) { std::lock_guard lock(mouseMutex_); @@ -184,7 +210,7 @@ void EventAdapter::RecognizePointerEvent(const TouchType type) pointerEvent_->screenX = 0; pointerEvent_->screenY = 0; pointerEvent_->type = type; - pointerEvent_->time = std::chrono::high_resolution_clock::now(); + pointerEvent_->time = GetExactTime(); pointerEvent_->size = sizeof(PointerEvent); pointerEvent_->force = 0; pointerEvent_->deviceId = 0; diff --git a/adapter/preview/entrance/ui_content_impl.cpp b/adapter/preview/entrance/ui_content_impl.cpp index ddf6fb4a36a..0a298c060b0 100644 --- a/adapter/preview/entrance/ui_content_impl.cpp +++ b/adapter/preview/entrance/ui_content_impl.cpp @@ -43,6 +43,12 @@ #ifdef INIT_ICU_DATA_PATH #include "unicode/putil.h" #endif +#ifdef NG_BUILD +#include "frameworks/bridge/declarative_frontend/ng/declarative_frontend_ng.h" +#else +#include "frameworks/bridge/declarative_frontend/declarative_frontend.h" +#endif + #include "frameworks/simulator/common/include/context.h" namespace OHOS::Ace { @@ -475,6 +481,7 @@ void UIContentImpl::Destroy() { LOGI("UIContentImpl: window destroy"); AceContainer::DestroyContainer(instanceId_); + rsWindow_ = nullptr; } uint32_t UIContentImpl::GetBackgroundColor() @@ -767,4 +774,24 @@ bool UIContentImpl::OperateComponent(const std::string& attrsJson) LOGI("Fast Preview end"); return true; } + +napi_value UIContentImpl::GetUINapiContext() +{ + auto container = Platform::AceContainer::GetContainer(instanceId_); + ContainerScope scope(instanceId_); + napi_value result = nullptr; + auto frontend = container->GetFrontend(); + CHECK_NULL_RETURN(frontend, result); + if (frontend->GetType() == FrontendType::DECLARATIVE_JS) { +#ifdef NG_BUILD + auto declarativeFrontend = AceType::DynamicCast(frontend); +#else + auto declarativeFrontend = AceType::DynamicCast(frontend); +#endif + CHECK_NULL_RETURN(declarativeFrontend, result); + return declarativeFrontend->GetContextValue(); + } + + return result; +} } // namespace OHOS::Ace diff --git a/adapter/preview/entrance/ui_content_impl.h b/adapter/preview/entrance/ui_content_impl.h index ba5e9eb5329..8d5bfac57ae 100644 --- a/adapter/preview/entrance/ui_content_impl.h +++ b/adapter/preview/entrance/ui_content_impl.h @@ -162,6 +162,8 @@ public: void SetForceSplitEnable(bool isForceSplit, const std::string& homePage, bool isRouter = true) override {}; + napi_value GetUINapiContext() override; + void EnableContainerModalGesture(bool isEnable) override {}; bool GetContainerFloatingTitleVisible() override diff --git a/adapter/preview/sdk/arkts_framework_modules.gni b/adapter/preview/sdk/arkts_framework_modules.gni index b22a7386827..7d504547c9b 100644 --- a/adapter/preview/sdk/arkts_framework_modules.gni +++ b/adapter/preview/sdk/arkts_framework_modules.gni @@ -279,6 +279,9 @@ arkts_framework_modules = [ { label = "//base/hiviewdfx/hiview/interfaces/ets/ani/loglibrary:loglibrary" }, + { + label = "//base/hiviewdfx/hilog/interfaces/ets/ani/hilog:hilog" + }, { label = "//base/hiviewdfx/hiappevent/frameworks/ets/ani/hiappevent:hiappevent" }, diff --git a/adapter/preview/sdk/sharedlib_config.gni b/adapter/preview/sdk/sharedlib_config.gni index 6904ba7d2ad..788a7dbca3d 100644 --- a/adapter/preview/sdk/sharedlib_config.gni +++ b/adapter/preview/sdk/sharedlib_config.gni @@ -99,6 +99,11 @@ common_bin = [ subsystem_name = "graphic" part_name = "graphic_2d" }, + { + label = "//foundation/graphic/graphic_2d/rosen/modules/platform:impl_eventhandler" + subsystem_name = "graphic" + part_name = "graphic_2d" + }, { label = "//third_party/glfw:glfw" subsystem_name = "thirdparty" @@ -342,17 +347,11 @@ napi_modules = [ if (use_linux) { shard_libs += [ { - label = "//foundation/arkui/ace_engine/frameworks/bridge/arkts_frontend:ArkoalaNative_ark" + label = "//foundation/arkui/ace_engine/frameworks/bridge/arkts_frontend/koala_mirror/arkoala-arkts:ArkoalaNative_ark" subsystem_name = "arkui" part_name = "ace_engine" lib_names = [ "ArkoalaNative_ark" ] }, - { - label = "//foundation/arkui/ace_engine/frameworks/bridge/arkts_frontend/koala_projects/arkoala-arkts/arkui-ohos/src/ani/native:arkoala_native_ani_linux" - subsystem_name = "arkui" - part_name = "ace_engine" - lib_names = [ "arkoala_native_ani" ] - }, ] } }, @@ -653,11 +652,33 @@ if (use_mac || use_mingw_win || use_linux) { part_name = "zlib" lib_names = [ "shared_libz" ] }, + { + label = "//foundation/arkui/ace_engine/build:libevent_adapter" + subsystem_name = "arkui" + part_name = "ace_engine" + }, + { + label = "//third_party/ffmpeg:libohosffmpeg" + subsystem_name = "thirdparty" + part_name = "ffmpeg" + lib_names = [ "ohosffmpeg" ] + }, ] } if (use_linux) { common_bin += [ + { + label = "//foundation/arkui/ace_engine/build:libevent_adapter" + subsystem_name = "arkui" + part_name = "ace_engine" + }, + { + label = "//third_party/ffmpeg:libohosffmpeg" + subsystem_name = "thirdparty" + part_name = "ffmpeg" + lib_names = [ "ohosffmpeg" ] + }, { label = "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog" subsystem_name = "hiviewdfx" @@ -681,6 +702,18 @@ if (use_linux) { subsystem_name = "arkcompiler" part_name = "runtime_core" }, + { + label = "//foundation/arkui/ace_engine/frameworks/bridge/arkts_frontend:arkts_frontend" + subsystem_name = "arkui" + part_name = "ace_engine" + lib_names = [ "arkts_frontend" ] + }, + { + label = "//base/hiviewdfx/hilog/interfaces/ets/ani/hilog:hilog_ani" + subsystem_name = "hiviewdfx" + part_name = "hilog" + lib_names = [ "hilog_ani" ] + }, ] } diff --git a/build/BUILD.gn b/build/BUILD.gn index b43ca55e2ac..bda60260916 100644 --- a/build/BUILD.gn +++ b/build/BUILD.gn @@ -166,6 +166,33 @@ ohos_shared_library("libace_compatible") { subsystem_name = ace_engine_subsystem } +if (is_ohos) { + group("libevent_adapter") { + # fake target for ohos + } +} else if (use_linux || use_mingw_win || use_mac) { + ohos_shared_library("libevent_adapter") { + sources = [ "../adapter/preview/entrance/samples/event_adapter.cpp" ] + include_dirs = [ + "$ace_root", + "$ace_root/frameworks", + "$ace_root/interfaces/inner_api/ace_kit/include", + ] + + external_deps = [ + "glfw:glfw", + "graphic_2d:libglfw_render_context", + "graphic_2d:librender_service_client", + ] + + cflags = [ "-std=c++17" ] + + public_external_deps = external_deps + part_name = ace_engine_part + subsystem_name = ace_engine_subsystem + } +} + if (!is_asan) { ohos_shared_library("libace") { external_deps = [] diff --git a/bundle.json b/bundle.json index 6e931582824..488178b5741 100644 --- a/bundle.json +++ b/bundle.json @@ -120,9 +120,12 @@ "egl", "request", "qrcodegen", - "sdk" + "sdk", + "glfw" ], - "third_party": [] + "third_party": [ + "ffmpeg" + ] }, "build": { "group_type": { @@ -231,6 +234,15 @@ }, "name": "//foundation/arkui/ace_engine/build:libace_compatible" }, + { + "header": { + "header_base": "//foundation/arkui/ace_engine/", + "header_files": [ + "adapter/preview/entrance/sample/event_adapter.h" + ] + }, + "name": "//foundation/arkui/ace_engine/build:libevent_adapter" + }, { "header": { "header_base": "//foundation/arkui/ace_engine/frameworks/core/common/", diff --git a/frameworks/core/common/container.cpp b/frameworks/core/common/container.cpp index 2a99ac7c475..47b59ad6558 100644 --- a/frameworks/core/common/container.cpp +++ b/frameworks/core/common/container.cpp @@ -43,7 +43,7 @@ int32_t Container::SafelyId() { uint32_t containerCount = ContainerScope::ContainerCount(); if (containerCount == 0) { - return INSTANCE_ID_UNDEFINED; + return DEFAULT_ID; } if (containerCount == 1) { return ContainerScope::SingletonId(); @@ -358,7 +358,7 @@ int32_t Container::GenerateId() #ifdef PLUGIN_COMPONENT_SUPPORTED return PluginManager::GetInstance().GetPluginSubContainerId(); #else - return INSTANCE_ID_UNDEFINED; + return DEFAULT_ID; #endif } diff --git a/frameworks/core/common/container_consts.h b/frameworks/core/common/container_consts.h index b31bb391af2..bc92ce3ba54 100755 --- a/frameworks/core/common/container_consts.h +++ b/frameworks/core/common/container_consts.h @@ -38,6 +38,12 @@ constexpr int32_t MIN_PLUGIN_SUBCONTAINER_ID = PLUGIN_SUBCONTAINER * CONTAINER_I constexpr int32_t MIN_SUBCONTAINER_ID = COMPONENT_SUBWINDOW_CONTAINER * CONTAINER_ID_DIVIDE_SIZE; constexpr int32_t MIN_PA_SERVICE_ID = PA_SERVICE_CONTAINER * CONTAINER_ID_DIVIDE_SIZE; constexpr int32_t WINDOW_FREE_CONTAINER_ID = WINDOW_FREE_CONTAINER * CONTAINER_ID_DIVIDE_SIZE; +// preview not support multi-instance, always using default instance id 0. +#if defined(PREVIEW) +constexpr int32_t DEFAULT_ID = 0; +#else +constexpr int32_t DEFAULT_ID = INSTANCE_ID_UNDEFINED; +#endif } // namespace OHOS::Ace #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_CONTAINER_CONSTS_H diff --git a/frameworks/core/common/container_scope.cpp b/frameworks/core/common/container_scope.cpp index 893ab9943b5..3807a86eb89 100644 --- a/frameworks/core/common/container_scope.cpp +++ b/frameworks/core/common/container_scope.cpp @@ -18,13 +18,6 @@ namespace OHOS::Ace { namespace { -// preview not support multi-instance, always using default instance id 0. -#if defined(PREVIEW) -constexpr int32_t DEFAULT_ID = 0; -#else -constexpr int32_t DEFAULT_ID = INSTANCE_ID_UNDEFINED; -#endif - std::shared_mutex mutex_; std::set containerSet_; thread_local int32_t currentLocalId_(DEFAULT_ID); @@ -54,13 +47,13 @@ int32_t ContainerScope::DefaultId() std::shared_lock lock(mutex_); return *containerSet_.rbegin(); } - return INSTANCE_ID_UNDEFINED; + return DEFAULT_ID; } int32_t ContainerScope::SingletonId() { if (ContainerCount() != 1) { - return INSTANCE_ID_UNDEFINED; + return DEFAULT_ID; } std::shared_lock lock(mutex_); return *containerSet_.begin(); @@ -84,7 +77,7 @@ std::pair ContainerScope::CurrentIdWithReason() } uint32_t containerCount = ContainerCount(); if (containerCount == 0) { - return { INSTANCE_ID_UNDEFINED, InstanceIdGenReason::UNDEFINED }; + return { DEFAULT_ID, InstanceIdGenReason::UNDEFINED }; } if (containerCount == 1) { return { SingletonId(), InstanceIdGenReason::SINGLETON }; @@ -137,10 +130,10 @@ void ContainerScope::RemoveAndCheck(int32_t id) { Remove(id); if (RecentActiveId() == id) { - UpdateRecentActive(INSTANCE_ID_UNDEFINED); + UpdateRecentActive(DEFAULT_ID); } if (RecentForegroundId() == id) { - UpdateRecentForeground(INSTANCE_ID_UNDEFINED); + UpdateRecentForeground(DEFAULT_ID); } } -- Gitee