/* * 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 "root_scene.h" #include #include #include #include #include #include #include #include #include #include "ability_context.h" #include "app_mgr_client.h" #include "display_manager.h" #include "extension/extension_business_info.h" #include "fold_screen_state_internel.h" #include "input_transfer_station.h" #include "rs_adapter.h" #include "screen_session_manager_client.h" #include "singleton.h" #include "singleton_container.h" #include "intention_event_manager.h" #include "window_manager_hilog.h" namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "RootScene" }; const std::string INPUT_AND_VSYNC_THREAD = "InputAndVsyncThread"; constexpr int32_t API_VERSION_18 = 18; class BundleStatusCallback : public IRemoteStub { public: explicit BundleStatusCallback(RootScene* rootScene) : rootScene_(rootScene) {} virtual ~BundleStatusCallback() = default; void OnBundleStateChanged(const uint8_t installType, const int32_t resultCode, const std::string& resultMsg, const std::string& bundleName) override {} void OnBundleAdded(const std::string& bundleName, const int userId) override { rootScene_->OnBundleUpdated(bundleName); } void OnBundleUpdated(const std::string& bundleName, const int userId) override { rootScene_->OnBundleUpdated(bundleName); } void OnBundleRemoved(const std::string& bundleName, const int userId) override {} private: RootScene* rootScene_; }; } // namespace sptr RootScene::staticRootScene_; std::function&)> RootScene::configurationUpdatedCallback_; RootScene::RootScene() { launcherService_ = new AppExecFwk::LauncherService(); if (!launcherService_->RegisterCallback(new BundleStatusCallback(this))) { WLOGFE("Failed to register bundle status callback."); } NodeId nodeId = 0; vsyncStation_ = std::make_shared(nodeId); handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); } RootScene::~RootScene() { TLOGI(WmsLogTag::WMS_MAIN, "destroyed"); RemoveRootScene(DEFAULT_DISPLAY_ID); uiContent_ = nullptr; } void RootScene::LoadContent(const std::string& contentUrl, napi_env env, napi_value storage, AbilityRuntime::Context* context) { if (context == nullptr) { WLOGFE("context is nullptr!"); return; } uiContent_ = Ace::UIContent::Create(context, reinterpret_cast(env)); if (uiContent_ == nullptr) { WLOGFE("uiContent_ is nullptr!"); return; } context_ = context->weak_from_this(); uiContent_->Initialize(this, contentUrl, storage); uiContent_->Foreground(); uiContent_->SetFrameLayoutFinishCallback(std::move(frameLayoutFinishCb_)); uiContent_->AddFocusActiveChangeCallback(notifyWatchFocusActiveChangeCallback_); wptr weakWindow(this); AddRootScene(DEFAULT_DISPLAY_ID, weakWindow); RegisterInputEventListener(); } void RootScene::SetDisplayOrientation(int32_t orientation) { orientation_ = orientation; } void RootScene::UpdateViewportConfig(const Rect& rect, WindowSizeChangeReason reason) { if (updateRootSceneRectCallback_ != nullptr) { updateRootSceneRectCallback_(rect); } if (uiContent_ == nullptr) { TLOGD(WmsLogTag::DEFAULT, "uiContent_ is nullptr!"); return; } Ace::ViewportConfig config; config.SetSize(rect.width_, rect.height_); config.SetPosition(rect.posX_, rect.posY_); config.SetDensity(density_); config.SetOrientation(orientation_); config.SetDisplayId(GetDisplayId()); uiContent_->UpdateViewportConfig(config, reason); } void RootScene::UpdateConfiguration(const std::shared_ptr& configuration) { TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root map size: %{public}u", static_cast(rootSceneMap_.size())); for (const auto& sceneMap : rootSceneMap_) { if (sceneMap.second == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "root window is null, display=%{public}" PRIu64, sceneMap.first); continue; } auto window = sceneMap.second.promote(); if (window == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "root win is null, display=%{public}" PRIu64, sceneMap.first); continue; } auto uiContent = window->GetUIContent(); if (uiContent == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent is null, root win=%{public}u, display=%{public}" PRIu64, window->GetWindowId(), window->GetDisplayId()); continue; } TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root win=%{public}u, display=%{public}" PRIu64, window->GetWindowId(), window->GetDisplayId()); uiContent->UpdateConfiguration(configuration); if (configuration == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "config is null, root win=%{public}u, display=%{public}" PRIu64, window->GetWindowId(), window->GetDisplayId()); continue; } std::string colorMode = configuration->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE); bool isDark = (colorMode == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK); bool ret = RSInterfaces::GetInstance().SetGlobalDarkColorMode(isDark); if (ret == false) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "SetGlobalDarkColorMode fail, colorMode : %{public}s", colorMode.c_str()); } } } void RootScene::UpdateConfigurationForSpecified(const std::shared_ptr& configuration, const std::shared_ptr& resourceManager) { if (uiContent_ == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent null, root win=%{public}u, display=%{public}" PRIu64, GetWindowId(), GetDisplayId()); return; } uiContent_->UpdateConfiguration(configuration, resourceManager); if (configuration == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "config is null, root win=%{public}u, display=%{public}" PRIu64, GetWindowId(), GetDisplayId()); return; } TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root win=%{public}u, display=%{public}" PRIu64, GetWindowId(), GetDisplayId()); std::string colorMode = configuration->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE); bool isDark = (colorMode == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK); if (!RSInterfaces::GetInstance().SetGlobalDarkColorMode(isDark)) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "set dark color mode failed, winId: %{public}u, colorMode: %{public}s", GetWindowId(), colorMode.c_str()); } } void RootScene::UpdateConfigurationForAll(const std::shared_ptr& configuration, const std::vector>& ignoreWindowContexts) { if (staticRootScene_) { if (std::count(ignoreWindowContexts.begin(), ignoreWindowContexts.end(), staticRootScene_->GetContext()) == 0) { TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root win=%{public}u, display=%{public}" PRIu64, staticRootScene_->GetWindowId(), staticRootScene_->GetDisplayId()); staticRootScene_->UpdateConfiguration(configuration); if (configurationUpdatedCallback_) { configurationUpdatedCallback_(configuration); } } else { TLOGI(WmsLogTag::WMS_ATTRIBUTE, "skip root win=%{public}u, display=%{public}" PRIu64, staticRootScene_->GetWindowId(), staticRootScene_->GetDisplayId()); } } else { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "root is null"); } } void RootScene::UpdateConfigurationSync(const std::shared_ptr& configuration) { TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root map size: %{public}u", static_cast(rootSceneMap_.size())); for (const auto& sceneMap : rootSceneMap_) { if (sceneMap.second == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "root window is null, display=%{public}" PRIu64, sceneMap.first); continue; } auto window = sceneMap.second.promote(); if (window == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "root win is null, display=%{public}" PRIu64, sceneMap.first); continue; } auto uiContent = window->GetUIContent(); if (uiContent == nullptr) { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent is null, root win=%{public}u, display=%{public}" PRIu64, window->GetWindowId(), window->GetDisplayId()); continue; } TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root win=%{public}u, display=%{public}" PRIu64, window->GetWindowId(), window->GetDisplayId()); uiContent->UpdateConfigurationSyncForAll(configuration); } } void RootScene::UpdateConfigurationSyncForAll(const std::shared_ptr& configuration) { if (staticRootScene_ != nullptr) { TLOGD(WmsLogTag::WMS_ATTRIBUTE, "root win=%{public}u, display=%{public}" PRIu64, staticRootScene_->GetWindowId(), staticRootScene_->GetDisplayId()); staticRootScene_->UpdateConfigurationSync(configuration); } else { TLOGE(WmsLogTag::WMS_ATTRIBUTE, "root is null"); } } void RootScene::RegisterInputEventListener() { auto mainEventRunner = AppExecFwk::EventRunner::GetMainEventRunner(); if (mainEventRunner) { WLOGFD("MainEventRunner is available"); eventHandler_ = std::make_shared(mainEventRunner); } else { WLOGFD("MainEventRunner is not available"); eventHandler_ = AppExecFwk::EventHandler::Current(); if (!eventHandler_) { eventHandler_ = std::make_shared(AppExecFwk::EventRunner::Create(INPUT_AND_VSYNC_THREAD)); } } if (!(DelayedSingleton::GetInstance()->EnableInputEventListener( uiContent_.get(), eventHandler_, this))) { WLOGFE("EnableInputEventListener fail"); } InputTransferStation::GetInstance().MarkRegisterToMMI(); } void RootScene::RequestVsync(const std::shared_ptr& vsyncCallback) { vsyncStation_->RequestVsync(vsyncCallback); } int64_t RootScene::GetVSyncPeriod() { return vsyncStation_->GetVSyncPeriod(); } void RootScene::FlushFrameRate(uint32_t rate, int32_t animatorExpectedFrameRate, uint32_t rateType) { vsyncStation_->FlushFrameRate(GetRSUIContext(), rate, animatorExpectedFrameRate, rateType); } bool RootScene::IsLastFrameLayoutFinished() { int32_t requestTimes = vsyncStation_->GetRequestVsyncTimes(); TLOGD(WmsLogTag::WMS_LAYOUT, "vsync request times: %{public}d", requestTimes); return requestTimes <= 0; } void RootScene::OnFlushUIParams() { vsyncStation_->DecreaseRequestVsyncTimes(); } void RootScene::OnBundleUpdated(const std::string& bundleName) { WLOGFD("bundle %{public}s updated", bundleName.c_str()); if (uiContent_) { uiContent_->UpdateResource(); } } void RootScene::SetOnConfigurationUpdatedCallback( const std::function&)>& callback) { configurationUpdatedCallback_ = callback; } void RootScene::SetFrameLayoutFinishCallback(std::function&& callback) { frameLayoutFinishCb_ = callback; if (uiContent_) { uiContent_->SetFrameLayoutFinishCallback(std::move(frameLayoutFinishCb_)); } TLOGI(WmsLogTag::WMS_LAYOUT, "end"); } void RootScene::SetUiDvsyncSwitch(bool dvsyncSwitch) { vsyncStation_->SetUiDvsyncSwitch(dvsyncSwitch); } void RootScene::SetTouchEvent(int32_t touchType) { vsyncStation_->SetTouchEvent(touchType); } WMError RootScene::GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea, const Rect& rect, int32_t apiVersion) { if (getSessionAvoidAreaByTypeCallback_ == nullptr) { TLOGE(WmsLogTag::WMS_IMMS, "getSessionAvoidAreaByTypeCallback is nullptr"); return WMError::WM_ERROR_NULLPTR; } if (apiVersion != API_VERSION_INVALID && apiVersion < API_VERSION_18) { TLOGI(WmsLogTag::WMS_IMMS, "root scene UIExtension type %{public}u api %{public}d not supported", type, apiVersion); return WMError::WM_DO_NOTHING; } avoidArea = getSessionAvoidAreaByTypeCallback_(type); TLOGI(WmsLogTag::WMS_IMMS, "root scene type %{public}u area %{public}s", type, avoidArea.ToString().c_str()); return WMError::WM_OK; } void RootScene::RegisterGetSessionAvoidAreaByTypeCallback(GetSessionAvoidAreaByTypeCallback&& callback) { getSessionAvoidAreaByTypeCallback_ = std::move(callback); } uint32_t RootScene::GetStatusBarHeight() const { uint32_t height = 0; if (getStatusBarHeightCallback_ == nullptr) { TLOGE(WmsLogTag::WMS_IMMS, "getStatusBarHeightCallback_ is nullptr"); return height; } height = getStatusBarHeightCallback_(); TLOGI(WmsLogTag::WMS_IMMS, "root scene height %{public}u", height); return height; } void RootScene::RegisterGetStatusBarHeightCallback(GetStatusBarHeightCallback&& callback) { getStatusBarHeightCallback_ = std::move(callback); } void RootScene::RegisterUpdateRootSceneRectCallback(UpdateRootSceneRectCallback&& callback) { updateRootSceneRectCallback_ = std::move(callback); } void RootScene::RegisterUpdateRootSceneAvoidAreaCallback(UpdateRootSceneAvoidAreaCallback&& callback) { updateRootSceneAvoidAreaCallback_ = std::move(callback); } WMError RootScene::RegisterAvoidAreaChangeListener(const sptr& listener) { if (listener == nullptr) { TLOGE(WmsLogTag::WMS_IMMS, "listener is null"); return WMError::WM_ERROR_NULLPTR; } bool firstInserted = false; { std::lock_guard lock(mutex_); if (avoidAreaChangeListeners_.find(listener) == avoidAreaChangeListeners_.end()) { TLOGI(WmsLogTag::WMS_IMMS, "register success"); avoidAreaChangeListeners_.insert(listener); firstInserted = true; } } if (firstInserted) { updateRootSceneAvoidAreaCallback_(); } return WMError::WM_OK; } WMError RootScene::UnregisterAvoidAreaChangeListener(const sptr& listener) { if (listener == nullptr) { TLOGE(WmsLogTag::WMS_IMMS, "listener is null"); return WMError::WM_ERROR_NULLPTR; } TLOGI(WmsLogTag::WMS_IMMS, "unregister success"); std::lock_guard lock(mutex_); avoidAreaChangeListeners_.erase(listener); return WMError::WM_OK; } void RootScene::NotifyAvoidAreaChangeForRoot(const sptr& avoidArea, AvoidAreaType type, const sptr& info) { AvoidArea area = {}; if (avoidArea != nullptr) { area= *avoidArea; TLOGI(WmsLogTag::WMS_IMMS, "type %{public}d area %{public}s.", type, avoidArea->ToString().c_str()); } std::lock_guard lock(mutex_); for (auto& listener : avoidAreaChangeListeners_) { if (listener != nullptr) { listener->OnAvoidAreaChanged(area, type, info); } } } WMError RootScene::RegisterOccupiedAreaChangeListener(const sptr& listener) { if (listener == nullptr) { TLOGE(WmsLogTag::WMS_KEYBOARD, "listener is null"); return WMError::WM_ERROR_NULLPTR; } std::lock_guard lock(occupiedAreaMutex_); if (occupiedAreaChangeListeners_.find(listener) == occupiedAreaChangeListeners_.end()) { TLOGI(WmsLogTag::WMS_KEYBOARD, "register success"); occupiedAreaChangeListeners_.insert(listener); } return WMError::WM_OK; } WMError RootScene::UnregisterOccupiedAreaChangeListener(const sptr& listener) { if (listener == nullptr) { TLOGE(WmsLogTag::WMS_KEYBOARD, "listener is null"); return WMError::WM_ERROR_NULLPTR; } TLOGI(WmsLogTag::WMS_KEYBOARD, "unregister success"); std::lock_guard lock(occupiedAreaMutex_); occupiedAreaChangeListeners_.erase(listener); return WMError::WM_OK; } void RootScene::NotifyOccupiedAreaChangeForRoot(const sptr& info) { if (info == nullptr) { TLOGI(WmsLogTag::WMS_KEYBOARD, "occupied area info is null"); return; } if (handler_ == nullptr) { TLOGI(WmsLogTag::WMS_KEYBOARD, "handler_ is null, notify occupied area for root failed."); return; } TLOGI(WmsLogTag::WMS_KEYBOARD, "occupiedRect: %{public}s, textField PositionY_: %{public}f, Height_: %{public}f", info->rect_.ToString().c_str(), info->textFieldPositionY_, info->textFieldHeight_); auto task = [weak = wptr(this), info]() { auto window = weak.promote(); if (!window) { TLOGE(WmsLogTag::WMS_KEYBOARD, "window is null"); return; } std::lock_guard lock(window->occupiedAreaMutex_); for (const auto& listener : window->occupiedAreaChangeListeners_) { if (listener != nullptr) { listener->OnSizeChange(info); } } }; handler_->PostTask(task, __func__); } void RootScene::RegisterNotifyWatchFocusActiveChangeCallback(NotifyWatchFocusActiveChangeCallback&& callback) { notifyWatchFocusActiveChangeCallback_ = std::move(callback); } std::shared_ptr RootScene::GetRSNodeByStringID(const std::string& stringId) { TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}s", stringId.c_str()); if (uiContent_ == nullptr) { TLOGE(WmsLogTag::WMS_LAYOUT, "uiContent is null, winId: %{public}d", GetWindowId()); return nullptr; } TLOGI(WmsLogTag::WMS_LAYOUT, "end"); return uiContent_->GetRSNodeByStringID(stringId); } void RootScene::SetTopWindowBoundaryByID(const std::string& stringId) { TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}s", stringId.c_str()); if (uiContent_ == nullptr) { TLOGE(WmsLogTag::WMS_LAYOUT, "uiContent is null, winId: %{public}d", GetWindowId()); return; } TLOGI(WmsLogTag::WMS_LAYOUT, "end"); uiContent_->SetTopWindowBoundaryByID(stringId); } void RootScene::GetExtensionConfig(AAFwk::WantParams& want) const { int32_t rootHostWindowType = static_cast(WindowType::WINDOW_TYPE_SCENE_BOARD); want.SetParam(Extension::ROOT_HOST_WINDOW_TYPE_FIELD, AAFwk::Integer::Box(rootHostWindowType)); } UIContentResult RootScene::GetUIContentByDisplayId(DisplayId displayId) { auto iter = rootSceneMap_.find(displayId); if (iter == rootSceneMap_.end()) { TLOGE(WmsLogTag::WMS_FOCUS, "Can not find rootScene, displayId: %{public}" PRIu64, displayId); return std::make_pair(GetUIContent(), false); } if (iter->second != nullptr) { auto window = iter->second.promote(); if (window != nullptr) { return std::make_pair(window->GetUIContent(), true); } } return std::make_pair(nullptr, true); } void RootScene::AddRootScene(DisplayId displayId, wptr window) { auto iter = rootSceneMap_.find(displayId); if (iter == rootSceneMap_.end()) { rootSceneMap_.emplace(displayId, window); TLOGI(WmsLogTag::WMS_FOCUS, "insert rootScene, displayId: %{public}" PRIu64, displayId); } else { iter->second = window; TLOGI(WmsLogTag::WMS_FOCUS, "update rootScene, displayId: %{public}" PRIu64, displayId); } } void RootScene::RemoveRootScene(DisplayId displayId) { TLOGI(WmsLogTag::WMS_FOCUS, "displayId: %{public}" PRIu64, displayId); auto iter = rootSceneMap_.find(displayId); if (iter == rootSceneMap_.end()) { TLOGE(WmsLogTag::WMS_FOCUS, "Can not find rootScene, displayId: %{public}" PRIu64, displayId); return; } rootSceneMap_.erase(displayId); } std::shared_ptr RootScene::GetRSUIDirector() const { RETURN_IF_RS_CLIENT_MULTI_INSTANCE_DISABLED(nullptr); sptr display; if (displayId_ == DISPLAY_ID_INVALID) { display = DisplayManager::GetInstance().GetDefaultDisplay(); TLOGE(WmsLogTag::WMS_SCB, "displayId is invalid, use default display"); } else { display = DisplayManager::GetInstance().GetDisplayById(displayId_); } if (!display) { TLOGE(WmsLogTag::WMS_SCB, "display is null, displayId: %{public}" PRIu64, displayId_); return nullptr; } auto screenId = display->GetScreenId(); auto rsUIDirector = ScreenSessionManagerClient::GetInstance().GetRSUIDirector(screenId); TLOGD(WmsLogTag::WMS_SCB, "%{public}s, screenId: %{public}" PRIu64 ", windowId: %{public}d", RSAdapterUtil::RSUIDirectorToStr(rsUIDirector).c_str(), screenId, GetWindowId()); return rsUIDirector; } std::shared_ptr RootScene::GetRSUIContext() const { RETURN_IF_RS_CLIENT_MULTI_INSTANCE_DISABLED(nullptr); auto rsUIDirector = GetRSUIDirector(); auto rsUIContext = rsUIDirector ? rsUIDirector->GetRSUIContext() : nullptr; TLOGD(WmsLogTag::WMS_SCB, "%{public}s, windowId: %{public}d", RSAdapterUtil::RSUIContextToStr(rsUIContext).c_str(), GetWindowId()); return rsUIContext; } } // namespace Rosen } // namespace OHOS