/* * Copyright (c) 2022-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 #include #include #include #include #include #include "display_group_info.h" #include "remote_animation.h" #include "rs_adapter.h" #include "starting_window.h" #include "window_helper.h" #include "window_inner_manager.h" #include "window_manager_hilog.h" #include "window_manager_service.h" #include "window_manager_service_utils.h" #include "window_system_effect.h" namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "StartingWindow"}; constexpr int32_t DEFAULT_GIF_DELAY = 100; //default delay time for gif } const std::map ABILITY_TO_WMS_ORIENTATION_MAP { {OHOS::AppExecFwk::DisplayOrientation::UNSPECIFIED, Orientation::UNSPECIFIED}, {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE, Orientation::HORIZONTAL}, {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT, Orientation::VERTICAL}, {OHOS::AppExecFwk::DisplayOrientation::FOLLOWRECENT, Orientation::LOCKED}, {OHOS::AppExecFwk::DisplayOrientation::LANDSCAPE_INVERTED, Orientation::REVERSE_HORIZONTAL}, {OHOS::AppExecFwk::DisplayOrientation::PORTRAIT_INVERTED, Orientation::REVERSE_VERTICAL}, {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION, Orientation::SENSOR}, {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE, Orientation::SENSOR_HORIZONTAL}, {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT, Orientation::SENSOR_VERTICAL}, {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_RESTRICTED, Orientation::AUTO_ROTATION_RESTRICTED}, {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED, Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED}, {OHOS::AppExecFwk::DisplayOrientation::AUTO_ROTATION_PORTRAIT_RESTRICTED, Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED}, {OHOS::AppExecFwk::DisplayOrientation::LOCKED, Orientation::LOCKED}, }; std::recursive_mutex StartingWindow::mutex_; WindowMode StartingWindow::defaultMode_ = WindowMode::WINDOW_MODE_FULLSCREEN; bool StartingWindow::transAnimateEnable_ = true; WindowUIType StartingWindow::windowUIType_ = WindowUIType::INVALID_WINDOW; AnimationConfig StartingWindow::animationConfig_; StartingWindowShowInfo StartingWindow::startingWindowShowInfo_; std::atomic StartingWindow::startingWindowShowRunning_{false}; std::thread StartingWindow::startingWindowShowThread_; std::mutex StartingWindow::firstFrameMutex_; std::condition_variable StartingWindow::firstFrameCondition_; std::atomic StartingWindow::firstFrameCompleted_ = false; void StartingWindow::RegisterStartingWindowShowInfo(const sptr& node, const Rect& rect, const std::shared_ptr& info, float vpRatio) { StartingWindowShowInfo startingWindowShowInfo { node, rect, info, vpRatio }; std::array, size_t(StartWindowResType::Count)> resources = { info->appIcon, info->illustration, info->branding, info->bgImage }; auto now = std::chrono::steady_clock::now(); for (size_t i = 0; i < resources.size(); ++i) { auto resInfo = resources[i].lock(); auto& state = startingWindowShowInfo.resStates[i]; if (!resInfo) { TLOGE(WmsLogTag::WMS_PATTERN, "null resource to record frame index."); state.frameCount = 0; continue; } state.delay = (!resInfo->delayTimes.empty()) ? resInfo->delayTimes : std::vector{ INT32_MAX }; if (std::all_of(state.delay.begin(), state.delay.end(), [](int32_t delay) { return delay == 0; })) { for (auto& delay : state.delay) { TLOGD(WmsLogTag::WMS_PATTERN, "Invalid delay time: %{public}d", delay); delay = DEFAULT_GIF_DELAY; } } state.frameCount = (resInfo->pixelMaps.size() > 1) ? resInfo->pixelMaps.size() : 1; state.next = now; } startingWindowShowInfo_ = std::move(startingWindowShowInfo); } void StartingWindow::UnRegisterStartingWindowShowInfo() { auto cleanResource = [](std::shared_ptr& resInfo) { if (resInfo) { for (auto& pixelMap : resInfo->pixelMaps) { pixelMap->FreePixelMap(); } resInfo->pixelMaps.clear(); resInfo->delayTimes.clear(); resInfo.reset(); } }; if (startingWindowShowInfo_.info) { cleanResource(startingWindowShowInfo_.info->appIcon); cleanResource(startingWindowShowInfo_.info->bgImage); cleanResource(startingWindowShowInfo_.info->illustration); cleanResource(startingWindowShowInfo_.info->branding); } startingWindowShowInfo_.info.reset(); TLOGE(WmsLogTag::WMS_PATTERN, "starting window draw resource cleaned."); } void StartingWindow::UpdateWindowShowInfo(StartingWindowShowInfo& startingWindowShowInfo, bool& needRedraw) { for (size_t i = 0; i < startingWindowShowInfo.resStates.size(); ++i) { auto& state = startingWindowShowInfo.resStates[i]; auto now = std::chrono::steady_clock::now(); if (state.frameCount == 0 || now < state.next) { TLOGD(WmsLogTag::WMS_PATTERN, "null resource or not time yet"); continue; } state.frameIdx = (state.frameIdx + 1) % state.frameCount; state.next = now + std::chrono::milliseconds(state.delay[state.frameIdx]); startingWindowShowInfo.frameIndex[i] = state.frameIdx; needRedraw = true; } } void StartingWindow::DrawStartingWindowShowInfo() { startingWindowShowRunning_ = true; int32_t minDelay(DEFAULT_GIF_DELAY); for (const auto& state : startingWindowShowInfo_.resStates) { for (int32_t delay : state.delay) { if (delay > 0 && delay < minDelay) { minDelay = delay; } } } auto drawTask = [minDelay]() { bool firstDraw = true; while (startingWindowShowRunning_.load()) { bool needRedraw = false; UpdateWindowShowInfo(startingWindowShowInfo_, needRedraw); if (!needRedraw) { TLOGD(WmsLogTag::WMS_PATTERN, "no resource updated need to draw."); continue; } bool ret = SurfaceDraw::DrawCustomStartingWindow( startingWindowShowInfo_.node.promote()->startingWinSurfaceNode_, startingWindowShowInfo_.rect, startingWindowShowInfo_.info, startingWindowShowInfo_.vpRatio, startingWindowShowInfo_.frameIndex); if (firstDraw && !ret) { std::unique_lock lock(firstFrameMutex_); startingWindowShowRunning_ = false; firstFrameCompleted_ = true; firstFrameCondition_.notify_one(); TLOGE(WmsLogTag::WMS_PATTERN, "Failed to draw first frame of StartingWindow."); break; } if (firstDraw) { std::unique_lock lock(firstFrameMutex_); firstFrameCompleted_ = true; firstFrameCondition_.notify_one(); firstDraw = false; } std::this_thread::sleep_for(std::chrono::milliseconds(minDelay)); } }; startingWindowShowThread_ = std::thread(drawTask); } sptr StartingWindow::CreateWindowNode(const sptr& info, uint32_t winId) { sptr property = InitializeWindowProperty(info, winId); if (property == nullptr) { return nullptr; } sptr node = new(std::nothrow) WindowNode(property); if (node == nullptr) { return nullptr; } node->stateMachine_.SetWindowId(winId); node->abilityToken_ = info->GetAbilityToken(); node->SetWindowSizeLimits(info->GetWindowSizeLimits()); node->abilityInfo_.missionId_ = info->GetMissionId(); node->abilityInfo_.bundleName_ = info->GetBundleName(); node->abilityInfo_.abilityName_ = info->GetAbilityName(); uint32_t windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(info->GetWindowSupportModes()); node->SetWindowModeSupportType(windowModeSupportType); if (CreateLeashAndStartingSurfaceNode(node) != WMError::WM_OK) { return nullptr; } node->stateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED); return node; } sptr StartingWindow::InitializeWindowProperty(const sptr& info, uint32_t winId) { sptr property = new(std::nothrow) WindowProperty(); if (property == nullptr || info == nullptr) { return nullptr; } property->SetRequestRect(info->GetWindowRect()); if (WindowHelper::IsValidWindowMode(info->GetWindowMode())) { property->SetWindowMode(info->GetWindowMode()); } else { property->SetWindowMode(defaultMode_); } AppExecFwk::DisplayOrientation displayOrientation = info->GetOrientation(); if (ABILITY_TO_WMS_ORIENTATION_MAP.count(displayOrientation) == 0) { WLOGFE("id:%{public}u Do not support this Orientation type", winId); return nullptr; } Orientation orientation = ABILITY_TO_WMS_ORIENTATION_MAP.at(displayOrientation); if (orientation < Orientation::BEGIN || orientation > Orientation::END) { WLOGFE("Set orientation from ability failed"); return nullptr; } property->SetRequestedOrientation(orientation); property->SetDisplayId(info->GetDisplayId()); property->SetWindowType(info->GetWindowType()); ChangePropertyByApiVersion(info, orientation, property); property->SetApiCompatibleVersion(info->GetApiCompatibleVersion()); if (info->GetShowFlagWhenLocked()) { if (property->GetApiCompatibleVersion() < 9 || info->isSystemCalling_) { // 9: api version. property->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); } else { WLOGFW("Only API 9- or system calling support showing when locked."); } } property->SetWindowId(winId); return property; } void StartingWindow::ChangePropertyByApiVersion(const sptr& info, const Orientation orientation, sptr& property) { // 10 ArkUI new framework support after API10 if (info->GetApiCompatibleVersion() < 10) { auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(info->GetDisplayId()); if (!(displayInfo && WmsUtils::IsExpectedRotatableWindow(orientation, displayInfo->GetDisplayOrientation(), property->GetWindowMode(), property->GetWindowFlags(), false))) { property->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); } } else { if (WindowHelper::IsMainWindow(property->GetWindowType())) { SystemBarProperty statusSystemBarProperty(true, 0x00FFFFFF, 0xFF000000); SystemBarProperty navigationSystemBarProperty(true, 0x00FFFFFF, 0xFF000000); property->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusSystemBarProperty); property->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, navigationSystemBarProperty); } } } WMError StartingWindow::CreateLeashAndStartingSurfaceNode(sptr& node) { struct RSSurfaceNodeConfig rsSurfaceNodeConfig; rsSurfaceNodeConfig.SurfaceNodeName = "leashWindow" + std::to_string(node->GetWindowId()); auto rsUIContext = node->GetRSUIContext(); node->leashWinSurfaceNode_ = RSSurfaceNode::Create( rsSurfaceNodeConfig, RSSurfaceNodeType::LEASH_WINDOW_NODE, true, false, rsUIContext); if (node->leashWinSurfaceNode_ == nullptr) { TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "create leashWinSurfaceNode failed"); return WMError::WM_ERROR_NULLPTR; } RSAdapterUtil::SetSkipCheckInMultiInstance(node->leashWinSurfaceNode_, true); TLOGD(WmsLogTag::WMS_SCB, "Create RSSurfaceNode: %{public}s, name: %{public}s", RSAdapterUtil::RSNodeToStr(node->leashWinSurfaceNode_).c_str(), rsSurfaceNodeConfig.SurfaceNodeName.c_str()); rsSurfaceNodeConfig.SurfaceNodeName = "startingWindow" + std::to_string(node->GetWindowId()); node->startingWinSurfaceNode_ = RSSurfaceNode::Create( rsSurfaceNodeConfig, RSSurfaceNodeType::STARTING_WINDOW_NODE, true, false, rsUIContext); if (node->startingWinSurfaceNode_ == nullptr) { TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "create startingWinSurfaceNode failed"); node->leashWinSurfaceNode_ = nullptr; return WMError::WM_ERROR_NULLPTR; } RSAdapterUtil::SetSkipCheckInMultiInstance(node->startingWinSurfaceNode_, true); TLOGD(WmsLogTag::WMS_SCB, "Create RSSurfaceNode: %{public}s, name: %{public}s", RSAdapterUtil::RSNodeToStr(node->startingWinSurfaceNode_).c_str(), rsSurfaceNodeConfig.SurfaceNodeName.c_str()); TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "Create leashWinSurfaceNode and startingWinSurfaceNode success with id:%{public}u!", node->GetWindowId()); return WMError::WM_OK; } WMError StartingWindow::DrawStartingWindow(sptr& node, std::shared_ptr pixelMap, uint32_t bkgColor, bool isColdStart) { if (node == nullptr) { return WMError::WM_ERROR_NULLPTR; } // using snapshot to support hot start since node destroy when hide HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DrawStartingWindow(%u)", node->GetWindowId()); Rect rect = node->GetWindowRect(); if (RemoteAnimation::CheckRemoteAnimationEnabled(node->GetDisplayId()) && node->leashWinSurfaceNode_) { // hides this node until RSProxyNode send valid context alpha/matrix node->leashWinSurfaceNode_->ResetContextAlpha(); } if (!isColdStart) { return WMError::WM_OK; } if (node->startingWinSurfaceNode_ == nullptr) { TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "no starting Window SurfaceNode!"); return WMError::WM_ERROR_NULLPTR; } auto staringWindowPageDrawInfo = GetCustomStartingWindowInfo(node, GetBundleManager()); if (staringWindowPageDrawInfo) { if (DrawStartingWindow(staringWindowPageDrawInfo, node, rect) == WMError::WM_OK) { return WMError::WM_OK; } } // set window effect WindowSystemEffect::SetWindowEffect(node); if (pixelMap == nullptr) { SurfaceDraw::DrawColor(node->startingWinSurfaceNode_, rect.width_, rect.height_, bkgColor); return WMError::WM_OK; } TLOGD(WmsLogTag::WMS_STARTUP_PAGE, "draw background in sperate"); SurfaceDraw::DrawImageRect(node->startingWinSurfaceNode_, rect, pixelMap, bkgColor); return WMError::WM_OK; } WMError StartingWindow::SetStartingWindowAnimation(wptr weak) { auto weakNode = weak.promote(); if (weakNode == nullptr || !weakNode->startingWinSurfaceNode_) { TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or startingWinSurfaceNode_ is nullptr"); return WMError::WM_ERROR_NULLPTR; } StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::START_WINDOW_ANIMATION), "StartingWindowAnimate(%u)", weakNode->GetWindowId()); weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityStart_); auto execute = [weak]() { auto weakNode = weak.promote(); if (weakNode == nullptr) { TLOGNE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode is nullptr"); return; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:ExecuteAnimate(%d)", weakNode->GetWindowId()); weakNode->startingWinSurfaceNode_->SetAlpha(animationConfig_.startWinAnimationConfig_.opacityEnd_); }; auto finish = [weak]() { auto weakNode = weak.promote(); if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) { TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or leashWinSurfaceNode_ is nullptr"); return; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "StartingWindow:AnimateFinish(%d)", weakNode->GetWindowId()); TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId()); weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_); weakNode->startingWinSurfaceNode_ = nullptr; RSTransactionAdapter::FlushImplicitTransaction(weakNode->leashWinSurfaceNode_); FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::START_WINDOW_ANIMATION), "StartingWindowAnimate(%u)", weakNode->GetWindowId()); }; auto rsUIContext = weakNode->startingWinSurfaceNode_->GetRSUIContext(); RSNode::Animate(rsUIContext, animationConfig_.startWinAnimationConfig_.timingProtocol_, animationConfig_.startWinAnimationConfig_.timingCurve_, execute, finish); RSTransactionAdapter::FlushImplicitTransaction(rsUIContext); FinishTrace(HITRACE_TAG_WINDOW_MANAGER); return WMError::WM_OK; } void StartingWindow::HandleClientWindowCreate(sptr& node, sptr& window, uint32_t& windowId, const std::shared_ptr& surfaceNode, sptr& property, int32_t pid, int32_t uid) { if (node == nullptr) { TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "node is nullptr"); return; } node->surfaceNode_ = surfaceNode; node->SetWindowToken(window); node->SetCallingPid(pid); node->SetCallingUid(uid); windowId = node->GetWindowId(); // test node->stateMachine_.SetWindowId(windowId); node->stateMachine_.SetWindowType(property->GetWindowType()); TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "after set Id:%{public}u, " "requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]", node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_, node->GetRequestRect().width_, node->GetRequestRect().height_); // Register FirstFrame Callback to rs, replace startwin wptr weak = node; auto firstFrameCompleteCallback = [weak]() { auto task = [weak]() { FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::STARTING_WINDOW), "wms:async:ShowStartingWindow"); auto weakNode = weak.promote(); if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) { TLOGNE(WmsLogTag::WMS_STARTUP_PAGE, "windowNode or leashWinSurfaceNode_ is nullptr"); return; } TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::FirstFrameCallback come, id: %{public}u", weakNode->GetWindowId()); if (transAnimateEnable_) { SetStartingWindowAnimation(weakNode); } else { weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_); weakNode->startingWinSurfaceNode_ = nullptr; RSTransactionAdapter::FlushImplicitTransaction(weakNode->leashWinSurfaceNode_); TLOGNI(WmsLogTag::WMS_STARTUP_PAGE, "StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId()); } WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode); weakNode->firstFrameAvailable_ = true; startingWindowShowRunning_ = false; if (startingWindowShowThread_.joinable()) { startingWindowShowThread_.join(); } UnRegisterStartingWindowShowInfo(); }; WindowManagerService::GetInstance().PostAsyncTask(task, "firstFrameCompleteCallback"); }; node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback); RSTransactionAdapter::FlushImplicitTransaction(node->surfaceNode_); } void StartingWindow::ReleaseStartWinSurfaceNode(sptr& node) { std::lock_guard lock(mutex_); if (!node->leashWinSurfaceNode_) { TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "cannot release leashwindow since leash is null, id:%{public}u", node->GetWindowId()); return; } if (startingWindowShowRunning_.load()) { startingWindowShowRunning_ = false; if (startingWindowShowThread_.joinable()) { startingWindowShowThread_.join(); } UnRegisterStartingWindowShowInfo(); } node->leashWinSurfaceNode_->RemoveChild(node->startingWinSurfaceNode_); node->leashWinSurfaceNode_->RemoveChild(node->closeWinSurfaceNode_); node->leashWinSurfaceNode_->RemoveChild(node->surfaceNode_); RSTransactionAdapter::FlushImplicitTransaction(node->leashWinSurfaceNode_); node->leashWinSurfaceNode_ = nullptr; node->startingWinSurfaceNode_ = nullptr; node->closeWinSurfaceNode_ = nullptr; TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "Release startwindow surfaceNode end id: %{public}u, " "[leashWinSurface]: use_count: %{public}ld, [startWinSurface]: use_count: %{public}ld ", node->GetWindowId(), node->leashWinSurfaceNode_.use_count(), node->startingWinSurfaceNode_.use_count()); } bool StartingWindow::IsWindowFollowParent(WindowType type) { if (windowUIType_ != WindowUIType::PHONE_WINDOW) { return false; } return WindowHelper::IsWindowFollowParent(type); } void StartingWindow::AddNodeOnRSTree(sptr& node, bool isMultiDisplay) { auto updateRSTreeFunc = [&node, isMultiDisplay]() { UpdateRSTree(node, isMultiDisplay); }; wptr weakNode = node; auto finishCallBack = [weakNode]() { auto weak = weakNode.promote(); if (weak == nullptr) { return; } auto winRect = weak->GetWindowRect(); TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "before setBounds windowRect: %{public}d, %{public}d, %{public}d, %{public}d", winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); if (weak->leashWinSurfaceNode_) { weak->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); weak->leashWinSurfaceNode_->SetAnimationFinished(); } RSTransactionAdapter::FlushImplicitTransaction(weak->leashWinSurfaceNode_); }; if (!RemoteAnimation::CheckAnimationController()) { std::shared_ptr rsUIContext; if (node->leashWinSurfaceNode_) { rsUIContext = node->leashWinSurfaceNode_->GetRSUIContext(); } RSNode::Animate(rsUIContext, animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_, animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc, finishCallBack); } else { // add or remove window without animation updateRSTreeFunc(); } } void StartingWindow::UpdateRSTree(sptr& node, bool isMultiDisplay) { auto& dms = DisplayManagerServiceInner::GetInstance(); DisplayId displayId = node->GetDisplayId(); if (!node->surfaceNode_) { // cold start if (!WindowHelper::IsMainWindow(node->GetWindowType())) { TLOGE(WmsLogTag::WMS_MAIN, "window id: %{public}d type: %{public}u is not Main Window!", node->GetWindowId(), static_cast(node->GetWindowType())); } dms.UpdateRSTree(displayId, displayId, node->leashWinSurfaceNode_, true, isMultiDisplay); node->leashWinSurfaceNode_->AddChild(node->startingWinSurfaceNode_, -1); TLOGD(WmsLogTag::WMS_MAIN, "Add startingWinSurfaceNode_ to leashWinSurfaceNode_ end during cold start"); return; } // hot start const auto& displayIdVec = node->GetShowingDisplays(); for (auto& shownDisplayId : displayIdVec) { if (node->leashWinSurfaceNode_) { // to app dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->leashWinSurfaceNode_, true, isMultiDisplay); } else { // to launcher dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->surfaceNode_, true, isMultiDisplay); } for (auto& child : node->children_) { if (IsWindowFollowParent(child->GetWindowType())) { continue; } if (child->currentVisibility_) { dms.UpdateRSTree(shownDisplayId, shownDisplayId, child->surfaceNode_, true, isMultiDisplay); } } } TLOGD(WmsLogTag::WMS_MAIN, "Update RsTree with hot start"); } void StartingWindow::SetDefaultWindowMode(WindowMode defaultMode) { defaultMode_ = defaultMode; } void StartingWindow::SetAnimationConfig(AnimationConfig config) { animationConfig_ = config; } sptr StartingWindow::GetBundleManager() { auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (systemAbilityMgr == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "Failed to get SystemAbilityManager."); return nullptr; } auto bmsProxy = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); if (bmsProxy == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "Failed to get BundleManagerService."); return nullptr; } return iface_cast(bmsProxy); } std::shared_ptr StartingWindow::GetAbilityInfoFromBMS(const sptr& node, const sptr& bundleMgr) { if (node == nullptr || bundleMgr == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "node or bundleMgr is nullptr."); return nullptr; } AAFwk::Want want; AppExecFwk::AbilityInfo abilityInfo; want.SetElementName("", node->abilityInfo_.bundleName_, node->abilityInfo_.abilityName_, ""); if (!bundleMgr->QueryAbilityInfo( want, AppExecFwk::GET_ABILITY_INFO_DEFAULT, AppExecFwk::Constants::ANY_USERID, abilityInfo)) { TLOGE(WmsLogTag::WMS_PATTERN, "Get ability info from BMS failed!"); return nullptr; } return std::make_shared(std::move(abilityInfo)); } std::shared_ptr StartingWindow::CreateResourceManager( const std::shared_ptr& abilityInfo) { if (abilityInfo == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "abilityInfo is nullptr."); return nullptr; } std::unique_ptr resConfig(Global::Resource::CreateResConfig()); if (resConfig == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "resConfig is nullptr."); return nullptr; } std::shared_ptr resourceMgr(Global::Resource::CreateResourceManager( abilityInfo->bundleName, abilityInfo->moduleName, "", {}, *resConfig)); if (resourceMgr == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "resourceMgr is nullptr."); return nullptr; } std::string loadPath = abilityInfo->hapPath.empty() ? abilityInfo->resourcePath : abilityInfo->hapPath; if (!resourceMgr->AddResource(loadPath.c_str(), Global::Resource::SELECT_COLOR | Global::Resource::SELECT_MEDIA)) { TLOGE(WmsLogTag::WMS_PATTERN, "Add resource %{private}s failed.", loadPath.c_str()); } return resourceMgr; } std::shared_ptr StartingWindow::GetPixelMapListInfo(uint32_t mediaDataId, const std::shared_ptr& resourceMgr, const std::shared_ptr& abilityInfo) { if (mediaDataId <= 0 || resourceMgr == nullptr || abilityInfo == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "invalid mediaDataId or null resourceMgr and abilityInfo."); return nullptr; } Media::SourceOptions opts; uint32_t errorCode = 0; std::unique_ptr imageSource; if (!abilityInfo->hapPath.empty()) { size_t len = 0; std::unique_ptr dataOut; if (resourceMgr->GetMediaDataById(mediaDataId, len, dataOut) != Global::Resource::RState::SUCCESS) { return nullptr; } imageSource = Media::ImageSource::CreateImageSource(dataOut.get(), len, opts, errorCode); } else { std::string dataPath; if (resourceMgr->GetMediaById(mediaDataId, dataPath) != Global::Resource::RState::SUCCESS) { return nullptr; } imageSource = Media::ImageSource::CreateImageSource(dataPath, opts, errorCode); } if (errorCode != 0 || imageSource == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "imageSource failed, id %{public}u err %{public}u", mediaDataId, errorCode); return nullptr; } Media::DecodeOptions decodeOpts; auto pixelMapList = imageSource->CreatePixelMapList(decodeOpts, errorCode); if (errorCode != 0) { TLOGE(WmsLogTag::WMS_PATTERN, "pixelMapList failed, id %{public}u err %{public}u", mediaDataId, errorCode); return nullptr; } auto info = std::make_shared(); std::transform(pixelMapList->begin(), pixelMapList->end(), std::back_inserter(info->pixelMaps), [](auto& ptr) { return std::move(ptr); }); if (info->pixelMaps.size() > 1) { // multi frames auto delaytimes = imageSource->GetDelayTime(errorCode); if (errorCode != 0) { TLOGE(WmsLogTag::WMS_PATTERN, "delaytimes failed, id %{public}u err %{public}u", mediaDataId, errorCode); return nullptr; } info->delayTimes = std::move(*delaytimes); } return info; } std::shared_ptr StartingWindow::GetCustomStartingWindowInfo( const sptr& node, const sptr& bundleMgr) { if (node == nullptr || bundleMgr == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "node or bundleMgr is nullptr."); return nullptr; } auto abilityInfo = GetAbilityInfoFromBMS(node, bundleMgr); if (abilityInfo == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "Failed to retrieve abilityinfo from BMS"); return nullptr; } auto resourceMgr = CreateResourceManager(abilityInfo); if (resourceMgr == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "Failed to create resource manager"); return nullptr; } return DoGetCustomStartingWindowInfo(abilityInfo, resourceMgr); } std::shared_ptr StartingWindow::DoGetCustomStartingWindowInfo( const std::shared_ptr& abilityInfo, const std::shared_ptr& resourceMgr) { if (resourceMgr == nullptr || abilityInfo == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "resourMgr or abilityInfo is nullptr."); return nullptr; } const auto& startWindowRes = abilityInfo->startWindowResource; auto loadPixelMap = [&](uint32_t resId) { return GetPixelMapListInfo(resId, resourceMgr, abilityInfo); }; auto info = std::make_shared(); if (resourceMgr->GetColorById(startWindowRes.startWindowBackgroundColorId, info->bgColor) == Global::Resource::RState::SUCCESS) { info->bgImage = loadPixelMap(startWindowRes.startWindowBackgroundImageId); info->branding = loadPixelMap(startWindowRes.startWindowBrandingImageId); info->startWindowBackgroundImageFit = startWindowRes.startWindowBackgroundImageFit; info->appIcon = loadPixelMap(startWindowRes.startWindowAppIconId); if (info->appIcon == nullptr) { info->illustration = loadPixelMap(startWindowRes.startWindowIllustrationId); } return info; } TLOGE(WmsLogTag::WMS_PATTERN, "Failed to load custom startingwindow color."); return nullptr; } WMError StartingWindow::DrawStartingWindow(const std::shared_ptr& info, const sptr& node, const Rect& rect) { if (startingWindowShowRunning_.load()) { startingWindowShowRunning_ = false; if (startingWindowShowThread_.joinable()) { startingWindowShowThread_.join(); } firstFrameCompleted_ = false; UnRegisterStartingWindowShowInfo(); } if (info == nullptr) { TLOGE(WmsLogTag::WMS_PATTERN, "startingWindowPageDrawInfo is nullptr."); return WMError::WM_ERROR_NULLPTR; } const float vpRatio = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId()); RegisterStartingWindowShowInfo(node, rect, info, vpRatio); const auto& resInfo = startingWindowShowInfo_.info; if (resInfo && !resInfo->appIcon && !resInfo->bgImage && !resInfo->branding && !resInfo->illustration) { if (!(SurfaceDraw::DrawCustomStartingWindow(node->startingWinSurfaceNode_, rect, resInfo, vpRatio, startingWindowShowInfo_.frameIndex))) { TLOGE(WmsLogTag::WMS_PATTERN, "Failed to draw Custom starting window."); return WMError::WM_ERROR_INVALID_PARAM; } return WMError::WM_OK; } DrawStartingWindowShowInfo(); std::unique_lock lock(firstFrameMutex_); firstFrameCondition_.wait(lock, []() { return firstFrameCompleted_ == true; }); if (!startingWindowShowRunning_.load()) { TLOGE(WmsLogTag::WMS_PATTERN, "Failed to start Custom starting window show."); if (startingWindowShowThread_.joinable()) { startingWindowShowThread_.join(); } UnRegisterStartingWindowShowInfo(); return WMError::WM_ERROR_INVALID_PARAM; } return WMError::WM_OK; } } // Rosen } // OHOS