* Copyright (c) 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.
*/
#include "screen_scene.h"
#include <event_handler.h>
#include <ui_content.h>
#include <viewport_config.h>
#include "app_mgr_client.h"
#include "dm_common.h"
#include "display_manager.h"
#include "rs_adapter.h"
#include "screen_session_manager_client.h"
#include "singleton.h"
#include "singleton_container.h"
#include "window_manager_hilog.h"
#include "root_scene.h"
#include "load_intention_event.h"
#include <transaction/rs_interfaces.h>
#include "intention_event_manager.h"
#include "input_transfer_station.h"
namespace OHOS {
namespace Rosen {
namespace {
constexpr float MIN_DPI = 1e-6;
std::atomic<bool> g_ssIsDestroyed = false;
const std::string INPUT_AND_VSYNC_THREAD = "InputAndVsyncThread";
}
ScreenScene::ScreenScene(std::string name) : name_(name)
{
orientation_ = static_cast<int32_t>(DisplayOrientation::PORTRAIT);
NodeId nodeId = 0;
vsyncStation_ = std::make_shared<VsyncStation>(nodeId);
handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
g_ssIsDestroyed = false;
displayId_ = DISPLAY_ID_INVALID;
}
ScreenScene::~ScreenScene()
{
g_ssIsDestroyed = true;
Destroy();
}
WMError ScreenScene::Destroy(uint32_t reason, bool isFromInnerkits)
{
std::function<void()> task;
{
std::lock_guard<std::mutex> lock(mutex_);
if (!uiContent_) {
TLOGD(WmsLogTag::DMS, "Destroy uiContent_ is nullptr!");
return WMError::WM_OK;
}
std::shared_ptr<Ace::UIContent> uiContent = std::move(uiContent_);
uiContent_ = nullptr;
RootScene::staticRootScene_->RemoveRootScene(displayId_);
vsyncStation_->Destroy();
task = [uiContent]() {
if (uiContent != nullptr) {
uiContent->Destroy();
TLOGW(WmsLogTag::DMS, "ScreenScene: uiContent destroy success!");
}
};
}
if (handler_) {
handler_->PostSyncTask(task, "ScreenScene:Destroy");
} else {
task();
}
return WMError::WM_OK;
}
void ScreenScene::LoadContent(const std::string& contentUrl, napi_env env, napi_value storage,
AbilityRuntime::Context* context)
{
if (g_ssIsDestroyed) {
TLOGI(WmsLogTag::DMS, "ScreenScene has been destructed!");
return;
}
if (context == nullptr) {
TLOGE(WmsLogTag::DMS, "context is nullptr!");
return;
}
std::lock_guard<std::mutex> lock(mutex_);
uiContent_ = Ace::UIContent::Create(context, reinterpret_cast<NativeEngine*>(env));
if (uiContent_ == nullptr) {
TLOGE(WmsLogTag::DMS, "uiContent_ is nullptr!");
return;
}
TLOGW(WmsLogTag::DMS, "load concent");
uiContent_->Initialize(this, contentUrl, storage);
uiContent_->Foreground();
uiContent_->SetFrameLayoutFinishCallback(std::move(frameLayoutFinishCb_));
wptr<Window> weakWindow(this);
RootScene::staticRootScene_->AddRootScene(displayId_, weakWindow);
RegisterInputEventListener();
}
void ScreenScene::RegisterInputEventListener()
{
auto mainEventRunner = AppExecFwk::EventRunner::GetMainEventRunner();
if (mainEventRunner) {
TLOGI(WmsLogTag::DMS, "MainEventRunner is available");
handler_ = std::make_shared<AppExecFwk::EventHandler>(mainEventRunner);
} else {
TLOGI(WmsLogTag::DMS, "MainEventRunner is not available");
handler_ = AppExecFwk::EventHandler::Current();
if (!handler_) {
handler_ =
std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::Create(INPUT_AND_VSYNC_THREAD));
}
}
if (RootScene::staticRootScene_ != nullptr && LoadIntentionEvent() &&
!EnableInputEventListener(uiContent_.get(), handler_, this)) {
TLOGI(WmsLogTag::DMS, "EnableInputEventListener fail");
}
InputTransferStation::GetInstance().MarkRegisterToMMI();
}
void ScreenScene::UpdateViewportConfig(const Rect& rect, WindowSizeChangeReason reason)
{
if (g_ssIsDestroyed) {
TLOGI(WmsLogTag::DMS, "ScreenScene has been destructed!");
return;
}
std::lock_guard<std::mutex> lock(mutex_);
if (uiContent_ == nullptr) {
TLOGE(WmsLogTag::DMS, "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 ScreenScene::UpdateConfiguration(const std::shared_ptr<AppExecFwk::Configuration>& configuration)
{
if (g_ssIsDestroyed) {
TLOGI(WmsLogTag::DMS, "ScreenScene has been destructed!");
return;
}
std::lock_guard<std::mutex> lock(mutex_);
if (uiContent_) {
TLOGD(WmsLogTag::DMS, "notify root scene ace");
uiContent_->UpdateConfiguration(configuration);
if (configuration == nullptr) {
return;
}
std::string colorMode = configuration->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE);
bool isDark = (colorMode == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
auto rsUICtx = GetRSUIContext();
if (rsUICtx == nullptr) {
TLOGE(WmsLogTag::DMS, "no rsUICtx");
return;
}
if (auto rsInterface = rsUICtx->GetRSRenderInterface()) {
bool ret = rsInterface->SetGlobalDarkColorMode(isDark);
TLOGI(WmsLogTag::DMS, "screen colorMode: %{public}s, ret: %{public}d", colorMode.c_str(), ret);
}
}
}
void ScreenScene::RequestVsync(const std::shared_ptr<VsyncCallback>& vsyncCallback)
{
vsyncStation_->RequestVsync(vsyncCallback);
}
int64_t ScreenScene::GetVSyncPeriod()
{
return vsyncStation_->GetVSyncPeriod();
}
void ScreenScene::FlushFrameRate(uint32_t rate, int32_t animatorExpectedFrameRate, uint32_t rateType)
{
vsyncStation_->FlushFrameRate(GetRSUIContext(), rate, animatorExpectedFrameRate, rateType);
}
void ScreenScene::OnBundleUpdated(const std::string& bundleName)
{
if (g_ssIsDestroyed) {
TLOGI(WmsLogTag::DMS, "ScreenScene has been destructed!");
return;
}
TLOGD(WmsLogTag::DMS, "bundle %{public}s updated", bundleName.c_str());
std::lock_guard<std::mutex> lock(mutex_);
if (uiContent_) {
uiContent_->UpdateResource();
}
}
void ScreenScene::UpdateConfigurationForAll(const std::shared_ptr<AppExecFwk::Configuration>& configuration)
{
TLOGI(WmsLogTag::DMS, "in");
UpdateConfiguration(configuration);
if (configurationUpdateCallback_) {
configurationUpdateCallback_(configuration);
}
}
void ScreenScene::SetOnConfigurationUpdatedCallback(
const std::function<void(const std::shared_ptr<AppExecFwk::Configuration>&)>& callback)
{
configurationUpdateCallback_ = callback;
}
void ScreenScene::SetFrameLayoutFinishCallback(std::function<void()>&& callback)
{
if (g_ssIsDestroyed) {
TLOGI(WmsLogTag::DMS, "ScreenScene has been destructed!");
return;
}
frameLayoutFinishCb_ = callback;
std::lock_guard<std::mutex> lock(mutex_);
if (uiContent_) {
uiContent_->SetFrameLayoutFinishCallback(std::move(frameLayoutFinishCb_));
}
TLOGI(WmsLogTag::WMS_LAYOUT, "SetFrameLayoutFinishCallback end");
}
void ScreenScene::SetDisplayDensity(float density)
{
if (density < MIN_DPI) {
TLOGE(WmsLogTag::DMS, "invalid density");
return;
}
density_ = density;
}
uint64_t ScreenScene::GetDisplayId() const
{
return displayId_;
}
void ScreenScene::SetDisplayId(DisplayId displayId)
{
displayId_ = displayId;
}
void ScreenScene::SetDisplayOrientation(int32_t orientation)
{
if (orientation < static_cast<int32_t>(DisplayOrientation::PORTRAIT) ||
orientation > static_cast<int32_t>(DisplayOrientation::UNKNOWN)) {
TLOGE(WmsLogTag::DMS, "invalid orientation");
return;
}
orientation_ = orientation;
}
Ace::UIContent* ScreenScene::GetUIContent() const
{
std::lock_guard<std::mutex> lock(mutex_);
if (uiContent_) {
return uiContent_.get();
} else {
TLOGE(WmsLogTag::DMS, "uiContent_ is nullptr!");
return nullptr;
}
}
std::shared_ptr<RSUIDirector> ScreenScene::GetRSUIDirector() const
{
RETURN_IF_RS_CLIENT_MULTI_INSTANCE_DISABLED(nullptr);
auto rsUIDirector = ScreenSessionManagerClient::GetInstance().GetRSUIDirector(displayId_);
TLOGD(WmsLogTag::WMS_SCB, "%{public}s, displayId: %{public}" PRIu64 ", windowId: %{public}d",
RSAdapterUtil::RSUIDirectorToStr(rsUIDirector).c_str(), displayId_, GetWindowId());
return rsUIDirector;
}
std::shared_ptr<RSUIContext> ScreenScene::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;
}
}
}