/* * Copyright (c) 2023 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 "adapter/preview/entrance/ui_content_impl.h" #include <ui/rs_surface_node.h> #include <ui/rs_ui_director.h> #include "include/core/SkFontMgr.h" #include "adapter/ohos/entrance/ace_new_pipe_judgement.h" #include "adapter/ohos/entrance/platform_event_callback.h" #include "adapter/preview/entrance/ace_application_info.h" #include "adapter/preview/entrance/ace_container.h" #include "adapter/preview/entrance/clipboard/clipboard_impl.h" #include "adapter/preview/entrance/clipboard/clipboard_proxy_impl.h" #include "adapter/preview/entrance/event_dispatcher.h" #include "adapter/preview/entrance/rs_dir_asset_provider.h" #include "adapter/preview/external/multimodalinput/axis_event.h" #include "adapter/preview/external/multimodalinput/key_event.h" #include "adapter/preview/external/multimodalinput/pointer_event.h" #include "adapter/preview/inspector/inspector_client.h" #include "base/log/log_wrapper.h" #include "frameworks/base/log/log.h" #include "frameworks/base/utils/utils.h" #include "frameworks/bridge/common/utils/utils.h" #include "frameworks/bridge/js_frontend/js_frontend.h" #include "frameworks/core/common/ace_engine.h" #ifdef INIT_ICU_DATA_PATH #include "unicode/putil.h" #endif #include "frameworks/simulator/common/include/context.h" namespace OHOS::Ace { using namespace Platform; namespace { #ifdef WINDOWS_PLATFORM constexpr char DELIMITER[] = "\\"; constexpr char ASSET_PATH_SHARE_STAGE[] = "resources\\base\\profile"; #else constexpr char DELIMITER[] = "/"; constexpr char ASSET_PATH_SHARE_STAGE[] = "resources/base/profile"; #endif NG::SafeAreaInsets ConvertAvoidArea(const OHOS::Rosen::AvoidArea& avoidArea) { return NG::SafeAreaInsets({ avoidArea.leftRect_.posX_, avoidArea.leftRect_.posX_ + avoidArea.leftRect_.width_ }, { avoidArea.topRect_.posY_, avoidArea.topRect_.posY_ + avoidArea.topRect_.height_ }, { avoidArea.rightRect_.posX_, avoidArea.rightRect_.posX_ + avoidArea.rightRect_.width_ }, { avoidArea.bottomRect_.posY_, avoidArea.bottomRect_.posY_ + avoidArea.bottomRect_.height_ }); } void SetFontMgrConfig(const std::string& containerSdkPath) { // To check if use ohos or container fonts. std::string runtimeOS = "OHOS_Container"; std::string containerFontBasePath = containerSdkPath + DELIMITER + "resources" + DELIMITER + "fonts" + DELIMITER; RSDirAssetProvider dirAsset(containerFontBasePath); std::vector<std::string> fileList; dirAsset.GetAssetList("", fileList); if (containerSdkPath.empty() || fileList.empty()) { runtimeOS = "OHOS"; containerFontBasePath = ""; } SkFontMgr::SetFontMgrConfig(runtimeOS, containerFontBasePath); } } // namespace using ContentFinishCallback = std::function<void()>; using ContentStartAbilityCallback = std::function<void(const std::string& address)>; class ContentEventCallback final : public PlatformEventCallback { public: explicit ContentEventCallback(ContentFinishCallback onFinish) : onFinish_(onFinish) {} ContentEventCallback(ContentFinishCallback onFinish, ContentStartAbilityCallback onStartAbility) : onFinish_(onFinish), onStartAbility_(onStartAbility) {} ~ContentEventCallback() override = default; void OnFinish() const override { LOGI("UIContent OnFinish"); CHECK_NULL_VOID(onFinish_); onFinish_(); } void OnStartAbility(const std::string& address) override { LOGI("UIContent OnStartAbility"); CHECK_NULL_VOID(onStartAbility_); onStartAbility_(address); } void OnStatusBarBgColorChanged(uint32_t color) override { LOGI("UIContent OnStatusBarBgColorChanged"); } private: ContentFinishCallback onFinish_; ContentStartAbilityCallback onStartAbility_; }; class DragWindowListener : public OHOS::Rosen::IWindowDragListener { public: explicit DragWindowListener(int32_t instanceId) : instanceId_(instanceId) {} ~DragWindowListener() = default; void OnDrag(int32_t x, int32_t y, OHOS::Rosen::DragEvent event) { LOGI("[Engine Log] The feature is not supported on the previewer, and instanceId_ = %{public}d", instanceId_); } private: int32_t instanceId_ = -1; }; class TouchOutsideListener : public OHOS::Rosen::ITouchOutsideListener { public: explicit TouchOutsideListener(int32_t instanceId) : instanceId_(instanceId) {} ~TouchOutsideListener() = default; void OnTouchOutside() const { LOGI("[Engine Log] The feature is not supported on the previewer, and instanceId_ = %{public}d", instanceId_); } private: int32_t instanceId_ = -1; }; class IIgnoreViewSafeAreaListener : public OHOS::Rosen::IIgnoreViewSafeAreaListener { public: explicit IIgnoreViewSafeAreaListener(int32_t instanceId) : instanceId_(instanceId) {} ~IIgnoreViewSafeAreaListener() = default; void SetIgnoreViewSafeArea(bool ignoreViewSafeArea) { LOGD("[instanceId_:%{public}d]: SetIgnoreViewSafeArea:%{public}u", instanceId_, ignoreViewSafeArea); auto container = AceEngine::Get().GetContainer(instanceId_); CHECK_NULL_VOID(container); auto pipelineContext = container->GetPipelineContext(); auto taskExecutor = container->GetTaskExecutor(); CHECK_NULL_VOID(taskExecutor); taskExecutor->PostSyncTask( [&pipelineContext, container, ignoreSafeArea = ignoreViewSafeArea]() { pipelineContext->SetIgnoreViewSafeArea(ignoreSafeArea); }, TaskExecutor::TaskType::UI, "ArkUISetIgnoreViewSafeArea"); } private: int32_t instanceId_ = -1; }; class AvoidAreaChangedListener : public OHOS::Rosen::IAvoidAreaChangedListener { public: explicit AvoidAreaChangedListener(int32_t instanceId) : instanceId_(instanceId) {} ~AvoidAreaChangedListener() = default; void OnAvoidAreaChanged(const OHOS::Rosen::AvoidArea avoidArea, OHOS::Rosen::AvoidAreaType type) { LOGD("Avoid area changed, type:%{public}d, topRect: avoidArea:x:%{public}d, y:%{public}d, " "width:%{public}d, height:%{public}d; bottomRect: avoidArea:x:%{public}d, y:%{public}d, " "width:%{public}d, height:%{public}d", type, avoidArea.topRect_.posX_, avoidArea.topRect_.posY_, (int32_t)avoidArea.topRect_.width_, (int32_t)avoidArea.topRect_.height_, avoidArea.bottomRect_.posX_, avoidArea.bottomRect_.posY_, (int32_t)avoidArea.bottomRect_.width_, (int32_t)avoidArea.bottomRect_.height_); auto container = Platform::AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); auto pipeline = container->GetPipelineContext(); CHECK_NULL_VOID(pipeline); auto taskExecutor = container->GetTaskExecutor(); CHECK_NULL_VOID(taskExecutor); if (type == Rosen::AvoidAreaType::TYPE_SYSTEM) { systemSafeArea_ = ConvertAvoidArea(avoidArea); } else if (type == Rosen::AvoidAreaType::TYPE_NAVIGATION_INDICATOR) { navigationBar_ = ConvertAvoidArea(avoidArea); } else if (type == Rosen::AvoidAreaType::TYPE_CUTOUT) { cutoutSafeArea_ = ConvertAvoidArea(avoidArea); } auto safeArea = systemSafeArea_; auto navSafeArea = navigationBar_; auto cutoutSafeArea = cutoutSafeArea_; ContainerScope scope(instanceId_); taskExecutor->PostTask( [pipeline, safeArea, navSafeArea, cutoutSafeArea, type, avoidArea] { if (type == Rosen::AvoidAreaType::TYPE_SYSTEM) { pipeline->UpdateSystemSafeArea(safeArea); } else if (type == Rosen::AvoidAreaType::TYPE_NAVIGATION_INDICATOR) { pipeline->UpdateNavSafeArea(navSafeArea); } else if (type == Rosen::AvoidAreaType::TYPE_CUTOUT && pipeline->GetUseCutout()) { pipeline->UpdateCutoutSafeArea(cutoutSafeArea); } // for ui extension component pipeline->UpdateOriginAvoidArea(avoidArea, static_cast<uint32_t>(type)); }, TaskExecutor::TaskType::UI, "ArkUIUpdateOriginAvoidArea"); } private: NG::SafeAreaInsets systemSafeArea_; NG::SafeAreaInsets navigationBar_; NG::SafeAreaInsets cutoutSafeArea_; int32_t instanceId_ = -1; }; extern "C" ACE_FORCE_EXPORT void* OHOS_ACE_CreateUIContent(void* context, void* runtime) { return new UIContentImpl(reinterpret_cast<OHOS::AbilityRuntime::Context*>(context), runtime); } extern "C" ACE_FORCE_EXPORT void* OHOS_ACE_CreateFormContent(void* context, void* runtime, bool isCard) { return new UIContentImpl(reinterpret_cast<OHOS::AbilityRuntime::Context*>(context), runtime, isCard); } extern "C" ACE_FORCE_EXPORT void* OHOS_ACE_CreateSubWindowUIContent(void* ability) { return new UIContentImpl(reinterpret_cast<OHOS::AppExecFwk::Ability*>(ability)); } UIContentImpl::UIContentImpl(OHOS::AbilityRuntime::Context* context, void* runtime) : instanceId_(ACE_INSTANCE_ID), runtime_(runtime) { // 基于Options的方å¼ä¼ 递傿•° auto options = context->GetOptions(); assetPath_ = options.assetPath; systemResourcesPath_ = options.systemResourcePath; appResourcesPath_ = options.appResourcePath; containerSdkPath_ = options.containerSdkPath; language_ = options.language; region_ = options.region; script_ = options.script; themeId_ = options.themeId; deviceWidth_ = options.deviceWidth; deviceHeight_ = options.deviceHeight; isRound_ = options.isRound; onRouterChange_ = options.onRouterChange; deviceConfig_.orientation = static_cast<DeviceOrientation>(options.deviceConfig.orientation); deviceConfig_.deviceType = static_cast<DeviceType>(options.deviceConfig.deviceType); deviceConfig_.colorMode = static_cast<ColorMode>(options.deviceConfig.colorMode); deviceConfig_.density = options.deviceConfig.density; deviceConfig_.fontRatio = options.deviceConfig.fontRatio; bundleName_ = options.bundleName; compatibleVersion_ = options.compatibleVersion; installationFree_ = options.installationFree; labelId_ = options.labelId; moduleName_ = options.moduleName; compileMode_ = options.compileMode; pageProfile_ = options.pageProfile; const std::string profilePrefix = "$profile:"; if (pageProfile_.compare(0, profilePrefix.size(), profilePrefix) == 0) { pageProfile_ = pageProfile_.substr(profilePrefix.length()).append(".json"); } targetVersion_ = options.targetVersion; auto releaseType = options.releaseType; bool enablePartialUpdate = options.enablePartialUpdate; useNewPipeline_ = AceNewPipeJudgement::QueryAceNewPipeEnabledStage( "", compatibleVersion_, targetVersion_, releaseType, !enablePartialUpdate); } UIContentImpl::UIContentImpl(OHOS::AbilityRuntime::Context* context, void* runtime, bool isCard) : instanceId_(ACE_INSTANCE_ID), runtime_(runtime), isFormRender_(isCard) { LOGI("The constructor is used to support ets card, isFormRender_ = %{public}d", isFormRender_); if (context) { auto options = context->GetOptions(); bundleName_ = options.bundleName; moduleName_ = options.moduleName; } } UIContentImpl::UIContentImpl(OHOS::AppExecFwk::Ability* ability) : instanceId_(ACE_INSTANCE_ID) {} void UIContentImpl::DestroyUIDirector() { auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); auto pipelineContext = AceType::DynamicCast<PipelineContext>(container->GetPipelineContext()); CHECK_NULL_VOID(pipelineContext); auto rsUIDirector = pipelineContext->GetRSUIDirector(); CHECK_NULL_VOID(rsUIDirector); rsUIDirector->Destroy(); } void UIContentImpl::DestroyCallback() const { auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); auto pipelineContext = container->GetPipelineContext(); CHECK_NULL_VOID(pipelineContext); pipelineContext->SetNextFrameLayoutCallback(nullptr); } UIContentErrorCode UIContentImpl::Initialize(OHOS::Rosen::Window* window, const std::string& url, napi_value storage) { auto errorCode = UIContentErrorCode::NO_ERRORS; errorCode = CommonInitialize(window, url, storage); CHECK_ERROR_CODE_RETURN(errorCode); errorCode = AceContainer::RunPage(instanceId_, url, ""); return errorCode; } std::string UIContentImpl::GetContentInfo(ContentInfoType type) const { return AceContainer::GetContentInfo(instanceId_, type); } UIContentErrorCode UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::string& contentInfo, napi_value storage) { static std::once_flag onceFlag; std::call_once(onceFlag, []() { #ifdef INIT_ICU_DATA_PATH std::string icuPath = "."; u_setDataDirectory(icuPath.c_str()); #endif Container::UpdateCurrent(INSTANCE_ID_PLATFORM); ClipboardProxy::GetInstance()->SetDelegate(std::make_unique<Platform::ClipboardProxyImpl>()); }); rsWindow_ = window; AceApplicationInfo::GetInstance().SetLocale(language_, region_, script_, ""); AceApplicationInfo::GetInstance().SetApiTargetVersion(targetVersion_); SetFontMgrConfig(containerSdkPath_); EventDispatcher::GetInstance().Initialize(); SystemProperties::SetExtSurfaceEnabled(!containerSdkPath_.empty()); SystemProperties::InitDeviceInfo(deviceWidth_, deviceHeight_, deviceConfig_.orientation == DeviceOrientation::PORTRAIT ? 0 : 1, deviceConfig_.density, isRound_); SystemProperties::InitDeviceType(deviceConfig_.deviceType); SystemProperties::SetColorMode(deviceConfig_.colorMode); LOGI("CreateContainer with JSDECLARATIVE frontend, set MinPlatformVersion to %{public}d", compatibleVersion_); AceContainer::CreateContainer(instanceId_, FrontendType::DECLARATIVE_JS, useNewPipeline_); auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_RETURN(container, UIContentErrorCode::NULL_POINTER); container->SetContainerSdkPath(containerSdkPath_); container->SetIsFRSCardContainer(false); container->SetBundleName(bundleName_); container->SetModuleName(moduleName_); LOGI("Save bundle %{public}s, module %{public}s", bundleName_.c_str(), moduleName_.c_str()); if (runtime_) { container->GetSettings().SetUsingSharedRuntime(true); container->SetSharedRuntime(runtime_); } else { container->GetSettings().SetUsingSharedRuntime(false); } container->SetInstallationFree(installationFree_); container->SetLabelId(labelId_); auto config = container->GetResourceConfiguration(); config.SetDeviceType(SystemProperties::GetDeviceType()); config.SetOrientation(SystemProperties::GetDeviceOrientation()); config.SetDensity(SystemProperties::GetResolution()); config.SetColorMode(SystemProperties::GetColorMode()); config.SetFontRatio(deviceConfig_.fontRatio); container->SetResourceConfiguration(config); container->SetPageProfile(pageProfile_); container->SetApiTargetVersion(targetVersion_); std::vector<std::string> paths; paths.push_back(assetPath_); std::string appResourcesPath(appResourcesPath_); if (!OHOS::Ace::Framework::EndWith(appResourcesPath, DELIMITER)) { appResourcesPath.append(DELIMITER); } paths.push_back(appResourcesPath); paths.push_back(appResourcesPath + ASSET_PATH_SHARE_STAGE); if (!containerSdkPath_.empty()) { paths.push_back(containerSdkPath_); } AceContainer::AddAssetPath(instanceId_, "", paths); AceContainer::SetResourcesPathAndThemeStyle( instanceId_, systemResourcesPath_, containerSdkPath_, appResourcesPath_, themeId_, deviceConfig_.colorMode); auto view = AceViewPreview::CreateView(instanceId_, false, container->GetSettings().usePlatformAsUIThread); UIEnvCallback callback = [window = rsWindow_, id = instanceId_]( const OHOS::Ace::RefPtr<PipelineContext>& context) mutable { CHECK_NULL_VOID(context); CHECK_NULL_VOID(window); auto director = OHOS::Rosen::RSUIDirector::Create(); CHECK_NULL_VOID(director); director->SetRSSurfaceNode(window->GetSurfaceNode()); auto container = AceContainer::GetContainerInstance(id); CHECK_NULL_VOID(container); auto func = [taskExecutor = container->GetTaskExecutor(), id]( const std::function<void()>& task, uint32_t delay) { CHECK_NULL_VOID(taskExecutor); ContainerScope scope(id); taskExecutor->PostDelayedTask( task, TaskExecutor::TaskType::UI, delay, "ArkUIRenderServiceTask", PriorityType::HIGH); }; director->SetUITaskRunner(func, id); director->Init(); context->SetRSUIDirector(director); }; AceContainer::SetView(view, rsWindow_, deviceConfig_.density, deviceWidth_, deviceHeight_, callback); // Drive the native engine with the platform thread. container->RunNativeEngineLoop(); auto pipelineContext = container->GetPipelineContext(); if (pipelineContext) { pipelineContext->SetMinPlatformVersion(compatibleVersion_); pipelineContext->SetDisplayWindowRectInfo( Rect(Offset(0.0f, 0.0f), Size(deviceWidth_, deviceHeight_))); } container->InitializeAppConfig(assetPath_, bundleName_, moduleName_, compileMode_); AceContainer::AddRouterChangeCallback(instanceId_, onRouterChange_); // Should make it possible to update surface changes by using viewWidth and viewHeight. view->NotifySurfaceChanged(deviceWidth_, deviceHeight_); view->NotifyDensityChanged(deviceConfig_.density); avoidAreaChangedListener_ = new AvoidAreaChangedListener(instanceId_); rsWindow_->RegisterAvoidAreaChangeListener(avoidAreaChangedListener_); ignoreViewSafeAreaListener_ = new IIgnoreViewSafeAreaListener(instanceId_); window->RegisterIgnoreViewSafeAreaListener(ignoreViewSafeAreaListener_); OHOS::Rosen::AvoidArea avoidArea; rsWindow_->GetAvoidAreaByType(OHOS::Rosen::AvoidAreaType::TYPE_SYSTEM, avoidArea); avoidAreaChangedListener_->OnAvoidAreaChanged(avoidArea, OHOS::Rosen::AvoidAreaType::TYPE_SYSTEM); rsWindow_->GetAvoidAreaByType(OHOS::Rosen::AvoidAreaType::TYPE_NAVIGATION_INDICATOR, avoidArea); avoidAreaChangedListener_->OnAvoidAreaChanged(avoidArea, OHOS::Rosen::AvoidAreaType::TYPE_NAVIGATION_INDICATOR); return UIContentErrorCode::NO_ERRORS; } void UIContentImpl::Destroy() { LOGI("UIContentImpl: window destroy"); AceContainer::DestroyContainer(instanceId_); } uint32_t UIContentImpl::GetBackgroundColor() { auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_RETURN(container, 0x000000); auto taskExecutor = container->GetTaskExecutor(); CHECK_NULL_RETURN(taskExecutor, 0x000000); ContainerScope scope(instanceId_); uint32_t bgColor = 0x000000; taskExecutor->PostSyncTask( [&bgColor, container]() { CHECK_NULL_VOID(container); auto pipelineContext = container->GetPipelineContext(); CHECK_NULL_VOID(pipelineContext); bgColor = pipelineContext->GetAppBgColor().GetValue(); }, TaskExecutor::TaskType::UI, "ArkUIGetAppBackgroundColor"); return bgColor; } void UIContentImpl::SetBackgroundColor(uint32_t color) { LOGI("UIContentImpl: SetBackgroundColor color is %{public}u", color); auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); ContainerScope scope(instanceId_); auto taskExecutor = container->GetTaskExecutor(); CHECK_NULL_VOID(taskExecutor); taskExecutor->PostSyncTask( [container, bgColor = color]() { auto pipelineContext = container->GetPipelineContext(); CHECK_NULL_VOID(pipelineContext); pipelineContext->SetAppBgColor(Color(bgColor)); }, TaskExecutor::TaskType::UI, "ArkUISetAppBackgroundColor"); } bool UIContentImpl::ProcessBackPressed() { LOGI("Process Back Pressed Event"); return EventDispatcher::GetInstance().DispatchBackPressedEvent(); } bool UIContentImpl::ProcessPointerEvent(const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent) { return EventDispatcher::GetInstance().DispatchTouchEvent(pointerEvent); } bool UIContentImpl::ProcessPointerEventWithCallback( const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent, const std::function<void()>& callback) { auto result = EventDispatcher::GetInstance().DispatchTouchEvent(pointerEvent); if (callback) { callback(); } return result; } bool UIContentImpl::ProcessKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent>& keyEvent, bool isPreIme) { // previewer never gets preIme-key event because there is no window return EventDispatcher::GetInstance().DispatchKeyEvent(keyEvent); } bool UIContentImpl::ProcessAxisEvent(const std::shared_ptr<OHOS::MMI::AxisEvent>& axisEvent) { return false; } bool UIContentImpl::ProcessVsyncEvent(uint64_t timeStampNanos) { return false; } void UIContentImpl::UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config) {} void UIContentImpl::UpdateViewportConfig(const ViewportConfig& config, OHOS::Rosen::WindowSizeChangeReason reason, const std::shared_ptr<OHOS::Rosen::RSTransaction>& rsTransaction, const std::map<OHOS::Rosen::AvoidAreaType, OHOS::Rosen::AvoidArea>& avoidAreas) { LOGI("ViewportConfig: %{public}s", config.ToString().c_str()); auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); auto context = container->GetPipelineContext(); CHECK_NULL_VOID(context); context->SetDisplayWindowRectInfo( Rect(Offset(config.Left(), config.Top()), Size(config.Width(), config.Height()))); auto viewPtr = AceType::DynamicCast<AceViewPreview>(container->GetAceView()); CHECK_NULL_VOID(viewPtr); SystemProperties::InitDeviceInfo( config.Width(), config.Height(), config.Height() >= config.Width() ? 0 : 1, config.Density(), false); deviceConfig_.orientation = config.Height() >= config.Width() ? DeviceOrientation::PORTRAIT : DeviceOrientation::LANDSCAPE; deviceConfig_.density = config.Density(); // Unlike the real machine, previewer require updating device configuration information to change window size. container->UpdateDeviceConfig(deviceConfig_); viewPtr->NotifyDensityChanged(config.Density()); viewPtr->NotifySurfaceChanged(config.Width(), config.Height()); } void UIContentImpl::DumpInfo(const std::vector<std::string>& params, std::vector<std::string>& info) { auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); container->Dump(params, info); } void UIContentImpl::SetNextFrameLayoutCallback(std::function<void()>&& callback) { CHECK_NULL_VOID(callback); auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); auto pipelineContext = container->GetPipelineContext(); CHECK_NULL_VOID(pipelineContext); pipelineContext->SetNextFrameLayoutCallback(std::move(callback)); } void UIContentImpl::NotifyMemoryLevel(int32_t level) { LOGI("Receive Memory level notification, level: %{public}d", level); auto container = AceContainer::GetContainerInstance(instanceId_); CHECK_NULL_VOID(container); auto pipelineContext = container->GetPipelineContext(); CHECK_NULL_VOID(pipelineContext); ContainerScope scope(instanceId_); pipelineContext->NotifyMemoryLevel(level); } int32_t UIContentImpl::CreateModalUIExtension( const AAFwk::Want& want, const ModalUIExtensionCallbacks& callbacks, const ModalUIExtensionConfig& config) { return 0; } void UIContentImpl::CloseModalUIExtension(int32_t sessionId) {} void UIContentImpl::SetStatusBarItemColor(uint32_t color) { ContainerScope scope(instanceId_); auto container = Platform::AceContainer::GetContainer(instanceId_); CHECK_NULL_VOID(container); auto appBar = container->GetAppBar(); CHECK_NULL_VOID(appBar); appBar->SetStatusBarItemColor(IsDarkColor(color)); } } // namespace OHOS::Ace