From 2e6627e283e71a8e187f3ebcb6d6e4283f9db069 Mon Sep 17 00:00:00 2001 From: jincanran Date: Thu, 17 Feb 2022 14:39:50 +0800 Subject: [PATCH 01/70] add tile switch to cascade strategy Signed-off-by: jincanran Change-Id: Id8599766cd8556ddb775d0d792b9353debb580c5 --- utils/include/wm_common_inner.h | 9 +++++++++ wmserver/include/window_node_container.h | 2 +- wmserver/include/window_root.h | 2 +- wmserver/src/window_controller.cpp | 10 +++++----- wmserver/src/window_node_container.cpp | 10 +++++++--- wmserver/src/window_root.cpp | 4 ++-- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/utils/include/wm_common_inner.h b/utils/include/wm_common_inner.h index d967fcad..fda04fe8 100644 --- a/utils/include/wm_common_inner.h +++ b/utils/include/wm_common_inner.h @@ -35,6 +35,15 @@ enum class WindowStateChangeReason : uint32_t { NORMAL, KEYGUARD, }; + +enum class WindowUpdateReason : uint32_t { + UPDATE_ALL, + UPDATE_MODE, + UPDATE_RECT, + UPDATE_FLAGS, + UPDATE_TYPE, + UPDATE_OTHER_PROPS, +}; } } #endif // OHOS_ROSEN_WM_COMMON_INNER_H \ No newline at end of file diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 298f3cff..a9f487e9 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -33,7 +33,7 @@ public: ~WindowNodeContainer(); WMError AddWindowNode(sptr& node, sptr& parentNode); WMError RemoveWindowNode(sptr& node); - WMError UpdateWindowNode(sptr& node); + WMError UpdateWindowNode(sptr& node, WindowUpdateReason reason); WMError DestroyWindowNode(sptr& node, std::vector& windowIds); const std::vector& Destroy(); void AssignZOrder(); diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index b784adf3..ac5777b0 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -44,7 +44,7 @@ public: WMError AddWindowNode(uint32_t parentId, sptr& node); WMError RemoveWindowNode(uint32_t windowId); WMError DestroyWindow(uint32_t windowId, bool onlySelf); - WMError UpdateWindowNode(uint32_t windowId); + WMError UpdateWindowNode(uint32_t windowId, WindowUpdateReason reason); bool isVerticalDisplay(sptr& node) const; WMError RequestFocus(uint32_t windowId); diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index 54b2994f..7e91d7c1 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -148,7 +148,7 @@ WMError WindowController::ResizeRect(uint32_t windowId, const Rect& rect, Window } property->SetWindowRect(newRect); - WMError res = windowRoot_->UpdateWindowNode(windowId); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_RECT); if (res != WMError::WM_OK) { return res; } @@ -202,7 +202,7 @@ WMError WindowController::SetWindowMode(uint32_t windowId, WindowMode dstMode) return res; } } - res = windowRoot_->UpdateWindowNode(windowId); + res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_MODE); if (res != WMError::WM_OK) { WLOGFE("Set window mode failed, update node failed"); return res; @@ -315,7 +315,7 @@ WMError WindowController::SetWindowType(uint32_t windowId, WindowType type) auto property = node->GetWindowProperty(); property->SetWindowType(type); UpdateWindowAnimation(node); - WMError res = windowRoot_->UpdateWindowNode(windowId); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_TYPE); if (res != WMError::WM_OK) { return res; } @@ -333,7 +333,7 @@ WMError WindowController::SetWindowFlags(uint32_t windowId, uint32_t flags) } auto property = node->GetWindowProperty(); property->SetWindowFlags(flags); - WMError res = windowRoot_->UpdateWindowNode(windowId); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_FLAGS); if (res != WMError::WM_OK) { return res; } @@ -350,7 +350,7 @@ WMError WindowController::SetSystemBarProperty(uint32_t windowId, WindowType typ return WMError::WM_ERROR_NULLPTR; } node->SetSystemBarProperty(type, property); - WMError res = windowRoot_->UpdateWindowNode(windowId); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_OTHER_PROPS); if (res != WMError::WM_OK) { return res; } diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 3ed3ef63..4c965e7b 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -137,13 +137,17 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr& node) +WMError WindowNodeContainer::UpdateWindowNode(sptr& node, WindowUpdateReason reason) { if (!node->surfaceNode_) { WLOGFE("surface node is nullptr!"); return WMError::WM_ERROR_NULLPTR; } - SwitchLayoutPolicy(WindowLayoutMode::CASCADE); + if (layoutMode_ == WindowLayoutMode::TILE) { + if (WindowHelper::IsMainWindow(node->GetWindowType()) && reason != WindowUpdateReason::UPDATE_OTHER_PROPS) { + SwitchLayoutPolicy(WindowLayoutMode::CASCADE); + } + } layoutPolicy_->UpdateWindowNode(node); if (avoidController_->IsAvoidAreaNode(node)) { avoidController_->UpdateAvoidAreaNode(node); @@ -906,7 +910,7 @@ WMError WindowNodeContainer::UpdateWindowPairInfo(sptr& triggerNode, WindowMode::WINDOW_MODE_SPLIT_SECONDARY : WindowMode::WINDOW_MODE_SPLIT_PRIMARY; pairNode->SetWindowMode(pairDstMode); pairNode->GetWindowToken()->UpdateWindowMode(pairDstMode); - WMError ret = UpdateWindowNode(pairNode); + WMError ret = UpdateWindowNode(pairNode, WindowUpdateReason::UPDATE_MODE); if (ret != WMError::WM_OK) { WLOGFE("Update window pair info failed"); return ret; diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index 0f385109..0edede25 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -191,7 +191,7 @@ WMError WindowRoot::RemoveWindowNode(uint32_t windowId) return container->RemoveWindowNode(node); } -WMError WindowRoot::UpdateWindowNode(uint32_t windowId) +WMError WindowRoot::UpdateWindowNode(uint32_t windowId, WindowUpdateReason reason) { auto node = GetWindowNode(windowId); if (node == nullptr) { @@ -203,7 +203,7 @@ WMError WindowRoot::UpdateWindowNode(uint32_t windowId) WLOGFE("add window failed, window container could not be found"); return WMError::WM_ERROR_NULLPTR; } - return container->UpdateWindowNode(node); + return container->UpdateWindowNode(node, reason); } WMError WindowRoot::EnterSplitWindowMode(sptr& node) From 5c7827a60959172904007f33e9b3038a2602d95c Mon Sep 17 00:00:00 2001 From: lu Date: Thu, 17 Feb 2022 16:26:47 +0800 Subject: [PATCH 02/70] clear DM warning Signed-off-by: lu Change-Id: I762ce417febfa918fee7665880db749cfd096286 --- dm/src/display_manager.cpp | 8 +- dm/src/screen_group.cpp | 7 +- .../include/display_manager_service_inner.h | 1 + dmserver/src/abstract_screen_controller.cpp | 5 +- interfaces/innerkits/dm/display_manager.h | 1 + interfaces/innerkits/dm/screen_group.h | 3 +- wmtest/BUILD.gn | 84 ---------------- wmtest/frameworks/main.cpp | 88 ----------------- wmtest/test/dm_native_test.cpp | 97 ------------------- wmtest/test/dm_native_test.h | 40 -------- wmtest/test/wm_native_test.cpp | 74 -------------- wmtest/test/wm_native_test.h | 39 -------- 12 files changed, 19 insertions(+), 428 deletions(-) delete mode 100644 wmtest/BUILD.gn delete mode 100644 wmtest/frameworks/main.cpp delete mode 100644 wmtest/test/dm_native_test.cpp delete mode 100644 wmtest/test/dm_native_test.h delete mode 100644 wmtest/test/wm_native_test.cpp delete mode 100644 wmtest/test/wm_native_test.h diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 588834c5..096078c0 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -167,6 +167,11 @@ const sptr DisplayManager::GetDisplayById(DisplayId displayId) return display; } +const sptr DisplayManager::GetDisplayByScreen(ScreenId screenId) +{ + return nullptr; +} + std::shared_ptr DisplayManager::GetScreenshot(DisplayId displayId) { if (displayId == DISPLAY_ID_INVALD) { @@ -372,8 +377,7 @@ void DisplayManager::NotifyDisplayStateChanged(DisplayId id, DisplayState state) void DisplayManager::NotifyDisplayChangedEvent(const sptr info, DisplayChangeEvent event) { - WLOGI("NotifyDisplayChangedEvent event:%{public}u, size:%{public}zu", event, - pImpl_->displayListeners_.size()); + WLOGI("NotifyDisplayChangedEvent event:%{public}u, size:%{public}zu", event, pImpl_->displayListeners_.size()); std::lock_guard lock(pImpl_->mutex_); for (auto& listener : pImpl_->displayListeners_) { listener->OnChange(info->id_, event); diff --git a/dm/src/screen_group.cpp b/dm/src/screen_group.cpp index 262da22d..91e17a8d 100644 --- a/dm/src/screen_group.cpp +++ b/dm/src/screen_group.cpp @@ -54,8 +54,13 @@ ScreenCombination ScreenGroup::GetCombination() const return pImpl_->combination_; } -std::vector ScreenGroup::GetChildrenIds() const +std::vector ScreenGroup::GetChild() const { return pImpl_->children_; } + +std::vector ScreenGroup::GetChildPosition() const +{ + return pImpl_->position_; +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dmserver/include/display_manager_service_inner.h b/dmserver/include/display_manager_service_inner.h index b537d11d..1540ffde 100644 --- a/dmserver/include/display_manager_service_inner.h +++ b/dmserver/include/display_manager_service_inner.h @@ -36,6 +36,7 @@ public: std::vector GetAllDisplayIds(); ScreenId GetRSScreenId(DisplayId displayId) const; const sptr GetScreenInfoByDisplayId(DisplayId displayId) const; + const sptr GetScreenByDisplayId(DisplayId); void UpdateRSTree(DisplayId displayId, std::shared_ptr& surfaceNode, bool isAdd); void RegisterDisplayChangeListener(sptr listener); }; diff --git a/dmserver/src/abstract_screen_controller.cpp b/dmserver/src/abstract_screen_controller.cpp index a0f74e01..bde6c1ac 100644 --- a/dmserver/src/abstract_screen_controller.cpp +++ b/dmserver/src/abstract_screen_controller.cpp @@ -542,7 +542,7 @@ void AbstractScreenController::OnScreenRotate(ScreenId dmsId, Rotation before, R sptr abstractScreen = iter->second; // Notify rotation event to ScreenManager DisplayManagerAgentController::GetInstance().OnScreenChange( - abstractScreen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); + abstractScreen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); // Notify rotation event to AbstractDisplayController if (abstractScreenCallback_ != nullptr) { abstractScreenCallback_->onChange_(abstractScreen, DisplayChangeEvent::UPDATE_ROTATION); @@ -764,7 +764,8 @@ void AbstractScreenController::DumpScreenGroupInfo() const isMirrored.c_str(), screenGroup->rSDisplayNodeConfig_.mirrorNodeId); auto childrenScreen = screenGroup->GetChildren(); for (auto screen : childrenScreen) { - std::string isGroup = (dmsScreenGroupMap_.find(screen->dmsId_) != dmsScreenGroupMap_.end()) ? "true" : "false"; + std::string isGroup = + (dmsScreenGroupMap_.find(screen->dmsId_) != dmsScreenGroupMap_.end()) ? "true" : "false"; if (screen->type_ == ScreenType::UNDEFINE) { screenType = "UNDEFINE"; } else if (screen->type_ == ScreenType::REAL) { diff --git a/interfaces/innerkits/dm/display_manager.h b/interfaces/innerkits/dm/display_manager.h index 9bc7384b..07b0c4aa 100644 --- a/interfaces/innerkits/dm/display_manager.h +++ b/interfaces/innerkits/dm/display_manager.h @@ -42,6 +42,7 @@ public: DisplayId GetDefaultDisplayId(); const sptr GetDefaultDisplay(); const sptr GetDisplayById(DisplayId displayId); + const sptr GetDisplayByScreen(ScreenId screenId); std::vector GetAllDisplayIds(); bool RegisterDisplayListener(sptr listener); bool UnregisterDisplayListener(sptr listener); diff --git a/interfaces/innerkits/dm/screen_group.h b/interfaces/innerkits/dm/screen_group.h index fd64740d..78377f88 100644 --- a/interfaces/innerkits/dm/screen_group.h +++ b/interfaces/innerkits/dm/screen_group.h @@ -33,7 +33,8 @@ public: ScreenGroup(const ScreenGroupInfo* info); ~ScreenGroup(); ScreenCombination GetCombination() const; - std::vector GetChildrenIds() const; + std::vector GetChild() const; + std::vector GetChildPosition() const; private: class Impl; diff --git a/wmtest/BUILD.gn b/wmtest/BUILD.gn deleted file mode 100644 index f91fd2eb..00000000 --- a/wmtest/BUILD.gn +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2021 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. - -import("//build/ohos.gni") - -## Build rosenwmtest {{{ -config("rosenwmtest_config") { - visibility = [ ":*" ] - - include_dirs = [ - "frameworks", - - # for abilityContext - "//foundation/aafwk/standard/frameworks/kits/ability/ability_runtime/include", - "//foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include", - "//base/global/resmgr_standard/interfaces/innerkits/include", - "//third_party/node/deps/icu-small/source/common", - "//foundation/aafwk/standard/interfaces/innerkits/ability_manager/include", - "//foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content", - "//foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include", - "//foundation/aafwk/standard/interfaces/innerkits/base/include", - - # RSSurface - "//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client", - "//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base", - ] - - cflags = [ - "-Wall", - "-Werror", - "-g3", - ] -} - -ohos_executable("rosenwmtest") { - install_enable = false - - sources = [ - "frameworks/inative_test.cpp", - "frameworks/main.cpp", - "test/dm_native_test.cpp", - "test/wm_native_test.cpp", - ] - - configs = [ ":rosenwmtest_config" ] - - deps = [ - "//foundation/graphic/standard:libvsync_client", - "//foundation/graphic/standard:libwmclient", - "//foundation/graphic/standard:libwmservice", - "//foundation/windowmanager/utils:libwmutil", - "//foundation/windowmanager/wm:libwm", - "//foundation/windowmanager/wmserver:libwms", - "//third_party/zlib:libz", - - # ace - # native value - "//foundation/ace/ace_engine/interfaces/innerkits/ace:ace_uicontent", - "//foundation/ace/napi:ace_napi", - ] - - external_deps = [ "samgr_standard:samgr_proxy" ] - - part_name = "window_manager" - subsystem_name = "window" -} - -## Build rosenwmtest }}} - -group("test") { - testonly = true - - deps = [ "unittest:unittest" ] -} diff --git a/wmtest/frameworks/main.cpp b/wmtest/frameworks/main.cpp deleted file mode 100644 index 70e78401..00000000 --- a/wmtest/frameworks/main.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2021 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 - -#include "inative_test.h" - -using namespace OHOS::Rosen; - -namespace { -void Usage(const char *argv0) -{ - printf("Usage: %s type id\n", argv0); - auto visitFunc = [](const INativeTest *test) { - std::stringstream ss; - ss << test->GetDomain() << ", id="; - ss << test->GetID() << ": "; - ss << test->GetDescription(); - if (test->GetLastTime() != INativeTest::LAST_TIME_FOREVER) { - constexpr double msecToSec = 1000.0; - ss << " (last " << std::setprecision(1) << test->GetLastTime() / msecToSec << "s)"; - } - std::cout << ss.str() << std::endl; - }; - INativeTest::VisitTests(visitFunc); -} -} // namespace - -int32_t main(int32_t argc, const char **argv) -{ - constexpr int32_t argNumber = 2; - if (argc <= argNumber) { - Usage(argv[0]); - return 0; - } - - int32_t testcase = -1; - constexpr int32_t domainIndex = 1; - constexpr int32_t idIndex = 2; - std::stringstream ss(argv[idIndex]); - ss >> testcase; - if (ss.fail() == true || testcase == -1) { - Usage(argv[0]); - return 1; - } - - INativeTest *found = nullptr; - auto visitFunc = [argv, testcase, &found](INativeTest *test) { - if (test->GetDomain() == argv[domainIndex] && test->GetID() == testcase) { - found = test; - } - }; - INativeTest::VisitTests(visitFunc); - if (found == nullptr) { - printf("not found test %d\n", testcase); - return 1; - } - - auto runner = OHOS::AppExecFwk::EventRunner::Create(false); - auto handler = std::make_shared(runner); - handler->PostTask(std::bind(&INativeTest::Run, found, argc - 1, argv + 1)); - if (found->GetLastTime() != INativeTest::LAST_TIME_FOREVER) { - handler->PostTask(std::bind(&OHOS::AppExecFwk::EventRunner::Stop, runner), found->GetLastTime()); - } - - printf("%d %s run! pid=%d\n", found->GetID(), found->GetDescription().c_str(), getpid()); - runner->Run(); - return 0; -} diff --git a/wmtest/test/dm_native_test.cpp b/wmtest/test/dm_native_test.cpp deleted file mode 100644 index 3c1a9711..00000000 --- a/wmtest/test/dm_native_test.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2021 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 "dm_native_test.h" - -#include -#include -#include -#include "display_manager.h" -#include "singleton_container.h" -#include "wm_common.h" - -using namespace OHOS::Rosen; - -namespace { -DMNativeTest g_autoload; -} // namespace - -std::string DMNativeTest::GetDescription() const -{ - constexpr const char *desc = "normal display"; - return desc; -} - -std::string DMNativeTest::GetDomain() const -{ - constexpr const char *desc = "dmclient"; - return desc; -} - -int32_t DMNativeTest::GetID() const -{ - constexpr int32_t id = 1; - return id; -} - -uint32_t DMNativeTest::GetLastTime() const -{ - constexpr uint32_t lastTime = LAST_TIME_FOREVER; - return lastTime; -} - -void DMNativeTest::Run(int32_t argc, const char **argv) -{ - printf("DMNativeTest run begin\n"); - sptr dms = DisplayManager::GetInstance(); - if (dms == nullptr) { - printf("dms error!\n"); - return; - } - - DisplayId displayId = dms->GetDefaultDisplayId(); - printf("defaultDisplayId: %" PRIu64"\n", displayId); - - auto display = dms->GetDefaultDisplay(); - if (display == nullptr) { - printf("GetDefaultDisplay: failed!\n"); - } else { - printf("GetDefaultDisplay: id %" PRIu64", w %d, h %d, fps %u\n", display->GetId(), display->GetWidth(), - display->GetHeight(), display->GetFreshRate()); - } - - auto ids = dms->GetAllDisplayIds(); - for (auto id: ids) { - display = dms->GetDisplayById(displayId); - if (display == nullptr) { - printf("GetDisplayById(%" PRIu64"): failed!\n", id); - } else { - printf("GetDisplayById(%" PRIu64"): id %" PRIu64", w %d, h %d, fps %u\n", id, display->GetId(), - display->GetWidth(), display->GetHeight(), display->GetFreshRate()); - } - } - - auto displays = dms->GetAllDisplays(); - for (auto disp: displays) { - if (disp == nullptr) { - printf("GetAllDisplays: failed!\n"); - } else { - printf("GetAllDisplays: id %" PRIu64", w %d, h %d, fps %u\n", disp->GetId(), disp->GetWidth(), - disp->GetHeight(), disp->GetFreshRate()); - } - } - - printf("DMNativeTest run finish\n"); -} diff --git a/wmtest/test/dm_native_test.h b/wmtest/test/dm_native_test.h deleted file mode 100644 index 7b325bf8..00000000 --- a/wmtest/test/dm_native_test.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - -#ifndef OHOS_ROSEN_DM_NATIVE_TEST_H -#define OHOS_ROSEN_DM_NATIVE_TEST_H - -#include -#include "inative_test.h" - -namespace OHOS::Rosen { -class DMNativeTest : public INativeTest { -public: - virtual ~DMNativeTest() = default; - virtual std::string GetDescription() const override; - virtual std::string GetDomain() const override; - virtual int32_t GetID() const override; - virtual uint32_t GetLastTime() const override; - - virtual void Run(int32_t argc, const char **argv) override; - -private: - void PostTask(std::function func, uint32_t delayTime = 0); - void ExitTest(); - int64_t GetNowTime(); -}; -} - -#endif // OHOS_ROSEN_DM_NATIVE_TEST_H diff --git a/wmtest/test/wm_native_test.cpp b/wmtest/test/wm_native_test.cpp deleted file mode 100644 index f5749e97..00000000 --- a/wmtest/test/wm_native_test.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2021 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 "wm_native_test.h" - -#include -#include -#include -#include "window.h" -#include "window_life_cycle_interface.h" -#include "window_option.h" -#include "window_scene.h" -#include "wm_common.h" - -using namespace OHOS::Rosen; - -namespace { -WMNativeTest g_autoload; -} // namespace - -std::string WMNativeTest::GetDescription() const -{ - constexpr const char *desc = "normal window"; - return desc; -} - -std::string WMNativeTest::GetDomain() const -{ - constexpr const char *desc = "wmclient"; - return desc; -} - -int32_t WMNativeTest::GetID() const -{ - constexpr int32_t id = 1; - return id; -} - -uint32_t WMNativeTest::GetLastTime() const -{ - constexpr uint32_t lastTime = LAST_TIME_FOREVER; - return lastTime; -} - -void WMNativeTest::Run(int32_t argc, const char **argv) -{ - DisplayId displayId = 0; - sptr listener = nullptr; - sptr scene = new WindowScene(); - std::shared_ptr abilityContext = nullptr; - WMError rtn = scene->Init(displayId, abilityContext, listener); - if (rtn != OHOS::Rosen::WMError::WM_OK) { - return; - } - - while (true) { - scene->GoForeground(); - sleep(3); // Sleep for 3 seconds - scene->GoBackground(); - sleep(3); // Sleep for 3 seconds - } -} diff --git a/wmtest/test/wm_native_test.h b/wmtest/test/wm_native_test.h deleted file mode 100644 index 6b978531..00000000 --- a/wmtest/test/wm_native_test.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - -#ifndef OHOS_ROSEN_WM_NATIVE_TEST_H -#define OHOS_ROSEN_WM_NATIVE_TEST_H - -#include "inative_test.h" - -namespace OHOS::Rosen { -class WMNativeTest : public INativeTest { -public: - virtual ~WMNativeTest() = default; - virtual std::string GetDescription() const override; - virtual std::string GetDomain() const override; - virtual int32_t GetID() const override; - virtual uint32_t GetLastTime() const override; - - virtual void Run(int32_t argc, const char **argv) override; - -private: - void PostTask(std::function func, uint32_t delayTime = 0); - void ExitTest(); - int64_t GetNowTime(); -}; -} - -#endif // OHOS_ROSEN_WM_NATIVE_TEST_H From 33adcdcd885bff9b63316fa16dc5c5b2fe74d3dd Mon Sep 17 00:00:00 2001 From: youqijing Date: Thu, 17 Feb 2022 16:47:58 +0800 Subject: [PATCH 03/70] fix expand ut and st Signed-off-by: youqijing Change-Id: I8b31d3fba47809c642df65a59bf6a4e782c67cb9 --- dm/test/systemtest/screen_manager_test.cpp | 5 ++--- dm/test/unittest/screen_manager_test.cpp | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/dm/test/systemtest/screen_manager_test.cpp b/dm/test/systemtest/screen_manager_test.cpp index f78c3e36..bc0743ec 100644 --- a/dm/test/systemtest/screen_manager_test.cpp +++ b/dm/test/systemtest/screen_manager_test.cpp @@ -214,11 +214,13 @@ HWTEST_F(ScreenManagerTest, ScreenManager06, Function | MediumTest | Level2) { sptr screen = ScreenManager::GetInstance().GetScreenById(defaultScreenId_); auto modes = screen->GetSupportedModes(); + auto defaultModeId = screen->GetModeId(); ASSERT_GT(modes.size(), 0); for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) { ASSERT_EQ(true, screen->SetScreenActiveMode(modeIdx)); ASSERT_EQ(modeIdx, screen->GetModeId()); } + ASSERT_EQ(true, screen->SetScreenActiveMode(defaultModeId)); } /** @@ -233,7 +235,6 @@ HWTEST_F(ScreenManagerTest, ScreenManager07, Function | MediumTest | Level2) defaultoption_.surface_ = utils.psurface_; defaultoption_.isForShot_ = false; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultoption_); - ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); std::vector> screens = ScreenManager::GetInstance().GetAllScreens(); sptr DefaultScreen = screens.front(); std::vector options = {{DefaultScreen->GetId(), 0, 0}, {virtualScreenId, defaultWidth_, 0}}; @@ -255,7 +256,6 @@ HWTEST_F(ScreenManagerTest, ScreenManager08, Function | MediumTest | Level2) defaultoption_.surface_ = utils.psurface_; defaultoption_.isForShot_ = false; ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultoption_); - ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); std::vector> screens = ScreenManager::GetInstance().GetAllScreens(); sptr DefaultScreen = screens.front(); DisplayId virtualDisplayId = DISPLAY_ID_INVALD; @@ -265,7 +265,6 @@ HWTEST_F(ScreenManagerTest, ScreenManager08, Function | MediumTest | Level2) virtualDisplayId = id; // find the display id of virtual screen } } - ASSERT_NE(DISPLAY_ID_INVALD, virtualDisplayId); sptr window = CreateWindowByDisplayId(virtualDisplayId); ASSERT_NE(nullptr, window); sleep(TEST_SPEEP_S); diff --git a/dm/test/unittest/screen_manager_test.cpp b/dm/test/unittest/screen_manager_test.cpp index a84cce9b..d6da30be 100644 --- a/dm/test/unittest/screen_manager_test.cpp +++ b/dm/test/unittest/screen_manager_test.cpp @@ -123,8 +123,6 @@ HWTEST_F(ScreenManagerTest, MakeExpand_001, Function | SmallTest | Level1) HWTEST_F(ScreenManagerTest, MakeExpand_002, Function | SmallTest | Level1) { ScreenId invalidId = SCREEN_ID_INVALID; - std::unique_ptr m = std::make_unique(); - EXPECT_CALL(m->Mock(), MakeExpand(_, _)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); std::vector options = {}; ScreenId expansionId = ScreenManager::GetInstance().MakeExpand(options); ASSERT_EQ(expansionId, invalidId); From 497e525f61c443486381fa37b0bb2a73b5a166ba Mon Sep 17 00:00:00 2001 From: dubj Date: Thu, 17 Feb 2022 17:02:59 +0800 Subject: [PATCH 04/70] Resolve drag performance issues Signed-off-by: dubj Change-Id: Ida6fdee193f197ef12491dcc23a19118fab52342 --- wmserver/include/drag_controller.h | 2 +- wmserver/src/drag_controller.cpp | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/wmserver/include/drag_controller.h b/wmserver/include/drag_controller.h index f0a94f26..5b463438 100644 --- a/wmserver/include/drag_controller.h +++ b/wmserver/include/drag_controller.h @@ -31,7 +31,7 @@ public: void UpdateDragInfo(uint32_t windowId); void FinishDrag(uint32_t windowId); private: - sptr GetHitWindow(PointInfo point); + sptr GetHitWindow(DisplayId id, const PointInfo point); bool GetHitPoint(uint32_t windowId, PointInfo& point); sptr windowRoot_; uint64_t hitWindowId_ = 0; diff --git a/wmserver/src/drag_controller.cpp b/wmserver/src/drag_controller.cpp index 37e95d28..927cfb5e 100644 --- a/wmserver/src/drag_controller.cpp +++ b/wmserver/src/drag_controller.cpp @@ -17,7 +17,6 @@ #include #include "display.h" -#include "display_manager_service_inner.h" #include "window_helper.h" #include "window_manager_hilog.h" #include "window_node.h" @@ -37,7 +36,11 @@ void DragController::UpdateDragInfo(uint32_t windowId) if (!GetHitPoint(windowId, point)) { return; } - sptr hitWindowNode = GetHitWindow(point); + sptr dragNode = windowRoot_->GetWindowNode(windowId); + if (dragNode == nullptr) { + return; + } + sptr hitWindowNode = GetHitWindow(dragNode->GetDisplayId(), point); if (hitWindowNode == nullptr) { WLOGFE("Get point failed %{public}d %{public}d", point.x, point.y); return; @@ -61,7 +64,11 @@ void DragController::StartDrag(uint32_t windowId) WLOGFE("Get hit point failed"); return; } - sptr hitWindow = GetHitWindow(point); + sptr dragNode = windowRoot_->GetWindowNode(windowId); + if (dragNode == nullptr) { + return; + } + sptr hitWindow = GetHitWindow(dragNode->GetDisplayId(), point); if (hitWindow == nullptr) { WLOGFE("Get point failed %{public}d %{public}d", point.x, point.y); return; @@ -92,15 +99,13 @@ void DragController::FinishDrag(uint32_t windowId) WLOGFI("end drag"); } -sptr DragController::GetHitWindow(PointInfo point) +sptr DragController::GetHitWindow(DisplayId id, PointInfo point) { // TODO get display by point - DisplayId id = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); if (id == DISPLAY_ID_INVALD) { - WLOGFE("get invalid display"); + WLOGFE("Get invalid display"); return nullptr; } - sptr container = windowRoot_->GetOrCreateWindowNodeContainer(id); if (container == nullptr) { WLOGFE("get container failed %{public}" PRIu64"", id); From ecb008b6b65a53799ce18a3b370856d90320b6e4 Mon Sep 17 00:00:00 2001 From: qianlf Date: Thu, 17 Feb 2022 19:42:23 +0800 Subject: [PATCH 05/70] Change launcher window type Signed-off-by: qianlf Change-Id: I48e49474da23cbd9dfc1cb10203fb5d85e97f138 --- wm/src/window_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index c8036c84..db2f37da 100644 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -594,7 +594,7 @@ WMError WindowImpl::Show() if (!IsWindowValid()) { return WMError::WM_ERROR_INVALID_WINDOW; } - if (state_ == WindowState::STATE_SHOWN && property_->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) { + if (state_ == WindowState::STATE_SHOWN && property_->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { WLOGFI("Minimize all app windows"); SingletonContainer::Get().MinimizeAllAppWindows(property_->GetDisplayId()); for (auto& listener : lifecycleListeners_) { From 4c0a86c62daa2eb321fda8436d8daf6b5efe9fb6 Mon Sep 17 00:00:00 2001 From: jincanran Date: Thu, 17 Feb 2022 19:52:59 +0800 Subject: [PATCH 06/70] add notify when systembar callback register Signed-off-by: jincanran Change-Id: Ifbfd14a5be843de84a6e75ffe8a6a073479e908c --- wmserver/include/window_controller.h | 1 + wmserver/include/window_node_container.h | 1 + wmserver/include/window_root.h | 1 + wmserver/src/window_controller.cpp | 5 +++++ wmserver/src/window_layout_policy.cpp | 2 ++ wmserver/src/window_manager_service.cpp | 3 +++ wmserver/src/window_node_container.cpp | 24 ++++++++++++++++++++---- wmserver/src/window_root.cpp | 10 ++++++++++ 8 files changed, 43 insertions(+), 4 deletions(-) diff --git a/wmserver/include/window_controller.h b/wmserver/include/window_controller.h index 79e3d2c6..a61f8727 100644 --- a/wmserver/include/window_controller.h +++ b/wmserver/include/window_controller.h @@ -50,6 +50,7 @@ public: WMError ProcessWindowTouchedEvent(uint32_t windowId); void MinimizeAllAppWindows(DisplayId displayId); WMError SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mode); + void NotifySystemBarTints(); private: uint32_t GenWindowId(); diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index a9f487e9..52aa0985 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -56,6 +56,7 @@ public: sptr GetNextFocusableWindow(uint32_t windowId) const; void MinimizeAllAppWindows(); void NotifyWindowStateChange(WindowState state, WindowStateChangeReason reason); + void NotifySystemBarTints(); WMError MinimizeAppNodeExceptOptions(const std::vector &exceptionalIds = {}, const std::vector &exceptionalModes = {}); WMError EnterSplitWindowMode(sptr& node); diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index ac5777b0..4cd0b5f3 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -60,6 +60,7 @@ public: void NotifyWindowStateChange(WindowState state, WindowStateChangeReason reason); void NotifyDisplayChange(sptr abstractDisplay); void NotifyDisplayDestory(DisplayId displayId); + void NotifySystemBarTints(); WMError RaiseZOrderForAppWindow(sptr& node); private: diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index 7e91d7c1..357c1a6e 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -359,6 +359,11 @@ WMError WindowController::SetSystemBarProperty(uint32_t windowId, WindowType typ return res; } +void WindowController::NotifySystemBarTints() +{ + windowRoot_->NotifySystemBarTints(); +} + std::vector WindowController::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) { std::vector avoidArea = windowRoot_->GetAvoidAreaByType(windowId, avoidAreaType); diff --git a/wmserver/src/window_layout_policy.cpp b/wmserver/src/window_layout_policy.cpp index 71d588d8..8fa8cdd5 100644 --- a/wmserver/src/window_layout_policy.cpp +++ b/wmserver/src/window_layout_policy.cpp @@ -140,6 +140,8 @@ void WindowLayoutPolicy::RemoveWindowNode(sptr& node) } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode LayoutWindowTree(); } + Rect winRect = node->GetWindowProperty()->GetWindowRect(); + node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); } void WindowLayoutPolicy::UpdateWindowNode(sptr& node) diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index 1d9a9af0..28940a50 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -249,6 +249,9 @@ void WindowManagerService::RegisterWindowManagerAgent(WindowManagerAgentType typ } std::lock_guard lock(mutex_); WindowManagerAgentController::GetInstance().RegisterWindowManagerAgent(windowManagerAgent, type); + if (type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR) { // if system bar, notify once + windowController_->NotifySystemBarTints(); + } } void WindowManagerService::UnregisterWindowManagerAgent(WindowManagerAgentType type, diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 4c965e7b..a2fc0c82 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -143,10 +143,8 @@ WMError WindowNodeContainer::UpdateWindowNode(sptr& node, WindowUpda WLOGFE("surface node is nullptr!"); return WMError::WM_ERROR_NULLPTR; } - if (layoutMode_ == WindowLayoutMode::TILE) { - if (WindowHelper::IsMainWindow(node->GetWindowType()) && reason != WindowUpdateReason::UPDATE_OTHER_PROPS) { - SwitchLayoutPolicy(WindowLayoutMode::CASCADE); - } + if (WindowHelper::IsMainWindow(node->GetWindowType()) && reason != WindowUpdateReason::UPDATE_OTHER_PROPS) { + SwitchLayoutPolicy(WindowLayoutMode::CASCADE); } layoutPolicy_->UpdateWindowNode(node); if (avoidController_->IsAvoidAreaNode(node)) { @@ -475,6 +473,24 @@ void WindowNodeContainer::NotifyIfSystemBarRegionChanged() WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId_, tints); } +void WindowNodeContainer::NotifySystemBarTints() +{ + WM_FUNCTION_TRACE(); + SystemBarRegionTints tints; + for (auto it : sysBarTintMap_) { + WLOGFD("system bar cur notify, type: %{public}d, " \ + "visible: %{public}d, color: %{public}x | %{public}x, " \ + "region: [%{public}d, %{public}d, %{public}d, %{public}d]", + static_cast(it.first), + sysBarTintMap_[it.first].region_.posX_, sysBarTintMap_[it.first].region_.posY_, + sysBarTintMap_[it.first].region_.width_, sysBarTintMap_[it.first].region_.height_, + sysBarTintMap_[it.first].prop_.enable_, + sysBarTintMap_[it.first].prop_.backgroundColor_, sysBarTintMap_[it.first].prop_.contentColor_); + tints.push_back(sysBarTintMap_[it.first]); + } + WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId_, tints); +} + bool WindowNodeContainer::IsTopAppWindow(uint32_t windowId) const { if (appWindowNode_->children_.empty()) { diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index 0edede25..54d6af29 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -391,6 +391,16 @@ void WindowRoot::NotifyDisplayChange(sptr abstractDisplay) container->UpdateDisplayRect(abstractDisplay->GetWidth(), abstractDisplay->GetHeight()); } +void WindowRoot::NotifySystemBarTints() +{ + WLOGFD("notify current system bar tints"); + for (auto& it : windowNodeContainerMap_) { + if (it.second != nullptr) { + it.second->NotifySystemBarTints(); + } + } +} + WMError WindowRoot::RaiseZOrderForAppWindow(sptr& node) { if (node == nullptr) { From ae8e51c6956ba2c9a8251f8bb59790375ebdddc7 Mon Sep 17 00:00:00 2001 From: wangxinpeng Date: Thu, 17 Feb 2022 16:21:58 +0800 Subject: [PATCH 07/70] update screen info to IMS Signed-off-by: wangxinpeng Change-Id: Id5dad11922237bba6a724bab7bad388746c12aec --- .../include/display_manager_service_inner.h | 1 + dmserver/src/display_manager_service_inner.cpp | 17 +++++++++++++++++ wmserver/src/input_window_monitor.cpp | 17 +++++++++++------ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/dmserver/include/display_manager_service_inner.h b/dmserver/include/display_manager_service_inner.h index 1540ffde..c16ec7a2 100644 --- a/dmserver/include/display_manager_service_inner.h +++ b/dmserver/include/display_manager_service_inner.h @@ -37,6 +37,7 @@ public: ScreenId GetRSScreenId(DisplayId displayId) const; const sptr GetScreenInfoByDisplayId(DisplayId displayId) const; const sptr GetScreenByDisplayId(DisplayId); + const sptr GetScreenModesByDisplayId(DisplayId displayId); void UpdateRSTree(DisplayId displayId, std::shared_ptr& surfaceNode, bool isAdd); void RegisterDisplayChangeListener(sptr listener); }; diff --git a/dmserver/src/display_manager_service_inner.cpp b/dmserver/src/display_manager_service_inner.cpp index a53ccf8a..edaaa5cd 100644 --- a/dmserver/src/display_manager_service_inner.cpp +++ b/dmserver/src/display_manager_service_inner.cpp @@ -92,6 +92,23 @@ const sptr DisplayManagerServiceInner::GetScreenInfoByDisplayId(Disp DisplayManagerService::GetInstance().GetScreenIdByDisplayId(displayId)); } +const sptr DisplayManagerServiceInner::GetScreenModesByDisplayId(DisplayId displayId) +{ + const sptr display = GetDisplayById(displayId); + if (display == nullptr) { + WLOGFE("can not get display."); + return nullptr; + } + ScreenId dmsScreenId = display->GetAbstractScreenId(); + sptr abstractScreen = + DisplayManagerService::GetInstance().abstractScreenController_->GetAbstractScreen(dmsScreenId); + if (abstractScreen == nullptr) { + WLOGFE("can not get screenMode."); + return nullptr; + } + return abstractScreen->GetActiveScreenMode(); +} + void DisplayManagerServiceInner::RegisterDisplayChangeListener(sptr listener) { DisplayManagerService::GetInstance().RegisterDisplayChangeListener(listener); diff --git a/wmserver/src/input_window_monitor.cpp b/wmserver/src/input_window_monitor.cpp index 4b921aa4..f8ad19ac 100644 --- a/wmserver/src/input_window_monitor.cpp +++ b/wmserver/src/input_window_monitor.cpp @@ -79,19 +79,24 @@ void InputWindowMonitor::UpdateInputWindowByDisplayId(DisplayId displayId) void InputWindowMonitor::UpdateDisplaysInfo(const sptr& container, DisplayId displayId) { + sptr screenMode = + DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(displayId); + if (screenMode == nullptr) { + return; + } MMI::PhysicalDisplayInfo physicalDisplayInfo = { .id = static_cast(container->GetScreenId()), .leftDisplayId = static_cast(DISPLAY_ID_INVALD), .upDisplayId = static_cast(DISPLAY_ID_INVALD), - .topLeftX = container->GetDisplayRect().posX_, - .topLeftY = container->GetDisplayRect().posY_, - .width = static_cast(container->GetDisplayRect().width_), - .height = static_cast(container->GetDisplayRect().height_), + .topLeftX = 0, + .topLeftY = 0, + .width = static_cast(screenMode->width_), + .height = static_cast(screenMode->height_), .name = "physical_display0", .seatId = "seat0", .seatName = "default0", - .logicWidth = static_cast(container->GetDisplayRect().width_), - .logicHeight = static_cast(container->GetDisplayRect().height_), + .logicWidth = static_cast(screenMode->width_), + .logicHeight = static_cast(screenMode->height_), }; UpdateDisplayDirection(physicalDisplayInfo, displayId); auto physicalDisplayIter = std::find_if(physicalDisplays_.begin(), physicalDisplays_.end(), From 8e05c7ec268d29b6cde89fc5548c7a39608ef8df Mon Sep 17 00:00:00 2001 From: Zhang Peng Date: Fri, 18 Feb 2022 11:47:21 +0800 Subject: [PATCH 08/70] add switch to temporary disable window open/close animation Signed-off-by: Zhang Peng Change-Id: I8b513e853f6bfd3630ef64e589e3f229e3430613 --- dmserver/src/abstract_screen.cpp | 19 +++----- wm/src/window_manager.cpp | 3 +- wmserver/include/window_node_container.h | 6 ++- wmserver/src/window_node_container.cpp | 57 ++++++++++++++++++------ 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/dmserver/src/abstract_screen.cpp b/dmserver/src/abstract_screen.cpp index 2c6d0581..fb124012 100644 --- a/dmserver/src/abstract_screen.cpp +++ b/dmserver/src/abstract_screen.cpp @@ -68,18 +68,11 @@ void AbstractScreen::UpdateRSTree(std::shared_ptr& surfaceNode, b } WLOGFI("AbstractScreen::UpdateRSTree"); - // default duration 350ms - static const RSAnimationTimingProtocol timingProtocol(350); - // default curve EASE OUT - static const Rosen::RSAnimationTimingCurve curve = Rosen::RSAnimationTimingCurve::EASE_OUT; - // add or remove window with transition animation - RSNode::Animate(timingProtocol, curve, [=]() { - if (isAdd) { - rsDisplayNode_->AddChild(surfaceNode, -1); - } else { - rsDisplayNode_->RemoveChild(surfaceNode); - } - }); + if (isAdd) { + rsDisplayNode_->AddChild(surfaceNode, -1); + } else { + rsDisplayNode_->RemoveChild(surfaceNode); + } } void AbstractScreen::InitRSDisplayNode(RSDisplayNodeConfig& config) @@ -347,4 +340,4 @@ size_t AbstractScreenGroup::GetChildCount() const { return abstractScreenMap_.size(); } -} // namespace OHOS::Rosen \ No newline at end of file +} // namespace OHOS::Rosen diff --git a/wm/src/window_manager.cpp b/wm/src/window_manager.cpp index b2ab5c63..73e2610d 100644 --- a/wm/src/window_manager.cpp +++ b/wm/src/window_manager.cpp @@ -14,6 +14,7 @@ */ #include "foundation/windowmanager/interfaces/innerkits/wm/window_manager.h" + #include #include @@ -278,4 +279,4 @@ void WindowManager::UpdateWindowStatus(const sptr& windowInfo, Windo pImpl_->NotifyWindowUpdate(windowInfo, type); } } // namespace Rosen -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 52aa0985..e345ecaf 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -122,7 +122,9 @@ private: std::unordered_map pairedWindowMap_; void RaiseInputMethodWindowPriorityIfNeeded(const sptr& node) const; const int32_t WINDOW_TYPE_RAISED_INPUT_METHOD = 115; + + static bool ReadIsWindowAnimationEnabledProperty(); }; -} -} +} // namespace Rosen +} // namespace OHOS #endif // OHOS_ROSEN_WINDOW_NODE_CONTAINER_H diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index a2fc0c82..b247eb22 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -15,21 +15,21 @@ #include "window_node_container.h" -#include #include +#include #include +#include "common_event_manager.h" #include "display_manager_service_inner.h" #include "dm_common.h" #include "window_helper.h" +#include "window_inner_manager.h" #include "window_layout_policy_cascade.h" #include "window_layout_policy_tile.h" #include "window_manager_agent_controller.h" -#include "window_inner_manager.h" #include "window_manager_hilog.h" #include "wm_common.h" #include "wm_trace.h" -#include "common_event_manager.h" namespace OHOS { namespace Rosen { @@ -177,19 +177,38 @@ void WindowNodeContainer::UpdateWindowTree(sptr& node) bool WindowNodeContainer::UpdateRSTree(sptr& node, bool isAdd) { WM_FUNCTION_TRACE(); - if (isAdd) { - DisplayManagerServiceInner::GetInstance().UpdateRSTree(displayId_, node->surfaceNode_, true); - for (auto& child : node->children_) { - if (child->currentVisibility_) { - DisplayManagerServiceInner::GetInstance().UpdateRSTree(displayId_, child->surfaceNode_, true); + static const bool IsWindowAnimationEnabled = ReadIsWindowAnimationEnabledProperty(); + + auto updateRSTreeFunc = [&]() { + auto& dms = DisplayManagerServiceInner::GetInstance(); + if (isAdd) { + dms.UpdateRSTree(displayId_, node->surfaceNode_, true); + for (auto& child : node->children_) { + if (child->currentVisibility_) { + dms.UpdateRSTree(displayId_, child->surfaceNode_, true); + } + } + } else { + dms.UpdateRSTree(displayId_, node->surfaceNode_, false); + for (auto& child : node->children_) { + dms.UpdateRSTree(displayId_, child->surfaceNode_, false); } } + }; + + if (IsWindowAnimationEnabled) { + // default transition duration: 350ms + static const RSAnimationTimingProtocol timingProtocol(350); + // default transition curve: EASE OUT + static const Rosen::RSAnimationTimingCurve curve = Rosen::RSAnimationTimingCurve::EASE_OUT; + + // add or remove window with transition animation + RSNode::Animate(timingProtocol, curve, updateRSTreeFunc); } else { - DisplayManagerServiceInner::GetInstance().UpdateRSTree(displayId_, node->surfaceNode_, false); - for (auto& child : node->children_) { - DisplayManagerServiceInner::GetInstance().UpdateRSTree(displayId_, child->surfaceNode_, false); - } + // add or remove window without animation + updateRSTreeFunc(); } + return true; } @@ -1041,5 +1060,17 @@ sptr WindowNodeContainer::GetAboveAppWindowNode() const { return aboveAppWindowNode_; } + +namespace { + const char DISABLE_WINDOW_ANIMATION_PATH[] = "/etc/disable_window_animation"; } -} \ No newline at end of file + +bool WindowNodeContainer::ReadIsWindowAnimationEnabledProperty() +{ + if (access(DISABLE_WINDOW_ANIMATION_PATH, F_OK) == 0) { + return false; + } + return true; +} +} // namespace Rosen +} // namespace OHOS From 21b77cdd68df320f89a2654b55cd821bc1f830de Mon Sep 17 00:00:00 2001 From: lu Date: Fri, 18 Feb 2022 12:10:56 +0800 Subject: [PATCH 09/70] Fix deadlock when rotate a screen Signed-off-by: lu Change-Id: I3c2dc087c8bc593ac963797d7e3b967ce33a94a2 --- .../include/display_manager_service_inner.h | 1 - dmserver/src/abstract_display_controller.cpp | 52 ++++++++++--------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/dmserver/include/display_manager_service_inner.h b/dmserver/include/display_manager_service_inner.h index c16ec7a2..5558e6ff 100644 --- a/dmserver/include/display_manager_service_inner.h +++ b/dmserver/include/display_manager_service_inner.h @@ -36,7 +36,6 @@ public: std::vector GetAllDisplayIds(); ScreenId GetRSScreenId(DisplayId displayId) const; const sptr GetScreenInfoByDisplayId(DisplayId displayId) const; - const sptr GetScreenByDisplayId(DisplayId); const sptr GetScreenModesByDisplayId(DisplayId displayId); void UpdateRSTree(DisplayId displayId, std::shared_ptr& surfaceNode, bool isAdd); void RegisterDisplayChangeListener(sptr listener); diff --git a/dmserver/src/abstract_display_controller.cpp b/dmserver/src/abstract_display_controller.cpp index aa9899e8..0eb33c2f 100644 --- a/dmserver/src/abstract_display_controller.cpp +++ b/dmserver/src/abstract_display_controller.cpp @@ -211,35 +211,37 @@ void AbstractDisplayController::OnAbstractScreenChange(sptr absS void AbstractDisplayController::ProcessDisplayUpdateRotation(sptr absScreen) { sptr abstractDisplay = nullptr; - std::lock_guard lock(mutex_); - auto iter = abstractDisplayMap_.begin(); - for (; iter != abstractDisplayMap_.end(); iter++) { - abstractDisplay = iter->second; - if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) { - WLOGFD("find abstract display of the screen. display %{public}" PRIu64", screen %{public}" PRIu64"", - abstractDisplay->GetId(), absScreen->dmsId_); - break; + { + std::lock_guard lock(mutex_); + auto iter = abstractDisplayMap_.begin(); + for (; iter != abstractDisplayMap_.end(); iter++) { + abstractDisplay = iter->second; + if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) { + WLOGFD("find abstract display of the screen. display %{public}" PRIu64", screen %{public}" PRIu64"", + abstractDisplay->GetId(), absScreen->dmsId_); + break; + } } - } - sptr group = absScreen->GetGroup(); - if (group == nullptr) { - WLOGFE("cannot get screen group"); - return; - } - if (iter == abstractDisplayMap_.end()) { - if (group->combination_ == ScreenCombination::SCREEN_ALONE - || group->combination_ == ScreenCombination::SCREEN_EXPAND) { - WLOGFE("cannot find abstract display of the screen %{public}" PRIu64"", absScreen->dmsId_); - return; - } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) { - // If the 'absScreen' cannot be found in 'abstractDisplayMap_', it means that the screen is the secondary. - WLOGFI("It's the secondary screen of the mirrored."); - return; - } else { - WLOGFE("Unknow combination"); + sptr group = absScreen->GetGroup(); + if (group == nullptr) { + WLOGFE("cannot get screen group"); return; } + if (iter == abstractDisplayMap_.end()) { + if (group->combination_ == ScreenCombination::SCREEN_ALONE + || group->combination_ == ScreenCombination::SCREEN_EXPAND) { + WLOGFE("cannot find abstract display of the screen %{public}" PRIu64"", absScreen->dmsId_); + return; + } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) { + // If the screen cannot be found in 'abstractDisplayMap_', it means that the screen is the secondary + WLOGFI("It's the secondary screen of the mirrored."); + return; + } else { + WLOGFE("Unknow combination"); + return; + } + } } if (abstractDisplay->RequestRotation(absScreen->rotation_)) { // Notify rotation event to WMS From 7851c1b8c65b53417165c26626447c72ac305f3a Mon Sep 17 00:00:00 2001 From: fanby01 Date: Mon, 14 Feb 2022 18:37:58 +0800 Subject: [PATCH 10/70] support colorgamut for wms, adapter to render service. Change-Id: I915e7d4f5651667023a6e97ffc8c4d6d4a6f196a Signed-off-by: fanby01 --- wm/test/systemtest/window_gamut_test.cpp | 4 ++ wm/test/unittest/mock_window_adapter.h | 3 ++ wm/test/unittest/window_impl_test.cpp | 57 ++++++++++++++++++++++++ wmserver/include/window_controller.h | 5 +++ wmserver/include/window_node.h | 14 ++++++ wmserver/src/window_controller.cpp | 33 +++++++++++++- wmserver/src/window_manager_proxy.cpp | 2 +- wmserver/src/window_manager_service.cpp | 13 ++++-- wmserver/src/window_node.cpp | 43 ++++++++++++++++++ 9 files changed, 169 insertions(+), 5 deletions(-) diff --git a/wm/test/systemtest/window_gamut_test.cpp b/wm/test/systemtest/window_gamut_test.cpp index 2d94f4d9..bfdb6de5 100644 --- a/wm/test/systemtest/window_gamut_test.cpp +++ b/wm/test/systemtest/window_gamut_test.cpp @@ -83,6 +83,10 @@ HWTEST_F(WindowGamutTest, SetGetColorSpace01, Function | MediumTest | Level3) const sptr& window = utils::CreateTestWindow(fullScreenAppInfo_); window->SetColorSpace(ColorSpace::COLOR_SPACE_DEFAULT); + window->SetColorSpace(ColorSpace::COLOR_SPACE_WIDE_GAMUT); + ColorSpace invalidColorSpace = + static_cast(static_cast(ColorSpace::COLOR_SPACE_WIDE_GAMUT) + 1); + window->SetColorSpace(invalidColorSpace); // invalid param ASSERT_EQ(ColorSpace::COLOR_SPACE_DEFAULT, window->GetColorSpace()); window->Destroy(); diff --git a/wm/test/unittest/mock_window_adapter.h b/wm/test/unittest/mock_window_adapter.h index 3535378f..61d225ef 100644 --- a/wm/test/unittest/mock_window_adapter.h +++ b/wm/test/unittest/mock_window_adapter.h @@ -33,6 +33,9 @@ public: MOCK_METHOD2(SetAlpha, WMError(uint32_t windowId, float alpha)); MOCK_METHOD2(SaveAbilityToken, WMError(const sptr& abilityToken, uint32_t windowId)); MOCK_METHOD3(SetSystemBarProperty, WMError(uint32_t windowId, WindowType type, const SystemBarProperty& property)); + MOCK_METHOD1(IsSupportWideGamut, bool(uint32_t windowId)); + MOCK_METHOD2(SetColorSpace, void(uint32_t windowId, ColorSpace colorSpace)); + MOCK_METHOD1(GetColorSpace, ColorSpace(uint32_t windowId)); }; } } // namespace OHOS diff --git a/wm/test/unittest/window_impl_test.cpp b/wm/test/unittest/window_impl_test.cpp index 3d0a3725..4d24396f 100644 --- a/wm/test/unittest/window_impl_test.cpp +++ b/wm/test/unittest/window_impl_test.cpp @@ -718,6 +718,63 @@ HWTEST_F(WindowImplTest, Minimize02, Function | SmallTest | Level3) window->Minimize(); ASSERT_TRUE(window->GetShowState()); } + +/** + * @tc.name: IsSupportWideGamut01 + * @tc.desc: IsSupportWideGamut + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, IsSupportWideGamut01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("WindowImplTest_IsSupportWideGamut01"); + auto window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(""); + EXPECT_CALL(m->Mock(), IsSupportWideGamut(_)).Times(1).WillOnce(Return(true)); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + ASSERT_TRUE(window->IsSupportWideGamut()); +} + +/** + * @tc.name: SetColorSpace01 + * @tc.desc: SetColorSpace + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetColorSpace01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("WindowImplTest_SetColorSpace01"); + auto window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(""); + EXPECT_CALL(m->Mock(), SetColorSpace(_, _)).Times(1).WillOnce(Return()); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + window->SetColorSpace(ColorSpace::COLOR_SPACE_WIDE_GAMUT); +} + +/** + * @tc.name: GetColorSpace01 + * @tc.desc: GetColorSpace + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetColorSpace01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("WindowImplTest_GetColorSpace01"); + auto window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(""); + EXPECT_CALL(m->Mock(), GetColorSpace(_)).Times(1).WillOnce(Return(ColorSpace::COLOR_SPACE_WIDE_GAMUT)); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + ASSERT_EQ(ColorSpace::COLOR_SPACE_WIDE_GAMUT, window->GetColorSpace()); +} } } // namespace Rosen } // namespace OHOS diff --git a/wmserver/include/window_controller.h b/wmserver/include/window_controller.h index a61f8727..937975cc 100644 --- a/wmserver/include/window_controller.h +++ b/wmserver/include/window_controller.h @@ -52,6 +52,11 @@ public: WMError SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mode); void NotifySystemBarTints(); + // colorspace, gamut + bool IsSupportWideGamut(uint32_t windowId) const; + void SetColorSpace(uint32_t windowId, ColorSpace colorSpace); + ColorSpace GetColorSpace(uint32_t windowId) const; + private: uint32_t GenWindowId(); void FlushWindowInfo(uint32_t windowId); diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index 863b89eb..94eb7b26 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -68,6 +68,11 @@ public: bool IsSplitMode() const; WindowSizeChangeReason GetWindowSizeChangeReason() const; + // colorspace, gamut + bool IsSupportWideGamut() const; + void SetColorSpace(ColorSpace colorSpace); + ColorSpace GetColorSpace() const; + sptr parent_; std::vector> children_; std::shared_ptr surfaceNode_; @@ -78,6 +83,15 @@ public: bool hasDecorated_ = false; private: + // colorspace, gamut + using ColorSpaceConvertMap = struct { + ColorSpace colorSpace; + SurfaceColorGamut sufaceColorGamut; + }; + static const ColorSpaceConvertMap colorSpaceConvertMap[]; + static ColorSpace GetColorSpaceFromSurfaceGamut(SurfaceColorGamut surfaceColorGamut); + static SurfaceColorGamut GetSurfaceGamutFromColorSpace(ColorSpace colorSpace); + sptr property_; sptr windowToken_; Rect layoutRect_ { 0, 0, 0, 0 }; diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index 6300f04f..0dfa4844 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -17,6 +17,7 @@ #include #include "window_manager_hilog.h" #include "window_helper.h" +#include "wm_common.h" #include "wm_trace.h" namespace OHOS { @@ -274,7 +275,7 @@ void WindowController::ProcessDisplayChange(DisplayId displayId, DisplayStateCha WLOGFE("get display failed displayId:%{public}" PRId64 "", displayId); return; } - + switch (type) { case DisplayStateChangeType::UPDATE_ROTATION: { windowRoot_->NotifyDisplayChange(abstractDisplay); @@ -438,5 +439,35 @@ WMError WindowController::SetWindowLayoutMode(DisplayId displayId, WindowLayoutM FlushWindowInfoWithDisplayId(displayId); return res; } + +bool WindowController::IsSupportWideGamut(uint32_t windowId) const +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return false; + } + return node->IsSupportWideGamut(); +} + +void WindowController::SetColorSpace(uint32_t windowId, ColorSpace colorSpace) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return; + } + node->SetColorSpace(colorSpace); +} + +ColorSpace WindowController::GetColorSpace(uint32_t windowId) const +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return ColorSpace::COLOR_SPACE_DEFAULT; + } + return node->GetColorSpace(); +} } } \ No newline at end of file diff --git a/wmserver/src/window_manager_proxy.cpp b/wmserver/src/window_manager_proxy.cpp index ac2a8773..1a1b9509 100644 --- a/wmserver/src/window_manager_proxy.cpp +++ b/wmserver/src/window_manager_proxy.cpp @@ -518,7 +518,7 @@ void WindowManagerProxy::SetColorSpace(uint32_t windowId, ColorSpace colorSpace) { MessageParcel data; MessageParcel reply; - MessageOption option; + MessageOption option(MessageOption::TF_ASYNC); if (!data.WriteInterfaceToken(GetDescriptor())) { WLOGFE("WriteInterfaceToken failed"); return; diff --git a/wmserver/src/window_manager_service.cpp b/wmserver/src/window_manager_service.cpp index 28940a50..5fa115b9 100644 --- a/wmserver/src/window_manager_service.cpp +++ b/wmserver/src/window_manager_service.cpp @@ -303,19 +303,26 @@ void WindowManagerService::MinimizeAllAppWindows(DisplayId displayId) bool WindowManagerService::IsSupportWideGamut(uint32_t windowId) { - bool ret = true; - WLOGFI("IsSupportWideGamut %{public}d", ret); + WM_SCOPED_TRACE("wms:IsSupportWideGamut"); + std::lock_guard lock(mutex_); + bool ret = windowController_->IsSupportWideGamut(windowId); + WLOGFI("IsSupportWideGamut windowId %{public}u, ret %{public}d", windowId, ret); return ret; } void WindowManagerService::SetColorSpace(uint32_t windowId, ColorSpace colorSpace) { WLOGFI("SetColorSpace windowId %{public}u, ColorSpace %{public}u", windowId, colorSpace); + WM_SCOPED_TRACE("wms:SetColorSpace(%u)", colorSpace); + std::lock_guard lock(mutex_); + windowController_->SetColorSpace(windowId, colorSpace); } ColorSpace WindowManagerService::GetColorSpace(uint32_t windowId) { - ColorSpace colorSpace = ColorSpace::COLOR_SPACE_DEFAULT; + WM_SCOPED_TRACE("wms:GetColorSpace"); + std::lock_guard lock(mutex_); + ColorSpace colorSpace = windowController_->GetColorSpace(windowId); WLOGFI("GetColorSpace windowId %{public}u, ColorSpace %{public}u", windowId, colorSpace); return colorSpace; } diff --git a/wmserver/src/window_node.cpp b/wmserver/src/window_node.cpp index 44d6ef9d..e17a389e 100644 --- a/wmserver/src/window_node.cpp +++ b/wmserver/src/window_node.cpp @@ -22,6 +22,12 @@ namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "WindowNode"}; } + +const WindowNode::ColorSpaceConvertMap WindowNode::colorSpaceConvertMap[] = { + { ColorSpace::COLOR_SPACE_DEFAULT, COLOR_GAMUT_SRGB }, + { ColorSpace::COLOR_SPACE_WIDE_GAMUT, COLOR_GAMUT_DCI_P3 }, +}; + void WindowNode::SetDisplayId(DisplayId displayId) { property_->SetDisplayId(displayId); @@ -202,5 +208,42 @@ WindowSizeChangeReason WindowNode::GetWindowSizeChangeReason() const { return windowSizeChangeReason_; } + +ColorSpace WindowNode::GetColorSpaceFromSurfaceGamut(SurfaceColorGamut surfaceColorGamut) +{ + for (auto item: colorSpaceConvertMap) { + if (item.sufaceColorGamut == surfaceColorGamut) { + return item.colorSpace; + } + } + return ColorSpace::COLOR_SPACE_DEFAULT; +} + +SurfaceColorGamut WindowNode::GetSurfaceGamutFromColorSpace(ColorSpace colorSpace) +{ + for (auto item: colorSpaceConvertMap) { + if (item.colorSpace == colorSpace) { + return item.sufaceColorGamut; + } + } + return SurfaceColorGamut::COLOR_GAMUT_SRGB; +} + +bool WindowNode::IsSupportWideGamut() const +{ + return true; +} + +void WindowNode::SetColorSpace(ColorSpace colorSpace) +{ + auto surfaceGamut = GetSurfaceGamutFromColorSpace(colorSpace); + surfaceNode_->SetColorSpace(surfaceGamut); +} + +ColorSpace WindowNode::GetColorSpace() const +{ + auto surfaceGamut = surfaceNode_->GetColorSpace(); + return GetColorSpaceFromSurfaceGamut(surfaceGamut); +} } } From 983301f03291f3350484d8c1c639729592965542 Mon Sep 17 00:00:00 2001 From: huandong Date: Wed, 16 Feb 2022 22:01:05 +0800 Subject: [PATCH 11/70] =?UTF-8?q?=E5=A2=9E=E5=8A=A0VirtualPixelRatio,=20?= =?UTF-8?q?=E7=83=AD=E5=8C=BA=E8=AE=A1=E7=AE=97=E7=A7=BB=E5=8A=A8=E5=88=B0?= =?UTF-8?q?layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huandong Change-Id: If397c747352872bfc8dbbb3438745a56d82a419a --- interfaces/innerkits/wm/wm_common.h | 7 -- utils/include/window_helper.h | 14 ++-- utils/include/wm_common_inner.h | 12 ++++ wm/test/systemtest/window_layout_test.cpp | 14 ++-- wm/test/systemtest/window_move_drag_test.cpp | 62 ++++++++-------- wm/test/systemtest/window_test_utils.cpp | 48 +++++++++---- wm/test/systemtest/window_test_utils.h | 5 +- wmserver/BUILD.gn | 1 + wmserver/include/window_layout_policy.h | 2 + wmserver/include/window_node.h | 2 + wmserver/include/window_node_container.h | 1 + wmserver/include/window_root.h | 1 + wmserver/src/window_controller.cpp | 7 +- wmserver/src/window_layout_policy.cpp | 71 ++++++++++++++++--- wmserver/src/window_layout_policy_cascade.cpp | 33 +++++---- wmserver/src/window_layout_policy_tile.cpp | 2 + wmserver/src/window_node.cpp | 23 ++---- wmserver/src/window_node_container.cpp | 6 ++ wmserver/src/window_root.cpp | 6 ++ 19 files changed, 215 insertions(+), 102 deletions(-) diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 6a866ded..70058ca9 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -138,14 +138,7 @@ struct PointInfo { namespace { constexpr uint32_t SYSTEM_COLOR_WHITE = 0xE5FFFFFF; constexpr uint32_t SYSTEM_COLOR_BLACK = 0x66000000; - constexpr float DEFAULT_SPLIT_RATIO = 0.5; - constexpr uint32_t DIVIDER_WIDTH = 8; constexpr uint32_t INVALID_WINDOW_ID = 0; - constexpr uint32_t HOTZONE = 40; - constexpr uint32_t MIN_VERTICAL_FLOATING_WIDTH = 240; - constexpr uint32_t MIN_VERTICAL_FLOATING_HEIGHT = 426; - constexpr uint32_t MIN_VERTICAL_SPLIT_HEIGHT = 426; - constexpr uint32_t MIN_HORIZONTAL_SPLIT_WIDTH = 426; } struct SystemBarProperty { diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index f521d3be..9e822ae0 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -17,6 +17,7 @@ #define OHOS_WM_INCLUDE_WM_HELPER_H #include +#include namespace OHOS { namespace Rosen { @@ -79,15 +80,18 @@ public: return (r.posX_ == 0 && r.posY_ == 0 && r.width_ == 0 && r.height_ == 0); } - static Rect GetFixedWindowRectByMinRect(const Rect& oriDstRect, const Rect& lastRect, bool isVertical) + static Rect GetFixedWindowRectByMinRect(const Rect& oriDstRect, const Rect& lastRect, bool isVertical, + float virtualPixelRatio) { + uint32_t minVerticalFloatingW = static_cast(MIN_VERTICAL_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minVerticalFloatingH = static_cast(MIN_VERTICAL_FLOATING_HEIGHT * virtualPixelRatio); Rect dstRect = oriDstRect; if (isVertical) { - dstRect.width_ = std::max(MIN_VERTICAL_FLOATING_WIDTH, oriDstRect.width_); - dstRect.height_ = std::max(MIN_VERTICAL_FLOATING_HEIGHT, oriDstRect.height_); + dstRect.width_ = std::max(minVerticalFloatingW, oriDstRect.width_); + dstRect.height_ = std::max(minVerticalFloatingH, oriDstRect.height_); } else { - dstRect.width_ = std::max(MIN_VERTICAL_FLOATING_HEIGHT, oriDstRect.width_); - dstRect.height_ = std::max(MIN_VERTICAL_FLOATING_WIDTH, oriDstRect.height_); + dstRect.width_ = std::max(minVerticalFloatingH, oriDstRect.width_); + dstRect.height_ = std::max(minVerticalFloatingW, oriDstRect.height_); } // limit position by fixed width or height diff --git a/utils/include/wm_common_inner.h b/utils/include/wm_common_inner.h index fda04fe8..369fd40d 100644 --- a/utils/include/wm_common_inner.h +++ b/utils/include/wm_common_inner.h @@ -44,6 +44,18 @@ enum class WindowUpdateReason : uint32_t { UPDATE_TYPE, UPDATE_OTHER_PROPS, }; +namespace { + constexpr float DEFAULT_SPLIT_RATIO = 0.5; + constexpr uint32_t DIVIDER_WIDTH = 8; + constexpr uint32_t WINDOW_TITLE_BAR_HEIGHT = 48; + constexpr uint32_t WINDOW_FRAME_WIDTH = 4; + constexpr uint32_t HOTZONE = 40; + constexpr uint32_t DIV_HOTZONE = 20; + constexpr uint32_t MIN_VERTICAL_FLOATING_WIDTH = 240; + constexpr uint32_t MIN_VERTICAL_FLOATING_HEIGHT = 426; + constexpr uint32_t MIN_VERTICAL_SPLIT_HEIGHT = 426; + constexpr uint32_t MIN_HORIZONTAL_SPLIT_WIDTH = 426; +} } } #endif // OHOS_ROSEN_WM_COMMON_INNER_H \ No newline at end of file diff --git a/wm/test/systemtest/window_layout_test.cpp b/wm/test/systemtest/window_layout_test.cpp index 9b5b381e..6bb5c15a 100644 --- a/wm/test/systemtest/window_layout_test.cpp +++ b/wm/test/systemtest/window_layout_test.cpp @@ -32,6 +32,7 @@ public: DisplayId displayId_ = 0; std::vector> activeWindows_; static vector fullScreenExpecteds_; + static inline float virtualPixelRatio_ = 0.0; }; vector WindowLayoutTest::fullScreenExpecteds_; @@ -47,6 +48,9 @@ void WindowLayoutTest::SetUpTestCase() } Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; utils::InitByDisplayRect(displayRect); + + virtualPixelRatio_ = WindowTestUtils::GetVirtualPixelRatio(0); + // calc expected rects Rect expected = { // 0. only statusBar 0, @@ -110,7 +114,7 @@ HWTEST_F(WindowLayoutTest, LayoutWindow02, Function | MediumTest | Level3) activeWindows_.push_back(window); ASSERT_EQ(WMError::WM_OK, window->Show()); - ASSERT_TRUE(utils::RectEqualTo(window, utils::GetFloatingLimitedRect(utils::customAppRect_))); + ASSERT_TRUE(utils::RectEqualTo(window, utils::GetFloatingLimitedRect(utils::customAppRect_, virtualPixelRatio_))); ASSERT_EQ(WMError::WM_OK, window->Hide()); } @@ -140,12 +144,12 @@ HWTEST_F(WindowLayoutTest, LayoutWindow04, Function | MediumTest | Level3) activeWindows_.push_back(statBar); ASSERT_EQ(WMError::WM_OK, appWin->Show()); - ASSERT_TRUE(utils::RectEqualTo(appWin, utils::GetFloatingLimitedRect(utils::customAppRect_))); + ASSERT_TRUE(utils::RectEqualTo(appWin, utils::GetFloatingLimitedRect(utils::customAppRect_, virtualPixelRatio_))); ASSERT_EQ(WMError::WM_OK, statBar->Show()); - ASSERT_TRUE(utils::RectEqualTo(appWin, utils::GetFloatingLimitedRect(utils::customAppRect_))); + ASSERT_TRUE(utils::RectEqualTo(appWin, utils::GetFloatingLimitedRect(utils::customAppRect_, virtualPixelRatio_))); ASSERT_TRUE(utils::RectEqualTo(statBar, utils::statusBarRect_)); ASSERT_EQ(WMError::WM_OK, statBar->Hide()); - ASSERT_TRUE(utils::RectEqualTo(appWin, utils::GetFloatingLimitedRect(utils::customAppRect_))); + ASSERT_TRUE(utils::RectEqualTo(appWin, utils::GetFloatingLimitedRect(utils::customAppRect_, virtualPixelRatio_))); } /** @@ -277,7 +281,7 @@ HWTEST_F(WindowLayoutTest, LayoutWindow09, Function | MediumTest | Level3) ASSERT_EQ(WMError::WM_OK, window->Resize(2u, 2u)); // 2: custom min size Rect finalExcept = { expect.posX_, expect.posY_, 2u, 2u}; // 2: custom min size - finalExcept = utils::GetFloatingLimitedRect(finalExcept); + finalExcept = utils::GetFloatingLimitedRect(finalExcept, virtualPixelRatio_); ASSERT_TRUE(utils::RectEqualTo(window, finalExcept)); ASSERT_EQ(WMError::WM_OK, window->Hide()); } diff --git a/wm/test/systemtest/window_move_drag_test.cpp b/wm/test/systemtest/window_move_drag_test.cpp index 38783803..fc033776 100644 --- a/wm/test/systemtest/window_move_drag_test.cpp +++ b/wm/test/systemtest/window_move_drag_test.cpp @@ -18,6 +18,7 @@ #include "pointer_event.h" #include "window_helper.h" #include "window_test_utils.h" +#include "wm_common_inner.h" using namespace testing; using namespace testing::ext; @@ -54,6 +55,8 @@ private: static inline Rect startPointRect_ = {0, 0, 0, 0}; static inline Rect expectRect_ = {0, 0, 0, 0}; static inline sptr window_ = nullptr; + static inline float virtualPixelRatio_ = 0.0; + static inline uint32_t hotZone_ = 0; }; void WindowMoveDragTest::SetUpTestCase() @@ -83,6 +86,9 @@ void WindowMoveDragTest::SetUp() Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; utils::InitByDisplayRect(displayRect); + virtualPixelRatio_ = WindowTestUtils::GetVirtualPixelRatio(0); + hotZone_ = static_cast(HOTZONE * virtualPixelRatio_); + winInfo_ = { .name = "Floating", .rect = {0, 0, 0, 0}, @@ -174,7 +180,7 @@ void WindowMoveDragTest::CalExpectRects() } } bool isVertical = (utils::displayRect_.width_ < utils::displayRect_.height_) ? true : false; - expectRect_ = WindowHelper::GetFixedWindowRectByMinRect(oriRect, startPointRect_, isVertical); + expectRect_ = WindowHelper::GetFixedWindowRectByMinRect(oriRect, startPointRect_, isVertical, virtualPixelRatio_); } namespace { @@ -188,10 +194,10 @@ HWTEST_F(WindowMoveDragTest, DragWindow01, Function | MediumTest | Level3) { ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); - startPointX_ = startPointRect_.posX_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointX_ = startPointRect_.posX_ - hotZone_ * POINT_HOTZONE_RATIO; startPointY_ = startPointRect_.posY_ + startPointRect_.height_ * POINT_HOTZONE_RATIO; - pointX_ = startPointRect_.posX_ + HOTZONE * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + hotZone_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -206,11 +212,11 @@ HWTEST_F(WindowMoveDragTest, DragWindow02, Function | MediumTest | Level3) { ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); - startPointX_ = startPointRect_.posX_ - HOTZONE * POINT_HOTZONE_RATIO; - startPointY_ = startPointRect_.posY_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointX_ = startPointRect_.posX_ - hotZone_ * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ - hotZone_ * POINT_HOTZONE_RATIO; - pointX_ = startPointRect_.posX_ + HOTZONE * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + hotZone_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -225,11 +231,11 @@ HWTEST_F(WindowMoveDragTest, DragWindow03, Function | MediumTest | Level3) { ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); - startPointX_ = startPointRect_.posX_ - HOTZONE * POINT_HOTZONE_RATIO; - startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointX_ = startPointRect_.posX_ - hotZone_ * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * POINT_HOTZONE_RATIO; - pointX_ = startPointRect_.posX_ + HOTZONE * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + hotZone_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -244,10 +250,10 @@ HWTEST_F(WindowMoveDragTest, DragWindow04, Function | MediumTest | Level3) { ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); - startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + hotZone_ * POINT_HOTZONE_RATIO; startPointY_ = startPointRect_.posY_ + startPointRect_.height_ * POINT_HOTZONE_RATIO; - pointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + startPointRect_.width_ + hotZone_ * DRAG_HOTZONE_RATIO; pointY_ = startPointRect_.posY_ + startPointRect_.height_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); @@ -263,11 +269,11 @@ HWTEST_F(WindowMoveDragTest, DragWindow05, Function | MediumTest | Level3) { ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); - startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * POINT_HOTZONE_RATIO; - startPointY_ = startPointRect_.posY_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + hotZone_ * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ - hotZone_ * POINT_HOTZONE_RATIO; - pointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + startPointRect_.width_ + hotZone_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -282,11 +288,11 @@ HWTEST_F(WindowMoveDragTest, DragWindow06, Function | MediumTest | Level3) { ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); - startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * POINT_HOTZONE_RATIO; - startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointX_ = startPointRect_.posX_ + startPointRect_.width_ + hotZone_ * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * POINT_HOTZONE_RATIO; - pointX_ = startPointRect_.posX_ + startPointRect_.width_ + HOTZONE * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointX_ = startPointRect_.posX_ + startPointRect_.width_ + hotZone_ * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -302,10 +308,10 @@ HWTEST_F(WindowMoveDragTest, DragWindow07, Function | MediumTest | Level3) ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); startPointX_ = startPointRect_.posX_ + startPointRect_.width_ * POINT_HOTZONE_RATIO; - startPointY_ = startPointRect_.posY_ - HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ - hotZone_ * POINT_HOTZONE_RATIO; pointX_ = startPointRect_.posX_ + startPointRect_.width_ * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ - HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ - hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -321,10 +327,10 @@ HWTEST_F(WindowMoveDragTest, DragWindow08, Function | MediumTest | Level3) ASSERT_EQ(WMError::WM_OK, window_->Show()); startPointRect_ = window_->GetRect(); startPointX_ = startPointRect_.posX_ + startPointRect_.width_ * POINT_HOTZONE_RATIO; - startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * POINT_HOTZONE_RATIO; + startPointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * POINT_HOTZONE_RATIO; pointX_ = startPointRect_.posX_ + startPointRect_.width_ * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -343,7 +349,7 @@ HWTEST_F(WindowMoveDragTest, DragWindow09, Function | MediumTest | Level3) startPointY_ = startPointRect_.posY_ + 1; pointX_ = startPointRect_.posX_ + startPointRect_.width_ * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + startPointRect_.height_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + startPointRect_.height_ + hotZone_ * DRAG_HOTZONE_RATIO; DoMoveOrDrag(); ASSERT_EQ(WMError::WM_OK, window_->Hide()); } @@ -362,7 +368,7 @@ HWTEST_F(WindowMoveDragTest, DragWindow10, Function | MediumTest | Level3) startPointY_ = startPointRect_.posY_ + 1; pointX_ = startPointRect_.posX_ + startPointRect_.width_ * DRAG_HOTZONE_RATIO; - pointY_ = startPointRect_.posY_ + HOTZONE * DRAG_HOTZONE_RATIO; + pointY_ = startPointRect_.posY_ + hotZone_ * DRAG_HOTZONE_RATIO; window_->StartMove(); hasStartMove_ = true; DoMoveOrDrag(); diff --git a/wm/test/systemtest/window_test_utils.cpp b/wm/test/systemtest/window_test_utils.cpp index 23fa2b83..3f7b91dd 100644 --- a/wm/test/systemtest/window_test_utils.cpp +++ b/wm/test/systemtest/window_test_utils.cpp @@ -15,6 +15,7 @@ #include "window_test_utils.h" #include +#include "wm_common_inner.h" namespace OHOS { namespace Rosen { namespace { @@ -123,13 +124,18 @@ Rect WindowTestUtils::GetDefaultFoatingRect(const sptr& window) return resRect; } -Rect WindowTestUtils::GetLimitedDecoRect(const Rect& rect) +Rect WindowTestUtils::GetLimitedDecoRect(const Rect& rect, float virtualPixelRatio) { - constexpr uint32_t winFrameH = 52u; - constexpr uint32_t winFrameW = 8u; + constexpr uint32_t windowTitleBarHeight = 48; + constexpr uint32_t windowFrameWidth = 4; + uint32_t winFrameH = static_cast((windowTitleBarHeight + windowFrameWidth) * virtualPixelRatio); + uint32_t winFrameW = static_cast((windowFrameWidth + windowFrameWidth) * virtualPixelRatio); + uint32_t minVerticalFloatingW = static_cast(MIN_VERTICAL_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minVerticalFloatingH = static_cast(MIN_VERTICAL_FLOATING_HEIGHT * virtualPixelRatio); + bool vertical = displayRect_.width_ < displayRect_.height_; - uint32_t minFloatingW = vertical ? MIN_VERTICAL_FLOATING_WIDTH : MIN_VERTICAL_FLOATING_HEIGHT; - uint32_t minFloatingH = vertical ? MIN_VERTICAL_FLOATING_HEIGHT : MIN_VERTICAL_FLOATING_WIDTH; + uint32_t minFloatingW = vertical ? minVerticalFloatingW : minVerticalFloatingH; + uint32_t minFloatingH = vertical ? minVerticalFloatingH : minVerticalFloatingW; Rect resRect = { rect.posX_, rect.posY_, @@ -139,11 +145,14 @@ Rect WindowTestUtils::GetLimitedDecoRect(const Rect& rect) return resRect; } -Rect WindowTestUtils::GetFloatingLimitedRect(const Rect& rect) +Rect WindowTestUtils::GetFloatingLimitedRect(const Rect& rect, float virtualPixelRatio) { + uint32_t minVerticalFloatingW = static_cast(MIN_VERTICAL_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minVerticalFloatingH = static_cast(MIN_VERTICAL_FLOATING_HEIGHT * virtualPixelRatio); bool vertical = displayRect_.width_ < displayRect_.height_; - uint32_t minFloatingW = vertical ? MIN_VERTICAL_FLOATING_WIDTH : MIN_VERTICAL_FLOATING_HEIGHT; - uint32_t minFloatingH = vertical ? MIN_VERTICAL_FLOATING_HEIGHT : MIN_VERTICAL_FLOATING_WIDTH; + + uint32_t minFloatingW = vertical ? minVerticalFloatingW : minVerticalFloatingH; + uint32_t minFloatingH = vertical ? minVerticalFloatingH : minVerticalFloatingW; Rect resRect = { rect.posX_, rect.posY_, @@ -257,18 +266,21 @@ void WindowTestUtils::InitSplitRects() displayRect_ = displayRect; limitDisplayRect_ = displayRect; + float virtualPixelRatio = WindowTestUtils::GetVirtualPixelRatio(0); + uint32_t dividerWidth = static_cast(DIVIDER_WIDTH * virtualPixelRatio); + if (displayRect_.width_ < displayRect_.height_) { isVerticalDisplay_ = true; } if (isVerticalDisplay_) { splitRects_.dividerRect = { 0, - static_cast((displayRect_.height_ - DIVIDER_WIDTH) * DEFAULT_SPLIT_RATIO), + static_cast((displayRect_.height_ - dividerWidth) * DEFAULT_SPLIT_RATIO), displayRect_.width_, - DIVIDER_WIDTH, }; + dividerWidth, }; } else { - splitRects_.dividerRect = { static_cast((displayRect_.width_ - DIVIDER_WIDTH) * DEFAULT_SPLIT_RATIO), + splitRects_.dividerRect = { static_cast((displayRect_.width_ - dividerWidth) * DEFAULT_SPLIT_RATIO), 0, - DIVIDER_WIDTH, + dividerWidth, displayRect_.height_ }; } } @@ -374,5 +386,17 @@ void WindowTestUtils::UpdateLimitSplitRect(Rect& limitSplitRect) curLimitRect.posY_ + curLimitRect.height_) - limitSplitRect.posY_; } + +float WindowTestUtils::GetVirtualPixelRatio(DisplayId displayId) +{ + auto display = DisplayManager::GetInstance().GetDisplayById(displayId); + if (display == nullptr) { + WLOGFE("GetVirtualPixel fail. Get display fail. displayId:%{public}" PRIu64", vpr:%{public}f", displayId, 0.0); + return 0.0; + } + float virtualPixelRatio = display->GetVirtualPixelRatio(); + WLOGFI("GetVirtualPixel success. displayId:%{public}" PRIu64", vpr:%{public}f", displayId, virtualPixelRatio); + return virtualPixelRatio; +} } // namespace ROSEN } // namespace OHOS diff --git a/wm/test/systemtest/window_test_utils.h b/wm/test/systemtest/window_test_utils.h index 2742aa30..5234262b 100644 --- a/wm/test/systemtest/window_test_utils.h +++ b/wm/test/systemtest/window_test_utils.h @@ -66,9 +66,10 @@ public: static void UpdateSplitRects(const sptr& window); static bool RectEqualToRect(const Rect& l, const Rect& r); static Rect GetDefaultFoatingRect(const sptr& window); - static Rect GetLimitedDecoRect(const Rect& rect); - static Rect GetFloatingLimitedRect(const Rect& rect); + static Rect GetLimitedDecoRect(const Rect& rect, float virtualPixelRatio); + static Rect GetFloatingLimitedRect(const Rect& rect, float virtualPixelRatio); static void InitTileWindowRects(const sptr& window); + static float GetVirtualPixelRatio(DisplayId displayId); private: void UpdateLimitDisplayRect(Rect& avoidRect); diff --git a/wmserver/BUILD.gn b/wmserver/BUILD.gn index 1f438fb3..7224420b 100644 --- a/wmserver/BUILD.gn +++ b/wmserver/BUILD.gn @@ -75,6 +75,7 @@ ohos_shared_library("libwms") { ":window_divider_image", "//foundation/ace/ace_engine/build/external_config/flutter/skia:ace_skia_ohos", "//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client", + "//foundation/windowmanager/dm:libdm", "//foundation/windowmanager/dmserver:libdms", "//foundation/windowmanager/utils:libwmutil", "//foundation/windowmanager/wm:libwm", diff --git a/wmserver/include/window_layout_policy.h b/wmserver/include/window_layout_policy.h index d2b0fc7a..20738683 100644 --- a/wmserver/include/window_layout_policy.h +++ b/wmserver/include/window_layout_policy.h @@ -50,6 +50,7 @@ public: virtual void UpdateWindowNode(sptr& node); virtual void UpdateLayoutRect(sptr& node) = 0; void UpdateDefaultFoatingRect(); + float GetVirtualPixelRatio() const; protected: const Rect& displayRect_; @@ -66,6 +67,7 @@ protected: void UpdateLimitRect(const sptr& node, Rect& limitRect); virtual void LayoutWindowNode(sptr& node); AvoidPosType GetAvoidPosType(const Rect& rect); + void CalcAndSetNodeHotZone(Rect layoutOutRect, sptr& node); void LimitWindowSize(const sptr& node, const Rect& displayRect, Rect& winRect); void SetRectForFloating(const sptr& node); Rect ComputeDecoratedWindowRect(const Rect& winRect); diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index 863b89eb..00cdf28b 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -42,6 +42,7 @@ public: void SetDisplayId(DisplayId displayId); void SetLayoutRect(const Rect& rect); + void SetHotZoneRect(const Rect& rect); void SetWindowRect(const Rect& rect); void SetWindowProperty(const sptr& property); void SetSystemBarProperty(WindowType type, const SystemBarProperty& property); @@ -81,6 +82,7 @@ private: sptr property_; sptr windowToken_; Rect layoutRect_ { 0, 0, 0, 0 }; + Rect hotZoneRect_ { 0, 0, 0, 0 }; int32_t callingPid_; int32_t callingUid_; WindowSizeChangeReason windowSizeChangeReason_ {WindowSizeChangeReason::UNDEFINED}; diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index e345ecaf..6dc7ef72 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -66,6 +66,7 @@ public: sptr GetBelowAppWindowNode() const; sptr GetAppWindowNode() const; sptr GetAboveAppWindowNode() const; + float GetVirtualPixelRatio() const; private: void AssignZOrder(sptr& node); diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index 4cd0b5f3..b1525014 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -62,6 +62,7 @@ public: void NotifyDisplayDestory(DisplayId displayId); void NotifySystemBarTints(); WMError RaiseZOrderForAppWindow(sptr& node); + float GetVirtualPixelRatio(DisplayId displayId) const; private: void OnRemoteDied(const sptr& remoteObject); diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index 6300f04f..7faa0cd5 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -140,8 +140,9 @@ WMError WindowController::ResizeRect(uint32_t windowId, const Rect& rect, Window } else if (reason == WindowSizeChangeReason::DRAG) { if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { // fix rect in case of moving window when dragging - newRect = WindowHelper::GetFixedWindowRectByMinRect(rect, - property->GetWindowRect(), windowRoot_->isVerticalDisplay(node)); + float virtualPixelRatio = windowRoot_->GetVirtualPixelRatio(node->GetDisplayId()); + newRect = WindowHelper::GetFixedWindowRectByMinRect(rect, property->GetWindowRect(), + windowRoot_->isVerticalDisplay(node), virtualPixelRatio); } else { newRect = rect; } @@ -274,7 +275,7 @@ void WindowController::ProcessDisplayChange(DisplayId displayId, DisplayStateCha WLOGFE("get display failed displayId:%{public}" PRId64 "", displayId); return; } - + switch (type) { case DisplayStateChangeType::UPDATE_ROTATION: { windowRoot_->NotifyDisplayChange(abstractDisplay); diff --git a/wmserver/src/window_layout_policy.cpp b/wmserver/src/window_layout_policy.cpp index 3ec0e274..a3ccfb89 100644 --- a/wmserver/src/window_layout_policy.cpp +++ b/wmserver/src/window_layout_policy.cpp @@ -14,16 +14,16 @@ */ #include "window_layout_policy.h" +#include "display_manager.h" #include "window_helper.h" #include "window_manager_hilog.h" +#include "wm_common_inner.h" #include "wm_trace.h" namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowLayoutPolicy"}; - constexpr uint32_t WINDOW_TITLE_BAR_HEIGHT = 48; - constexpr uint32_t WINDOW_FRAME_WIDTH = 4; } WindowLayoutPolicy::WindowLayoutPolicy(const Rect& displayRect, const uint64_t& screenId, sptr& belowAppNode, sptr& appNode, sptr& aboveAppNode) @@ -115,11 +115,14 @@ void WindowLayoutPolicy::UpdateDefaultFoatingRect() void WindowLayoutPolicy::SetRectForFloating(const sptr& node) { + float virtualPixelRatio = GetVirtualPixelRatio(); + uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * virtualPixelRatio); + uint32_t winTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); // deduct decor size Rect rect = defaultFloatingRect_; if (node->GetWindowProperty()->GetDecorEnable()) { - rect.width_ -= (WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH); - rect.height_ -= (WINDOW_TITLE_BAR_HEIGHT + WINDOW_FRAME_WIDTH); + rect.width_ -= (winFrameW + winFrameW); + rect.height_ -= (winTitleBarH + winFrameW); } node->SetWindowRect(rect); @@ -174,11 +177,15 @@ void WindowLayoutPolicy::UpdateFloatingLayoutRect(Rect& limitRect, Rect& winRect Rect WindowLayoutPolicy::ComputeDecoratedWindowRect(const Rect& winRect) { + float virtualPixelRatio = GetVirtualPixelRatio(); + uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * virtualPixelRatio); + uint32_t winTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + Rect rect; rect.posX_ = winRect.posX_; rect.posY_ = winRect.posY_; - rect.width_ = winRect.width_ + WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH; - rect.height_ = winRect.height_ + WINDOW_TITLE_BAR_HEIGHT + WINDOW_FRAME_WIDTH; + rect.width_ = winRect.width_ + winFrameW + winFrameW; + rect.height_ = winRect.height_ + winTitleBarH + winFrameW; return rect; } @@ -221,14 +228,44 @@ void WindowLayoutPolicy::UpdateLayoutRect(sptr& node) LimitWindowSize(node, displayRect, winRect); node->SetLayoutRect(winRect); + CalcAndSetNodeHotZone(winRect, node); if (!(lastRect == winRect)) { node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); } } +void WindowLayoutPolicy::CalcAndSetNodeHotZone(Rect layoutOutRect, sptr& node) +{ + Rect rect = layoutOutRect; + float virtualPixelRatio = GetVirtualPixelRatio(); + uint32_t hotZone = static_cast(HOTZONE * virtualPixelRatio); + uint32_t divHotZone = static_cast(DIV_HOTZONE * virtualPixelRatio); + + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + if (rect.width_ < rect.height_) { + rect.posX_ -= divHotZone; + rect.width_ += (divHotZone + divHotZone); + } else { + rect.posY_ -= divHotZone; + rect.height_ += (divHotZone + divHotZone); + } + } else if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + rect.posX_ -= hotZone; + rect.posY_ -= hotZone; + rect.width_ += (hotZone + hotZone); + rect.height_ += (hotZone + hotZone); + } + node->SetHotZoneRect(rect); +} + void WindowLayoutPolicy::LimitWindowSize(const sptr& node, const Rect& displayRect, Rect& winRect) { + float virtualPixelRatio = GetVirtualPixelRatio(); + uint32_t minVerticalFloatingW = static_cast(MIN_VERTICAL_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minVerticalFloatingH = static_cast(MIN_VERTICAL_FLOATING_HEIGHT * virtualPixelRatio); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + WindowType windowType = node->GetWindowType(); WindowMode windowMode = node->GetWindowMode(); bool isVertical = (displayRect.height_ > displayRect.width_) ? true : false; @@ -238,16 +275,16 @@ void WindowLayoutPolicy::LimitWindowSize(const sptr& node, const Rec } if ((windowMode == WindowMode::WINDOW_MODE_FLOATING) && !WindowHelper::IsSystemWindow(windowType)) { if (isVertical) { - winRect.width_ = std::max(MIN_VERTICAL_FLOATING_WIDTH, winRect.width_); - winRect.height_ = std::max(MIN_VERTICAL_FLOATING_HEIGHT, winRect.height_); + winRect.width_ = std::max(minVerticalFloatingW, winRect.width_); + winRect.height_ = std::max(minVerticalFloatingH, winRect.height_); } else { - winRect.width_ = std::max(MIN_VERTICAL_FLOATING_HEIGHT, winRect.width_); - winRect.height_ = std::max(MIN_VERTICAL_FLOATING_WIDTH, winRect.height_); + winRect.width_ = std::max(minVerticalFloatingH, winRect.width_); + winRect.height_ = std::max(minVerticalFloatingW, winRect.height_); } } if (WindowHelper::IsMainFloatingWindow(windowType, windowMode)) { winRect.posY_ = std::max(limitRect_.posY_, winRect.posY_); - winRect.posY_ = std::min(limitRect_.posY_ + static_cast(limitRect_.height_ - WINDOW_TITLE_BAR_HEIGHT), + winRect.posY_ = std::min(limitRect_.posY_ + static_cast(limitRect_.height_ - windowTitleBarH), winRect.posY_); } } @@ -314,5 +351,17 @@ void WindowLayoutPolicy::UpdateLimitRect(const sptr& node, Rect& lim void WindowLayoutPolicy::Reset() { } + +float WindowLayoutPolicy::GetVirtualPixelRatio() const +{ + auto display = DisplayManager::GetInstance().GetDisplayById(screenId_); + if (display == nullptr) { + WLOGFE("GetVirtualPixel fail. Get display fail. displayId:%{public}" PRIu64", use Default vpr:1.0", screenId_); + return 1.0; // Use DefaultVPR 1.0 + } + float virtualPixelRatio = display->GetVirtualPixelRatio(); + WLOGFI("GetVirtualPixel success. displayId:%{public}" PRIu64", vpr:%{public}f", screenId_, virtualPixelRatio); + return virtualPixelRatio; +} } } diff --git a/wmserver/src/window_layout_policy_cascade.cpp b/wmserver/src/window_layout_policy_cascade.cpp index 490449df..3854543b 100644 --- a/wmserver/src/window_layout_policy_cascade.cpp +++ b/wmserver/src/window_layout_policy_cascade.cpp @@ -17,6 +17,7 @@ #include "window_helper.h" #include "window_inner_manager.h" #include "window_manager_hilog.h" +#include "wm_common_inner.h" #include "wm_trace.h" namespace OHOS { @@ -130,19 +131,23 @@ static bool IsLayoutChanged(const Rect& l, const Rect& r) void WindowLayoutPolicyCascade::LimitMoveBounds(Rect& rect) { + float virtualPixelRatio = GetVirtualPixelRatio(); + uint32_t minHorizontalSplitW = static_cast(MIN_HORIZONTAL_SPLIT_WIDTH * virtualPixelRatio); + uint32_t minVerticalSplitH = static_cast(MIN_VERTICAL_SPLIT_HEIGHT * virtualPixelRatio); + if (rect.width_ < rect.height_) { - if (rect.posX_ < (limitRect_.posX_ + static_cast(MIN_HORIZONTAL_SPLIT_WIDTH))) { - rect.posX_ = limitRect_.posX_ + static_cast(MIN_HORIZONTAL_SPLIT_WIDTH); + if (rect.posX_ < (limitRect_.posX_ + static_cast(minHorizontalSplitW))) { + rect.posX_ = limitRect_.posX_ + static_cast(minHorizontalSplitW); } else if (rect.posX_ > - (limitRect_.posX_ + limitRect_.width_ - static_cast(MIN_HORIZONTAL_SPLIT_WIDTH))) { - rect.posX_ = limitRect_.posX_ + static_cast(limitRect_.width_ - MIN_HORIZONTAL_SPLIT_WIDTH); + (limitRect_.posX_ + limitRect_.width_ - static_cast(minHorizontalSplitW))) { + rect.posX_ = limitRect_.posX_ + static_cast(limitRect_.width_ - minHorizontalSplitW); } } else { - if (rect.posY_ < (limitRect_.posY_ + static_cast(MIN_VERTICAL_SPLIT_HEIGHT))) { - rect.posY_ = limitRect_.posY_ + static_cast(MIN_VERTICAL_SPLIT_HEIGHT); + if (rect.posY_ < (limitRect_.posY_ + static_cast(minVerticalSplitH))) { + rect.posY_ = limitRect_.posY_ + static_cast(minVerticalSplitH); } else if (rect.posY_ > - (limitRect_.posY_ + static_cast(limitRect_.height_ - MIN_VERTICAL_SPLIT_HEIGHT))) { - rect.posY_ = limitRect_.posY_ + static_cast(limitRect_.height_ - MIN_VERTICAL_SPLIT_HEIGHT); + (limitRect_.posY_ + static_cast(limitRect_.height_ - minVerticalSplitH))) { + rect.posY_ = limitRect_.posY_ + static_cast(limitRect_.height_ - minVerticalSplitH); } } } @@ -215,6 +220,7 @@ void WindowLayoutPolicyCascade::UpdateLayoutRect(sptr& node) } node->SetLayoutRect(winRect); + CalcAndSetNodeHotZone(winRect, node); if (IsLayoutChanged(lastRect, winRect)) { node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); @@ -265,12 +271,15 @@ void WindowLayoutPolicyCascade::UpdateSplitLimitRect(const Rect& limitRect, Rect void WindowLayoutPolicyCascade::InitSplitRects() { + float virtualPixelRatio = GetVirtualPixelRatio(); + uint32_t dividerWidth = static_cast(DIVIDER_WIDTH * virtualPixelRatio); + if (!IsVertical()) { - dividerRect_ = { static_cast((displayRect_.width_ - DIVIDER_WIDTH) * DEFAULT_SPLIT_RATIO), 0, - DIVIDER_WIDTH, displayRect_.height_ }; + dividerRect_ = { static_cast((displayRect_.width_ - dividerWidth) * DEFAULT_SPLIT_RATIO), 0, + dividerWidth, displayRect_.height_ }; } else { - dividerRect_ = { 0, static_cast((displayRect_.height_ - DIVIDER_WIDTH) * DEFAULT_SPLIT_RATIO), - displayRect_.width_, DIVIDER_WIDTH }; + dividerRect_ = { 0, static_cast((displayRect_.height_ - dividerWidth) * DEFAULT_SPLIT_RATIO), + displayRect_.width_, dividerWidth }; } WLOGFI("init dividerRect :[%{public}d, %{public}d, %{public}u, %{public}u]", dividerRect_.posX_, dividerRect_.posY_, dividerRect_.width_, dividerRect_.height_); diff --git a/wmserver/src/window_layout_policy_tile.cpp b/wmserver/src/window_layout_policy_tile.cpp index 073ada6a..9c24ada2 100644 --- a/wmserver/src/window_layout_policy_tile.cpp +++ b/wmserver/src/window_layout_policy_tile.cpp @@ -99,6 +99,7 @@ void WindowLayoutPolicyTile::LayoutForegroundNodeQueue() Rect lastRect = node->GetLayoutRect(); Rect winRect = node->GetWindowProperty()->GetWindowRect(); node->SetLayoutRect(winRect); + CalcAndSetNodeHotZone(winRect, node); if (!(lastRect == winRect)) { node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); @@ -204,6 +205,7 @@ void WindowLayoutPolicyTile::UpdateLayoutRect(sptr& node) } LimitWindowSize(node, displayRect, winRect); node->SetLayoutRect(winRect); + CalcAndSetNodeHotZone(winRect, node); if (!(lastRect == winRect)) { node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); diff --git a/wmserver/src/window_node.cpp b/wmserver/src/window_node.cpp index 44d6ef9d..23d8f4dd 100644 --- a/wmserver/src/window_node.cpp +++ b/wmserver/src/window_node.cpp @@ -32,6 +32,11 @@ void WindowNode::SetLayoutRect(const Rect& rect) layoutRect_ = rect; } +void WindowNode::SetHotZoneRect(const Rect& rect) +{ + hotZoneRect_ = rect; +} + void WindowNode::SetWindowRect(const Rect& rect) { property_->SetWindowRect(rect); @@ -128,23 +133,7 @@ const Rect& WindowNode::GetLayoutRect() const Rect WindowNode::GetHotZoneRect() const { - Rect rect = layoutRect_; - if (GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { - const int32_t divHotZone = 20; - if (rect.width_ < rect.height_) { - rect.posX_ -= divHotZone; - rect.width_ += (divHotZone + divHotZone); - } else { - rect.posY_ -= divHotZone; - rect.height_ += (divHotZone + divHotZone); - } - } else if (WindowHelper::IsMainFloatingWindow(GetWindowType(), GetWindowMode())) { - rect.posX_ -= HOTZONE; - rect.posY_ -= HOTZONE; - rect.width_ += (HOTZONE + HOTZONE); - rect.height_ += (HOTZONE + HOTZONE); - } - return rect; + return hotZoneRect_; } WindowType WindowNode::GetWindowType() const diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index b247eb22..776e34f8 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -29,6 +29,7 @@ #include "window_manager_agent_controller.h" #include "window_manager_hilog.h" #include "wm_common.h" +#include "wm_common_inner.h" #include "wm_trace.h" namespace OHOS { @@ -1061,6 +1062,11 @@ sptr WindowNodeContainer::GetAboveAppWindowNode() const return aboveAppWindowNode_; } +float WindowNodeContainer::GetVirtualPixelRatio() const +{ + return layoutPolicy_->GetVirtualPixelRatio(); +} + namespace { const char DISABLE_WINDOW_ANIMATION_PATH[] = "/etc/disable_window_animation"; } diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index 49d1646b..5a18a646 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -477,5 +477,11 @@ void WindowRoot::NotifyDisplayDestory(DisplayId expandDisplayId) defaultDisplaycontainer->MoveWindowNode(expandDisplaycontainer); NotifyDisplayRemoved(expandDisplayId); } + +float WindowRoot::GetVirtualPixelRatio(DisplayId displayId) const +{ + auto container = const_cast(this)->GetOrCreateWindowNodeContainer(displayId); + return container->GetVirtualPixelRatio(); +} } } From 350f701cc0086603238a6cb98d7c6f28a0871e52 Mon Sep 17 00:00:00 2001 From: jincanran Date: Fri, 18 Feb 2022 16:56:47 +0800 Subject: [PATCH 12/70] add tile window remove process Signed-off-by: jincanran Change-Id: I4caf57ff3fdfd5d599bcf1f217f3d5e9ead88d80 --- wmserver/include/window_layout_policy_tile.h | 8 +- wmserver/src/window_layout_policy_tile.cpp | 84 +++++++++++++------- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/wmserver/include/window_layout_policy_tile.h b/wmserver/include/window_layout_policy_tile.h index 37e02e1b..fc455230 100644 --- a/wmserver/include/window_layout_policy_tile.h +++ b/wmserver/include/window_layout_policy_tile.h @@ -17,6 +17,7 @@ #define OHOS_ROSEN_WINDOW_LAYOUT_POLICY_TILE_H #include +#include #include #include @@ -34,20 +35,21 @@ public: ~WindowLayoutPolicyTile() = default; void Launch() override; void AddWindowNode(sptr& node) override; + void RemoveWindowNode(sptr& node) override; void UpdateLayoutRect(sptr& node) override; private: Rect singleRect_ = { 0, 0, 0, 0 }; std::vector doubleRects_ = std::vector(2); std::vector tripleRects_ = std::vector(3); - std::vector> foregroundNodes_; - uint32_t lastForegroundNodeId_ = 0; + std::deque> foregroundNodes_; void UpdateDisplayInfo() override; void InitTileWindowRects(); void AssignNodePropertyForTileWindows(); void LayoutForegroundNodeQueue(); void InitForegroundNodeQueue(); - void UpdateForegroundNodeQueue(sptr& node); + void ForegroundNodeQueuePush(sptr& node); + void ForegroundNodeQueueRemove(sptr& node); }; } } diff --git a/wmserver/src/window_layout_policy_tile.cpp b/wmserver/src/window_layout_policy_tile.cpp index 073ada6a..5b678f9f 100644 --- a/wmserver/src/window_layout_policy_tile.cpp +++ b/wmserver/src/window_layout_policy_tile.cpp @@ -85,7 +85,7 @@ void WindowLayoutPolicyTile::AddWindowNode(sptr& node) { WM_FUNCTION_TRACE(); if (WindowHelper::IsMainWindow(node->GetWindowType())) { - UpdateForegroundNodeQueue(node); + ForegroundNodeQueuePush(node); AssignNodePropertyForTileWindows(); LayoutForegroundNodeQueue(); } else { @@ -93,6 +93,22 @@ void WindowLayoutPolicyTile::AddWindowNode(sptr& node) } } +void WindowLayoutPolicyTile::RemoveWindowNode(sptr& node) +{ + WM_FUNCTION_TRACE(); + auto type = node->GetWindowType(); + // affect other windows, trigger off global layout + if (avoidTypes_.find(type) != avoidTypes_.end()) { + LayoutWindowTree(); + } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode + LayoutWindowTree(); + } else { + ForegroundNodeQueueRemove(node); + } + Rect winRect = node->GetWindowProperty()->GetWindowRect(); + node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); +} + void WindowLayoutPolicyTile::LayoutForegroundNodeQueue() { for (auto& node : foregroundNodes_) { @@ -112,30 +128,38 @@ void WindowLayoutPolicyTile::LayoutForegroundNodeQueue() void WindowLayoutPolicyTile::InitForegroundNodeQueue() { foregroundNodes_.clear(); - lastForegroundNodeId_ = 0; for (auto& node : appWindowNode_->children_) { if (WindowHelper::IsMainWindow(node->GetWindowType())) { - UpdateForegroundNodeQueue(node); + ForegroundNodeQueuePush(node); } } } -void WindowLayoutPolicyTile::UpdateForegroundNodeQueue(sptr& node) +void WindowLayoutPolicyTile::ForegroundNodeQueuePush(sptr& node) { if (node == nullptr) { return; } WLOGFI("add win in tile for win id: %{public}d", node->GetWindowId()); uint32_t maxTileWinNum = IsVertical() ? MAX_WIN_NUM_VERTICAL : MAX_WIN_NUM_HORIZONTAL; - if (foregroundNodes_.size() < maxTileWinNum) { - foregroundNodes_.push_back(node); - lastForegroundNodeId_ = ((++lastForegroundNodeId_) % maxTileWinNum); - } else { - WLOGFI("minimize win %{public}d in tile", foregroundNodes_[lastForegroundNodeId_]->GetWindowId()); - AAFwk::AbilityManagerClient::GetInstance()-> - MinimizeAbility(foregroundNodes_[lastForegroundNodeId_]->abilityToken_); - foregroundNodes_[lastForegroundNodeId_] = node; - lastForegroundNodeId_ = ((++lastForegroundNodeId_) % maxTileWinNum); + while (foregroundNodes_.size() >= maxTileWinNum) { + auto removeNode = foregroundNodes_.front(); + foregroundNodes_.pop_front(); + WLOGFI("minimize win %{public}d in tile", removeNode->GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(removeNode->abilityToken_); + } + foregroundNodes_.push_back(node); +} + +void WindowLayoutPolicyTile::ForegroundNodeQueueRemove(sptr& node) +{ + if (node == nullptr) { + return; + } + auto iter = std::find(foregroundNodes_.begin(), foregroundNodes_.end(), node); + if (iter != foregroundNodes_.end()) { + WLOGFI("remove win in tile for win id: %{public}d", node->GetWindowId()); + foregroundNodes_.erase(iter); } } @@ -144,26 +168,28 @@ void WindowLayoutPolicyTile::AssignNodePropertyForTileWindows() // set rect for foreground windows int num = foregroundNodes_.size(); if (num == 1) { - WLOGFI("set rect for win id: %{public}d", foregroundNodes_[0]->GetWindowMode()); - foregroundNodes_[0]->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); - foregroundNodes_[0]->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); - foregroundNodes_[0]->SetWindowRect(singleRect_); - foregroundNodes_[0]->hasDecorated_ = true; + WLOGFI("set rect for win id: %{public}d", foregroundNodes_.front()->GetWindowMode()); + foregroundNodes_.front()->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + foregroundNodes_.front()->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); + foregroundNodes_.front()->SetWindowRect(singleRect_); + foregroundNodes_.front()->hasDecorated_ = true; WLOGFI("set rect for win id: %{public}d [%{public}d %{public}d %{public}d %{public}d]", - foregroundNodes_[0]->GetWindowId(), + foregroundNodes_.front()->GetWindowId(), singleRect_.posX_, singleRect_.posY_, singleRect_.width_, singleRect_.height_); - } else { - auto& rects = (num == MAX_WIN_NUM_HORIZONTAL) ? tripleRects_ : doubleRects_; - for (uint32_t i = 0; i < foregroundNodes_.size(); i++) { - foregroundNodes_[(lastForegroundNodeId_ + i) % num]->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); - foregroundNodes_[(lastForegroundNodeId_ + i) % num]->GetWindowToken()-> - UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); - foregroundNodes_[(lastForegroundNodeId_ + i) % num]->SetWindowRect(rects[i]); - foregroundNodes_[(lastForegroundNodeId_ + i) % num]->hasDecorated_ = true; + } else if (num <= 3) { + auto rit = (num == MAX_WIN_NUM_HORIZONTAL) ? tripleRects_.begin() : doubleRects_.begin(); + for (auto it : foregroundNodes_) { + auto& rect = (*rit); + it->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + it->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); + it->SetWindowRect(rect); + it->hasDecorated_ = true; WLOGFI("set rect for qwin id: %{public}d [%{public}d %{public}d %{public}d %{public}d]", - foregroundNodes_[(lastForegroundNodeId_ + i) % num]->GetWindowId(), - rects[i].posX_, rects[i].posY_, rects[i].width_, rects[i].height_); + it->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); + rit++; } + } else { + WLOGE("too many window node in tile queue"); } } From eb129556649320bdd6954f908075b9fb356a3218 Mon Sep 17 00:00:00 2001 From: youqijing Date: Fri, 18 Feb 2022 17:31:47 +0800 Subject: [PATCH 13/70] =?UTF-8?q?=E8=A7=A3=E5=86=B3Expand=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E4=B8=8BDisplay=E5=B0=BA=E5=AF=B8=E5=8F=98=E5=8C=96?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E6=AD=BB=E9=94=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: youqijing Change-Id: Iae2ae474a0c4ddb6083f62be470f81663e5b951a --- .../include/abstract_display_controller.h | 4 +- dmserver/src/abstract_display_controller.cpp | 71 +++++++++++-------- dmserver/src/abstract_screen_controller.cpp | 4 +- 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/dmserver/include/abstract_display_controller.h b/dmserver/include/abstract_display_controller.h index f57fb987..ed3119a8 100644 --- a/dmserver/include/abstract_display_controller.h +++ b/dmserver/include/abstract_display_controller.h @@ -51,8 +51,8 @@ private: void BindAloneScreenLocked(sptr absScreen); void AddScreenToMirrorLocked(sptr absScreen); void AddScreenToExpandLocked(sptr absScreen); - void ProcessNormalScreenDisconnected(sptr absScreen, sptr screenGroup); - void ProcessExpandScreenDisconnected(sptr absScreen, sptr screenGroup); + DisplayId ProcessNormalScreenDisconnected(sptr absScreen, sptr screenGroup); + DisplayId ProcessExpandScreenDisconnected(sptr absScreen, sptr screenGroup); bool UpdateDisplaySize(sptr absDisplay, sptr info); std::recursive_mutex& mutex_; diff --git a/dmserver/src/abstract_display_controller.cpp b/dmserver/src/abstract_display_controller.cpp index aa9899e8..9fa335c1 100644 --- a/dmserver/src/abstract_display_controller.cpp +++ b/dmserver/src/abstract_display_controller.cpp @@ -129,67 +129,82 @@ void AbstractDisplayController::OnAbstractScreenConnect(sptr abs void AbstractDisplayController::OnAbstractScreenDisconnect(sptr absScreen) { - WLOGI("disconnect screen. id:%{public}" PRIu64"", absScreen->dmsId_); if (absScreen == nullptr) { WLOGE("the information of the screen is wrong"); return; } - std::lock_guard lock(mutex_); - sptr screenGroup = absScreen->GetGroup(); - if (screenGroup == nullptr) { - WLOGE("the group information of the screen is wrong"); + WLOGI("disconnect screen. id:%{public}" PRIu64"", absScreen->dmsId_); + sptr screenGroup; + DisplayId absDisplayId = DISPLAY_ID_INVALD; + { + std::lock_guard lock(mutex_); + screenGroup = absScreen->GetGroup(); + if (screenGroup == nullptr) { + WLOGE("the group information of the screen is wrong"); + return; + } + if (screenGroup->combination_ == ScreenCombination::SCREEN_ALONE + || screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR) { + absDisplayId = ProcessNormalScreenDisconnected(absScreen, screenGroup); + } else if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { + absDisplayId = ProcessExpandScreenDisconnected(absScreen, screenGroup); + } else { + WLOGE("support in future. combination:%{public}u", screenGroup->combination_); + } + } + if (absDisplayId == DISPLAY_ID_INVALD) { + WLOGE("the displayId of the disconnected expand screen was not found"); return; } if (screenGroup->combination_ == ScreenCombination::SCREEN_ALONE || screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR) { - ProcessNormalScreenDisconnected(absScreen, screenGroup); + if (screenGroup->GetChildCount() == 0) { + abstractDisplayMap_.erase(absDisplayId); + DisplayManagerAgentController::GetInstance().OnDisplayDestroy(absDisplayId); + } } else if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { - ProcessExpandScreenDisconnected(absScreen, screenGroup); + DisplayManagerService::GetInstance().NotifyDisplayStateChange( + absDisplayId, DisplayStateChangeType::DESTROY); + DisplayManagerAgentController::GetInstance().OnDisplayDestroy(absDisplayId); + abstractDisplayMap_.erase(absDisplayId); } else { WLOGE("support in future. combination:%{public}u", screenGroup->combination_); } } -void AbstractDisplayController::ProcessNormalScreenDisconnected( +DisplayId AbstractDisplayController::ProcessNormalScreenDisconnected( sptr absScreen, sptr screenGroup) { WLOGI("normal screen disconnect"); ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); sptr defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId); for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) { + DisplayId displayId = iter->first; sptr abstractDisplay = iter->second; - if (abstractDisplay->GetAbstractScreenId() != absScreen->dmsId_) { - continue; - } - abstractDisplay->BindAbstractScreen(defaultScreen); - if (screenGroup->GetChildCount() == 0) { - abstractDisplayMap_.erase(iter); - DisplayManagerAgentController::GetInstance().OnDisplayDestroy(abstractDisplay->GetId()); + if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) { + WLOGI("normal screen disconnect, displayId: %{public}" PRIu64", screenId: %{public}" PRIu64"", + displayId, abstractDisplay->GetAbstractScreenId()); + abstractDisplay->BindAbstractScreen(defaultScreen); + return displayId; } } + return DISPLAY_ID_INVALD; } -void AbstractDisplayController::ProcessExpandScreenDisconnected( +DisplayId AbstractDisplayController::ProcessExpandScreenDisconnected( sptr absScreen, sptr screenGroup) { WLOGI("expand screen disconnect"); - ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); - sptr defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId); for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) { DisplayId displayId = iter->first; sptr abstractDisplay = iter->second; - if (abstractDisplay->GetAbstractScreenId() != absScreen->dmsId_) { - continue; + if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) { + WLOGI("expand screen disconnect, displayId: %{public}" PRIu64", screenId: %{public}" PRIu64"", + displayId, abstractDisplay->GetAbstractScreenId()); + return displayId; } - WLOGI("notify wms and dm which expand screen disconnect, displayId: %{public}" PRIu64"" - ", screenId: %{public}" PRIu64"", displayId, abstractDisplay->GetAbstractScreenId()); - // Notify disconnect event to WMS - DisplayManagerService::GetInstance().NotifyDisplayStateChange(displayId, DisplayStateChangeType::DESTROY); - // Notify disconnect event to DisplayManager - DisplayManagerAgentController::GetInstance().OnDisplayDestroy(abstractDisplay->GetId()); - abstractDisplayMap_.erase(iter); - break; } + return DISPLAY_ID_INVALD; } void AbstractDisplayController::OnAbstractScreenChange(sptr absScreen, DisplayChangeEvent event) diff --git a/dmserver/src/abstract_screen_controller.cpp b/dmserver/src/abstract_screen_controller.cpp index 956fa434..ed327ffd 100644 --- a/dmserver/src/abstract_screen_controller.cpp +++ b/dmserver/src/abstract_screen_controller.cpp @@ -752,7 +752,7 @@ void AbstractScreenController::DumpScreenGroupInfo() const std::string screenType = "UNDEFINE"; NodeId nodeId = (screenGroup->rsDisplayNode_ == nullptr) ? 0 : screenGroup->rsDisplayNode_->GetId(); WLOGI("%{public}10s %{public}20" PRIu64" %{public}20" PRIu64" %{public}20" PRIu64" %{public}10s %{public}20" - PRIu64" %{public}10s %{public}20" PRIu64" ", isGroup.c_str(), screenGroup->dmsId_,screenGroup->rsId_, + PRIu64" %{public}10s %{public}20" PRIu64" ", isGroup.c_str(), screenGroup->dmsId_, screenGroup->rsId_, screenGroup->groupDmsId_, screenType.c_str(), nodeId, isMirrored.c_str(), screenGroup->rSDisplayNodeConfig_.mirrorNodeId); auto childrenScreen = screenGroup->GetChildren(); @@ -769,7 +769,7 @@ void AbstractScreenController::DumpScreenGroupInfo() const isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false"; nodeId = (screen->rsDisplayNode_ == nullptr) ? 0 : screen->rsDisplayNode_->GetId(); WLOGI("%{public}10s %{public}20" PRIu64" %{public}20" PRIu64" %{public}20" PRIu64" %{public}10s %{public}20" - PRIu64" %{public}10s %{public}20" PRIu64" ", isGroup.c_str(), screen->dmsId_,screen->rsId_, + PRIu64" %{public}10s %{public}20" PRIu64" ", isGroup.c_str(), screen->dmsId_, screen->rsId_, screen->groupDmsId_, screenType.c_str(), nodeId, isMirrored.c_str(), screen->rSDisplayNodeConfig_.mirrorNodeId); } From 56b10f345d9bcec013f74584006487b730ebfa0e Mon Sep 17 00:00:00 2001 From: zengqingyu Date: Thu, 17 Feb 2022 21:08:39 +0800 Subject: [PATCH 14/70] offer display change js interface Signed-off-by: zengqingyu Change-Id: I46d60b1387bdf6814d1537f7a8d647c63f54c84d --- .../js/declaration/api/@ohos.display.d.ts | 19 ++ interfaces/kits/napi/BUILD.gn | 2 +- interfaces/kits/napi/display/BUILD.gn | 39 ++- interfaces/kits/napi/display/js_display.cpp | 98 +++++++ interfaces/kits/napi/display/js_display.h | 37 +++ .../kits/napi/display/js_display_listener.cpp | 143 ++++++++++ .../kits/napi/display/js_display_listener.h | 47 ++++ .../kits/napi/display/js_display_manager.cpp | 256 ++++++++++++++++++ ..._display_module.h => js_display_manager.h} | 47 ++-- .../kits/napi/display/js_display_module.cpp | 29 ++ .../napi/display/native_display_module.cpp | 113 -------- .../display_runtime/api/@ohos.screen.d.ts | 2 + .../napi/display_runtime/napi/js_screen.cpp | 4 + .../napi/js_screen_listener.cpp | 90 ++++-- .../napi/js_screen_manager.cpp | 8 + .../window_runtime/window_napi/js_window.cpp | 4 + 16 files changed, 768 insertions(+), 170 deletions(-) create mode 100644 interfaces/kits/napi/display/js_display.cpp create mode 100644 interfaces/kits/napi/display/js_display.h create mode 100644 interfaces/kits/napi/display/js_display_listener.cpp create mode 100644 interfaces/kits/napi/display/js_display_listener.h create mode 100644 interfaces/kits/napi/display/js_display_manager.cpp rename interfaces/kits/napi/display/{native_display_module.h => js_display_manager.h} (59%) create mode 100644 interfaces/kits/napi/display/js_display_module.cpp delete mode 100644 interfaces/kits/napi/display/native_display_module.cpp diff --git a/interfaces/kits/js/declaration/api/@ohos.display.d.ts b/interfaces/kits/js/declaration/api/@ohos.display.d.ts index 17ac54ae..1ed8bbbb 100644 --- a/interfaces/kits/js/declaration/api/@ohos.display.d.ts +++ b/interfaces/kits/js/declaration/api/@ohos.display.d.ts @@ -13,8 +13,11 @@ * limitations under the License. */ +import { AsyncCallback, Callback } from './basic'; + /** * interface of display manager + * @syscap SystemCapability.WindowManager.WindowManager.Core * @devices tv, phone, tablet, wearable */ declare namespace display { @@ -24,9 +27,24 @@ declare namespace display { */ function getDefaultDisplay(): Promise; + /** + * register the callback of display change + * @param type: type of callback + * @devices tv, phone, tablet, wearable, car + */ + function on(type: 'add' | 'remove' | 'change', callback: Callback): void; + + /** + * unregister the callback of display change + * @param type: type of callback + * #devices tv, phone, tablet, wearable, car + */ + function off(type: 'add' | 'remove' | 'change', callback: Callback): void; + /** /** * the state of display + * @syscap SystemCapability.WindowManager.WindowManager.Core * @devices tv, phone, tablet, wearable */ enum DisplayState { @@ -62,6 +80,7 @@ declare namespace display { /** * Properties of display, it couldn't update automatically + * @syscap SystemCapability.WindowManager.WindowManager.Core * @devices tv, phone, tablet, wearable */ interface Display { diff --git a/interfaces/kits/napi/BUILD.gn b/interfaces/kits/napi/BUILD.gn index acf61db4..acc6f77a 100644 --- a/interfaces/kits/napi/BUILD.gn +++ b/interfaces/kits/napi/BUILD.gn @@ -16,7 +16,7 @@ import("//build/ohos.gni") group("napi_packages") { deps = [ - "display:display", + "display:display_napi", "display_runtime:screen_napi", "screenshot:screenshot", "window_runtime:window_napi", diff --git a/interfaces/kits/napi/display/BUILD.gn b/interfaces/kits/napi/display/BUILD.gn index 26840d26..73e68386 100644 --- a/interfaces/kits/napi/display/BUILD.gn +++ b/interfaces/kits/napi/display/BUILD.gn @@ -13,22 +13,47 @@ import("//build/ohos.gni") -## Build display.so {{{ -ohos_shared_library("display") { - sources = [ "native_display_module.cpp" ] +config("display_config") { + visibility = [ ":*" ] + + include_dirs = [ + "//foundation/windowmanager/interfaces/kits/napi/display", + "//foundation/windowmanager/utils/include", + ] +} + +## Build display_napi.so {{{ +ohos_shared_library("display_napi") { + sources = [ + "js_display.cpp", + "js_display_listener.cpp", + "js_display_manager.cpp", + "js_display_module.cpp", + ] + + configs = [ ":display_config" ] deps = [ "../common:wm_napi_common", + "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native", + "//foundation/aafwk/standard/frameworks/kits/appkit:app_context", + "//foundation/aafwk/standard/frameworks/kits/appkit:appkit_native", + "//foundation/aafwk/standard/interfaces/innerkits/want:want", + "//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client", "//foundation/windowmanager/dm:libdm", "//foundation/windowmanager/utils:libwmutil", - "//foundation/windowmanager/wm:libwm", - "//foundation/windowmanager/wmserver:libwms", ] - external_deps = [ "multimedia_image_standard:image_native" ] + external_deps = [ + "ability_runtime:ability_manager", + "ability_runtime:runtime", + "hiviewdfx_hilog_native:libhilog", + "multimedia_image_standard:image_native", + "napi:ace_napi", + ] relative_install_dir = "module" part_name = "window_manager" subsystem_name = "window" } -## Build display.so }}} +## Build display_napi.so }}} diff --git a/interfaces/kits/napi/display/js_display.cpp b/interfaces/kits/napi/display/js_display.cpp new file mode 100644 index 00000000..0b008353 --- /dev/null +++ b/interfaces/kits/napi/display/js_display.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022 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 "js_display.h" + +#include +#include +#include "display.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsDisplay"}; +} + +static std::map> g_JsDisplayMap; +std::recursive_mutex g_mutex; + +JsDisplay::JsDisplay(const sptr& display) : display_(display) +{ +} + +JsDisplay::~JsDisplay() +{ + WLOGFI("JsDisplay::~JsDisplay is called"); +} + +void JsDisplay::Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFI("JsDisplay::Finalizer is called"); + auto jsDisplay = std::unique_ptr(static_cast(data)); + if (jsDisplay == nullptr) { + WLOGFE("JsDisplay::Finalizer jsDisplay is null"); + return; + } + sptr display = jsDisplay->display_; + if (display == nullptr) { + WLOGFE("JsDisplay::Finalizer display is null"); + return; + } + DisplayId displayId = display->GetId(); + WLOGFI("JsDisplay::Finalizer displayId : %{public}" PRIu64"", displayId); + std::lock_guard lock(g_mutex); + if (g_JsDisplayMap.find(displayId) != g_JsDisplayMap.end()) { + WLOGFI("JsDisplay::Finalizer Display is destroyed: %{public}" PRIu64"", displayId); + g_JsDisplayMap.erase(displayId); + } +} + +NativeValue* CreateJsDisplayObject(NativeEngine& engine, sptr& display) +{ + WLOGFI("JsDisplay::CreateJsDisplay is called"); + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return engine.CreateUndefined(); + } + std::unique_ptr jsDisplay = std::make_unique(display); + object->SetNativePointer(jsDisplay.release(), JsDisplay::Finalizer, nullptr); + + object->SetProperty("id", CreateJsValue(engine, static_cast(display->GetId()))); + object->SetProperty("width", CreateJsValue(engine, display->GetWidth())); + object->SetProperty("height", CreateJsValue(engine, display->GetHeight())); + object->SetProperty("refreshRate", CreateJsValue(engine, display->GetFreshRate())); + object->SetProperty("name", engine.CreateUndefined()); + object->SetProperty("alive", engine.CreateUndefined()); + object->SetProperty("state", engine.CreateUndefined()); + object->SetProperty("rotation", engine.CreateUndefined()); + object->SetProperty("densityDPI", engine.CreateUndefined()); + object->SetProperty("densityPixels", engine.CreateUndefined()); + object->SetProperty("scaledDensity", engine.CreateUndefined()); + object->SetProperty("xDPI", engine.CreateUndefined()); + object->SetProperty("yDPI", engine.CreateUndefined()); + + std::shared_ptr jsDisplayRef; + jsDisplayRef.reset(engine.CreateReference(objValue, 1)); + DisplayId displayId = display->GetId(); + std::lock_guard lock(g_mutex); + g_JsDisplayMap[displayId] = jsDisplayRef; + return objValue; +} +} // namespace Rosen +} // namespace OHOS diff --git a/interfaces/kits/napi/display/js_display.h b/interfaces/kits/napi/display/js_display.h new file mode 100644 index 00000000..837fb3b9 --- /dev/null +++ b/interfaces/kits/napi/display/js_display.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef OHOS_JS_DISPLAY_H +#define OHOS_JS_DISPLAY_H +#include "js_runtime_utils.h" +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "display.h" + +namespace OHOS { +namespace Rosen { +NativeValue* CreateJsDisplayObject(NativeEngine& engine, sptr& Display); +class JsDisplay final { +public: + explicit JsDisplay(const sptr& Display); + ~JsDisplay(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + +private: + sptr display_ = nullptr; +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/interfaces/kits/napi/display/js_display_listener.cpp b/interfaces/kits/napi/display/js_display_listener.cpp new file mode 100644 index 00000000..ea78441e --- /dev/null +++ b/interfaces/kits/napi/display/js_display_listener.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022 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 "js_display_listener.h" +#include "js_runtime_utils.h" +#include "window_manager_hilog.h" +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsDisplayListener"}; +} + +void JsDisplayListener::AddCallback(NativeValue* jsListenerObject) +{ + WLOGFI("JsDisplayListener::AddCallback is called"); + std::unique_ptr callbackRef; + if (engine_ == nullptr) { + WLOGFE("engine_ nullptr"); + return; + } + callbackRef.reset(engine_->CreateReference(jsListenerObject, 1)); + std::lock_guard lock(mtx_); + jsCallBack_.push_back(std::move(callbackRef)); + WLOGFI("JsDisplayListener::AddCallback success jsCallBack_ size: %{public}u!", + static_cast(jsCallBack_.size())); +} + +void JsDisplayListener::RemoveAllCallback() +{ + std::lock_guard lock(mtx_); + jsCallBack_.clear(); +} + +void JsDisplayListener::RemoveCallback(NativeValue* jsListenerObject) +{ + std::lock_guard lock(mtx_); + for (auto iter = jsCallBack_.begin(); iter != jsCallBack_.end();) { + if (jsListenerObject->StrictEquals((*iter)->Get())) { + jsCallBack_.erase(iter); + } else { + iter++; + } + } + WLOGFI("JsDisplayListener::RemoveCallback success jsCallBack_ size: %{public}u!", + static_cast(jsCallBack_.size())); +} + +void JsDisplayListener::CallJsMethod(const char* methodName, NativeValue* const* argv, size_t argc) +{ + WLOGFI("CallJsMethod methodName = %{public}s", methodName); + if (engine_ == nullptr) { + WLOGFE("engine_ nullptr"); + return; + } + for (auto& callback : jsCallBack_) { + NativeValue* method = callback->Get(); + if (method == nullptr) { + WLOGFE("Failed to get method callback from object"); + continue; + } + engine_->CallFunction(engine_->CreateUndefined(), method, argv, argc); + } +} + +void JsDisplayListener::OnCreate(DisplayId id) +{ + std::lock_guard lock(mtx_); + WLOGFI("JsDisplayListener::OnCreate is called, displayId: %{public}d", static_cast(id)); + if (jsCallBack_.empty()) { + WLOGFE("JsDisplayListener::OnCreate not register!"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod("add", argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} + +void JsDisplayListener::OnDestroy(DisplayId id) +{ + std::lock_guard lock(mtx_); + WLOGFI("JsDisplayListener::OnDestroy is called, displayId: %{public}d", static_cast(id)); + if (jsCallBack_.empty()) { + WLOGFE("JsDisplayListener::OnDestroy not register!"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod("remove", argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} + +void JsDisplayListener::OnChange(DisplayId id, DisplayChangeEvent event) +{ + std::lock_guard lock(mtx_); + WLOGFI("JsDisplayListener::OnChange is called, displayId: %{public}d", static_cast(id)); + if (jsCallBack_.empty()) { + WLOGFE("JsDisplayListener::OnChange not register!"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod("change", argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/display/js_display_listener.h b/interfaces/kits/napi/display/js_display_listener.h new file mode 100644 index 00000000..6566b655 --- /dev/null +++ b/interfaces/kits/napi/display/js_display_listener.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef OHOS_JS_DISPLAY_LISTENER_H +#define OHOS_JS_DISPLAY_LISTENER_H + +#include +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "refbase.h" +#include "display_manager.h" + +namespace OHOS { +namespace Rosen { +class JsDisplayListener : public DisplayManager::IDisplayListener { +public: + explicit JsDisplayListener(NativeEngine* engine) : engine_(engine) {} + ~JsDisplayListener() override = default; + void AddCallback(NativeValue* jsListenerObject); + void RemoveAllCallback(); + void RemoveCallback(NativeValue* jsListenerObject); + void OnCreate(DisplayId id) override; + void OnDestroy(DisplayId id) override; + void OnChange(DisplayId id, DisplayChangeEvent event) override; + +private: + void CallJsMethod(const char* methodName, NativeValue* const* argv = nullptr, size_t argc = 0); + NativeEngine* engine_ = nullptr; + std::mutex mtx_; + std::vector> jsCallBack_; + NativeValue* CreateDisplayIdArray(NativeEngine& engine, const std::vector& data); +}; +} // namespace Rosen +} // namespace OHOS +#endif /* OHOS_JS_DISPLAY_LISTENER_H */ \ No newline at end of file diff --git a/interfaces/kits/napi/display/js_display_manager.cpp b/interfaces/kits/napi/display/js_display_manager.cpp new file mode 100644 index 00000000..f0557f95 --- /dev/null +++ b/interfaces/kits/napi/display/js_display_manager.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022 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 "js_runtime_utils.h" +#include "native_engine/native_reference.h" +#include "display_manager.h" +#include "window_manager_hilog.h" +#include "singleton_container.h" +#include "js_display_listener.h" +#include "js_display.h" +#include "js_display_manager.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +constexpr size_t ARGC_ONE = 1; +constexpr size_t ARGC_TWO = 2; +constexpr int32_t INDEX_ONE = 1; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsDisplayManager"}; +} + +class JsDisplayManager { +public: +explicit JsDisplayManager(NativeEngine* engine) { +} + +~JsDisplayManager() = default; + +static void Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFI("JsDisplayManager::Finalizer is called"); + std::unique_ptr(static_cast(data)); +} + +static NativeValue* GetDefaultDisplay(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetDefaultDisplay(*engine, *info) : nullptr; +} + +static NativeValue* RegisterDisplayManagerCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnRegisterDisplayManagerCallback(*engine, *info) : nullptr; +} + +static NativeValue* UnregisterDisplayManagerCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnUnregisterDisplayManagerCallback(*engine, *info) : nullptr; +} + +private: +std::map, sptr>> jsCbMap_; +std::mutex mtx_; + +NativeValue* OnGetDefaultDisplay(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnGetDefaultDisplay is called"); + AsyncTask::CompleteCallback complete = + [](NativeEngine& engine, AsyncTask& task, int32_t status) { + sptr display = SingletonContainer::Get().GetDefaultDisplay(); + if (display != nullptr) { + task.Resolve(engine, CreateJsDisplayObject(engine, display)); + WLOGFI("JsDisplayManager::OnGetDefaultDisplay success"); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DMError::DM_ERROR_NULLPTR), "JsDisplayManager::OnGetDefaultDisplay failed.")); + } + }; + NativeValue* lastParam = nullptr; + NativeValue* result = nullptr; + AsyncTask::Schedule( + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +void RegisterDisplayListenerWithType(NativeEngine& engine, const std::string& type, NativeValue* value) +{ + if (IfCallbackRegistered(type, value)) { + WLOGFE("JsDisplayManager::RegisterDisplayListenerWithType callback already registered!"); + return; + } + std::unique_ptr callbackRef; + callbackRef.reset(engine.CreateReference(value, 1)); + sptr displayListener = new JsDisplayListener(&engine); + if (type == "add" || type == "remove" || type == "change") { + SingletonContainer::Get().RegisterDisplayListener(displayListener); + WLOGFI("JsDisplayManager::RegisterDisplayListenerWithType success"); + } else { + WLOGFE("JsDisplayManager::RegisterDisplayListenerWithType failed method: %{public}s not support!", + type.c_str()); + return; + } + displayListener->AddCallback(value); + jsCbMap_[type][std::move(callbackRef)] = displayListener; +} + +bool IfCallbackRegistered(const std::string& type, NativeValue* jsListenerObject) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("JsDisplayManager::IfCallbackRegistered methodName %{public}s not registered!", type.c_str()); + return false; + } + + for (auto& iter : jsCbMap_[type]) { + if (jsListenerObject->StrictEquals(iter.first->Get())) { + WLOGFE("JsDisplayManager::IfCallbackRegistered callback already registered!"); + return true; + } + } + return false; +} + +void UnregisterAllDisplayListenerWithType(const std::string& type) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("JsDisplayManager::UnregisterAllDisplayListenerWithType methodName %{public}s not registered!", + type.c_str()); + return; + } + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + it->second->RemoveAllCallback(); + if (type == "add" || type == "remove" || type == "change") { + sptr thisListener(it->second); + SingletonContainer::Get().UnregisterDisplayListener(thisListener); + WLOGFI("JsDisplayManager::UnregisterAllDisplayListenerWithType success"); + } + jsCbMap_[type].erase(it++); + } + jsCbMap_.erase(type); +} + +void UnRegisterDisplayListenerWithType(const std::string& type, NativeValue* value) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("JsDisplayManager::UnRegisterDisplayListenerWithType methodName %{public}s not registered!", + type.c_str()); + return; + } + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + if (value->StrictEquals(it->first->Get())) { + it->second->RemoveCallback(value); + if (type == "add" || type == "remove" || type == "change") { + sptr thisListener(it->second); + SingletonContainer::Get().UnregisterDisplayListener(thisListener); + WLOGFI("JsDisplayManager::UnRegisterDisplayListenerWithType success"); + } + jsCbMap_[type].erase(it++); + break; + } else { + it++; + } + } + if (jsCbMap_[type].empty()) { + jsCbMap_.erase(type); + } +} + +NativeValue* OnRegisterDisplayManagerCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback is called"); + if (info.argc != ARGC_TWO) { + WLOGFE("JsDisplayManager Params not match: %{public}zu", info.argc); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("Failed to convert parameter to callbackType"); + return engine.CreateUndefined(); + } + NativeValue* value = info.argv[INDEX_ONE]; + if (value == nullptr) { + WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is nullptr"); + return engine.CreateUndefined(); + } + if (!value->IsCallable()) { + WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is not callable"); + return engine.CreateUndefined(); + } + std::lock_guard lock(mtx_); + RegisterDisplayListenerWithType(engine, cbType, value); + return engine.CreateUndefined(); +} + +NativeValue* OnUnregisterDisplayManagerCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnUnregisterDisplayCallback is called"); + if (info.argc == 0) { + WLOGFE("JsDisplayManager Params not match %{public}zu", info.argc); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("Failed to convert parameter to callbackType"); + return engine.CreateUndefined(); + } + std::lock_guard lock(mtx_); + if (info.argc == ARGC_ONE) { + UnregisterAllDisplayListenerWithType(cbType); + } else { + NativeValue* value = info.argv[INDEX_ONE]; + if (value == nullptr) { + WLOGFI("JsDisplayManager::OnUnregisterDisplayManagerCallback info->argv[1] is nullptr"); + return engine.CreateUndefined(); + } + if (!value->IsCallable()) { + WLOGFI("JsDisplayManager::OnUnregisterDisplayManagerCallback info->argv[1] is not callable"); + return engine.CreateUndefined(); + } + UnRegisterDisplayListenerWithType(cbType, value); + } + return engine.CreateUndefined(); +} +}; + +NativeValue* JsDisplayManagerInit(NativeEngine* engine, NativeValue* exportObj) +{ + WLOGFI("JsDisplayManagerInit is called"); + + if (engine == nullptr || exportObj == nullptr) { + WLOGFE("JsDisplayManagerInit engine or exportObj is nullptr"); + return nullptr; + } + + NativeObject* object = ConvertNativeValueTo(exportObj); + if (object == nullptr) { + WLOGFE("JsDisplayManagerInit object is nullptr"); + return nullptr; + } + + std::unique_ptr jsDisplayManager = std::make_unique(engine); + object->SetNativePointer(jsDisplayManager.release(), JsDisplayManager::Finalizer, nullptr); + + BindNativeFunction(*engine, *object, "getDefaultDisplay", JsDisplayManager::GetDefaultDisplay); + BindNativeFunction(*engine, *object, "on", JsDisplayManager::RegisterDisplayManagerCallback); + BindNativeFunction(*engine, *object, "off", JsDisplayManager::UnregisterDisplayManagerCallback); + return engine->CreateUndefined(); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/napi/display/native_display_module.h b/interfaces/kits/napi/display/js_display_manager.h similarity index 59% rename from interfaces/kits/napi/display/native_display_module.h rename to interfaces/kits/napi/display/js_display_manager.h index a24c7026..30f19812 100644 --- a/interfaces/kits/napi/display/native_display_module.h +++ b/interfaces/kits/napi/display/js_display_manager.h @@ -1,19 +1,28 @@ -/* - * Copyright (c) 2021 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. - */ - -#ifndef INTERFACES_KITS_NAPI_GRAPHIC_DISPLAY_NATIVE_MODULE_H -#define INTERFACES_KITS_NAPI_GRAPHIC_DISPLAY_NATIVE_MODULE_H - -#endif // INTERFACES_KITS_NAPI_GRAPHIC_DISPLAY_NATIVE_MODULE_H +/* + * Copyright (c) 2022 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. + */ + +#ifndef OHOS_JS_DISPLAY_MANAGER_H +#define OHOS_JS_DISPLAY_MANAGER_H + +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" + +namespace OHOS { +namespace Rosen { +NativeValue* JsDisplayManagerInit(NativeEngine* engine, NativeValue* exportObj); +} // namespace Rosen +} // namespace OHOS + +#endif diff --git a/interfaces/kits/napi/display/js_display_module.cpp b/interfaces/kits/napi/display/js_display_module.cpp new file mode 100644 index 00000000..83e7418a --- /dev/null +++ b/interfaces/kits/napi/display/js_display_module.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 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 "js_display_manager.h" +#include "native_engine/native_engine.h" + +extern "C" __attribute__((constructor)) void NAPI_application_displaymanager_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "display", + .fileName = "module/libdisplay_napi.so/display.js", + .registerCallback = OHOS::Rosen::JsDisplayManagerInit, + }; + + moduleManager->Register(&newModuleInfo); +} diff --git a/interfaces/kits/napi/display/native_display_module.cpp b/interfaces/kits/napi/display/native_display_module.cpp deleted file mode 100644 index 3f6db473..00000000 --- a/interfaces/kits/napi/display/native_display_module.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2021 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 "display_manager.h" - -#include - -#include "native_display_module.h" -#include "wm_common.h" -#include "wm_napi_common.h" - -namespace OHOS { -namespace Rosen { -namespace getDefaultDisplay { -struct Param { - WMError wret; - sptr display; -}; - -void Async(napi_env env, std::unique_ptr ¶m) -{ - param->display = DisplayManager::GetInstance().GetDefaultDisplay(); - if (param->display == nullptr) { - GNAPI_LOG("Get display failed!"); - param->wret = WMError::WM_ERROR_NULLPTR; - return; - } - GNAPI_LOG("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d", - param->display->GetId(), param->display->GetWidth(), param->display->GetHeight()); - param->wret = WMError::WM_OK; -} - -napi_value Resolve(napi_env env, std::unique_ptr ¶m) -{ - napi_value result; - if (param->wret != WMError::WM_OK) { - NAPI_CALL(env, napi_get_undefined(env, &result)); - return result; - } - - DisplayId id = param->display->GetId(); - int32_t width = param->display->GetWidth(); - int32_t height = param->display->GetHeight(); - GNAPI_LOG("id : %{public}" PRIu64"", id); - GNAPI_LOG("width : %{public}d", width); - GNAPI_LOG("height : %{public}d", height); - - NAPI_CALL(env, napi_create_object(env, &result)); - NAPI_CALL(env, SetMemberInt32(env, result, "id", id)); - NAPI_CALL(env, SetMemberUndefined(env, result, "name")); - NAPI_CALL(env, SetMemberUndefined(env, result, "alive")); - NAPI_CALL(env, SetMemberUndefined(env, result, "state")); - NAPI_CALL(env, SetMemberUndefined(env, result, "refreshRate")); - NAPI_CALL(env, SetMemberUndefined(env, result, "rotation")); - NAPI_CALL(env, SetMemberUint32(env, result, "width", width)); - NAPI_CALL(env, SetMemberUint32(env, result, "height", height)); - NAPI_CALL(env, SetMemberUndefined(env, result, "densityDPI")); - NAPI_CALL(env, SetMemberUndefined(env, result, "densityPixels")); - NAPI_CALL(env, SetMemberUndefined(env, result, "scaledDensity")); - NAPI_CALL(env, SetMemberUndefined(env, result, "xDPI")); - NAPI_CALL(env, SetMemberUndefined(env, result, "yDPI")); - - return result; -} - -napi_value MainFunc(napi_env env, napi_callback_info info) -{ - GNAPI_LOG("Display Interface: getDefaultDisplay()"); - GNAPI_LOG("%{public}s called", __PRETTY_FUNCTION__); - auto param = std::make_unique(); - return CreatePromise(env, __PRETTY_FUNCTION__, Async, Resolve, param); -} -} // namespace getDefaultDisplay - -napi_value DisplayModuleInit(napi_env env, napi_value exports) -{ - GNAPI_LOG("%{public}s called", __PRETTY_FUNCTION__); - - napi_property_descriptor properties[] = { - DECLARE_NAPI_FUNCTION("getDefaultDisplay", getDefaultDisplay::MainFunc), - }; - - NAPI_CALL(env, napi_define_properties(env, - exports, sizeof(properties) / sizeof(properties[0]), properties)); - return exports; -} -} // namespace Rosen -} // namespace OHOS - -extern "C" __attribute__((constructor)) void RegisterModule(void) -{ - napi_module displayModule = { - .nm_version = 1, // NAPI v1 - .nm_flags = 0, // normal - .nm_filename = nullptr, - .nm_register_func = OHOS::Rosen::DisplayModuleInit, - .nm_modname = "display", - .nm_priv = nullptr, - }; - napi_module_register(&displayModule); -} diff --git a/interfaces/kits/napi/display_runtime/api/@ohos.screen.d.ts b/interfaces/kits/napi/display_runtime/api/@ohos.screen.d.ts index 0f6c6060..93a42702 100644 --- a/interfaces/kits/napi/display_runtime/api/@ohos.screen.d.ts +++ b/interfaces/kits/napi/display_runtime/api/@ohos.screen.d.ts @@ -150,6 +150,8 @@ declare namespace screen { ADD_TO_GROUP = 0, REMOVE_FROM_GROUP = 1, CHANGE_GROUP = 2, + UPDATE_ROTATION = 3, + CHANGE_MODE = 4, } /** diff --git a/interfaces/kits/napi/display_runtime/napi/js_screen.cpp b/interfaces/kits/napi/display_runtime/napi/js_screen.cpp index e977b597..d284fa77 100644 --- a/interfaces/kits/napi/display_runtime/napi/js_screen.cpp +++ b/interfaces/kits/napi/display_runtime/napi/js_screen.cpp @@ -43,6 +43,10 @@ void JsScreen::Finalizer(NativeEngine* engine, void* data, void* hint) { WLOGFI("JsScreen::Finalizer is called"); auto jsScreen = std::unique_ptr(static_cast(data)); + if (jsScreen == nullptr) { + WLOGFE("jsScreen::Finalizer jsScreen is null"); + return; + } sptr screen = jsScreen->screen_; if (screen == nullptr) { WLOGFE("JsScreen::Finalizer screen is null"); diff --git a/interfaces/kits/napi/display_runtime/napi/js_screen_listener.cpp b/interfaces/kits/napi/display_runtime/napi/js_screen_listener.cpp index 2f225be9..adffec51 100644 --- a/interfaces/kits/napi/display_runtime/napi/js_screen_listener.cpp +++ b/interfaces/kits/napi/display_runtime/napi/js_screen_listener.cpp @@ -80,16 +80,26 @@ void JsScreenListener::OnConnect(ScreenId id) WLOGFE("JsScreenListener::OnConnect not register!"); return; } - NativeValue* propertyValue = engine_->CreateObject(); - NativeObject* object = ConvertNativeValueTo(propertyValue); - if (object == nullptr) { - WLOGFE("Failed to convert prop to jsObject"); - return; - } - object->SetProperty("screenId", CreateJsValue(*engine_, static_cast(id))); - object->SetProperty("type", CreateJsValue(*engine_, SCREEN_CONNECT_TYPE)); - NativeValue* argv[] = {propertyValue}; - CallJsMethod("screenConnectEvent", argv, ArraySize(argv)); + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* propertyValue = engine_->CreateObject(); + NativeObject* object = ConvertNativeValueTo(propertyValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return; + } + object->SetProperty("screenId", CreateJsValue(*engine_, static_cast(id))); + object->SetProperty("type", CreateJsValue(*engine_, SCREEN_CONNECT_TYPE)); + NativeValue* argv[] = {propertyValue}; + CallJsMethod("screenConnectEvent", argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); } void JsScreenListener::OnDisconnect(ScreenId id) @@ -100,16 +110,26 @@ void JsScreenListener::OnDisconnect(ScreenId id) WLOGFE("JsScreenListener::OnDisconnect not register!"); return; } - NativeValue* propertyValue = engine_->CreateObject(); - NativeObject* object = ConvertNativeValueTo(propertyValue); - if (object == nullptr) { - WLOGFE("Failed to convert prop to jsObject"); - return; - } - object->SetProperty("screenId", CreateJsValue(*engine_, static_cast(id))); - object->SetProperty("type", CreateJsValue(*engine_, SCREEN_DISCONNECT_TYPE)); - NativeValue* argv[] = {propertyValue}; - CallJsMethod("screenConnectEvent", argv, ArraySize(argv)); + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* propertyValue = engine_->CreateObject(); + NativeObject* object = ConvertNativeValueTo(propertyValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return; + } + object->SetProperty("screenId", CreateJsValue(*engine_, static_cast(id))); + object->SetProperty("type", CreateJsValue(*engine_, SCREEN_DISCONNECT_TYPE)); + NativeValue* argv[] = {propertyValue}; + CallJsMethod("screenConnectEvent", argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); } void JsScreenListener::OnChange(const std::vector &vector, ScreenChangeEvent event) @@ -120,16 +140,26 @@ void JsScreenListener::OnChange(const std::vector &vector, ScreenChang WLOGFE("JsScreenListener::OnChange not register!"); return; } - NativeValue* propertyValue = engine_->CreateObject(); - NativeObject* object = ConvertNativeValueTo(propertyValue); - if (object == nullptr) { - WLOGFE("Failed to convert prop to jsObject"); - return; - } - object->SetProperty("screenId", CreateScreenIdArray(*engine_, vector)); - object->SetProperty("type", CreateJsValue(*engine_, event)); - NativeValue* argv[] = {propertyValue}; - CallJsMethod("screenChangeEvent", argv, ArraySize(argv)); + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* propertyValue = engine_->CreateObject(); + NativeObject* object = ConvertNativeValueTo(propertyValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return; + } + object->SetProperty("screenId", CreateScreenIdArray(*engine_, vector)); + object->SetProperty("type", CreateJsValue(*engine_, event)); + NativeValue* argv[] = {propertyValue}; + CallJsMethod("screenChangeEvent", argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule(*engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); } NativeValue* JsScreenListener::CreateScreenIdArray(NativeEngine& engine, const std::vector& data) diff --git a/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp b/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp index f70e49fa..40773b52 100644 --- a/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp +++ b/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp @@ -209,6 +209,10 @@ NativeValue* OnRegisterScreenMangerCallback(NativeEngine& engine, NativeCallback return engine.CreateUndefined(); } NativeValue* value = info.argv[INDEX_ONE]; + if (value == nullptr) { + WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback info->argv[1] is nullptr"); + return engine.CreateUndefined(); + } if (!value->IsCallable()) { WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback info->argv[1] is not callable"); return engine.CreateUndefined(); @@ -235,6 +239,10 @@ NativeValue* OnUnregisterScreenManagerCallback(NativeEngine& engine, NativeCallb UnregisterAllScreenListenerWithType(cbType); } else { NativeValue* value = info.argv[INDEX_ONE]; + if (value == nullptr) { + WLOGFI("JsScreenManager::OnUnregisterScreenManagerCallback info->argv[1] is nullptr"); + return engine.CreateUndefined(); + } if (!value->IsCallable()) { WLOGFI("JsScreenManager::OnUnregisterScreenManagerCallback info->argv[1] is not callable"); return engine.CreateUndefined(); diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp index dc8c5fec..fdbe8dd1 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -48,6 +48,10 @@ void JsWindow::Finalizer(NativeEngine* engine, void* data, void* hint) { WLOGFI("JsWindow::Finalizer is called"); auto jsWin = std::unique_ptr(static_cast(data)); + if (jsWin == nullptr) { + WLOGFE("JsWindow::Finalizer JsWindow is null"); + return; + } std::string windowName = jsWin->GetWindowName(); WLOGFI("JsWindow::Finalizer windowName : %{public}s", windowName.c_str()); std::lock_guard lock(g_mutex); From b4c86170c82de4cf55591f943385fd7caa1d3d23 Mon Sep 17 00:00:00 2001 From: lu Date: Sat, 19 Feb 2022 17:20:36 +0800 Subject: [PATCH 15/70] update the size of the Display after rotate screen Signed-off-by: lu Change-Id: I918630d93678f4cdce904461e4a0f0efc846b2fd --- dm/include/display_manager_adapter.h | 2 ++ dm/src/display.cpp | 30 ++++++++++++++++++++++ dm/src/display_manager_adapter.cpp | 32 ++++++++++++++++++++++++ dm/src/screen.cpp | 32 ++++++++++++++++++++++++ dmserver/include/abstract_display.h | 1 + dmserver/src/abstract_display.cpp | 5 ++++ dmserver/src/display_manager_service.cpp | 1 + 7 files changed, 103 insertions(+) diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index bc1e6377..aa129871 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -67,6 +67,8 @@ public: virtual void NotifyDisplayEvent(DisplayEvent event); virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); virtual void Clear(); + virtual DisplayInfo GetDisplayInfo(DisplayId displayId); + virtual sptr GetScreenInfo(ScreenId screenId); virtual sptr GetScreenById(ScreenId screenId); virtual sptr GetScreenGroupById(ScreenId screenId); virtual std::vector> GetAllScreens(); diff --git a/dm/src/display.cpp b/dm/src/display.cpp index 503d1d41..4b354442 100644 --- a/dm/src/display.cpp +++ b/dm/src/display.cpp @@ -15,19 +15,40 @@ #include "display.h" #include "display_info.h" +#include "display_manager_adapter.h" +#include "window_manager_hilog.h" namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "Display"}; +} class Display::Impl : public RefBase { friend class Display; private: + void UpdateDisplay(sptr info); + std::string name_; DisplayId id_ { DISPLAY_ID_INVALD }; int32_t width_ { 0 }; int32_t height_ { 0 }; uint32_t freshRate_ { 0 }; ScreenId screenId_ {SCREEN_ID_INVALID}; + Rotation rotation_ { Rotation::ROTATION_0 }; }; +void Display::Impl::UpdateDisplay(sptr info) +{ + if (info == nullptr) { + WLOGFE("info is nullptr."); + return; + } + width_ = info->width_; + height_ = info->height_; + freshRate_ = info->freshRate_; + screenId_ = info->screenId_; + rotation_ = info->rotation_; +} + Display::Display(const std::string& name, DisplayInfo* info) : pImpl_(new Impl()) { @@ -37,6 +58,7 @@ Display::Display(const std::string& name, DisplayInfo* info) pImpl_->height_ = info->height_; pImpl_->freshRate_ = info->freshRate_; pImpl_->screenId_ = info->screenId_; + pImpl_->rotation_ = info->rotation_; } DisplayId Display::GetId() const @@ -46,21 +68,29 @@ DisplayId Display::GetId() const int32_t Display::GetWidth() const { + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(&info); return pImpl_->width_; } int32_t Display::GetHeight() const { + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(&info); return pImpl_->height_; } uint32_t Display::GetFreshRate() const { + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(&info); return pImpl_->freshRate_; } ScreenId Display::GetScreenId() const { + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(&info); return pImpl_->screenId_; } diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 9e2151b2..80ad19ba 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -378,6 +378,38 @@ DMError DisplayManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vectorMakeMirror(mainScreenId, mirrorScreenId); } +sptr DisplayManagerAdapter::GetScreenInfo(ScreenId screenId) +{ + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("screen id is invalid"); + return nullptr; + } + std::lock_guard lock(mutex_); + if (!InitDMSProxyLocked()) { + WLOGFE("InitDMSProxyLocked failed!"); + return nullptr; + } + sptr screenInfo = displayManagerServiceProxy_->GetScreenInfoById(screenId); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is null"); + } + return screenInfo; +} + +DisplayInfo DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) +{ + if (displayId == DISPLAY_ID_INVALD) { + WLOGFE("screen id is invalid"); + return DisplayInfo(); + } + std::lock_guard lock(mutex_); + if (!InitDMSProxyLocked()) { + WLOGFE("InitDMSProxyLocked failed!"); + return DisplayInfo(); + } + return displayManagerServiceProxy_->GetDisplayInfoById(displayId); +} + sptr DisplayManagerAdapter::GetScreenById(ScreenId screenId) { std::lock_guard lock(mutex_); diff --git a/dm/src/screen.cpp b/dm/src/screen.cpp index 61875599..d4a227b3 100644 --- a/dm/src/screen.cpp +++ b/dm/src/screen.cpp @@ -29,6 +29,7 @@ friend class Screen; public: Impl() = default; ~Impl() = default; + void UpdateScreen(sptr info); ScreenId id_ { SCREEN_ID_INVALID }; uint32_t virtualWidth_ { 0 }; @@ -41,6 +42,22 @@ public: Rotation rotation_ { Rotation::ROTATION_0 }; }; +void Screen::Impl::UpdateScreen(sptr info) +{ + if (info == nullptr) { + WLOGFE("info is nullptr."); + return; + } + virtualWidth_ = info->virtualWidth_; + virtualHeight_ = info->virtualHeight_; + virtualPixelRatio_ = info->virtualPixelRatio_; + parent_ = info->parent_; + canHasChild_ = info->canHasChild_; + modeId_ = info->modeId_; + modes_ = info->modes_; + rotation_ = info->rotation_; +} + Screen::Screen(const ScreenInfo* info) : pImpl_(new Impl()) { @@ -56,6 +73,7 @@ Screen::Screen(const ScreenInfo* info) pImpl_->canHasChild_ = info->canHasChild_; pImpl_->modeId_ = info->modeId_; pImpl_->modes_ = info->modes_; + pImpl_->rotation_ = info->rotation_; } Screen::~Screen() @@ -64,6 +82,8 @@ Screen::~Screen() bool Screen::IsGroup() const { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); return pImpl_->canHasChild_; } @@ -74,6 +94,8 @@ ScreenId Screen::GetId() const uint32_t Screen::GetWidth() const { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); auto modeId = pImpl_->modeId_; auto modes = pImpl_->modes_; if (modeId < 0 || modeId >= modes.size()) { @@ -84,6 +106,8 @@ uint32_t Screen::GetWidth() const uint32_t Screen::GetHeight() const { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); auto modeId = pImpl_->modeId_; auto modes = pImpl_->modes_; if (modeId < 0 || modeId >= modes.size()) { @@ -94,21 +118,29 @@ uint32_t Screen::GetHeight() const uint32_t Screen::GetVirtualWidth() const { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); return pImpl_->virtualWidth_; } uint32_t Screen::GetVirtualHeight() const { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); return pImpl_->virtualHeight_; } float Screen::GetVirtualPixelRatio() const { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); return pImpl_->virtualPixelRatio_; } Rotation Screen::GetRotation() { + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); return pImpl_->rotation_; } diff --git a/dmserver/include/abstract_display.h b/dmserver/include/abstract_display.h index bfd4e03c..3b505006 100644 --- a/dmserver/include/abstract_display.h +++ b/dmserver/include/abstract_display.h @@ -51,6 +51,7 @@ public: void SetFreshRate(uint32_t freshRate); void SetVirtualPixelRatio(float virtualPixelRatio); bool RequestRotation(Rotation rotation); + Rotation GetRotation(); private: DisplayId id_ { DISPLAY_ID_INVALD }; diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index 7f8334a9..e9ad85f9 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -107,6 +107,11 @@ bool AbstractDisplay::RequestRotation(Rotation rotation) return true; } +Rotation AbstractDisplay::GetRotation() +{ + return rotation_; +} + bool AbstractDisplay::BindAbstractScreen(ScreenId dmsScreenId) { sptr screenController diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index b2c9b499..0e3c34e0 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -102,6 +102,7 @@ DisplayInfo DisplayManagerService::GetDisplayInfoById(DisplayId displayId) displayInfo.height_ = display->GetHeight(); displayInfo.freshRate_ = display->GetFreshRate(); displayInfo.screenId_ = display->GetAbstractScreenId(); + displayInfo.rotation_ = display->GetRotation(); return displayInfo; } From 81e986f270086cd2a0f051a118345acf430c7dcc Mon Sep 17 00:00:00 2001 From: chenqinxin Date: Mon, 21 Feb 2022 10:12:56 +0800 Subject: [PATCH 16/70] =?UTF-8?q?=E9=94=81=E5=B1=8F=E8=A7=A3=E9=94=81?= =?UTF-8?q?=E4=BB=A5=E5=90=8E=E5=9B=9E=E8=B0=83ability=E7=94=9F=E5=91=BD?= =?UTF-8?q?=E5=91=A8=E6=9C=9F=E5=8F=98=E5=8C=96=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chenqinxin Change-Id: I04fb2e448c089bd5fee2e66d9dc22fd726b962a2 --- wm/src/window_impl.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index a92b3194..bd797a1a 100644 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -1125,26 +1125,22 @@ void WindowImpl::UpdateWindowState(WindowState state) switch (state) { case WindowState::STATE_FROZEN: { state_ = WindowState::STATE_HIDDEN; - if (uiContent_ != nullptr) { - uiContent_->Background(); - } if (abilityContext_ != nullptr) { WLOGFD("DoAbilityBackground KEYGUARD, id: %{public}d", GetWindowId()); AAFwk::AbilityManagerClient::GetInstance()->DoAbilityBackground(abilityContext_->GetToken(), static_cast(WindowStateChangeReason::KEYGUARD)); } + NotifyAfterBackground(); break; } case WindowState::STATE_UNFROZEN: { state_ = WindowState::STATE_SHOWN; - if (uiContent_ != nullptr) { - uiContent_->Foreground(); - } if (abilityContext_ != nullptr) { WLOGFD("DoAbilityForeground KEYGUARD, id: %{public}d", GetWindowId()); AAFwk::AbilityManagerClient::GetInstance()->DoAbilityForeground(abilityContext_->GetToken(), static_cast(WindowStateChangeReason::KEYGUARD)); } + NotifyAfterForeground(); break; } default: { From 3a709974503fd4056a934a1e605ebb19f1ac2819 Mon Sep 17 00:00:00 2001 From: xiaojianfeng Date: Thu, 17 Feb 2022 16:39:39 +0800 Subject: [PATCH 17/70] =?UTF-8?q?modify=20screenInfo=EF=BC=8C=20screengrou?= =?UTF-8?q?pinfo=EF=BC=8C=20displayInfo=EF=BC=8C=20screen=EF=BC=8C=20scree?= =?UTF-8?q?ngroup=EF=BC=8C=20display?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiaojianfeng Change-Id: I16c23ce2bba78db54f35be08423c0d6675d1e643 --- dm/include/display_manager_adapter.h | 94 +++++----- dm/src/display.cpp | 92 ++++------ dm/src/display_manager.cpp | 12 +- dm/src/display_manager_adapter.cpp | 164 +++++++++++------- dm/src/screen.cpp | 133 ++++++-------- dm/src/screen_group.cpp | 40 +++-- dm/src/screen_manager.cpp | 28 +-- .../unittest/mock_display_manager_adapter.h | 34 +++- dm/test/unittest/screen_manager_test.cpp | 2 +- dm/test/unittest/screen_test.cpp | 2 +- dmserver/include/abstract_display.h | 4 +- dmserver/include/abstract_screen.h | 4 +- dmserver/include/display_manager_interface.h | 2 +- dmserver/include/display_manager_proxy.h | 2 +- dmserver/include/display_manager_service.h | 2 +- dmserver/src/abstract_display.cpp | 16 +- dmserver/src/abstract_screen.cpp | 4 +- dmserver/src/display_manager_proxy.cpp | 19 +- dmserver/src/display_manager_service.cpp | 13 +- .../src/display_manager_service_inner.cpp | 2 +- dmserver/src/display_manager_stub.cpp | 7 +- interfaces/innerkits/dm/display.h | 15 +- interfaces/innerkits/dm/screen.h | 10 +- interfaces/innerkits/dm/screen_group.h | 12 +- utils/include/class_var_defination.h | 59 +++++++ utils/include/display_info.h | 29 ++-- utils/include/screen_group_info.h | 19 +- utils/include/screen_info.h | 30 ++-- utils/src/display_info.cpp | 24 +-- utils/src/screen_group_info.cpp | 27 ++- utils/src/screen_info.cpp | 28 ++- wmserver/src/input_window_monitor.cpp | 2 +- 32 files changed, 497 insertions(+), 434 deletions(-) create mode 100644 utils/include/class_var_defination.h diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index aa129871..19fe9849 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -28,35 +28,34 @@ #include "singleton_delegator.h" namespace OHOS::Rosen { -class DMSDeathRecipient : public IRemoteObject::DeathRecipient { +class BaseAdapter { public: - virtual void OnRemoteDied(const wptr& wptrDeath) override; -}; - -class DisplayManagerAdapter { -WM_DECLARE_SINGLE_INSTANCE(DisplayManagerAdapter); -public: - virtual DisplayId GetDefaultDisplayId(); - virtual sptr GetDisplayById(DisplayId displayId); - - virtual ScreenId CreateVirtualScreen(VirtualScreenOption option); - virtual DMError DestroyVirtualScreen(ScreenId screenId); - virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); - virtual bool RequestRotation(ScreenId screenId, Rotation rotation); - virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); - - // colorspace, gamut - virtual DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts); - virtual DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut); - virtual DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx); - virtual DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap); - virtual DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap); - virtual DMError SetScreenColorTransform(ScreenId screenId); - virtual bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type); virtual bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type); + virtual void Clear(); +protected: + bool InitDMSProxyLocked(); + std::recursive_mutex mutex_; + sptr displayManagerServiceProxy_ = nullptr; + sptr dmsDeath_ = nullptr; +}; + +class DMSDeathRecipient : public IRemoteObject::DeathRecipient { +public: + DMSDeathRecipient(BaseAdapter& adapter); + virtual void OnRemoteDied(const wptr& wptrDeath) override; +private: + BaseAdapter& adapter_; +}; + +class DisplayManagerAdapter : public BaseAdapter { +WM_DECLARE_SINGLE_INSTANCE(DisplayManagerAdapter); +public: + virtual DisplayId GetDefaultDisplayId(); + virtual sptr GetDisplayById(DisplayId displayId); + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); virtual bool WakeUpBegin(PowerStateChangeReason reason); virtual bool WakeUpEnd(); virtual bool SuspendBegin(PowerStateChangeReason reason); @@ -65,28 +64,45 @@ public: virtual bool SetDisplayState(DisplayState state); virtual DisplayState GetDisplayState(DisplayId displayId); virtual void NotifyDisplayEvent(DisplayEvent event); - virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); - virtual void Clear(); - virtual DisplayInfo GetDisplayInfo(DisplayId displayId); - virtual sptr GetScreenInfo(ScreenId screenId); - virtual sptr GetScreenById(ScreenId screenId); - virtual sptr GetScreenGroupById(ScreenId screenId); - virtual std::vector> GetAllScreens(); - virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); - virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); - + virtual void UpdateDisplayInfo(DisplayId); private: - bool InitDMSProxyLocked(); + sptr GetDisplayInfo(DisplayId displayId); static inline SingletonDelegator delegator; - std::recursive_mutex mutex_; - sptr displayManagerServiceProxy_ = nullptr; - sptr dmsDeath_ = nullptr; std::map> displayMap_; + DisplayId defaultDisplayId_; +}; + +class ScreenManagerAdapter : public BaseAdapter { +WM_DECLARE_SINGLE_INSTANCE(ScreenManagerAdapter); +public: + virtual bool RequestRotation(ScreenId screenId, Rotation rotation); + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option); + virtual DMError DestroyVirtualScreen(ScreenId screenId); + virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); + virtual sptr GetScreenById(ScreenId screenId); + virtual sptr GetScreenGroupById(ScreenId screenId); + virtual std::vector> GetAllScreens(); + virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); + virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); + virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); + virtual void UpdateScreenInfo(ScreenId); + + // colorspace, gamut + virtual DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts); + virtual DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut); + virtual DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx); + virtual DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap); + virtual DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap); + virtual DMError SetScreenColorTransform(ScreenId screenId); +private: + sptr GetScreenInfo(ScreenId screenId); + + static inline SingletonDelegator delegator; + std::map> screenMap_; std::map> screenGroupMap_; - DisplayId defaultDisplayId_; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DM_DISPLAY_MANAGER_ADAPTER_H diff --git a/dm/src/display.cpp b/dm/src/display.cpp index 4b354442..6f3465d4 100644 --- a/dm/src/display.cpp +++ b/dm/src/display.cpp @@ -23,90 +23,61 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "Display"}; } class Display::Impl : public RefBase { -friend class Display; -private: - void UpdateDisplay(sptr info); - - std::string name_; - DisplayId id_ { DISPLAY_ID_INVALD }; - int32_t width_ { 0 }; - int32_t height_ { 0 }; - uint32_t freshRate_ { 0 }; - ScreenId screenId_ {SCREEN_ID_INVALID}; - Rotation rotation_ { Rotation::ROTATION_0 }; +public: + Impl(const std::string& name, sptr info) + { + name_= name; + if (info == nullptr) { + WLOGFE("DisplayInfo is nullptr."); + } + displayInfo_ = info; + } + ~Impl() = default; + DEFINE_VAR_FUNC_GET_SET(std::string, Name, name); + DEFINE_VAR_FUNC_GET_SET(sptr, DisplayInfo, displayInfo); }; -void Display::Impl::UpdateDisplay(sptr info) +Display::Display(const std::string& name, sptr info) + : pImpl_(new Impl(name, info)) { - if (info == nullptr) { - WLOGFE("info is nullptr."); - return; - } - width_ = info->width_; - height_ = info->height_; - freshRate_ = info->freshRate_; - screenId_ = info->screenId_; - rotation_ = info->rotation_; -} - -Display::Display(const std::string& name, DisplayInfo* info) - : pImpl_(new Impl()) -{ - pImpl_->name_ = name; - pImpl_->id_ = info->id_; - pImpl_->width_ = info->width_; - pImpl_->height_ = info->height_; - pImpl_->freshRate_ = info->freshRate_; - pImpl_->screenId_ = info->screenId_; - pImpl_->rotation_ = info->rotation_; } DisplayId Display::GetId() const { - return pImpl_->id_; + return pImpl_->GetDisplayInfo()->GetDisplayId(); } int32_t Display::GetWidth() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(&info); - return pImpl_->width_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetWidth(); } int32_t Display::GetHeight() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(&info); - return pImpl_->height_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetHeight(); } uint32_t Display::GetFreshRate() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(&info); - return pImpl_->freshRate_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetFreshRate(); } ScreenId Display::GetScreenId() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(&info); - return pImpl_->screenId_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetScreenId(); } -void Display::SetWidth(int32_t width) +void Display::UpdateDisplayInfo(sptr displayInfo) { - pImpl_->width_ = width; -} - -void Display::SetHeight(int32_t height) -{ - pImpl_->height_ = height; -} - -void Display::SetFreshRate(uint32_t freshRate) -{ - pImpl_->freshRate_ = freshRate; + if (displayInfo == nullptr) { + WLOGFE("displayInfo is invalid"); + return; + } + pImpl_->SetDisplayInfo(displayInfo); } float Display::GetVirtualPixelRatio() const @@ -118,9 +89,4 @@ float Display::GetVirtualPixelRatio() const return 2.0f; #endif } - -void Display::SetId(DisplayId id) -{ - pImpl_->id_ = id; -} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 096078c0..3bf45203 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -54,7 +54,7 @@ public: void OnDisplayCreate(sptr displayInfo) override { - if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { + if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayCreate, displayInfo is invalid."); return; } @@ -63,7 +63,7 @@ public: return; } for (auto listener : pImpl_->displayListeners_) { - listener->OnCreate(displayInfo->id_); + listener->OnCreate(displayInfo->GetDisplayId()); } }; @@ -84,7 +84,7 @@ public: void OnDisplayChange(const sptr displayInfo, DisplayChangeEvent event) override { - if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { + if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayChange, displayInfo is invalid."); return; } @@ -92,9 +92,9 @@ public: WLOGFE("OnDisplayChange, impl is nullptr."); return; } - WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->id_, event); + WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->GetDisplayId(), event); for (auto listener : pImpl_->displayListeners_) { - listener->OnChange(displayInfo->id_, event); + listener->OnChange(displayInfo->GetDisplayId(), event); } }; private: @@ -380,7 +380,7 @@ void DisplayManager::NotifyDisplayChangedEvent(const sptr info, Dis WLOGI("NotifyDisplayChangedEvent event:%{public}u, size:%{public}zu", event, pImpl_->displayListeners_.size()); std::lock_guard lock(pImpl_->mutex_); for (auto& listener : pImpl_->displayListeners_) { - listener->OnChange(info->id_, event); + listener->OnChange(info->GetDisplayId(), event); } } diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 80ad19ba..2e58f1d6 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -26,6 +26,7 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAdapter"}; } WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerAdapter) +WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManagerAdapter) DisplayId DisplayManagerAdapter::GetDefaultDisplayId() { @@ -56,35 +57,34 @@ sptr DisplayManagerAdapter::GetDisplayById(DisplayId displayId) if (iter != displayMap_.end()) { // Update display in map // should be updated automatically - DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); - if (displayInfo.id_ == DISPLAY_ID_INVALD) { + auto displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + if (displayInfo == nullptr) { + WLOGFE("GetDisplayById: displayInfo is nullptr!"); + displayMap_.erase(iter); + return nullptr; + } + if (displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { WLOGFE("GetDisplayById: Get invalid displayInfo!"); + displayMap_.erase(iter); return nullptr; } sptr display = iter->second; - if (displayInfo.width_ != display->GetWidth()) { - display->SetWidth(displayInfo.width_); - WLOGFI("GetDisplayById: set new width %{public}d", display->GetWidth()); - } - if (displayInfo.height_ != display->GetHeight()) { - display->SetHeight(displayInfo.height_); - WLOGFI("GetDisplayById: set new height %{public}d", display->GetHeight()); - } - if (displayInfo.freshRate_ != display->GetFreshRate()) { - display->SetFreshRate(displayInfo.freshRate_); - WLOGFI("GetDisplayById: set new freshRate %{public}ud", display->GetFreshRate()); - } + display->UpdateDisplayInfo(displayInfo); return iter->second; } - DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); - sptr display = new Display("", &displayInfo); + auto displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + if (displayInfo == nullptr) { + WLOGFE("GetDisplayById: displayInfo is nullptr!"); + return nullptr; + } + sptr display = new Display("", displayInfo); if (display->GetId() != DISPLAY_ID_INVALD) { displayMap_[display->GetId()] = display; } return display; } -bool DisplayManagerAdapter::RequestRotation(ScreenId screenId, Rotation rotation) +bool ScreenManagerAdapter::RequestRotation(ScreenId screenId, Rotation rotation) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -109,7 +109,7 @@ std::shared_ptr DisplayManagerAdapter::GetDisplaySnapshot(Displ return dispalySnapshot; } -DMError DisplayManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, +DMError ScreenManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) { std::lock_guard lock(mutex_); @@ -123,7 +123,7 @@ DMError DisplayManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, return ret; } -DMError DisplayManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +DMError ScreenManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) { std::lock_guard lock(mutex_); @@ -136,7 +136,7 @@ DMError DisplayManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColo return ret; } -DMError DisplayManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +DMError ScreenManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) { std::lock_guard lock(mutex_); @@ -149,7 +149,7 @@ DMError DisplayManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t co return ret; } -DMError DisplayManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +DMError ScreenManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) { std::lock_guard lock(mutex_); @@ -162,7 +162,7 @@ DMError DisplayManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutM return ret; } -DMError DisplayManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +DMError ScreenManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) { std::lock_guard lock(mutex_); @@ -175,7 +175,7 @@ DMError DisplayManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutM return ret; } -DMError DisplayManagerAdapter::SetScreenColorTransform(ScreenId screenId) +DMError ScreenManagerAdapter::SetScreenColorTransform(ScreenId screenId) { std::lock_guard lock(mutex_); @@ -188,7 +188,7 @@ DMError DisplayManagerAdapter::SetScreenColorTransform(ScreenId screenId) return ret; } -ScreenId DisplayManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) +ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) { if (!InitDMSProxyLocked()) { return SCREEN_ID_INVALID; @@ -197,7 +197,7 @@ ScreenId DisplayManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) return displayManagerServiceProxy_->CreateVirtualScreen(option); } -DMError DisplayManagerAdapter::DestroyVirtualScreen(ScreenId screenId) +DMError ScreenManagerAdapter::DestroyVirtualScreen(ScreenId screenId) { if (!InitDMSProxyLocked()) { return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; @@ -206,7 +206,7 @@ DMError DisplayManagerAdapter::DestroyVirtualScreen(ScreenId screenId) return displayManagerServiceProxy_->DestroyVirtualScreen(screenId); } -DMError DisplayManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +DMError ScreenManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { if (!InitDMSProxyLocked()) { return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; @@ -215,7 +215,7 @@ DMError DisplayManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptrSetVirtualScreenSurface(screenId, surface); } -bool DisplayManagerAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, +bool BaseAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) { std::lock_guard lock(mutex_); @@ -225,7 +225,7 @@ bool DisplayManagerAdapter::RegisterDisplayManagerAgent(const sptrRegisterDisplayManagerAgent(displayManagerAgent, type); } -bool DisplayManagerAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, +bool BaseAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) { std::lock_guard lock(mutex_); @@ -308,7 +308,7 @@ void DisplayManagerAdapter::NotifyDisplayEvent(DisplayEvent event) displayManagerServiceProxy_->NotifyDisplayEvent(event); } -bool DisplayManagerAdapter::InitDMSProxyLocked() +bool BaseAdapter::InitDMSProxyLocked() { if (!displayManagerServiceProxy_) { sptr systemAbilityManager = @@ -331,7 +331,7 @@ bool DisplayManagerAdapter::InitDMSProxyLocked() return false; } - dmsDeath_ = new DMSDeathRecipient(); + dmsDeath_ = new DMSDeathRecipient(*this); if (!dmsDeath_) { WLOGFE("Failed to create death Recipient ptr DMSDeathRecipient"); return false; @@ -344,6 +344,10 @@ bool DisplayManagerAdapter::InitDMSProxyLocked() return true; } +DMSDeathRecipient::DMSDeathRecipient(BaseAdapter& adapter) : adapter_(adapter) +{ +} + void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) { if (wptrDeath == nullptr) { @@ -356,11 +360,11 @@ void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) WLOGFE("object is null"); return; } - SingletonContainer::Get().Clear(); + adapter_.Clear(); return; } -void DisplayManagerAdapter::Clear() +void BaseAdapter::Clear() { std::lock_guard lock(mutex_); if ((displayManagerServiceProxy_ != nullptr) && (displayManagerServiceProxy_->AsObject() != nullptr)) { @@ -369,7 +373,7 @@ void DisplayManagerAdapter::Clear() displayManagerServiceProxy_ = nullptr; } -DMError DisplayManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +DMError ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -378,7 +382,7 @@ DMError DisplayManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vectorMakeMirror(mainScreenId, mirrorScreenId); } -sptr DisplayManagerAdapter::GetScreenInfo(ScreenId screenId) +sptr ScreenManagerAdapter::GetScreenInfo(ScreenId screenId) { if (screenId == SCREEN_ID_INVALID) { WLOGFE("screen id is invalid"); @@ -396,80 +400,76 @@ sptr DisplayManagerAdapter::GetScreenInfo(ScreenId screenId) return screenInfo; } -DisplayInfo DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) +sptr DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) { if (displayId == DISPLAY_ID_INVALD) { WLOGFE("screen id is invalid"); - return DisplayInfo(); + return nullptr; } std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); - return DisplayInfo(); + return nullptr; } return displayManagerServiceProxy_->GetDisplayInfoById(displayId); } -sptr DisplayManagerAdapter::GetScreenById(ScreenId screenId) +sptr ScreenManagerAdapter::GetScreenById(ScreenId screenId) { std::lock_guard lock(mutex_); - if (screenId == SCREEN_ID_INVALID) { - WLOGFE("screen id is invalid"); + sptr screenInfo = GetScreenInfo(screenId); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is null"); + screenMap_.erase(screenId); return nullptr; } auto iter = screenMap_.find(screenId); if (iter != screenMap_.end()) { WLOGFI("get screen in screen map"); + iter->second->UpdateScreenInfo(screenInfo); return iter->second; } - - if (!InitDMSProxyLocked()) { - WLOGFE("InitDMSProxyLocked failed!"); - return nullptr; - } - sptr screenInfo = displayManagerServiceProxy_->GetScreenInfoById(screenId); - if (screenInfo == nullptr) { - WLOGFE("screenInfo is null"); - return nullptr; - } - sptr screen = new Screen(screenInfo.GetRefPtr()); + sptr screen = new Screen(screenInfo); screenMap_.insert(std::make_pair(screenId, screen)); return screen; } -sptr DisplayManagerAdapter::GetScreenGroupById(ScreenId screenId) +sptr ScreenManagerAdapter::GetScreenGroupById(ScreenId screenId) { std::lock_guard lock(mutex_); if (screenId == SCREEN_ID_INVALID) { WLOGFE("screenGroup id is invalid"); return nullptr; } - auto iter = screenGroupMap_.find(screenId); - if (iter != screenGroupMap_.end()) { - WLOGFI("get screenGroup in screenGroup map"); - return iter->second; - } - if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); + screenGroupMap_.clear(); return nullptr; } sptr screenGroupInfo = displayManagerServiceProxy_->GetScreenGroupInfoById(screenId); if (screenGroupInfo == nullptr) { WLOGFE("screenGroupInfo is null"); + screenGroupMap_.erase(screenId); return nullptr; } - sptr screenGroup = new ScreenGroup(screenGroupInfo.GetRefPtr()); + auto iter = screenGroupMap_.find(screenId); + if (iter != screenGroupMap_.end()) { + WLOGFI("get screenGroup in screenGroup map"); + iter->second->UpdateScreenGroupInfo(screenGroupInfo); + return iter->second; + } + sptr screenGroup = new ScreenGroup(screenGroupInfo); screenGroupMap_.insert(std::make_pair(screenId, screenGroup)); return screenGroup; } -std::vector> DisplayManagerAdapter::GetAllScreens() +std::vector> ScreenManagerAdapter::GetAllScreens() { std::lock_guard lock(mutex_); std::vector> screens; if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); + screenMap_.clear(); return screens; } std::vector> screenInfos = displayManagerServiceProxy_->GetAllScreenInfos(); @@ -478,12 +478,24 @@ std::vector> DisplayManagerAdapter::GetAllScreens() WLOGFE("screenInfo is null"); continue; } - screens.emplace_back(new Screen(info.GetRefPtr())); + auto iter = screenMap_.find(info->GetScreenId()); + if (iter != screenMap_.end()) { + WLOGFI("get screen in screen map"); + iter->second->UpdateScreenInfo(info); + screens.emplace_back(iter->second); + } else { + sptr screen = new Screen(info); + screens.emplace_back(screen); + } + } + screenMap_.clear(); + for (auto screen: screens) { + screenMap_.insert(std::make_pair(screen->GetId(), screen)); } return screens; } -DMError DisplayManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) +DMError ScreenManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -492,7 +504,7 @@ DMError DisplayManagerAdapter::MakeExpand(std::vector screenId, std::v return displayManagerServiceProxy_->MakeExpand(screenId, startPoint); } -bool DisplayManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) +bool ScreenManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -500,4 +512,30 @@ bool DisplayManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t mode } return displayManagerServiceProxy_->SetScreenActiveMode(screenId, modeId); } + +void ScreenManagerAdapter::UpdateScreenInfo(ScreenId screenId) +{ + auto screenInfo = GetScreenInfo(screenId); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is invalid"); + return; + } + auto iter = screenMap_.find(screenId); + if (iter != screenMap_.end()) { + iter->second->UpdateScreenInfo(screenInfo); + } +} + +void DisplayManagerAdapter::UpdateDisplayInfo(DisplayId displayId) +{ + auto displayInfo = GetDisplayInfo(displayId); + if (displayInfo == nullptr) { + WLOGFE("displayInfo is invalid"); + return; + } + auto iter = displayMap_.find(displayId); + if (iter != displayMap_.end()) { + iter->second->UpdateDisplayInfo(displayInfo); + } +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen.cpp b/dm/src/screen.cpp index d4a227b3..ba7fd260 100644 --- a/dm/src/screen.cpp +++ b/dm/src/screen.cpp @@ -16,7 +16,6 @@ #include "screen.h" #include "display_manager_adapter.h" -#include "screen_group.h" #include "screen_info.h" #include "window_manager_hilog.h" @@ -25,55 +24,21 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "Screen"}; } class Screen::Impl : public RefBase { -friend class Screen; public: - Impl() = default; + Impl(sptr info) + { + if (info == nullptr) { + WLOGFE("ScreenInfo is nullptr."); + } + screenInfo_ = info; + } ~Impl() = default; - void UpdateScreen(sptr info); - - ScreenId id_ { SCREEN_ID_INVALID }; - uint32_t virtualWidth_ { 0 }; - uint32_t virtualHeight_ { 0 }; - float virtualPixelRatio_ { 0.0 }; - ScreenId parent_ { SCREEN_ID_INVALID }; - bool canHasChild_ { false }; - uint32_t modeId_ { 0 }; - std::vector> modes_ {}; - Rotation rotation_ { Rotation::ROTATION_0 }; + DEFINE_VAR_FUNC_GET_SET(sptr, ScreenInfo, screenInfo); }; -void Screen::Impl::UpdateScreen(sptr info) +Screen::Screen(sptr info) + : pImpl_(new Impl(info)) { - if (info == nullptr) { - WLOGFE("info is nullptr."); - return; - } - virtualWidth_ = info->virtualWidth_; - virtualHeight_ = info->virtualHeight_; - virtualPixelRatio_ = info->virtualPixelRatio_; - parent_ = info->parent_; - canHasChild_ = info->canHasChild_; - modeId_ = info->modeId_; - modes_ = info->modes_; - rotation_ = info->rotation_; -} - -Screen::Screen(const ScreenInfo* info) - : pImpl_(new Impl()) -{ - if (info == nullptr) { - WLOGFE("info is nullptr."); - return; - } - pImpl_->id_ = info->id_; - pImpl_->virtualWidth_ = info->virtualWidth_; - pImpl_->virtualHeight_ = info->virtualHeight_; - pImpl_->virtualPixelRatio_ = info->virtualPixelRatio_; - pImpl_->parent_ = info->parent_; - pImpl_->canHasChild_ = info->canHasChild_; - pImpl_->modeId_ = info->modeId_; - pImpl_->modes_ = info->modes_; - pImpl_->rotation_ = info->rotation_; } Screen::~Screen() @@ -82,22 +47,20 @@ Screen::~Screen() bool Screen::IsGroup() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->canHasChild_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetCanHasChild(); } ScreenId Screen::GetId() const { - return pImpl_->id_; + return pImpl_->GetScreenInfo()->GetScreenId(); } uint32_t Screen::GetWidth() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - auto modeId = pImpl_->modeId_; - auto modes = pImpl_->modes_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + auto modeId = GetModeId(); + auto modes = GetSupportedModes(); if (modeId < 0 || modeId >= modes.size()) { return 0; } @@ -106,10 +69,9 @@ uint32_t Screen::GetWidth() const uint32_t Screen::GetHeight() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - auto modeId = pImpl_->modeId_; - auto modes = pImpl_->modes_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + auto modeId = GetModeId(); + auto modes = GetSupportedModes(); if (modeId < 0 || modeId >= modes.size()) { return 0; } @@ -118,93 +80,98 @@ uint32_t Screen::GetHeight() const uint32_t Screen::GetVirtualWidth() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->virtualWidth_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetVirtualWidth(); } uint32_t Screen::GetVirtualHeight() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->virtualHeight_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetVirtualHeight(); } float Screen::GetVirtualPixelRatio() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->virtualPixelRatio_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetVirtualPixelRatio(); } Rotation Screen::GetRotation() { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->rotation_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetRotation(); } bool Screen::RequestRotation(Rotation rotation) { WLOGFD("rotation the screen"); - return SingletonContainer::Get().RequestRotation(pImpl_->id_, rotation); + return SingletonContainer::Get().RequestRotation(GetId(), rotation); } DMError Screen::GetScreenSupportedColorGamuts(std::vector& colorGamuts) const { - return SingletonContainer::Get().GetScreenSupportedColorGamuts(pImpl_->id_, colorGamuts); + return SingletonContainer::Get().GetScreenSupportedColorGamuts(GetId(), colorGamuts); } DMError Screen::GetScreenColorGamut(ScreenColorGamut& colorGamut) const { - return SingletonContainer::Get().GetScreenColorGamut(pImpl_->id_, colorGamut); + return SingletonContainer::Get().GetScreenColorGamut(GetId(), colorGamut); } DMError Screen::SetScreenColorGamut(int32_t colorGamutIdx) { - return SingletonContainer::Get().SetScreenColorGamut(pImpl_->id_, colorGamutIdx); + return SingletonContainer::Get().SetScreenColorGamut(GetId(), colorGamutIdx); } DMError Screen::GetScreenGamutMap(ScreenGamutMap& gamutMap) const { - return SingletonContainer::Get().GetScreenGamutMap(pImpl_->id_, gamutMap); + return SingletonContainer::Get().GetScreenGamutMap(GetId(), gamutMap); } DMError Screen::SetScreenGamutMap(ScreenGamutMap gamutMap) { - return SingletonContainer::Get().SetScreenGamutMap(pImpl_->id_, gamutMap); + return SingletonContainer::Get().SetScreenGamutMap(GetId(), gamutMap); } DMError Screen::SetScreenColorTransform() { - return SingletonContainer::Get().SetScreenColorTransform(pImpl_->id_); + return SingletonContainer::Get().SetScreenColorTransform(GetId()); } ScreenId Screen::GetParentId() const { - return pImpl_->parent_; + return pImpl_->GetScreenInfo()->GetParentId(); } uint32_t Screen::GetModeId() const { - return pImpl_->modeId_; + return pImpl_->GetScreenInfo()->GetModeId(); } std::vector> Screen::GetSupportedModes() const { - return pImpl_->modes_; + return pImpl_->GetScreenInfo()->GetModes(); } bool Screen::SetScreenActiveMode(uint32_t modeId) { - ScreenId screenId = pImpl_->id_; - if (modeId < 0 || modeId >= pImpl_->modes_.size()) { + ScreenId screenId = GetId(); + if (modeId < 0 || modeId >= GetSupportedModes().size()) { return false; } - if (SingletonContainer::Get().SetScreenActiveMode(screenId, modeId)) { - pImpl_->modeId_ = modeId; + if (SingletonContainer::Get().SetScreenActiveMode(screenId, modeId)) { + pImpl_->GetScreenInfo()->SetModeId(modeId); return true; } return false; } + +void Screen::UpdateScreenInfo(sptr screenInfo) +{ + if (screenInfo == nullptr) { + WLOGFE("ScreenInfo is invalid"); + return; + } + pImpl_->SetScreenInfo(screenInfo); +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen_group.cpp b/dm/src/screen_group.cpp index 91e17a8d..9ac64d7b 100644 --- a/dm/src/screen_group.cpp +++ b/dm/src/screen_group.cpp @@ -23,26 +23,30 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "ScreenGroup"}; } class ScreenGroup::Impl : public RefBase { -friend class ScreenGroup; -private: - Impl() = default; +public: + Impl(sptr info) + { + if (info == nullptr) { + WLOGFE("ScreenGroupInfo is nullptr."); + } + screenGroupInfo_ = info; + } ~Impl() = default; - std::vector children_; - std::vector position_; - ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; + DEFINE_VAR_FUNC_GET_SET(sptr, ScreenGroupInfo, screenGroupInfo); }; -ScreenGroup::ScreenGroup(const ScreenGroupInfo* info) - : Screen(info), pImpl_(new Impl()) +ScreenGroup::ScreenGroup(sptr info) + : Screen(info), pImpl_(new Impl(info)) +{ +} + +void ScreenGroup::UpdateScreenGroupInfo(sptr info) { if (info == nullptr) { - WLOGFE("info is nullptr."); - return; + WLOGFE("ScreenGroupInfo is nullptr."); } - pImpl_->children_ = info->children_; - pImpl_->position_ = info->position_; - pImpl_->combination_ = info->combination_; + pImpl_->SetScreenGroupInfo(info); } ScreenGroup::~ScreenGroup() @@ -51,16 +55,16 @@ ScreenGroup::~ScreenGroup() ScreenCombination ScreenGroup::GetCombination() const { - return pImpl_->combination_; + return pImpl_->GetScreenGroupInfo()->GetCombination(); } -std::vector ScreenGroup::GetChild() const +std::vector ScreenGroup::GetChildIds() const { - return pImpl_->children_; + return pImpl_->GetScreenGroupInfo()->GetChildren(); } -std::vector ScreenGroup::GetChildPosition() const +std::vector ScreenGroup::GetChildPositions() const { - return pImpl_->position_; + return pImpl_->GetScreenGroupInfo()->GetPosition(); } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen_manager.cpp b/dm/src/screen_manager.cpp index abbbee9d..b81e640e 100644 --- a/dm/src/screen_manager.cpp +++ b/dm/src/screen_manager.cpp @@ -43,7 +43,7 @@ public: void OnScreenConnect(sptr screenInfo) { - if (screenInfo == nullptr || screenInfo->id_ == SCREEN_ID_INVALID) { + if (screenInfo == nullptr || screenInfo->GetScreenId() == SCREEN_ID_INVALID) { WLOGFE("OnScreenConnect, screenInfo is invalid."); return; } @@ -52,7 +52,7 @@ public: return; } for (auto listener : pImpl_->screenListeners_) { - listener->OnConnect(screenInfo->id_); + listener->OnConnect(screenInfo->GetScreenId()); } }; @@ -84,8 +84,8 @@ public: WLOGFD("OnScreenChange. event %{public}u", event); std::vector screenIds; for (auto screenInfo : screenInfos) { - if (screenInfo->id_ != SCREEN_ID_INVALID) { - screenIds.push_back(screenInfo->id_); + if (screenInfo->GetScreenId() != SCREEN_ID_INVALID) { + screenIds.push_back(screenInfo->GetScreenId()); } } for (auto listener: pImpl_->screenListeners_) { @@ -108,17 +108,17 @@ ScreenManager::~ScreenManager() sptr ScreenManager::GetScreenById(ScreenId screenId) { - return SingletonContainer::Get().GetScreenById(screenId); + return SingletonContainer::Get().GetScreenById(screenId); } sptr ScreenManager::GetScreenGroupById(ScreenId screenId) { - return SingletonContainer::Get().GetScreenGroupById(screenId); + return SingletonContainer::Get().GetScreenGroupById(screenId); } std::vector> ScreenManager::GetAllScreens() { - return SingletonContainer::Get().GetAllScreens(); + return SingletonContainer::Get().GetAllScreens(); } bool ScreenManager::RegisterScreenListener(sptr listener) @@ -131,7 +131,7 @@ bool ScreenManager::RegisterScreenListener(sptr listener) pImpl_->screenListeners_.push_back(listener); if (screenManagerListener_ == nullptr) { screenManagerListener_ = new ScreenManagerListener(pImpl_); - SingletonContainer::Get().RegisterDisplayManagerAgent( + SingletonContainer::Get().RegisterDisplayManagerAgent( screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); } @@ -152,7 +152,7 @@ bool ScreenManager::UnregisterScreenListener(sptr listener) } pImpl_->screenListeners_.erase(iter); if (pImpl_->screenListeners_.empty() && screenManagerListener_ != nullptr) { - SingletonContainer::Get().UnregisterDisplayManagerAgent( + SingletonContainer::Get().UnregisterDisplayManagerAgent( screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); screenManagerListener_ = nullptr; @@ -172,7 +172,7 @@ ScreenId ScreenManager::MakeExpand(const std::vector& options) screenIds.emplace_back(option.screenId_); startPoints.emplace_back(Point(option.startX_, option.startY_)); } - DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); + DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); if (result != DMError::DM_OK) { return SCREEN_ID_INVALID; } @@ -184,7 +184,7 @@ ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector { WLOGFI("create mirror for screen: %{public}" PRIu64"", mainScreenId); // TODO: "record screen" should use another function, "MakeMirror" should return group id. - DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); + DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); if (result == DMError::DM_OK) { WLOGFI("create mirror success"); } @@ -193,16 +193,16 @@ ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector ScreenId ScreenManager::CreateVirtualScreen(VirtualScreenOption option) { - return SingletonContainer::Get().CreateVirtualScreen(option); + return SingletonContainer::Get().CreateVirtualScreen(option); } DMError ScreenManager::DestroyVirtualScreen(ScreenId screenId) { - return SingletonContainer::Get().DestroyVirtualScreen(screenId); + return SingletonContainer::Get().DestroyVirtualScreen(screenId); } DMError ScreenManager::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { - return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); + return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/test/unittest/mock_display_manager_adapter.h b/dm/test/unittest/mock_display_manager_adapter.h index 97dbef49..46ee9bc5 100644 --- a/dm/test/unittest/mock_display_manager_adapter.h +++ b/dm/test/unittest/mock_display_manager_adapter.h @@ -23,25 +23,45 @@ namespace OHOS { namespace Rosen { class MockDisplayManagerAdapter : public DisplayManagerAdapter { public: - MOCK_METHOD0(GetDefaultDisplayId, DisplayId()); - MOCK_METHOD1(GetDisplayById, sptr(DisplayId displayId)); - MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); - MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); - MOCK_METHOD1(GetDisplaySnapshot, std::shared_ptr(DisplayId displayId)); MOCK_METHOD0(Clear, void()); MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); + MOCK_METHOD0(GetDefaultDisplayId, DisplayId()); + MOCK_METHOD1(GetDisplayById, sptr(DisplayId displayId)); + MOCK_METHOD1(GetDisplaySnapshot, std::shared_ptr(DisplayId displayId)); + MOCK_METHOD1(WakeUpBegin, bool(PowerStateChangeReason reason)); MOCK_METHOD0(WakeUpEnd, bool()); MOCK_METHOD1(SuspendBegin, bool(PowerStateChangeReason reason)); MOCK_METHOD0(SuspendEnd, bool()); MOCK_METHOD2(SetScreenPowerForAll, bool(DisplayPowerState state, PowerStateChangeReason reason)); MOCK_METHOD1(SetDisplayState, bool(DisplayState state)); - MOCK_METHOD1(GetDisplayState, DisplayState(uint64_t displayId)); - MOCK_METHOD2(SetScreenActiveMode, bool(ScreenId screenId, uint32_t modeId)); + MOCK_METHOD1(GetDisplayState, DisplayState(DisplayId displayId)); + MOCK_METHOD1(NotifyDisplayEvent, void(DisplayEvent event)); + MOCK_METHOD1(UpdateDisplayInfo, void(DisplayId displayId)); +}; + +class MockScreenManagerAdapter : public ScreenManagerAdapter { +public: + MOCK_METHOD0(Clear, void()); + MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, + DisplayManagerAgentType type)); + MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, + DisplayManagerAgentType type)); + MOCK_METHOD2(RequestRotation, bool(ScreenId screenId, Rotation rotation)); + MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); + MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); + MOCK_METHOD2(SetVirtualScreenSurface, DMError(ScreenId screenId, sptr surface)); + MOCK_METHOD1(GetScreenById, sptr(ScreenId screenId)); + MOCK_METHOD1(GetScreenGroupById, sptr(ScreenId screenId)); + MOCK_METHOD0(GetAllScreens, std::vector>()); + MOCK_METHOD2(MakeMirror, DMError(ScreenId mainScreenId, std::vector mirrorScreenId)); MOCK_METHOD2(MakeExpand, DMError(std::vector screenId, std::vector startPoint)); + MOCK_METHOD2(SetScreenActiveMode, bool(ScreenId screenId, uint32_t modeId)); + MOCK_METHOD1(UpdateScreenInfo, void(ScreenId screenId)); + MOCK_METHOD2(GetScreenSupportedColorGamuts, DMError(ScreenId screenId, std::vector& colorGamuts)); MOCK_METHOD2(GetScreenColorGamut, DMError(ScreenId screenId, ScreenColorGamut& colorGamut)); MOCK_METHOD2(SetScreenColorGamut, DMError(ScreenId screenId, int32_t colorGamutIdx)); diff --git a/dm/test/unittest/screen_manager_test.cpp b/dm/test/unittest/screen_manager_test.cpp index d6da30be..eeafc8b3 100644 --- a/dm/test/unittest/screen_manager_test.cpp +++ b/dm/test/unittest/screen_manager_test.cpp @@ -22,7 +22,7 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { -using Mocker = SingletonMocker; +using Mocker = SingletonMocker; sptr ScreenManagerTest::defaultDisplay_ = nullptr; DisplayId ScreenManagerTest::defaultDisplayId_ = DISPLAY_ID_INVALD; diff --git a/dm/test/unittest/screen_test.cpp b/dm/test/unittest/screen_test.cpp index 23086993..e6aebea0 100644 --- a/dm/test/unittest/screen_test.cpp +++ b/dm/test/unittest/screen_test.cpp @@ -22,7 +22,7 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { -using Mocker = SingletonMocker; +using Mocker = SingletonMocker; sptr ScreenTest::defaultDisplay_ = nullptr; ScreenId ScreenTest::defaultScreenId_ = SCREEN_ID_INVALID; diff --git a/dmserver/include/abstract_display.h b/dmserver/include/abstract_display.h index 3b505006..79ba8b9c 100644 --- a/dmserver/include/abstract_display.h +++ b/dmserver/include/abstract_display.h @@ -28,7 +28,7 @@ public: constexpr static int32_t DEFAULT_HIGHT = 1280; constexpr static float DEFAULT_VIRTUAL_PIXEL_RATIO = 1.0; constexpr static uint32_t DEFAULT_FRESH_RATE = 60; - AbstractDisplay(const DisplayInfo& info); + AbstractDisplay(const DisplayInfo* info); AbstractDisplay(DisplayId id, ScreenId screenId, int32_t width, int32_t height, uint32_t freshRate); ~AbstractDisplay() = default; static inline bool IsVertical(Rotation rotation) @@ -43,7 +43,7 @@ public: ScreenId GetAbstractScreenId() const; bool BindAbstractScreen(ScreenId dmsScreenId); bool BindAbstractScreen(sptr abstractDisplay); - const sptr ConvertToDisplayInfo() const; + sptr ConvertToDisplayInfo() const; void SetId(DisplayId displayId); void SetWidth(int32_t width); diff --git a/dmserver/include/abstract_screen.h b/dmserver/include/abstract_screen.h index c89d392d..cbf32a2a 100644 --- a/dmserver/include/abstract_screen.h +++ b/dmserver/include/abstract_screen.h @@ -46,7 +46,7 @@ public: sptr GetActiveScreenMode() const; std::vector> GetAbstractScreenModes() const; sptr GetGroup() const; - const sptr ConvertToScreenInfo() const; + sptr ConvertToScreenInfo() const; void RequestRotation(Rotation rotation); Rotation GetRotation() const; @@ -90,7 +90,7 @@ public: std::vector> GetChildren() const; std::vector GetChildrenPosition() const; size_t GetChildCount() const; - const sptr ConvertToScreenGroupInfo() const; + sptr ConvertToScreenGroupInfo() const; bool SetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config); ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; diff --git a/dmserver/include/display_manager_interface.h b/dmserver/include/display_manager_interface.h index c4cb521b..9e9c40f6 100644 --- a/dmserver/include/display_manager_interface.h +++ b/dmserver/include/display_manager_interface.h @@ -68,7 +68,7 @@ public: }; virtual DisplayId GetDefaultDisplayId() = 0; - virtual DisplayInfo GetDisplayInfoById(DisplayId displayId) = 0; + virtual sptr GetDisplayInfoById(DisplayId displayId) = 0; virtual ScreenId CreateVirtualScreen(VirtualScreenOption option) = 0; virtual DMError DestroyVirtualScreen(ScreenId screenId) = 0; diff --git a/dmserver/include/display_manager_proxy.h b/dmserver/include/display_manager_proxy.h index 0d30ce4c..28d98a68 100644 --- a/dmserver/include/display_manager_proxy.h +++ b/dmserver/include/display_manager_proxy.h @@ -32,7 +32,7 @@ public: ~DisplayManagerProxy() {}; DisplayId GetDefaultDisplayId() override; - DisplayInfo GetDisplayInfoById(DisplayId displayId) override; + sptr GetDisplayInfoById(DisplayId displayId) override; ScreenId CreateVirtualScreen(VirtualScreenOption option) override; DMError DestroyVirtualScreen(ScreenId screenId) override; diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index ee3dc6d9..356521ba 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -51,7 +51,7 @@ public: DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; DisplayId GetDefaultDisplayId() override; - DisplayInfo GetDisplayInfoById(DisplayId displayId) override; + sptr GetDisplayInfoById(DisplayId displayId) override; bool RequestRotation(ScreenId screenId, Rotation rotation) override; std::shared_ptr GetDispalySnapshot(DisplayId displayId) override; ScreenId GetRSScreenId(DisplayId displayId) const; diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index e9ad85f9..c425a631 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -24,12 +24,16 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractDisplay"}; } -AbstractDisplay::AbstractDisplay(const DisplayInfo& info) - : id_(info.id_), - width_(info.width_), - height_(info.height_), - freshRate_(info.freshRate_) +AbstractDisplay::AbstractDisplay(const DisplayInfo* info) { + if (info == nullptr) { + WLOGFE("DisplayInfo is nullptr"); + return; + } + id_ = info->GetDisplayId(); + width_ = info->GetWidth(); + height_ = info->GetHeight(); + freshRate_ = info->GetHeight(); } AbstractDisplay::AbstractDisplay(DisplayId id, ScreenId screenId, int32_t width, int32_t height, uint32_t freshRate) @@ -146,7 +150,7 @@ ScreenId AbstractDisplay::GetAbstractScreenId() const return screenId_; } -const sptr AbstractDisplay::ConvertToDisplayInfo() const +sptr AbstractDisplay::ConvertToDisplayInfo() const { sptr displayInfo = new DisplayInfo(); displayInfo->width_ = width_; diff --git a/dmserver/src/abstract_screen.cpp b/dmserver/src/abstract_screen.cpp index fb124012..bddd68c8 100644 --- a/dmserver/src/abstract_screen.cpp +++ b/dmserver/src/abstract_screen.cpp @@ -53,7 +53,7 @@ sptr AbstractScreen::GetGroup() const return DisplayManagerService::GetInstance().GetAbstractScreenController()->GetAbstractScreenGroup(groupDmsId_); } -const sptr AbstractScreen::ConvertToScreenInfo() const +sptr AbstractScreen::ConvertToScreenInfo() const { sptr info = new ScreenInfo(); FillScreenInfo(info); @@ -215,7 +215,7 @@ AbstractScreenGroup::~AbstractScreenGroup() abstractScreenMap_.clear(); } -const sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const +sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const { sptr screenGroupInfo = new ScreenGroupInfo(); FillScreenInfo(screenGroupInfo); diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index 180dc4a4..3dfc287a 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -52,12 +52,12 @@ DisplayId DisplayManagerProxy::GetDefaultDisplayId() return displayId; } -DisplayInfo DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) +sptr DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) { sptr remote = Remote(); if (remote == nullptr) { WLOGFW("GetDisplayInfoById: remote is nullptr"); - return DisplayInfo(); + return nullptr; } MessageParcel data; @@ -65,23 +65,23 @@ DisplayInfo DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) MessageOption option; if (!data.WriteInterfaceToken(GetDescriptor())) { WLOGFE("GetDisplayInfoById: WriteInterfaceToken failed"); - return DisplayInfo(); + return nullptr; } if (!data.WriteUint64(displayId)) { WLOGFW("GetDisplayInfoById: WriteUint64 displayId failed"); - return DisplayInfo(); + return nullptr; } if (remote->SendRequest(TRANS_ID_GET_DISPLAY_BY_ID, data, reply, option) != ERR_NONE) { WLOGFW("GetDisplayInfoById: SendRequest failed"); - return DisplayInfo(); + return nullptr; } sptr info = reply.ReadParcelable(); if (info == nullptr) { WLOGFW("DisplayManagerProxy::GetDisplayInfoById SendRequest nullptr."); - return DisplayInfo(); + return nullptr; } - return *info; + return info; } ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption) @@ -682,9 +682,10 @@ sptr DisplayManagerProxy::GetScreenInfoById(ScreenId screenId) WLOGFW("GetScreenInfoById SendRequest nullptr."); return nullptr; } - for (int i = 0; i < info->modes_.size(); i++) { + auto modes = info->GetModes(); + for (int i = 0; i < modes.size(); i++) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", - info->modes_[i]->width_, info->modes_[i]->height_, info->modes_[i]->freshRate_); + modes[i]->width_, modes[i]->height_, modes[i]->freshRate_); } return info; } diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index 0e3c34e0..047dbfee 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -89,21 +89,14 @@ DisplayId DisplayManagerService::GetDefaultDisplayId() return GetDisplayIdFromScreenId(screenId); } -DisplayInfo DisplayManagerService::GetDisplayInfoById(DisplayId displayId) +sptr DisplayManagerService::GetDisplayInfoById(DisplayId displayId) { - DisplayInfo displayInfo; sptr display = GetDisplayByDisplayId(displayId); if (display == nullptr) { WLOGFE("GetDisplayById: Get invalid display!"); - return displayInfo; + return nullptr; } - displayInfo.id_ = displayId; - displayInfo.width_ = display->GetWidth(); - displayInfo.height_ = display->GetHeight(); - displayInfo.freshRate_ = display->GetFreshRate(); - displayInfo.screenId_ = display->GetAbstractScreenId(); - displayInfo.rotation_ = display->GetRotation(); - return displayInfo; + return display->ConvertToDisplayInfo(); } sptr DisplayManagerService::GetAbstractDisplay(DisplayId displayId) diff --git a/dmserver/src/display_manager_service_inner.cpp b/dmserver/src/display_manager_service_inner.cpp index edaaa5cd..8c84b84a 100644 --- a/dmserver/src/display_manager_service_inner.cpp +++ b/dmserver/src/display_manager_service_inner.cpp @@ -41,7 +41,7 @@ const sptr DisplayManagerServiceInner::GetDisplayById(DisplayId { sptr display = DisplayManagerService::GetInstance().GetAbstractDisplay(displayId); if (display == nullptr) { - DisplayInfo displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + auto displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); display = new AbstractDisplay(displayInfo); WLOGFE("GetDisplayById create new!\n"); } diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index 2504aef4..824fddaf 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -45,7 +45,7 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_DISPLAY_BY_ID: { DisplayId displayId = data.ReadUint64(); auto info = GetDisplayInfoById(displayId); - reply.WriteParcelable(&info); + reply.WriteParcelable(info); break; } case TRANS_ID_CREATE_VIRTUAL_SCREEN: { @@ -166,9 +166,10 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_SCREEN_INFO_BY_ID: { ScreenId screenId = static_cast(data.ReadUint64()); auto screenInfo = GetScreenInfoById(screenId); - for (int i = 0; i < screenInfo->modes_.size(); i++) { + auto modes = screenInfo->GetModes(); + for (int i = 0; i < modes.size(); i++) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", - screenInfo->modes_[i]->width_, screenInfo->modes_[i]->height_, screenInfo->modes_[i]->freshRate_); + modes[i]->width_, modes[i]->height_, modes[i]->freshRate_); } reply.WriteStrongParcelable(screenInfo); break; diff --git a/interfaces/innerkits/dm/display.h b/interfaces/innerkits/dm/display.h index a71df544..5846b76c 100644 --- a/interfaces/innerkits/dm/display.h +++ b/interfaces/innerkits/dm/display.h @@ -27,23 +27,22 @@ typedef enum DisplayType { } DisplayType; class Display : public RefBase { +friend class DisplayManagerAdapter; public: - Display(const std::string& name, DisplayInfo* info); ~Display() = default; - + Display(const Display&) = delete; + Display(Display&&) = delete; + Display& operator=(const Display&) = delete; + Display& operator=(Display&&) = delete; DisplayId GetId() const; int32_t GetWidth() const; int32_t GetHeight() const; uint32_t GetFreshRate() const; ScreenId GetScreenId() const; float GetVirtualPixelRatio() const; - - void SetId(DisplayId displayId); - void SetWidth(int32_t width); - void SetHeight(int32_t height); - void SetFreshRate(uint32_t freshRate); - private: + Display(const std::string& name, sptr info); + void UpdateDisplayInfo(sptr); class Impl; sptr pImpl_; }; diff --git a/interfaces/innerkits/dm/screen.h b/interfaces/innerkits/dm/screen.h index 8c71c4f9..baf1d56d 100644 --- a/interfaces/innerkits/dm/screen.h +++ b/interfaces/innerkits/dm/screen.h @@ -57,9 +57,13 @@ struct ExpandOption { }; class Screen : public RefBase { +friend class ScreenManagerAdapter; public: - Screen(const ScreenInfo* info); ~Screen(); + Screen(const Screen&) = delete; + Screen(Screen&&) = delete; + Screen& operator=(const Screen&) = delete; + Screen& operator=(Screen&&) = delete; bool IsGroup() const; ScreenId GetId() const; uint32_t GetWidth() const; @@ -81,7 +85,9 @@ public: DMError GetScreenGamutMap(ScreenGamutMap& gamutMap) const; DMError SetScreenGamutMap(ScreenGamutMap gamutMap); DMError SetScreenColorTransform(); - +protected: + Screen(sptr info); + void UpdateScreenInfo(sptr screenInfo); private: class Impl; sptr pImpl_; diff --git a/interfaces/innerkits/dm/screen_group.h b/interfaces/innerkits/dm/screen_group.h index 78377f88..bb879536 100644 --- a/interfaces/innerkits/dm/screen_group.h +++ b/interfaces/innerkits/dm/screen_group.h @@ -29,14 +29,20 @@ enum class ScreenCombination : uint32_t { }; class ScreenGroup : public Screen { +friend class ScreenManagerAdapter; public: - ScreenGroup(const ScreenGroupInfo* info); ~ScreenGroup(); + ScreenGroup(const ScreenGroup&) = delete; + ScreenGroup(ScreenGroup&&) = delete; + ScreenGroup& operator=(const ScreenGroup&) = delete; + ScreenGroup& operator=(ScreenGroup&&) = delete; ScreenCombination GetCombination() const; - std::vector GetChild() const; - std::vector GetChildPosition() const; + std::vector GetChildIds() const; + std::vector GetChildPositions() const; private: + ScreenGroup(sptr info); + void UpdateScreenGroupInfo(sptr info); class Impl; sptr pImpl_; }; diff --git a/utils/include/class_var_defination.h b/utils/include/class_var_defination.h new file mode 100644 index 00000000..27bce64e --- /dev/null +++ b/utils/include/class_var_defination.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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 p ermissions and + * limitations under the License. + */ + +#ifndef OHOS_ROSEN_CLASS_VAR_DEFINATION_H +#define OHOS_ROSEN_CLASS_VAR_DEFINATION_H +namespace OHOS::Rosen { +#define DEFINE_VAR(type, memberName) \ +private: \ + type memberName##_; + +#define DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ +private: \ + type memberName##_ {defaultValue}; + +#define DEFINE_FUNC_GET(type, funcName, memberName) \ +public: \ + type Get##funcName() const \ + { \ + return memberName##_; \ + } + +#define DEFINE_FUNC_SET(type, funcName, memberName) \ +public: \ + void Set##funcName(type value) \ + { \ + memberName##_ = value; \ + } + +#define DEFINE_VAR_FUNC_GET(type, funcName, memberName) \ + DEFINE_VAR(type, memberName) \ + DEFINE_FUNC_GET(type, funcName, memberName) + +#define DEFINE_VAR_DEFAULT_FUNC_GET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_GET(type, funcName, memberName) + +#define DEFINE_VAR_FUNC_GET_SET(type, funcName, memberName) \ + DEFINE_VAR(type, memberName) \ + DEFINE_FUNC_GET(type, funcName, memberName) \ + DEFINE_FUNC_SET(type, funcName, memberName) + +#define DEFINE_VAR_DEFAULT_FUNC_GET_SET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_GET(type, funcName, memberName) \ + DEFINE_FUNC_SET(type, funcName, memberName) +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_CLASS_VAR_DEFINATION_H diff --git a/utils/include/display_info.h b/utils/include/display_info.h index 0aab1010..e7ec23c9 100644 --- a/utils/include/display_info.h +++ b/utils/include/display_info.h @@ -18,29 +18,34 @@ #include +#include "class_var_defination.h" #include "display.h" #include "dm_common.h" namespace OHOS::Rosen { class DisplayInfo : public Parcelable { +friend class AbstractDisplay; public: - DisplayInfo() = default; ~DisplayInfo() = default; - - void Update(DisplayInfo* info); + DisplayInfo(const DisplayInfo&) = delete; + DisplayInfo(DisplayInfo&&) = delete; + DisplayInfo& operator=(const DisplayInfo&) = delete; + DisplayInfo& operator=(DisplayInfo&&) = delete; virtual bool Marshalling(Parcel& parcel) const override; static DisplayInfo *Unmarshalling(Parcel& parcel); - DisplayId id_ { DISPLAY_ID_INVALD }; - DisplayType type_ {DisplayType::DEFAULT }; - int32_t width_ { 0 }; - int32_t height_ { 0 }; - uint32_t freshRate_ { 0 }; - ScreenId screenId_ { SCREEN_ID_INVALID }; - float xDpi_ { 0.0 }; - float yDpi_ { 0.0 }; - Rotation rotation_ { Rotation::ROTATION_0 }; + DEFINE_VAR_DEFAULT_FUNC_GET(DisplayId, DisplayId, id, DISPLAY_ID_INVALD); + DEFINE_VAR_DEFAULT_FUNC_GET(DisplayType, DisplayType, type, DisplayType::DEFAULT); + DEFINE_VAR_DEFAULT_FUNC_GET(int32_t, Width, width, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(int32_t, Height, height, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, FreshRate, freshRate, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ScreenId, screenId, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET(float, XDpi, xDpi, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET(float, YDpi, yDpi, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); +private: + DisplayInfo() = default; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H \ No newline at end of file diff --git a/utils/include/screen_group_info.h b/utils/include/screen_group_info.h index 6a9addbf..c1980182 100644 --- a/utils/include/screen_group_info.h +++ b/utils/include/screen_group_info.h @@ -23,20 +23,23 @@ namespace OHOS::Rosen { class ScreenGroupInfo : public ScreenInfo { +friend class AbstractScreenGroup; public: - ScreenGroupInfo() = default; ~ScreenGroupInfo() = default; - - void Update(sptr info); + ScreenGroupInfo(const ScreenGroupInfo&) = delete; + ScreenGroupInfo(ScreenGroupInfo&&) = delete; + ScreenGroupInfo& operator=(const ScreenGroupInfo&) = delete; + ScreenGroupInfo& operator=(ScreenGroupInfo&&) = delete; virtual bool Marshalling(Parcel& parcel) const override; static ScreenGroupInfo* Unmarshalling(Parcel& parcel); - std::vector children_; - std::vector position_; - ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; -protected: - ScreenGroupInfo* InnerUnmarshalling(Parcel& parcel); + DEFINE_VAR_FUNC_GET(std::vector, Children, children); + DEFINE_VAR_FUNC_GET(std::vector, Position, position); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenCombination, Combination, combination, ScreenCombination::SCREEN_ALONE); +private: + ScreenGroupInfo() = default; + bool InnerUnmarshalling(Parcel& parcel); }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_SCREEN_GROUP_INFO_H \ No newline at end of file diff --git a/utils/include/screen_info.h b/utils/include/screen_info.h index c39fad9d..618a67ce 100644 --- a/utils/include/screen_info.h +++ b/utils/include/screen_info.h @@ -18,30 +18,34 @@ #include +#include "class_var_defination.h" #include "screen.h" namespace OHOS::Rosen { class ScreenInfo : public Parcelable { +friend class AbstractScreen; public: - ScreenInfo() = default; ~ScreenInfo() = default; - - void Update(sptr info); + ScreenInfo(const ScreenInfo&) = delete; + ScreenInfo(ScreenInfo&&) = delete; + ScreenInfo& operator=(const ScreenInfo&) = delete; + ScreenInfo& operator= (ScreenInfo&&) = delete; virtual bool Marshalling(Parcel& parcel) const override; static ScreenInfo* Unmarshalling(Parcel& parcel); - ScreenId id_ { SCREEN_ID_INVALID }; - uint32_t virtualWidth_ { 0 }; - uint32_t virtualHeight_ { 0 }; - float virtualPixelRatio_ { 0.0 }; - ScreenId parent_ { 0 }; - bool canHasChild_ { false }; - Rotation rotation_ { Rotation::ROTATION_0 }; - uint32_t modeId_ { 0 }; - std::vector> modes_ {}; + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ScreenId, id, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, VirtualWidth, virtualWidth, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, VirtualHeight, virtualHeight, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(float, VirtualPixelRatio, virtualPixelRatio, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ParentId, parent, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(bool, CanHasChild, canHasChild, false); + DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, ModeId, modeId, 0); + DEFINE_VAR_FUNC_GET(std::vector>, Modes, modes); protected: - ScreenInfo* InnerUnmarshalling(Parcel& parcel); + ScreenInfo() = default; + bool InnerUnmarshalling(Parcel& parcel); }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H diff --git a/utils/src/display_info.cpp b/utils/src/display_info.cpp index 0ff79f31..ca033643 100644 --- a/utils/src/display_info.cpp +++ b/utils/src/display_info.cpp @@ -16,19 +16,6 @@ #include "display_info.h" namespace OHOS::Rosen { -void DisplayInfo::Update(DisplayInfo* info) -{ - id_ = info->id_; - type_ = info->type_; - width_ = info->width_; - height_ = info->height_; - freshRate_ = info->freshRate_; - screenId_ = info->screenId_; - xDpi_ = info->xDpi_; - yDpi_ = info->yDpi_; - rotation_ = info->rotation_; -} - bool DisplayInfo::Marshalling(Parcel &parcel) const { return parcel.WriteUint64(id_) && parcel.WriteUint32(type_) && @@ -41,9 +28,6 @@ bool DisplayInfo::Marshalling(Parcel &parcel) const DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) { DisplayInfo *displayInfo = new DisplayInfo(); - if (displayInfo == nullptr) { - return nullptr; - } uint32_t type = (uint32_t)DisplayType::DEFAULT; uint32_t rotation; bool res = parcel.ReadUint64(displayInfo->id_) && parcel.ReadUint32(type) && @@ -52,11 +36,11 @@ DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) parcel.ReadFloat(displayInfo->xDpi_) && parcel.ReadFloat(displayInfo->yDpi_) && parcel.ReadUint32(rotation); if (!res) { - displayInfo = nullptr; - } else { - displayInfo->type_ = (DisplayType)type; - displayInfo->rotation_ = static_cast(rotation); + delete displayInfo; + return nullptr; } + displayInfo->type_ = (DisplayType)type; + displayInfo->rotation_ = static_cast(rotation); return displayInfo; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/utils/src/screen_group_info.cpp b/utils/src/screen_group_info.cpp index 56268c74..ed4e4122 100644 --- a/utils/src/screen_group_info.cpp +++ b/utils/src/screen_group_info.cpp @@ -16,16 +16,6 @@ #include "screen_group_info.h" namespace OHOS::Rosen { -void ScreenGroupInfo::Update(sptr info) -{ - ScreenInfo::Update(info); - children_.clear(); - children_.insert(children_.begin(), info->children_.begin(), info->children_.end()); - position_.clear(); - position_.insert(position_.begin(), info->position_.begin(), info->position_.end()); - combination_ = info->combination_; -} - bool ScreenGroupInfo::Marshalling(Parcel &parcel) const { bool res = ScreenInfo::Marshalling(parcel) && parcel.WriteUint32((uint32_t)combination_) && @@ -48,29 +38,34 @@ bool ScreenGroupInfo::Marshalling(Parcel &parcel) const ScreenGroupInfo* ScreenGroupInfo::Unmarshalling(Parcel &parcel) { ScreenGroupInfo* screenGroupInfo = new ScreenGroupInfo(); - return screenGroupInfo->InnerUnmarshalling(parcel); + bool res = screenGroupInfo->InnerUnmarshalling(parcel); + if (res) { + return screenGroupInfo; + } + delete screenGroupInfo; + return nullptr; } -ScreenGroupInfo* ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) +bool ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) { uint32_t combination; if (!ScreenInfo::InnerUnmarshalling(parcel) || !parcel.ReadUint32(combination) || !parcel.ReadUInt64Vector(&children_)) { - return nullptr; + return false; } combination_ = (ScreenCombination) combination; uint32_t size; if (!parcel.ReadUint32(size)) { - return nullptr; + return false; } for (size_t i = 0; i < size; i++) { Point point; if (parcel.ReadInt32(point.posX_) && parcel.ReadInt32(point.posY_)) { position_.push_back(point); } else { - return nullptr; + return false; } } - return this; + return true; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/utils/src/screen_info.cpp b/utils/src/screen_info.cpp index a3df26fe..4e16e2a7 100644 --- a/utils/src/screen_info.cpp +++ b/utils/src/screen_info.cpp @@ -16,19 +16,6 @@ #include "screen_info.h" namespace OHOS::Rosen { -void ScreenInfo::Update(sptr info) -{ - id_ = info->id_; - virtualWidth_ = info->virtualWidth_; - virtualHeight_ = info->virtualHeight_; - virtualPixelRatio_ = info->virtualPixelRatio_; - parent_ = info->parent_; - canHasChild_ = info->canHasChild_; - rotation_ = info->rotation_; - modeId_ = info->modeId_; - modes_ = info->modes_; -} - bool ScreenInfo::Marshalling(Parcel &parcel) const { bool res = parcel.WriteUint64(id_) && @@ -53,10 +40,15 @@ bool ScreenInfo::Marshalling(Parcel &parcel) const ScreenInfo* ScreenInfo::Unmarshalling(Parcel &parcel) { ScreenInfo* info = new ScreenInfo(); - return info->InnerUnmarshalling(parcel); + bool res = info->InnerUnmarshalling(parcel); + if (res) { + return info; + } + delete info; + return nullptr; } -ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) +bool ScreenInfo::InnerUnmarshalling(Parcel& parcel) { uint32_t size = 0; uint32_t rotation; @@ -66,7 +58,7 @@ ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) parcel.ReadBool(canHasChild_) && parcel.ReadUint32(rotation) && parcel.ReadUint32(modeId_) && parcel.ReadUint32(size); if (!res1) { - return nullptr; + return false; } modes_.clear(); for (uint32_t modeIndex = 0; modeIndex < size; modeIndex++) { @@ -76,10 +68,10 @@ ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) parcel.ReadUint32(mode->freshRate_)) { modes_.push_back(mode); } else { - return nullptr; + return false; } } rotation_ = static_cast(rotation); - return this; + return true; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/wmserver/src/input_window_monitor.cpp b/wmserver/src/input_window_monitor.cpp index f8ad19ac..393659c4 100644 --- a/wmserver/src/input_window_monitor.cpp +++ b/wmserver/src/input_window_monitor.cpp @@ -163,7 +163,7 @@ void InputWindowMonitor::TraverseWindowNodes(const std::vector> void InputWindowMonitor::UpdateDisplayDirection(MMI::PhysicalDisplayInfo& physicalDisplayInfo, DisplayId displayId) { - Rotation rotation = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(displayId)->rotation_; + Rotation rotation = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(displayId)->GetRotation(); switch (rotation) { case Rotation::ROTATION_0: physicalDisplayInfo.direction = MMI::Direction0; From 14bb0f754d24bfce570dea1f978deecbe7f8b3de Mon Sep 17 00:00:00 2001 From: jincanran Date: Fri, 18 Feb 2022 17:18:15 +0800 Subject: [PATCH 18/70] Signed-off-by: jincanran Change-Id: Ib7977ce1e0ae7cea34f3dbfb2cf13c509087ef40 Signed-off-by: jincanran Change-Id: I9581d37122b137e212517e967fadc8dca8119c4b Signed-off-by: jincanran --- wmserver/include/window_layout_policy_tile.h | 2 +- wmserver/src/window_layout_policy_tile.cpp | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/wmserver/include/window_layout_policy_tile.h b/wmserver/include/window_layout_policy_tile.h index fc455230..87995989 100644 --- a/wmserver/include/window_layout_policy_tile.h +++ b/wmserver/include/window_layout_policy_tile.h @@ -48,7 +48,7 @@ private: void AssignNodePropertyForTileWindows(); void LayoutForegroundNodeQueue(); void InitForegroundNodeQueue(); - void ForegroundNodeQueuePush(sptr& node); + void ForegroundNodeQueuePushBack(sptr& node); void ForegroundNodeQueueRemove(sptr& node); }; } diff --git a/wmserver/src/window_layout_policy_tile.cpp b/wmserver/src/window_layout_policy_tile.cpp index 5b678f9f..4d9b2450 100644 --- a/wmserver/src/window_layout_policy_tile.cpp +++ b/wmserver/src/window_layout_policy_tile.cpp @@ -85,7 +85,7 @@ void WindowLayoutPolicyTile::AddWindowNode(sptr& node) { WM_FUNCTION_TRACE(); if (WindowHelper::IsMainWindow(node->GetWindowType())) { - ForegroundNodeQueuePush(node); + ForegroundNodeQueuePushBack(node); AssignNodePropertyForTileWindows(); LayoutForegroundNodeQueue(); } else { @@ -100,10 +100,10 @@ void WindowLayoutPolicyTile::RemoveWindowNode(sptr& node) // affect other windows, trigger off global layout if (avoidTypes_.find(type) != avoidTypes_.end()) { LayoutWindowTree(); - } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode - LayoutWindowTree(); } else { ForegroundNodeQueueRemove(node); + AssignNodePropertyForTileWindows(); + LayoutForegroundNodeQueue(); } Rect winRect = node->GetWindowProperty()->GetWindowRect(); node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); @@ -130,12 +130,12 @@ void WindowLayoutPolicyTile::InitForegroundNodeQueue() foregroundNodes_.clear(); for (auto& node : appWindowNode_->children_) { if (WindowHelper::IsMainWindow(node->GetWindowType())) { - ForegroundNodeQueuePush(node); + ForegroundNodeQueuePushBack(node); } } } -void WindowLayoutPolicyTile::ForegroundNodeQueuePush(sptr& node) +void WindowLayoutPolicyTile::ForegroundNodeQueuePushBack(sptr& node) { if (node == nullptr) { return; @@ -145,8 +145,10 @@ void WindowLayoutPolicyTile::ForegroundNodeQueuePush(sptr& node) while (foregroundNodes_.size() >= maxTileWinNum) { auto removeNode = foregroundNodes_.front(); foregroundNodes_.pop_front(); - WLOGFI("minimize win %{public}d in tile", removeNode->GetWindowId()); - AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(removeNode->abilityToken_); + if (removeNode->abilityToken_ != nullptr) { + WLOGFI("minimize win %{public}d in tile", removeNode->GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(removeNode->abilityToken_); + } } foregroundNodes_.push_back(node); } @@ -176,7 +178,7 @@ void WindowLayoutPolicyTile::AssignNodePropertyForTileWindows() WLOGFI("set rect for win id: %{public}d [%{public}d %{public}d %{public}d %{public}d]", foregroundNodes_.front()->GetWindowId(), singleRect_.posX_, singleRect_.posY_, singleRect_.width_, singleRect_.height_); - } else if (num <= 3) { + } else if (num <= MAX_WIN_NUM_HORIZONTAL) { auto rit = (num == MAX_WIN_NUM_HORIZONTAL) ? tripleRects_.begin() : doubleRects_.begin(); for (auto it : foregroundNodes_) { auto& rect = (*rit); From 4cd011bad4d2c5e4b21ada6f62c8b4b8f594f9e3 Mon Sep 17 00:00:00 2001 From: chenqinxin Date: Mon, 21 Feb 2022 15:54:14 +0800 Subject: [PATCH 19/70] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=AE=E7=81=AD?= =?UTF-8?q?=E5=B1=8FST?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chenqinxin Change-Id: I67158586105b8859326b30ffc2c6d3855c5fc48e --- dm/test/systemtest/display_power_test.cpp | 25 +++++++++++++++++++- dm/test/unittest/display_power_unit_test.cpp | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/dm/test/systemtest/display_power_test.cpp b/dm/test/systemtest/display_power_test.cpp index a3fdc252..31f477e4 100644 --- a/dm/test/systemtest/display_power_test.cpp +++ b/dm/test/systemtest/display_power_test.cpp @@ -15,6 +15,7 @@ #include #include "display_manager.h" +#include "window.h" #include "window_manager_hilog.h" using namespace testing; @@ -53,7 +54,7 @@ public: static inline DisplayId defaultId_; static inline uint32_t brightnessLevel_ = 80; - static inline uint32_t invalidBrightnessLevel_ = 10000000; + static inline uint32_t invalidBrightnessLevel_ = 1000000000; static inline uint32_t times_ = 0; static inline bool isDisplayStateCallbackCalled_ = false; static sptr listener_; @@ -433,6 +434,28 @@ HWTEST_F(DisplayPowerTest, set_screen_brightness_002, Function | MediumTest | Le uint32_t level = DisplayManager::GetInstance().GetScreenBrightness(defaultId_); ASSERT_NE(level, invalidBrightnessLevel_); } + +/** +* @tc.name: window_life_cycle_001 +* @tc.desc: Add a window and then call SuspendEnd and check window state; Notify unlock and check window state +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, window_life_cycle_001, Function | MediumTest | Level2) +{ + sptr option = new WindowOption(); + sptr window = Window::Create("window1", option, nullptr); + EXPECT_EQ(WMError::WM_OK, window->Show()); + + DisplayManager::GetInstance().SuspendBegin(PowerStateChangeReason::POWER_BUTTON); + usleep(SLEEP_TIME_IN_US); + ASSERT_EQ(false, window->GetShowState()); + + DisplayManager::GetInstance().NotifyDisplayEvent(DisplayEvent::UNLOCK); + usleep(SLEEP_TIME_IN_US); + ASSERT_EQ(true, window->GetShowState()); + + window->Destroy(); +} } // namespace } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/dm/test/unittest/display_power_unit_test.cpp b/dm/test/unittest/display_power_unit_test.cpp index 6ecca2c4..fdabe9fc 100644 --- a/dm/test/unittest/display_power_unit_test.cpp +++ b/dm/test/unittest/display_power_unit_test.cpp @@ -39,7 +39,7 @@ public: static inline sptr listener_ = new DisplayPowerEventListener(); static inline DisplayId defaultId_ = 0; static inline uint32_t brightnessLevel_ = 80; - static inline uint32_t invalidBrightnessLevel_ = 10000000; + static inline uint32_t invalidBrightnessLevel_ = 1000000000; static inline DisplayPowerState initialPowerState_; static inline DisplayState initialState_; }; From 6f69df7ce627fdd07e645e84dd8d94dcb6155590 Mon Sep 17 00:00:00 2001 From: fanby01 Date: Mon, 21 Feb 2022 15:39:12 +0800 Subject: [PATCH 20/70] add test case for colorgamut Change-Id: Id7e7c80bacf9c370f3873d179a0de82430ca7320 Signed-off-by: fanby01 --- dm/test/systemtest/screen_gamut_test.cpp | 196 ++++++++++++++++++++--- wm/test/systemtest/window_gamut_test.cpp | 67 +++++++- 2 files changed, 236 insertions(+), 27 deletions(-) diff --git a/dm/test/systemtest/screen_gamut_test.cpp b/dm/test/systemtest/screen_gamut_test.cpp index e4959dd2..f014cb41 100644 --- a/dm/test/systemtest/screen_gamut_test.cpp +++ b/dm/test/systemtest/screen_gamut_test.cpp @@ -56,36 +56,135 @@ void ScreenGamutTest::TearDown() namespace { /** - * @tc.name: ScreenGamut01 - * @tc.desc: gamut + * @tc.name: GetScreenSupportedColorGamuts01 + * @tc.desc: gamut GetScreenSupportedColorGamuts * @tc.type: FUNC */ -HWTEST_F(ScreenGamutTest, ScreenGamut01, Function | MediumTest | Level1) +HWTEST_F(ScreenGamutTest, GetScreenSupportedColorGamuts01, Function | MediumTest | Level3) { ASSERT_NE(defaultScreen_, nullptr); DMError ret; std::vector colorGamuts; ret = defaultScreen_->GetScreenSupportedColorGamuts(colorGamuts); ASSERT_EQ(ret, DMError::DM_OK); - - ScreenColorGamut colorGamut; - ret = defaultScreen_->GetScreenColorGamut(colorGamut); - ASSERT_EQ(ret, DMError::DM_OK); - - ret = defaultScreen_->SetScreenColorGamut(0); - ASSERT_EQ(ret, DMError::DM_OK); - - const int32_t invalidColorGamutIndex = -1; - ret = defaultScreen_->SetScreenColorGamut(invalidColorGamutIndex); - ASSERT_NE(ret, DMError::DM_OK); + ASSERT_GT(colorGamuts.size(), 0); } /** - * @tc.name: ScreenGamut02 - * @tc.desc: gamut + * @tc.name: GetScreenColorGamut01 + * @tc.desc: gamut GetScreenColorGamut * @tc.type: FUNC */ -HWTEST_F(ScreenGamutTest, ScreenGamut02, Function | MediumTest | Level1) +HWTEST_F(ScreenGamutTest, GetScreenColorGamut01, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + ScreenColorGamut colorGamut; + ret = defaultScreen_->GetScreenColorGamut(colorGamut); + ASSERT_EQ(ret, DMError::DM_OK); + ASSERT_NE(COLOR_GAMUT_INVALID, colorGamut); +} + +/** + * @tc.name: SetScreenColorGamut01 + * @tc.desc: gamut SetScreenColorGamut, valid index + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, SetScreenColorGamut01, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + ScreenColorGamut colorGamutBackup; + int32_t colorGamutBackupIdx = -1; + ScreenColorGamut colorGamut; + std::vector colorGamuts; + + ret = defaultScreen_->GetScreenColorGamut(colorGamutBackup); // backup origin + ASSERT_EQ(ret, DMError::DM_OK); + + ret = defaultScreen_->GetScreenSupportedColorGamuts(colorGamuts); + ASSERT_EQ(ret, DMError::DM_OK); + + for (int32_t i = 0; i < static_cast(colorGamuts.size()); i++) { + ret = defaultScreen_->SetScreenColorGamut(i); + ASSERT_EQ(ret, DMError::DM_OK); + + ret = defaultScreen_->GetScreenColorGamut(colorGamut); + ASSERT_EQ(ret, DMError::DM_OK); + +#ifdef SCREEN_GAMUT_SET_GET_OK + ASSERT_EQ(colorGamut, colorGamuts[i]); +#endif + if (colorGamutBackup == colorGamuts[i]) { + colorGamutBackupIdx = i; + } + } + + ASSERT_GE(colorGamutBackupIdx, 0); + ret = defaultScreen_->SetScreenColorGamut(colorGamutBackupIdx); // restore + ASSERT_EQ(ret, DMError::DM_OK); +} + +/** + * @tc.name: SetScreenColorGamut02 + * @tc.desc: gamut SetScreenColorGamut, invalid index < 0 + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, SetScreenColorGamut02, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + ScreenColorGamut colorGamutBefore; + ScreenColorGamut colorGamutAfter; + + ret = defaultScreen_->GetScreenColorGamut(colorGamutBefore); + ASSERT_EQ(ret, DMError::DM_OK); + + constexpr int32_t invalidColorGamutIndex = -1; // index < 0 + ret = defaultScreen_->SetScreenColorGamut(invalidColorGamutIndex); + ASSERT_NE(ret, DMError::DM_OK); + + ret = defaultScreen_->GetScreenColorGamut(colorGamutAfter); + ASSERT_EQ(ret, DMError::DM_OK); + + ASSERT_EQ(colorGamutBefore, colorGamutAfter); // don't change colorgamut after invalid set +} + +/** + * @tc.name: SetScreenColorGamut03 + * @tc.desc: gamut SetScreenColorGamut, invalid index >= size + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, SetScreenColorGamut03, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + ScreenColorGamut colorGamutBefore; + ScreenColorGamut colorGamutAfter; + + ret = defaultScreen_->GetScreenColorGamut(colorGamutBefore); + ASSERT_EQ(ret, DMError::DM_OK); + + std::vector colorGamuts; + ret = defaultScreen_->GetScreenSupportedColorGamuts(colorGamuts); + ASSERT_EQ(ret, DMError::DM_OK); + + const int32_t invalidColorGamutIndex = static_cast(colorGamuts.size()); // index >= size + ret = defaultScreen_->SetScreenColorGamut(invalidColorGamutIndex); + ASSERT_NE(ret, DMError::DM_OK); + + ret = defaultScreen_->GetScreenColorGamut(colorGamutAfter); + ASSERT_EQ(ret, DMError::DM_OK); + + ASSERT_EQ(colorGamutBefore, colorGamutAfter); // don't change colorgamut after invalid set +} + +/** + * @tc.name: GetScreenGamutMap01 + * @tc.desc: gamut GetScreenGamutMap + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, GetScreenGamutMap01, Function | MediumTest | Level3) { ASSERT_NE(defaultScreen_, nullptr); DMError ret; @@ -93,21 +192,76 @@ HWTEST_F(ScreenGamutTest, ScreenGamut02, Function | MediumTest | Level1) ret = defaultScreen_->GetScreenGamutMap(gamutMap); ASSERT_EQ(ret, DMError::DM_OK); +} - ret = defaultScreen_->SetScreenGamutMap(gamutMap); +/** + * @tc.name: SetScreenGamutMap01 + * @tc.desc: gamut SetScreenGamutMap, valid param + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, SetScreenGamutMap01, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + const ScreenGamutMap gamutMaps[] = { + GAMUT_MAP_CONSTANT, + GAMUT_MAP_EXTENSION, + GAMUT_MAP_HDR_CONSTANT, + GAMUT_MAP_HDR_EXTENSION, + }; + ScreenGamutMap gamutMap; + ScreenGamutMap gamutMapBackup; + + ret = defaultScreen_->GetScreenGamutMap(gamutMapBackup); // backup origin + ASSERT_EQ(ret, DMError::DM_OK); + + for (uint32_t i = 0; i < sizeof(gamutMaps) / sizeof(ScreenGamutMap); i++) { + ret = defaultScreen_->SetScreenGamutMap(gamutMaps[i]); + ASSERT_EQ(ret, DMError::DM_OK); + + ret = defaultScreen_->GetScreenGamutMap(gamutMap); + ASSERT_EQ(ret, DMError::DM_OK); +#ifdef SCREEN_GAMUT_SET_GET_OK + ASSERT_EQ(gamutMaps[i], gamutMap); +#endif + } + + ret = defaultScreen_->SetScreenGamutMap(gamutMapBackup); // restore + ASSERT_EQ(ret, DMError::DM_OK); +} + +/** + * @tc.name: SetScreenGamutMap02 + * @tc.desc: gamut SetScreenGamutMap, invalid param + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, SetScreenGamutMap02, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + ScreenGamutMap gamutMap; + ScreenGamutMap gamutMapBefore; + ScreenGamutMap gamutMapAfter; + + ret = defaultScreen_->GetScreenGamutMap(gamutMapBefore); ASSERT_EQ(ret, DMError::DM_OK); gamutMap = static_cast(static_cast(ScreenGamutMap::GAMUT_MAP_HDR_EXTENSION) + 1); ret = defaultScreen_->SetScreenGamutMap(gamutMap); ASSERT_NE(ret, DMError::DM_OK); + + ret = defaultScreen_->GetScreenGamutMap(gamutMapAfter); + ASSERT_EQ(ret, DMError::DM_OK); + + ASSERT_EQ(gamutMapBefore, gamutMapAfter); } /** - * @tc.name: ScreenGamut03 - * @tc.desc: gamut + * @tc.name: SetScreenColorTransform01 + * @tc.desc: gamut SetScreenColorTransform * @tc.type: FUNC */ -HWTEST_F(ScreenGamutTest, ScreenGamut03, Function | MediumTest | Level1) +HWTEST_F(ScreenGamutTest, SetScreenColorTransform01, Function | MediumTest | Level3) { ASSERT_NE(defaultScreen_, nullptr); DMError ret; diff --git a/wm/test/systemtest/window_gamut_test.cpp b/wm/test/systemtest/window_gamut_test.cpp index bfdb6de5..27d88bce 100644 --- a/wm/test/systemtest/window_gamut_test.cpp +++ b/wm/test/systemtest/window_gamut_test.cpp @@ -22,6 +22,9 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { using utils = WindowTestUtils; +constexpr uint32_t MAX_WAIT_COUNT = 100; +constexpr uint32_t WAIT_DUR = 10 * 1000; + class WindowGamutTest : public testing::Test { public: static void SetUpTestCase(); @@ -73,21 +76,73 @@ HWTEST_F(WindowGamutTest, IsSupportWideGamut01, Function | MediumTest | Level3) } /** - * @tc.name: SetGetColorSpace01 - * @tc.desc: Set and Get ColorSpace + * @tc.name: GetColorSpace01 + * @tc.desc: Get ColorSpace * @tc.type: FUNC * @tc.require: */ -HWTEST_F(WindowGamutTest, SetGetColorSpace01, Function | MediumTest | Level3) +HWTEST_F(WindowGamutTest, GetColorSpace01, Function | MediumTest | Level3) { const sptr& window = utils::CreateTestWindow(fullScreenAppInfo_); - window->SetColorSpace(ColorSpace::COLOR_SPACE_DEFAULT); - window->SetColorSpace(ColorSpace::COLOR_SPACE_WIDE_GAMUT); + ASSERT_EQ(ColorSpace::COLOR_SPACE_DEFAULT, window->GetColorSpace()); + + window->Destroy(); +} + +/** + * @tc.name: SetColorSpace01 + * @tc.desc: Set ColorSpace, valid param + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(WindowGamutTest, SetColorSpace01, Function | MediumTest | Level3) +{ + uint32_t i, j; + const ColorSpace colorSpacesToTest[] = { + ColorSpace::COLOR_SPACE_DEFAULT, + ColorSpace::COLOR_SPACE_WIDE_GAMUT + }; + ColorSpace colorSpace; + const sptr& window = utils::CreateTestWindow(fullScreenAppInfo_); + + ColorSpace colorSpaceBackup = window->GetColorSpace(); // backup origin + + for (j = 0; j < sizeof(colorSpacesToTest) / sizeof(ColorSpace); j++) { + window->SetColorSpace(colorSpacesToTest[j]); // async func + for (i = 0; i < MAX_WAIT_COUNT; i++) { // wait some time for async set ok + colorSpace = window->GetColorSpace(); + if (colorSpace != colorSpacesToTest[j]) { + usleep(WAIT_DUR); + } else { + break; + } + } + ASSERT_EQ(colorSpacesToTest[j], window->GetColorSpace()); + } + + window->SetColorSpace(colorSpaceBackup); // restore + + window->Destroy(); +} + +/** + * @tc.name: SetColorSpace02 + * @tc.desc: Set ColorSpace, invalid param + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(WindowGamutTest, SetColorSpace02, Function | MediumTest | Level3) +{ + const sptr& window = utils::CreateTestWindow(fullScreenAppInfo_); + + ColorSpace colorSpaceBackup = window->GetColorSpace(); + ColorSpace invalidColorSpace = static_cast(static_cast(ColorSpace::COLOR_SPACE_WIDE_GAMUT) + 1); window->SetColorSpace(invalidColorSpace); // invalid param - ASSERT_EQ(ColorSpace::COLOR_SPACE_DEFAULT, window->GetColorSpace()); + + ASSERT_EQ(colorSpaceBackup, window->GetColorSpace()); window->Destroy(); } From edd166599b58b03c76f27e94c3c85533a1559f2a Mon Sep 17 00:00:00 2001 From: chenqinxin Date: Thu, 17 Feb 2022 17:02:01 +0800 Subject: [PATCH 21/70] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=8F=AF=E8=A7=81=E6=80=A7=E6=B3=A8=E5=86=8C=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chenqinxin Change-Id: I86cd8f99a77e3ea157868fc366f48469c5ccc977 --- dm/src/display_manager.cpp | 2 +- interfaces/innerkits/wm/window_manager.h | 25 ++ interfaces/innerkits/wm/wm_common.h | 9 +- wm/include/window_manager_agent.h | 1 + .../zidl/window_manager_agent_interface.h | 3 + wm/include/zidl/window_manager_agent_proxy.h | 1 + wm/src/window_manager.cpp | 74 +++++- wm/src/window_manager_agent.cpp | 5 + wm/src/zidl/window_manager_agent_proxy.cpp | 26 ++ wm/src/zidl/window_manager_agent_stub.cpp | 10 + wm/test/systemtest/BUILD.gn | 12 + .../window_visibility_info_test.cpp | 245 ++++++++++++++++++ .../include/window_manager_agent_controller.h | 1 + wmserver/include/window_node.h | 3 +- wmserver/include/window_node_container.h | 13 +- wmserver/include/window_root.h | 2 +- wmserver/src/window_controller.cpp | 2 +- .../src/window_manager_agent_controller.cpp | 10 + wmserver/src/window_node_container.cpp | 224 +++++++++++----- wmserver/src/window_root.cpp | 15 +- 20 files changed, 592 insertions(+), 91 deletions(-) create mode 100644 wm/test/systemtest/window_visibility_info_test.cpp diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 3bf45203..bc113aa9 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -484,7 +484,7 @@ bool DisplayManager::SetScreenBrightness(uint64_t screenId, uint32_t level) uint32_t DisplayManager::GetScreenBrightness(uint64_t screenId) const { uint32_t level = static_cast(RSInterfaces::GetInstance().GetScreenBacklight(screenId)); - WLOGFI("screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); + WLOGFD("screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); return level; } diff --git a/interfaces/innerkits/wm/window_manager.h b/interfaces/innerkits/wm/window_manager.h index 931d6ef0..989fdae0 100644 --- a/interfaces/innerkits/wm/window_manager.h +++ b/interfaces/innerkits/wm/window_manager.h @@ -49,6 +49,27 @@ public: virtual void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) = 0; }; +class WindowVisibilityInfo : public Parcelable { +public: + WindowVisibilityInfo() = default; + WindowVisibilityInfo(uint32_t winId, int32_t pid, int32_t uid, bool visibility) + : windowId_(winId), pid_(pid), uid_(uid), isVisible_(visibility) {}; + ~WindowVisibilityInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + static WindowVisibilityInfo* Unmarshalling(Parcel& parcel); + + uint32_t windowId_ { INVALID_WINDOW_ID }; + int32_t pid_ { 0 }; + int32_t uid_ { 0 }; + bool isVisible_ { false }; +}; + +class IVisibilityChangedListener : public RefBase { +public: + virtual void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) = 0; +}; + class WindowInfo : public Parcelable { public: WindowInfo() = default; @@ -78,6 +99,8 @@ public: void UnregisterSystemBarChangedListener(const sptr& listener); void RegisterWindowUpdateListener(const sptr& listener); void UnregisterWindowUpdateListener(const sptr& listener); + void RegisterVisibilityChangedListener(const sptr& listener); + void UnregisterVisibilityChangedListener(const sptr& listener); void MinimizeAllAppWindows(DisplayId displayId); void SetWindowLayoutMode(WindowLayoutMode mode, DisplayId displayId); @@ -91,6 +114,8 @@ private: DisplayId displayId, bool focused) const; void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) const; void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type); + void UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) const; }; } // namespace Rosen } // namespace OHOS diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 70058ca9..9256feac 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -124,10 +124,17 @@ struct Rect { int32_t posY_; uint32_t width_; uint32_t height_; - bool operator == (const Rect& a) const + + bool operator==(const Rect& a) const { return (posX_ == a.posX_ && posY_ == a.posY_ && width_ == a.width_ && height_ == a.height_); } + + bool IsInsideOf(const Rect& a) const + { + return (posX_ >= a.posX_ && posY_ >= a.posY_ && + posX_ + width_ <= a.posX_ + a.width_ && posY_ + height_ <= a.posY_ + a.height_); + } }; struct PointInfo { diff --git a/wm/include/window_manager_agent.h b/wm/include/window_manager_agent.h index b4325742..d3d1de42 100644 --- a/wm/include/window_manager_agent.h +++ b/wm/include/window_manager_agent.h @@ -30,6 +30,7 @@ public: DisplayId displayId, bool focused) override; void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& props) override; void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type) override; + void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) override; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/zidl/window_manager_agent_interface.h b/wm/include/zidl/window_manager_agent_interface.h index 57746aea..2c1daff8 100644 --- a/wm/include/zidl/window_manager_agent_interface.h +++ b/wm/include/zidl/window_manager_agent_interface.h @@ -26,6 +26,7 @@ enum class WindowManagerAgentType : uint32_t { WINDOW_MANAGER_AGENT_TYPE_FOCUS, WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR, WINDOW_MANAGER_AGENT_TYPE_WINDOW_UPDATE, + WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, }; class IWindowManagerAgent : public IRemoteBroker { @@ -36,12 +37,14 @@ public: TRANS_ID_UPDATE_FOCUS_STATUS = 1, TRANS_ID_UPDATE_SYSTEM_BAR_PROPS, TRANS_ID_UPDATE_WINDOW_STATUS, + TRANS_ID_UPDATE_WINDOW_VISIBILITY, }; virtual void UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, DisplayId displayId, bool focused) = 0; virtual void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) = 0; virtual void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type) = 0; + virtual void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) = 0; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/zidl/window_manager_agent_proxy.h b/wm/include/zidl/window_manager_agent_proxy.h index 7531213d..fd1b114d 100644 --- a/wm/include/zidl/window_manager_agent_proxy.h +++ b/wm/include/zidl/window_manager_agent_proxy.h @@ -31,6 +31,7 @@ public: DisplayId displayId, bool focused) override; void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) override; void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type) override; + void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) override; private: static inline BrokerDelegator delegator_; diff --git a/wm/src/window_manager.cpp b/wm/src/window_manager.cpp index 73e2610d..6774bcaf 100644 --- a/wm/src/window_manager.cpp +++ b/wm/src/window_manager.cpp @@ -29,6 +29,24 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManager"}; } +bool WindowVisibilityInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteUint32(windowId_) && parcel.WriteInt32(pid_) && + parcel.WriteInt32(uid_) && parcel.WriteBool(isVisible_); +} + +WindowVisibilityInfo* WindowVisibilityInfo::Unmarshalling(Parcel &parcel) +{ + WindowVisibilityInfo* windowVisibilityInfo = new WindowVisibilityInfo(); + bool res = parcel.ReadUint32(windowVisibilityInfo->windowId_) && parcel.ReadInt32(windowVisibilityInfo->pid_) && + parcel.ReadInt32(windowVisibilityInfo->uid_) && parcel.ReadBool(windowVisibilityInfo->isVisible_); + if (!res) { + delete windowVisibilityInfo; + return nullptr; + } + return windowVisibilityInfo; +} + bool WindowInfo::Marshalling(Parcel &parcel) const { return parcel.WriteInt32(wid_) && parcel.WriteUint32(windowRect_.width_) && @@ -40,13 +58,11 @@ bool WindowInfo::Marshalling(Parcel &parcel) const WindowInfo* WindowInfo::Unmarshalling(Parcel &parcel) { WindowInfo* windowInfo = new WindowInfo(); - if (windowInfo == nullptr) { - return nullptr; - } bool res = parcel.ReadInt32(windowInfo->wid_) && parcel.ReadUint32(windowInfo->windowRect_.width_) && parcel.ReadUint32(windowInfo->windowRect_.height_) && parcel.ReadInt32(windowInfo->windowRect_.posX_) && parcel.ReadInt32(windowInfo->windowRect_.posY_) && parcel.ReadBool(windowInfo->focused_); if (!res) { + delete windowInfo; return nullptr; } windowInfo->mode_ = static_cast(parcel.ReadUint32()); @@ -64,6 +80,7 @@ public: WindowType windowType, DisplayId displayId) const; void NotifySystemBarChanged(DisplayId displayId, const SystemBarRegionTints& tints) const; void NotifyWindowUpdate(const sptr& windowInfo, WindowUpdateType type) const; + void NotifyWindowVisibilityInfoChanged(const std::vector>& windowVisibilityInfos) const; static inline SingletonDelegator delegator_; std::recursive_mutex mutex_; @@ -73,6 +90,8 @@ public: sptr systemBarChangedListenerAgent_; std::vector> windowUpdateListeners_; sptr windowUpdateListenerAgent_; + std::vector> windowVisibilityListeners_; + sptr windowVisibilityListenerAgent_; }; void WindowManager::Impl::NotifyFocused(uint32_t windowId, const sptr& abilityToken, @@ -122,6 +141,14 @@ void WindowManager::Impl::NotifyWindowUpdate(const sptr& windowInfo, } } +void WindowManager::Impl::NotifyWindowVisibilityInfoChanged( + const std::vector>& windowVisibilityInfos) const +{ + for (auto& listener : windowVisibilityListeners_) { + listener->OnWindowVisibilityChanged(windowVisibilityInfos); + } +} + WindowManager::WindowManager() : pImpl_(std::make_unique()) { } @@ -257,6 +284,41 @@ void WindowManager::UnregisterWindowUpdateListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return; + } + std::lock_guard lock(pImpl_->mutex_); + pImpl_->windowVisibilityListeners_.emplace_back(listener); + if (pImpl_->windowVisibilityListenerAgent_ == nullptr) { + pImpl_->windowVisibilityListenerAgent_ = new WindowManagerAgent(); + SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, + pImpl_->windowVisibilityListenerAgent_); + } +} + +void WindowManager::UnregisterVisibilityChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + return; + } + std::lock_guard lock(pImpl_->mutex_); + pImpl_->windowVisibilityListeners_.erase(std::remove_if(pImpl_->windowVisibilityListeners_.begin(), + pImpl_->windowVisibilityListeners_.end(), [listener](sptr registeredListener) { + return registeredListener == listener; + }), pImpl_->windowVisibilityListeners_.end()); + + if (pImpl_->windowVisibilityListeners_.empty() && pImpl_->windowVisibilityListenerAgent_ != nullptr) { + SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, + pImpl_->windowVisibilityListenerAgent_); + pImpl_->windowVisibilityListenerAgent_ = nullptr; + } +} + void WindowManager::UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, DisplayId displayId, bool focused) const { @@ -278,5 +340,11 @@ void WindowManager::UpdateWindowStatus(const sptr& windowInfo, Windo { pImpl_->NotifyWindowUpdate(windowInfo, type); } + +void WindowManager::UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) const +{ + pImpl_->NotifyWindowVisibilityInfoChanged(windowVisibilityInfos); +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/window_manager_agent.cpp b/wm/src/window_manager_agent.cpp index b501c181..d3e7e7c6 100644 --- a/wm/src/window_manager_agent.cpp +++ b/wm/src/window_manager_agent.cpp @@ -35,5 +35,10 @@ void WindowManagerAgent::UpdateWindowStatus(const sptr& windowInfo, { SingletonContainer::Get().UpdateWindowStatus(windowInfo, type); } + +void WindowManagerAgent::UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) +{ + SingletonContainer::Get().UpdateWindowVisibilityInfo(visibilityInfos); +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/zidl/window_manager_agent_proxy.cpp b/wm/src/zidl/window_manager_agent_proxy.cpp index 80da77d8..b3ebe956 100644 --- a/wm/src/zidl/window_manager_agent_proxy.cpp +++ b/wm/src/zidl/window_manager_agent_proxy.cpp @@ -131,6 +131,32 @@ void WindowManagerAgentProxy::UpdateWindowStatus(const sptr& windowI WLOGFE("SendRequest failed"); } } + +void WindowManagerAgentProxy::UpdateWindowVisibilityInfo( + const std::vector>& visibilityInfos) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint32(static_cast(visibilityInfos.size()))) { + WLOGFE("write windowVisibilityInfos size failed"); + return; + } + for (auto& info : visibilityInfos) { + if (!data.WriteParcelable(info)) { + WLOGFE("Write windowVisibilityInfo failed"); + return; + } + } + + if (Remote()->SendRequest(TRANS_ID_UPDATE_WINDOW_VISIBILITY, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/zidl/window_manager_agent_stub.cpp b/wm/src/zidl/window_manager_agent_stub.cpp index 0a1fd55b..83e10486 100644 --- a/wm/src/zidl/window_manager_agent_stub.cpp +++ b/wm/src/zidl/window_manager_agent_stub.cpp @@ -62,6 +62,16 @@ int WindowManagerAgentStub::OnRemoteRequest(uint32_t code, MessageParcel& data, UpdateWindowStatus(windowInfo, type); break; } + case TRANS_ID_UPDATE_WINDOW_VISIBILITY: { + uint32_t size = data.ReadUint32(); + std::vector> windowVisibilityInfos; + for (uint32_t i = 0; i < size; ++i) { + sptr info = data.ReadParcelable(); + windowVisibilityInfos.emplace_back(info); + } + UpdateWindowVisibilityInfo(windowVisibilityInfos); + break; + } default: break; } diff --git a/wm/test/systemtest/BUILD.gn b/wm/test/systemtest/BUILD.gn index b5b193f7..4aa3d3a2 100644 --- a/wm/test/systemtest/BUILD.gn +++ b/wm/test/systemtest/BUILD.gn @@ -30,6 +30,7 @@ group("systemtest") { ":wm_window_split_immersive_test", ":wm_window_split_test", ":wm_window_subwindow_test", + ":wm_window_visibility_info_test", ] } @@ -154,6 +155,17 @@ ohos_systemtest("wm_window_gamut_test") { ## SystemTest window_gamut_test }}} +## SystemTest wm_window_visibility_info_test {{{ +ohos_systemtest("wm_window_visibility_info_test") { + module_out_path = module_out_path + + sources = [ "window_visibility_info_test.cpp" ] + + deps = [ ":wm_systemtest_common" ] +} + +## SystemTest wm_window_visibility_info_test }}} + ## Build wm_systemtest_common.a {{{ config("wm_systemtest_common_public_config") { include_dirs = [ diff --git a/wm/test/systemtest/window_visibility_info_test.cpp b/wm/test/systemtest/window_visibility_info_test.cpp new file mode 100644 index 00000000..668deab2 --- /dev/null +++ b/wm/test/systemtest/window_visibility_info_test.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2022 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. + */ + +// gtest +#include +#include "wm_common.h" +#include "window_manager.h" +#include "window_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowVisibilityInfoTest"}; +} + +using utils = WindowTestUtils; +constexpr int WAIT_ASYNC_US = 200000; // 200ms + +class VisibilityChangedListenerImpl : public IVisibilityChangedListener { +public: + void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override; + std::vector> windowVisibilityInfos_; +}; + +void VisibilityChangedListenerImpl::OnWindowVisibilityChanged( + const std::vector>& windowVisibilityInfo) +{ + WLOGFI("size:%{public}zu", windowVisibilityInfo.size()); + windowVisibilityInfos_ = std::move(windowVisibilityInfo); + for (auto& info : windowVisibilityInfos_) { + WLOGFI("windowId:%{public}u, covered:%{public}d, pid:%{public}d, uid:%{public}d", info->windowId_, + info->isVisible_, info->pid_, info->uid_); + } +} + +class WindowVisibilityInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + + static void TearDownTestCase(); + + virtual void SetUp() override; + + virtual void TearDown() override; + + static inline sptr visibilityChangedListener_ = new VisibilityChangedListenerImpl(); + utils::TestWindowInfo fullScreenAppInfo_; + utils::TestWindowInfo floatAppInfo_; + utils::TestWindowInfo subAppInfo_; +}; + +void WindowVisibilityInfoTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + if (display == nullptr) { + WLOGFE("GetDefaultDisplay: failed!"); + } else { + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetFreshRate()); + } + Rect displayRect = {0, 0, + static_cast(display->GetWidth()), static_cast(display->GetHeight())}; + utils::InitByDisplayRect(displayRect); + WindowManager::GetInstance().RegisterVisibilityChangedListener(visibilityChangedListener_); +} + +void WindowVisibilityInfoTest::TearDownTestCase() +{ + WindowManager::GetInstance().UnregisterVisibilityChangedListener(visibilityChangedListener_); +} + +void WindowVisibilityInfoTest::SetUp() +{ + fullScreenAppInfo_ = { + .name = "FullWindow", + .rect = utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentName = "", + }; + floatAppInfo_ = { + .name = "ParentWindow", + .rect = utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentName = "", + }; + subAppInfo_ = { + .name = "SubWindow", + .rect = utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentName = "", + }; +} + +void WindowVisibilityInfoTest::TearDown() +{ +} + +namespace { +/** +* @tc.name: WindowVisibilityInfoTest01 +* @tc.desc: add main window and sub window, show and hide and test callback +* @tc.type: FUNC +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest01, Function | MediumTest | Level1) +{ + floatAppInfo_.name = "window1"; + floatAppInfo_.rect = {250, 150, 300, 500}; + sptr window1 = utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow1"; + subAppInfo_.rect = {400, 200, 100, 100}; + subAppInfo_.parentName = window1->GetWindowName(); + sptr subWindow1 = utils::CreateTestWindow(subAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + window1->Destroy(); + subWindow1->Destroy(); +} + +/** +* @tc.name: WindowVisibilityInfoTest02 +* @tc.desc: add two fullscreen main window, test callback +* @tc.type: FUNC +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest02, Function | MediumTest | Level1) +{ + fullScreenAppInfo_.name = "window1"; + sptr window1 = utils::CreateTestWindow(fullScreenAppInfo_); + + fullScreenAppInfo_.name = "window2"; + sptr window2 = utils::CreateTestWindow(fullScreenAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + window1->Destroy(); + window2->Destroy(); +} + +/** +* @tc.name: WindowVisibilityInfoTest03 +* @tc.desc: add two main window and sub windows and test callback +* @tc.type: FUNC +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest03, Function | MediumTest | Level1) +{ + floatAppInfo_.name = "window1"; + floatAppInfo_.rect = {0, 0, 300, 600}; + sptr window1 = utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow1"; + subAppInfo_.rect = {400, 200, 100, 100}; + subAppInfo_.parentName = window1->GetWindowName(); + sptr subWindow1 = utils::CreateTestWindow(subAppInfo_); + + floatAppInfo_.name = "window2"; + floatAppInfo_.rect = {50, 150, 240, 426}; + sptr window2 = utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow2"; + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + subAppInfo_.parentName = window2->GetWindowName(); + sptr subWindow2 = utils::CreateTestWindow(subAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + window1->Destroy(); + subWindow1->Destroy(); + window2->Destroy(); + subWindow2->Destroy(); +} +} +} // namespace Rosen +} // namespace OHOS + diff --git a/wmserver/include/window_manager_agent_controller.h b/wmserver/include/window_manager_agent_controller.h index 9f99bf31..1f6204ac 100644 --- a/wmserver/include/window_manager_agent_controller.h +++ b/wmserver/include/window_manager_agent_controller.h @@ -35,6 +35,7 @@ public: DisplayId displayId, bool focused); void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints); void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type); + void UpdateWindowVisibilityInfo(const std::vector>& windowVisibilityInfos); private: WindowManagerAgentController() {} diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index 6ba52af3..2234a7e7 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -81,7 +81,8 @@ public: int32_t priority_ { 0 }; bool requestedVisibility_ { false }; bool currentVisibility_ { false }; - bool hasDecorated_ = false; + bool hasDecorated_ { false }; + bool isCovered_ { true }; // initial value true to ensure notification when this window is shown private: // colorspace, gamut diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 6dc7ef72..8acd73b5 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -27,6 +27,7 @@ namespace OHOS { namespace Rosen { +using WindowNodeOperationFunc = std::function)>; // return true indicates to stop traverse class WindowNodeContainer : public RefBase { public: WindowNodeContainer(DisplayId displayId, uint32_t width, uint32_t height); @@ -50,7 +51,6 @@ public: void UpdateDisplayRect(uint32_t width, uint32_t height); void OnAvoidAreaChange(const std::vector& avoidAreas); - void LayoutDividerWindow(sptr& node); bool isVerticalDisplay() const; WMError RaiseZOrderForAppWindow(sptr& node, sptr& parentNode); sptr GetNextFocusableWindow(uint32_t windowId) const; @@ -63,13 +63,10 @@ public: WMError ExitSplitWindowMode(sptr& node); WMError SwitchLayoutPolicy(WindowLayoutMode mode, bool reorder = false); void MoveWindowNode(sptr& container); - sptr GetBelowAppWindowNode() const; - sptr GetAppWindowNode() const; - sptr GetAboveAppWindowNode() const; float GetVirtualPixelRatio() const; + void TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom = true) const; private: - void AssignZOrder(sptr& node); void TraverseWindowNode(sptr& root, std::vector>& windowNodes) const; sptr FindRoot(WindowType type) const; sptr FindWindowNodeById(uint32_t id) const; @@ -92,6 +89,11 @@ private: void ResetLayoutPolicy(); bool IsFullImmersiveNode(sptr node) const; bool IsSplitImmersiveNode(sptr node) const; + bool TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const; + bool TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const; + + // cannot determine in case of a window covered by union of several windows or with transparent value + void UpdateWindowVisibilityInfos(std::vector>& infos); sptr avoidController_; sptr zorderPolicy_ = new WindowZorderPolicy(); @@ -101,6 +103,7 @@ private: std::vector removedIds_; DisplayId displayId_ = 0; Rect displayRect_; + std::vector currentCoveredArea_; std::unordered_map> sysBarNodeMap_ { { WindowType::WINDOW_TYPE_STATUS_BAR, nullptr }, { WindowType::WINDOW_TYPE_NAVIGATION_BAR, nullptr }, diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index b1525014..9cd558f1 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -59,7 +59,7 @@ public: void NotifyWindowStateChange(WindowState state, WindowStateChangeReason reason); void NotifyDisplayChange(sptr abstractDisplay); - void NotifyDisplayDestory(DisplayId displayId); + void NotifyDisplayDestroy(DisplayId displayId); void NotifySystemBarTints(); WMError RaiseZOrderForAppWindow(sptr& node); float GetVirtualPixelRatio(DisplayId displayId) const; diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index dcbc9d18..efaf27a0 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -259,7 +259,7 @@ void WindowController::NotifyDisplayStateChange(DisplayId displayId, DisplayStat break; } case DisplayStateChangeType::DESTROY: { - windowRoot_->NotifyDisplayDestory(displayId); + windowRoot_->NotifyDisplayDestroy(displayId); break; } default: { diff --git a/wmserver/src/window_manager_agent_controller.cpp b/wmserver/src/window_manager_agent_controller.cpp index d0ffad1c..d976b03c 100644 --- a/wmserver/src/window_manager_agent_controller.cpp +++ b/wmserver/src/window_manager_agent_controller.cpp @@ -65,5 +65,15 @@ void WindowManagerAgentController::UpdateWindowStatus(const sptr& wi agent->UpdateWindowStatus(windowInfo, type); } } + +void WindowManagerAgentController::UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) +{ + WLOGFD("UpdateWindowVisibilityInfo size:%{public}zu", windowVisibilityInfos.size()); + for (auto& agent : wmAgentContainer_.GetAgentsByType( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY)) { + agent->UpdateWindowVisibilityInfo(windowVisibilityInfos); + } +} } } \ No newline at end of file diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 776e34f8..feeb28b5 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "common_event_manager.h" #include "display_manager_service_inner.h" @@ -122,7 +123,6 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptrAddWindowNode(node); @@ -132,6 +132,8 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr> infos; + UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); UpdateWindowStatus(node, WindowUpdateType::WINDOW_UPDATE_ADDED); WLOGFI("AddWindowNode windowId: %{public}d end", node->GetWindowId()); @@ -256,8 +258,16 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) node->requestedVisibility_ = false; node->currentVisibility_ = false; node->hasDecorated_ = false; + node->isCovered_ = true; + std::vector> infos = {new WindowVisibilityInfo(node->GetWindowId(), + node->GetCallingPid(), node->GetCallingUid(), false)}; for (auto& child : node->children_) { - child->currentVisibility_ = false; + if (child->currentVisibility_) { + child->currentVisibility_ = false; + child->isCovered_ = true; + infos.emplace_back(new WindowVisibilityInfo(child->GetWindowId(), child->GetCallingPid(), + child->GetCallingUid(), false)); + } } if (node->IsSplitMode()) { @@ -276,6 +286,7 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) } else { NotifyIfSystemBarTintChanged(); } + UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); UpdateWindowStatus(node, WindowUpdateType::WINDOW_UPDATE_REMOVED); WLOGFI("RemoveWindowNode windowId: %{public}d end", node->GetWindowId()); @@ -347,43 +358,16 @@ void WindowNodeContainer::UpdateFocusStatus(uint32_t id, bool focused) const void WindowNodeContainer::AssignZOrder() { zOrder_ = 0; - for (auto& node : belowAppWindowNode_->children_) { - AssignZOrder(node); - } - for (auto& node : appWindowNode_->children_) { - AssignZOrder(node); - } - for (auto& node : aboveAppWindowNode_->children_) { - AssignZOrder(node); - } -} - -void WindowNodeContainer::AssignZOrder(sptr& node) -{ - if (node == nullptr) { - return; - } - auto iter = node->children_.begin(); - for (; iter < node->children_.end(); ++iter) { - if ((*iter)->priority_ < 0) { - if ((*iter)->surfaceNode_) { - (*iter)->surfaceNode_->SetPositionZ(zOrder_); - ++zOrder_; - } - } else { - break; + WindowNodeOperationFunc func = [this](sptr node) { + if (node->surfaceNode_ == nullptr) { + WLOGE("AssignZOrder: surfaceNode is nullptr, window Id:%{public}u", node->GetWindowId()); + return false; } - } - if (node->surfaceNode_) { node->surfaceNode_->SetPositionZ(zOrder_); ++zOrder_; - } - for (; iter < node->children_.end(); ++iter) { - if ((*iter)->surfaceNode_) { - (*iter)->surfaceNode_->SetPositionZ(zOrder_); - ++zOrder_; - } - } + return false; + }; + TraverseWindowTree(func, false); } WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId) @@ -636,18 +620,18 @@ void WindowNodeContainer::DumpScreenWindowTree() { WLOGFI("-------- display %{public}" PRIu64" dump window info begin---------", displayId_); WLOGFI("WindowName WinId Type Mode Flag ZOrd [ x y w h]"); - std::vector> windowNodes; - TraverseContainer(windowNodes); - int32_t zOrder = static_cast(windowNodes.size()); - for (auto node : windowNodes) { + uint32_t zOrder = zOrder_; + WindowNodeOperationFunc func = [&zOrder](sptr node) { Rect rect = node->GetLayoutRect(); const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ? node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH); - WLOGFI("%{public}10s %{public}5d %{public}4d %{public}4d %{public}4d %{public}4d [%{public}4d %{public}4d " \ - "%{public}4d %{public}4d]", windowName.c_str(), node->GetWindowId(), node->GetWindowType(), - node->GetWindowMode(), node->GetWindowFlags(), - --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_); - } + WLOGI("DumpScreenWindowTree: %{public}10s %{public}5d %{public}4d %{public}4d %{public}4d %{public}4d " \ + "[%{public}4d %{public}4d %{public}4d %{public}4d]", + windowName.c_str(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(), + node->GetWindowFlags(), --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_); + return false; + }; + TraverseWindowTree(func, true); WLOGFI("-------- display %{public}" PRIu64" dump window info end ---------", displayId_); } @@ -780,22 +764,21 @@ WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr& node, spt sptr WindowNodeContainer::GetNextFocusableWindow(uint32_t windowId) const { - std::vector> windowNodes; - TraverseContainer(windowNodes); - auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), - [windowId](sptr& node) { - return node->GetWindowId() == windowId; - }); - if (iter != windowNodes.end()) { - int index = std::distance(windowNodes.begin(), iter); - for (int i = index + 1; i < windowNodes.size(); i++) { - if (windowNodes[i]->GetWindowProperty()->GetFocusable()) { - return windowNodes[i]; - } + sptr nextFocusableWindow; + bool previousFocusedWindowFound = false; + WindowNodeOperationFunc func = [windowId, &nextFocusableWindow, &previousFocusedWindowFound]( + sptr node) { + if (previousFocusedWindowFound && node->GetWindowProperty()->GetFocusable()) { + nextFocusableWindow = node; + return true; } - } - WLOGFI("could not get next focusable window"); - return nullptr; + if (node->GetWindowId() == windowId) { + previousFocusedWindowFound = true; + } + return false; + }; + TraverseWindowTree(func, true); + return nextFocusableWindow; } void WindowNodeContainer::MinimizeAllAppWindows() @@ -1027,39 +1010,136 @@ void WindowNodeContainer::MoveWindowNode(sptr& container) { WLOGFI("MoveWindowNode: disconnect expand display: %{public}" PRId64 ", move window node to display: " "%{public}" PRId64 "", container->GetDisplayId(), displayId_); - sptr belowAppNode = container->GetBelowAppWindowNode(); - sptr appNode = container->GetAppWindowNode(); - sptr aboveAppNode = container->GetAboveAppWindowNode(); - for (auto& node : belowAppNode->children_) { + for (auto& node : container->belowAppWindowNode_->children_) { WLOGFI("belowAppWindowNode_: move windowNode: {public}%d", node->GetWindowId()); node->SetDisplayId(displayId_); belowAppWindowNode_->children_.push_back(node); } - for (auto& node : appNode->children_) { + for (auto& node : container->appWindowNode_->children_) { WLOGFI("appWindowNode_: move windowNode: {public}%d", node->GetWindowId()); node->SetDisplayId(displayId_); appWindowNode_->children_.push_back(node); } - for (auto& node : aboveAppNode->children_) { + for (auto& node : container->aboveAppWindowNode_->children_) { WLOGFI("aboveAppWindowNode_: move windowNode: {public}%d", node->GetWindowId()); node->SetDisplayId(displayId_); aboveAppWindowNode_->children_.push_back(node); } } -sptr WindowNodeContainer::GetBelowAppWindowNode() const +void WindowNodeContainer::TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const { - return belowAppWindowNode_; + std::vector> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ }; + if (isFromTopToBottom) { + std::reverse(rootNodes.begin(), rootNodes.end()); + } + + for (auto& node : rootNodes) { + if (isFromTopToBottom) { + for (auto iter = node->children_.rbegin(); iter != node->children_.rend(); ++iter) { + if (TraverseFromTopToBottom(*iter, func)) { + return; + } + } + } else { + for (auto iter = node->children_.begin(); iter != node->children_.end(); ++iter) { + if (TraverseFromBottomToTop(*iter, func)) { + return; + } + } + } + } } -sptr WindowNodeContainer::GetAppWindowNode() const +bool WindowNodeContainer::TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const { - return appWindowNode_; + if (node == nullptr) { + return false; + } + auto iterBegin = node->children_.rbegin(); + for (; iterBegin != node->children_.rend(); ++iterBegin) { + if ((*iterBegin)->priority_ <= 0) { + break; + } + if (func(*iterBegin)) { + return true; + } + } + if (func(node)) { + return true; + } + for (; iterBegin != node->children_.rend(); ++iterBegin) { + if (func(*iterBegin)) { + return true; + } + } + return false; } -sptr WindowNodeContainer::GetAboveAppWindowNode() const +bool WindowNodeContainer::TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const { - return aboveAppWindowNode_; + if (node == nullptr) { + return false; + } + auto iterBegin = node->children_.begin(); + for (; iterBegin != node->children_.end(); ++iterBegin) { + if ((*iterBegin)->priority_ >= 0) { + break; + } + if (func(*iterBegin)) { + return true; + } + } + if (func(node)) { + return true; + } + for (; iterBegin != node->children_.end(); ++iterBegin) { + if (func(*iterBegin)) { + return true; + } + } + return false; +} + +void WindowNodeContainer::UpdateWindowVisibilityInfos(std::vector>& infos) +{ + currentCoveredArea_.clear(); + WindowNodeOperationFunc func = [this, &infos](sptr node) { + if (node == nullptr) { + return false; + } + Rect layoutRect = node->GetLayoutRect(); + int32_t nodeX = std::max(0, layoutRect.posX_); + int32_t nodeY = std::max(0, layoutRect.posY_); + int32_t nodeXEnd = std::min(displayRect_.posX_ + static_cast(displayRect_.width_), + layoutRect.posX_ + static_cast(layoutRect.width_)); + int32_t nodeYEnd = std::min(displayRect_.posY_ + static_cast(displayRect_.height_), + layoutRect.posY_ + static_cast(layoutRect.height_)); + + Rect rectInDisplay = {nodeX, nodeY, + static_cast(nodeXEnd - nodeX), static_cast(nodeYEnd - nodeY)}; + bool isCovered = false; + for (auto& rect : currentCoveredArea_) { + if (rectInDisplay.IsInsideOf(rect)) { + isCovered = true; + WLOGD("UpdateWindowVisibilityInfos: find covered window:%{public}u", node->GetWindowId()); + break; + } + } + if (!isCovered) { + currentCoveredArea_.emplace_back(rectInDisplay); + } + if (isCovered != node->isCovered_) { + node->isCovered_ = isCovered; + infos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(), + node->GetCallingUid(), !isCovered)); + WLOGD("UpdateWindowVisibilityInfos: covered status changed window:%{public}u, covered:%{public}d", + node->GetWindowId(), isCovered); + } + return false; + }; + TraverseWindowTree(func, true); + WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(infos); } float WindowNodeContainer::GetVirtualPixelRatio() const diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index 5a18a646..6a67ba3b 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -467,14 +467,17 @@ WMError WindowRoot::SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mo return ret; } -void WindowRoot::NotifyDisplayDestory(DisplayId expandDisplayId) +void WindowRoot::NotifyDisplayDestroy(DisplayId expandDisplayId) { - WLOGFW("disconnect expand display, get default and expand display container"); + WLOGFD("disconnect expand display, get default and expand display container"); DisplayId defaultDisplayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); - auto expandDisplaycontainer = GetOrCreateWindowNodeContainer(expandDisplayId); - auto defaultDisplaycontainer = GetOrCreateWindowNodeContainer(defaultDisplayId); - - defaultDisplaycontainer->MoveWindowNode(expandDisplaycontainer); + auto expandDisplayContainer = GetOrCreateWindowNodeContainer(expandDisplayId); + auto defaultDisplayContainer = GetOrCreateWindowNodeContainer(defaultDisplayId); + if (expandDisplayContainer == nullptr || defaultDisplayContainer == nullptr) { + WLOGFE("window node container is nullptr!"); + return; + } + defaultDisplayContainer->MoveWindowNode(expandDisplayContainer); NotifyDisplayRemoved(expandDisplayId); } From 12460515d1b2c3f5108f9c9019b2c0e83e519afc Mon Sep 17 00:00:00 2001 From: xiaojianfeng Date: Mon, 21 Feb 2022 17:33:08 +0800 Subject: [PATCH 22/70] =?UTF-8?q?Revert=20"modify=20screenInfo=EF=BC=8C=20?= =?UTF-8?q?screengroupinfo=EF=BC=8C=20displayInfo=EF=BC=8C=20screen?= =?UTF-8?q?=EF=BC=8C=20screengroup=EF=BC=8C=20display"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3a709974503fd4056a934a1e605ebb19f1ac2819. Signed-off-by: xiaojianfeng Change-Id: Idcbdea473ba24223477dbdd19ea20ecd0217501a --- dm/include/display_manager_adapter.h | 82 ++++----- dm/src/display.cpp | 92 ++++++---- dm/src/display_manager.cpp | 12 +- dm/src/display_manager_adapter.cpp | 164 +++++++----------- dm/src/screen.cpp | 133 ++++++++------ dm/src/screen_group.cpp | 40 ++--- dm/src/screen_manager.cpp | 28 +-- .../unittest/mock_display_manager_adapter.h | 34 +--- dm/test/unittest/screen_manager_test.cpp | 2 +- dm/test/unittest/screen_test.cpp | 2 +- dmserver/include/abstract_display.h | 4 +- dmserver/include/abstract_screen.h | 4 +- dmserver/include/display_manager_interface.h | 2 +- dmserver/include/display_manager_proxy.h | 2 +- dmserver/include/display_manager_service.h | 2 +- dmserver/src/abstract_display.cpp | 16 +- dmserver/src/abstract_screen.cpp | 4 +- dmserver/src/display_manager_proxy.cpp | 19 +- dmserver/src/display_manager_service.cpp | 13 +- .../src/display_manager_service_inner.cpp | 2 +- dmserver/src/display_manager_stub.cpp | 7 +- interfaces/innerkits/dm/display.h | 15 +- interfaces/innerkits/dm/screen.h | 10 +- interfaces/innerkits/dm/screen_group.h | 12 +- utils/include/class_var_defination.h | 59 ------- utils/include/display_info.h | 29 ++-- utils/include/screen_group_info.h | 19 +- utils/include/screen_info.h | 30 ++-- utils/src/display_info.cpp | 24 ++- utils/src/screen_group_info.cpp | 27 +-- utils/src/screen_info.cpp | 28 +-- wmserver/src/input_window_monitor.cpp | 2 +- 32 files changed, 424 insertions(+), 495 deletions(-) delete mode 100644 utils/include/class_var_defination.h diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index 19fe9849..aa129871 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -28,66 +28,22 @@ #include "singleton_delegator.h" namespace OHOS::Rosen { -class BaseAdapter { -public: - virtual bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, - DisplayManagerAgentType type); - virtual bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, - DisplayManagerAgentType type); - virtual void Clear(); -protected: - bool InitDMSProxyLocked(); - std::recursive_mutex mutex_; - sptr displayManagerServiceProxy_ = nullptr; - sptr dmsDeath_ = nullptr; -}; - class DMSDeathRecipient : public IRemoteObject::DeathRecipient { public: - DMSDeathRecipient(BaseAdapter& adapter); virtual void OnRemoteDied(const wptr& wptrDeath) override; -private: - BaseAdapter& adapter_; }; -class DisplayManagerAdapter : public BaseAdapter { +class DisplayManagerAdapter { WM_DECLARE_SINGLE_INSTANCE(DisplayManagerAdapter); public: virtual DisplayId GetDefaultDisplayId(); virtual sptr GetDisplayById(DisplayId displayId); - virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); - virtual bool WakeUpBegin(PowerStateChangeReason reason); - virtual bool WakeUpEnd(); - virtual bool SuspendBegin(PowerStateChangeReason reason); - virtual bool SuspendEnd(); - virtual bool SetScreenPowerForAll(DisplayPowerState state, PowerStateChangeReason reason); - virtual bool SetDisplayState(DisplayState state); - virtual DisplayState GetDisplayState(DisplayId displayId); - virtual void NotifyDisplayEvent(DisplayEvent event); - virtual void UpdateDisplayInfo(DisplayId); -private: - sptr GetDisplayInfo(DisplayId displayId); - static inline SingletonDelegator delegator; - - std::map> displayMap_; - DisplayId defaultDisplayId_; -}; - -class ScreenManagerAdapter : public BaseAdapter { -WM_DECLARE_SINGLE_INSTANCE(ScreenManagerAdapter); -public: - virtual bool RequestRotation(ScreenId screenId, Rotation rotation); virtual ScreenId CreateVirtualScreen(VirtualScreenOption option); virtual DMError DestroyVirtualScreen(ScreenId screenId); virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); - virtual sptr GetScreenById(ScreenId screenId); - virtual sptr GetScreenGroupById(ScreenId screenId); - virtual std::vector> GetAllScreens(); - virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); - virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); - virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); - virtual void UpdateScreenInfo(ScreenId); + virtual bool RequestRotation(ScreenId screenId, Rotation rotation); + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); // colorspace, gamut virtual DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts); @@ -96,13 +52,41 @@ public: virtual DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap); virtual DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap); virtual DMError SetScreenColorTransform(ScreenId screenId); + + virtual bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type); + virtual bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type); + virtual bool WakeUpBegin(PowerStateChangeReason reason); + virtual bool WakeUpEnd(); + virtual bool SuspendBegin(PowerStateChangeReason reason); + virtual bool SuspendEnd(); + virtual bool SetScreenPowerForAll(DisplayPowerState state, PowerStateChangeReason reason); + virtual bool SetDisplayState(DisplayState state); + virtual DisplayState GetDisplayState(DisplayId displayId); + virtual void NotifyDisplayEvent(DisplayEvent event); + virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); + virtual void Clear(); + virtual DisplayInfo GetDisplayInfo(DisplayId displayId); + virtual sptr GetScreenInfo(ScreenId screenId); + virtual sptr GetScreenById(ScreenId screenId); + virtual sptr GetScreenGroupById(ScreenId screenId); + virtual std::vector> GetAllScreens(); + virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); + virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); + private: - sptr GetScreenInfo(ScreenId screenId); + bool InitDMSProxyLocked(); - static inline SingletonDelegator delegator; + static inline SingletonDelegator delegator; + std::recursive_mutex mutex_; + sptr displayManagerServiceProxy_ = nullptr; + sptr dmsDeath_ = nullptr; + std::map> displayMap_; std::map> screenMap_; std::map> screenGroupMap_; + DisplayId defaultDisplayId_; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DM_DISPLAY_MANAGER_ADAPTER_H diff --git a/dm/src/display.cpp b/dm/src/display.cpp index 6f3465d4..faa6ebf7 100644 --- a/dm/src/display.cpp +++ b/dm/src/display.cpp @@ -16,68 +16,89 @@ #include "display.h" #include "display_info.h" #include "display_manager_adapter.h" -#include "window_manager_hilog.h" namespace OHOS::Rosen { -namespace { - constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "Display"}; -} class Display::Impl : public RefBase { -public: - Impl(const std::string& name, sptr info) - { - name_= name; - if (info == nullptr) { - WLOGFE("DisplayInfo is nullptr."); - } - displayInfo_ = info; - } - ~Impl() = default; - DEFINE_VAR_FUNC_GET_SET(std::string, Name, name); - DEFINE_VAR_FUNC_GET_SET(sptr, DisplayInfo, displayInfo); +friend class Display; +private: + void UpdateDisplay(DisplayInfo& info); + + std::string name_; + DisplayId id_ { DISPLAY_ID_INVALD }; + int32_t width_ { 0 }; + int32_t height_ { 0 }; + uint32_t freshRate_ { 0 }; + ScreenId screenId_ {SCREEN_ID_INVALID}; + Rotation rotation_ { Rotation::ROTATION_0 }; }; -Display::Display(const std::string& name, sptr info) - : pImpl_(new Impl(name, info)) +void Display::Impl::UpdateDisplay(DisplayInfo& info) { + width_ = info.width_; + height_ = info.height_; + freshRate_ = info.freshRate_; + screenId_ = info.screenId_; + rotation_ = info.rotation_; +} + +Display::Display(const std::string& name, DisplayInfo* info) + : pImpl_(new Impl()) +{ + pImpl_->name_ = name; + pImpl_->id_ = info->id_; + pImpl_->width_ = info->width_; + pImpl_->height_ = info->height_; + pImpl_->freshRate_ = info->freshRate_; + pImpl_->screenId_ = info->screenId_; + pImpl_->rotation_ = info->rotation_; } DisplayId Display::GetId() const { - return pImpl_->GetDisplayInfo()->GetDisplayId(); + return pImpl_->id_; } int32_t Display::GetWidth() const { - SingletonContainer::Get().UpdateDisplayInfo(GetId()); - return pImpl_->GetDisplayInfo()->GetWidth(); + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(info); + return pImpl_->width_; } int32_t Display::GetHeight() const { - SingletonContainer::Get().UpdateDisplayInfo(GetId()); - return pImpl_->GetDisplayInfo()->GetHeight(); + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(info); + return pImpl_->height_; } uint32_t Display::GetFreshRate() const { - SingletonContainer::Get().UpdateDisplayInfo(GetId()); - return pImpl_->GetDisplayInfo()->GetFreshRate(); + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(info); + return pImpl_->freshRate_; } ScreenId Display::GetScreenId() const { - SingletonContainer::Get().UpdateDisplayInfo(GetId()); - return pImpl_->GetDisplayInfo()->GetScreenId(); + DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); + pImpl_->UpdateDisplay(info); + return pImpl_->screenId_; } -void Display::UpdateDisplayInfo(sptr displayInfo) +void Display::SetWidth(int32_t width) { - if (displayInfo == nullptr) { - WLOGFE("displayInfo is invalid"); - return; - } - pImpl_->SetDisplayInfo(displayInfo); + pImpl_->width_ = width; +} + +void Display::SetHeight(int32_t height) +{ + pImpl_->height_ = height; +} + +void Display::SetFreshRate(uint32_t freshRate) +{ + pImpl_->freshRate_ = freshRate; } float Display::GetVirtualPixelRatio() const @@ -89,4 +110,9 @@ float Display::GetVirtualPixelRatio() const return 2.0f; #endif } + +void Display::SetId(DisplayId id) +{ + pImpl_->id_ = id; +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 3bf45203..096078c0 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -54,7 +54,7 @@ public: void OnDisplayCreate(sptr displayInfo) override { - if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { + if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayCreate, displayInfo is invalid."); return; } @@ -63,7 +63,7 @@ public: return; } for (auto listener : pImpl_->displayListeners_) { - listener->OnCreate(displayInfo->GetDisplayId()); + listener->OnCreate(displayInfo->id_); } }; @@ -84,7 +84,7 @@ public: void OnDisplayChange(const sptr displayInfo, DisplayChangeEvent event) override { - if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { + if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayChange, displayInfo is invalid."); return; } @@ -92,9 +92,9 @@ public: WLOGFE("OnDisplayChange, impl is nullptr."); return; } - WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->GetDisplayId(), event); + WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->id_, event); for (auto listener : pImpl_->displayListeners_) { - listener->OnChange(displayInfo->GetDisplayId(), event); + listener->OnChange(displayInfo->id_, event); } }; private: @@ -380,7 +380,7 @@ void DisplayManager::NotifyDisplayChangedEvent(const sptr info, Dis WLOGI("NotifyDisplayChangedEvent event:%{public}u, size:%{public}zu", event, pImpl_->displayListeners_.size()); std::lock_guard lock(pImpl_->mutex_); for (auto& listener : pImpl_->displayListeners_) { - listener->OnChange(info->GetDisplayId(), event); + listener->OnChange(info->id_, event); } } diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 2e58f1d6..80ad19ba 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -26,7 +26,6 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAdapter"}; } WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerAdapter) -WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManagerAdapter) DisplayId DisplayManagerAdapter::GetDefaultDisplayId() { @@ -57,34 +56,35 @@ sptr DisplayManagerAdapter::GetDisplayById(DisplayId displayId) if (iter != displayMap_.end()) { // Update display in map // should be updated automatically - auto displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); - if (displayInfo == nullptr) { - WLOGFE("GetDisplayById: displayInfo is nullptr!"); - displayMap_.erase(iter); - return nullptr; - } - if (displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { + DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + if (displayInfo.id_ == DISPLAY_ID_INVALD) { WLOGFE("GetDisplayById: Get invalid displayInfo!"); - displayMap_.erase(iter); return nullptr; } sptr display = iter->second; - display->UpdateDisplayInfo(displayInfo); + if (displayInfo.width_ != display->GetWidth()) { + display->SetWidth(displayInfo.width_); + WLOGFI("GetDisplayById: set new width %{public}d", display->GetWidth()); + } + if (displayInfo.height_ != display->GetHeight()) { + display->SetHeight(displayInfo.height_); + WLOGFI("GetDisplayById: set new height %{public}d", display->GetHeight()); + } + if (displayInfo.freshRate_ != display->GetFreshRate()) { + display->SetFreshRate(displayInfo.freshRate_); + WLOGFI("GetDisplayById: set new freshRate %{public}ud", display->GetFreshRate()); + } return iter->second; } - auto displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); - if (displayInfo == nullptr) { - WLOGFE("GetDisplayById: displayInfo is nullptr!"); - return nullptr; - } - sptr display = new Display("", displayInfo); + DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + sptr display = new Display("", &displayInfo); if (display->GetId() != DISPLAY_ID_INVALD) { displayMap_[display->GetId()] = display; } return display; } -bool ScreenManagerAdapter::RequestRotation(ScreenId screenId, Rotation rotation) +bool DisplayManagerAdapter::RequestRotation(ScreenId screenId, Rotation rotation) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -109,7 +109,7 @@ std::shared_ptr DisplayManagerAdapter::GetDisplaySnapshot(Displ return dispalySnapshot; } -DMError ScreenManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, +DMError DisplayManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) { std::lock_guard lock(mutex_); @@ -123,7 +123,7 @@ DMError ScreenManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, return ret; } -DMError ScreenManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +DMError DisplayManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) { std::lock_guard lock(mutex_); @@ -136,7 +136,7 @@ DMError ScreenManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColor return ret; } -DMError ScreenManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +DMError DisplayManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) { std::lock_guard lock(mutex_); @@ -149,7 +149,7 @@ DMError ScreenManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t col return ret; } -DMError ScreenManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +DMError DisplayManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) { std::lock_guard lock(mutex_); @@ -162,7 +162,7 @@ DMError ScreenManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMa return ret; } -DMError ScreenManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +DMError DisplayManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) { std::lock_guard lock(mutex_); @@ -175,7 +175,7 @@ DMError ScreenManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMa return ret; } -DMError ScreenManagerAdapter::SetScreenColorTransform(ScreenId screenId) +DMError DisplayManagerAdapter::SetScreenColorTransform(ScreenId screenId) { std::lock_guard lock(mutex_); @@ -188,7 +188,7 @@ DMError ScreenManagerAdapter::SetScreenColorTransform(ScreenId screenId) return ret; } -ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) +ScreenId DisplayManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) { if (!InitDMSProxyLocked()) { return SCREEN_ID_INVALID; @@ -197,7 +197,7 @@ ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) return displayManagerServiceProxy_->CreateVirtualScreen(option); } -DMError ScreenManagerAdapter::DestroyVirtualScreen(ScreenId screenId) +DMError DisplayManagerAdapter::DestroyVirtualScreen(ScreenId screenId) { if (!InitDMSProxyLocked()) { return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; @@ -206,7 +206,7 @@ DMError ScreenManagerAdapter::DestroyVirtualScreen(ScreenId screenId) return displayManagerServiceProxy_->DestroyVirtualScreen(screenId); } -DMError ScreenManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +DMError DisplayManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { if (!InitDMSProxyLocked()) { return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; @@ -215,7 +215,7 @@ DMError ScreenManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptrSetVirtualScreenSurface(screenId, surface); } -bool BaseAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, +bool DisplayManagerAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) { std::lock_guard lock(mutex_); @@ -225,7 +225,7 @@ bool BaseAdapter::RegisterDisplayManagerAgent(const sptr& return displayManagerServiceProxy_->RegisterDisplayManagerAgent(displayManagerAgent, type); } -bool BaseAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, +bool DisplayManagerAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) { std::lock_guard lock(mutex_); @@ -308,7 +308,7 @@ void DisplayManagerAdapter::NotifyDisplayEvent(DisplayEvent event) displayManagerServiceProxy_->NotifyDisplayEvent(event); } -bool BaseAdapter::InitDMSProxyLocked() +bool DisplayManagerAdapter::InitDMSProxyLocked() { if (!displayManagerServiceProxy_) { sptr systemAbilityManager = @@ -331,7 +331,7 @@ bool BaseAdapter::InitDMSProxyLocked() return false; } - dmsDeath_ = new DMSDeathRecipient(*this); + dmsDeath_ = new DMSDeathRecipient(); if (!dmsDeath_) { WLOGFE("Failed to create death Recipient ptr DMSDeathRecipient"); return false; @@ -344,10 +344,6 @@ bool BaseAdapter::InitDMSProxyLocked() return true; } -DMSDeathRecipient::DMSDeathRecipient(BaseAdapter& adapter) : adapter_(adapter) -{ -} - void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) { if (wptrDeath == nullptr) { @@ -360,11 +356,11 @@ void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) WLOGFE("object is null"); return; } - adapter_.Clear(); + SingletonContainer::Get().Clear(); return; } -void BaseAdapter::Clear() +void DisplayManagerAdapter::Clear() { std::lock_guard lock(mutex_); if ((displayManagerServiceProxy_ != nullptr) && (displayManagerServiceProxy_->AsObject() != nullptr)) { @@ -373,7 +369,7 @@ void BaseAdapter::Clear() displayManagerServiceProxy_ = nullptr; } -DMError ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +DMError DisplayManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -382,7 +378,7 @@ DMError ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vectorMakeMirror(mainScreenId, mirrorScreenId); } -sptr ScreenManagerAdapter::GetScreenInfo(ScreenId screenId) +sptr DisplayManagerAdapter::GetScreenInfo(ScreenId screenId) { if (screenId == SCREEN_ID_INVALID) { WLOGFE("screen id is invalid"); @@ -400,76 +396,80 @@ sptr ScreenManagerAdapter::GetScreenInfo(ScreenId screenId) return screenInfo; } -sptr DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) +DisplayInfo DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) { if (displayId == DISPLAY_ID_INVALD) { WLOGFE("screen id is invalid"); - return nullptr; + return DisplayInfo(); } std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); - return nullptr; + return DisplayInfo(); } return displayManagerServiceProxy_->GetDisplayInfoById(displayId); } -sptr ScreenManagerAdapter::GetScreenById(ScreenId screenId) +sptr DisplayManagerAdapter::GetScreenById(ScreenId screenId) { std::lock_guard lock(mutex_); - sptr screenInfo = GetScreenInfo(screenId); - if (screenInfo == nullptr) { - WLOGFE("screenInfo is null"); - screenMap_.erase(screenId); + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("screen id is invalid"); return nullptr; } auto iter = screenMap_.find(screenId); if (iter != screenMap_.end()) { WLOGFI("get screen in screen map"); - iter->second->UpdateScreenInfo(screenInfo); return iter->second; } - sptr screen = new Screen(screenInfo); + + if (!InitDMSProxyLocked()) { + WLOGFE("InitDMSProxyLocked failed!"); + return nullptr; + } + sptr screenInfo = displayManagerServiceProxy_->GetScreenInfoById(screenId); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is null"); + return nullptr; + } + sptr screen = new Screen(screenInfo.GetRefPtr()); screenMap_.insert(std::make_pair(screenId, screen)); return screen; } -sptr ScreenManagerAdapter::GetScreenGroupById(ScreenId screenId) +sptr DisplayManagerAdapter::GetScreenGroupById(ScreenId screenId) { std::lock_guard lock(mutex_); if (screenId == SCREEN_ID_INVALID) { WLOGFE("screenGroup id is invalid"); return nullptr; } + auto iter = screenGroupMap_.find(screenId); + if (iter != screenGroupMap_.end()) { + WLOGFI("get screenGroup in screenGroup map"); + return iter->second; + } + if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); - screenGroupMap_.clear(); return nullptr; } sptr screenGroupInfo = displayManagerServiceProxy_->GetScreenGroupInfoById(screenId); if (screenGroupInfo == nullptr) { WLOGFE("screenGroupInfo is null"); - screenGroupMap_.erase(screenId); return nullptr; } - auto iter = screenGroupMap_.find(screenId); - if (iter != screenGroupMap_.end()) { - WLOGFI("get screenGroup in screenGroup map"); - iter->second->UpdateScreenGroupInfo(screenGroupInfo); - return iter->second; - } - sptr screenGroup = new ScreenGroup(screenGroupInfo); + sptr screenGroup = new ScreenGroup(screenGroupInfo.GetRefPtr()); screenGroupMap_.insert(std::make_pair(screenId, screenGroup)); return screenGroup; } -std::vector> ScreenManagerAdapter::GetAllScreens() +std::vector> DisplayManagerAdapter::GetAllScreens() { std::lock_guard lock(mutex_); std::vector> screens; if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); - screenMap_.clear(); return screens; } std::vector> screenInfos = displayManagerServiceProxy_->GetAllScreenInfos(); @@ -478,24 +478,12 @@ std::vector> ScreenManagerAdapter::GetAllScreens() WLOGFE("screenInfo is null"); continue; } - auto iter = screenMap_.find(info->GetScreenId()); - if (iter != screenMap_.end()) { - WLOGFI("get screen in screen map"); - iter->second->UpdateScreenInfo(info); - screens.emplace_back(iter->second); - } else { - sptr screen = new Screen(info); - screens.emplace_back(screen); - } - } - screenMap_.clear(); - for (auto screen: screens) { - screenMap_.insert(std::make_pair(screen->GetId(), screen)); + screens.emplace_back(new Screen(info.GetRefPtr())); } return screens; } -DMError ScreenManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) +DMError DisplayManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -504,7 +492,7 @@ DMError ScreenManagerAdapter::MakeExpand(std::vector screenId, std::ve return displayManagerServiceProxy_->MakeExpand(screenId, startPoint); } -bool ScreenManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) +bool DisplayManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -512,30 +500,4 @@ bool ScreenManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeI } return displayManagerServiceProxy_->SetScreenActiveMode(screenId, modeId); } - -void ScreenManagerAdapter::UpdateScreenInfo(ScreenId screenId) -{ - auto screenInfo = GetScreenInfo(screenId); - if (screenInfo == nullptr) { - WLOGFE("screenInfo is invalid"); - return; - } - auto iter = screenMap_.find(screenId); - if (iter != screenMap_.end()) { - iter->second->UpdateScreenInfo(screenInfo); - } -} - -void DisplayManagerAdapter::UpdateDisplayInfo(DisplayId displayId) -{ - auto displayInfo = GetDisplayInfo(displayId); - if (displayInfo == nullptr) { - WLOGFE("displayInfo is invalid"); - return; - } - auto iter = displayMap_.find(displayId); - if (iter != displayMap_.end()) { - iter->second->UpdateDisplayInfo(displayInfo); - } -} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen.cpp b/dm/src/screen.cpp index ba7fd260..d4a227b3 100644 --- a/dm/src/screen.cpp +++ b/dm/src/screen.cpp @@ -16,6 +16,7 @@ #include "screen.h" #include "display_manager_adapter.h" +#include "screen_group.h" #include "screen_info.h" #include "window_manager_hilog.h" @@ -24,21 +25,55 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "Screen"}; } class Screen::Impl : public RefBase { +friend class Screen; public: - Impl(sptr info) - { - if (info == nullptr) { - WLOGFE("ScreenInfo is nullptr."); - } - screenInfo_ = info; - } + Impl() = default; ~Impl() = default; - DEFINE_VAR_FUNC_GET_SET(sptr, ScreenInfo, screenInfo); + void UpdateScreen(sptr info); + + ScreenId id_ { SCREEN_ID_INVALID }; + uint32_t virtualWidth_ { 0 }; + uint32_t virtualHeight_ { 0 }; + float virtualPixelRatio_ { 0.0 }; + ScreenId parent_ { SCREEN_ID_INVALID }; + bool canHasChild_ { false }; + uint32_t modeId_ { 0 }; + std::vector> modes_ {}; + Rotation rotation_ { Rotation::ROTATION_0 }; }; -Screen::Screen(sptr info) - : pImpl_(new Impl(info)) +void Screen::Impl::UpdateScreen(sptr info) { + if (info == nullptr) { + WLOGFE("info is nullptr."); + return; + } + virtualWidth_ = info->virtualWidth_; + virtualHeight_ = info->virtualHeight_; + virtualPixelRatio_ = info->virtualPixelRatio_; + parent_ = info->parent_; + canHasChild_ = info->canHasChild_; + modeId_ = info->modeId_; + modes_ = info->modes_; + rotation_ = info->rotation_; +} + +Screen::Screen(const ScreenInfo* info) + : pImpl_(new Impl()) +{ + if (info == nullptr) { + WLOGFE("info is nullptr."); + return; + } + pImpl_->id_ = info->id_; + pImpl_->virtualWidth_ = info->virtualWidth_; + pImpl_->virtualHeight_ = info->virtualHeight_; + pImpl_->virtualPixelRatio_ = info->virtualPixelRatio_; + pImpl_->parent_ = info->parent_; + pImpl_->canHasChild_ = info->canHasChild_; + pImpl_->modeId_ = info->modeId_; + pImpl_->modes_ = info->modes_; + pImpl_->rotation_ = info->rotation_; } Screen::~Screen() @@ -47,20 +82,22 @@ Screen::~Screen() bool Screen::IsGroup() const { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - return pImpl_->GetScreenInfo()->GetCanHasChild(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + return pImpl_->canHasChild_; } ScreenId Screen::GetId() const { - return pImpl_->GetScreenInfo()->GetScreenId(); + return pImpl_->id_; } uint32_t Screen::GetWidth() const { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - auto modeId = GetModeId(); - auto modes = GetSupportedModes(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + auto modeId = pImpl_->modeId_; + auto modes = pImpl_->modes_; if (modeId < 0 || modeId >= modes.size()) { return 0; } @@ -69,9 +106,10 @@ uint32_t Screen::GetWidth() const uint32_t Screen::GetHeight() const { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - auto modeId = GetModeId(); - auto modes = GetSupportedModes(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + auto modeId = pImpl_->modeId_; + auto modes = pImpl_->modes_; if (modeId < 0 || modeId >= modes.size()) { return 0; } @@ -80,98 +118,93 @@ uint32_t Screen::GetHeight() const uint32_t Screen::GetVirtualWidth() const { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - return pImpl_->GetScreenInfo()->GetVirtualWidth(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + return pImpl_->virtualWidth_; } uint32_t Screen::GetVirtualHeight() const { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - return pImpl_->GetScreenInfo()->GetVirtualHeight(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + return pImpl_->virtualHeight_; } float Screen::GetVirtualPixelRatio() const { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - return pImpl_->GetScreenInfo()->GetVirtualPixelRatio(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + return pImpl_->virtualPixelRatio_; } Rotation Screen::GetRotation() { - SingletonContainer::Get().UpdateScreenInfo(GetId()); - return pImpl_->GetScreenInfo()->GetRotation(); + sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); + pImpl_->UpdateScreen(info); + return pImpl_->rotation_; } bool Screen::RequestRotation(Rotation rotation) { WLOGFD("rotation the screen"); - return SingletonContainer::Get().RequestRotation(GetId(), rotation); + return SingletonContainer::Get().RequestRotation(pImpl_->id_, rotation); } DMError Screen::GetScreenSupportedColorGamuts(std::vector& colorGamuts) const { - return SingletonContainer::Get().GetScreenSupportedColorGamuts(GetId(), colorGamuts); + return SingletonContainer::Get().GetScreenSupportedColorGamuts(pImpl_->id_, colorGamuts); } DMError Screen::GetScreenColorGamut(ScreenColorGamut& colorGamut) const { - return SingletonContainer::Get().GetScreenColorGamut(GetId(), colorGamut); + return SingletonContainer::Get().GetScreenColorGamut(pImpl_->id_, colorGamut); } DMError Screen::SetScreenColorGamut(int32_t colorGamutIdx) { - return SingletonContainer::Get().SetScreenColorGamut(GetId(), colorGamutIdx); + return SingletonContainer::Get().SetScreenColorGamut(pImpl_->id_, colorGamutIdx); } DMError Screen::GetScreenGamutMap(ScreenGamutMap& gamutMap) const { - return SingletonContainer::Get().GetScreenGamutMap(GetId(), gamutMap); + return SingletonContainer::Get().GetScreenGamutMap(pImpl_->id_, gamutMap); } DMError Screen::SetScreenGamutMap(ScreenGamutMap gamutMap) { - return SingletonContainer::Get().SetScreenGamutMap(GetId(), gamutMap); + return SingletonContainer::Get().SetScreenGamutMap(pImpl_->id_, gamutMap); } DMError Screen::SetScreenColorTransform() { - return SingletonContainer::Get().SetScreenColorTransform(GetId()); + return SingletonContainer::Get().SetScreenColorTransform(pImpl_->id_); } ScreenId Screen::GetParentId() const { - return pImpl_->GetScreenInfo()->GetParentId(); + return pImpl_->parent_; } uint32_t Screen::GetModeId() const { - return pImpl_->GetScreenInfo()->GetModeId(); + return pImpl_->modeId_; } std::vector> Screen::GetSupportedModes() const { - return pImpl_->GetScreenInfo()->GetModes(); + return pImpl_->modes_; } bool Screen::SetScreenActiveMode(uint32_t modeId) { - ScreenId screenId = GetId(); - if (modeId < 0 || modeId >= GetSupportedModes().size()) { + ScreenId screenId = pImpl_->id_; + if (modeId < 0 || modeId >= pImpl_->modes_.size()) { return false; } - if (SingletonContainer::Get().SetScreenActiveMode(screenId, modeId)) { - pImpl_->GetScreenInfo()->SetModeId(modeId); + if (SingletonContainer::Get().SetScreenActiveMode(screenId, modeId)) { + pImpl_->modeId_ = modeId; return true; } return false; } - -void Screen::UpdateScreenInfo(sptr screenInfo) -{ - if (screenInfo == nullptr) { - WLOGFE("ScreenInfo is invalid"); - return; - } - pImpl_->SetScreenInfo(screenInfo); -} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen_group.cpp b/dm/src/screen_group.cpp index 9ac64d7b..91e17a8d 100644 --- a/dm/src/screen_group.cpp +++ b/dm/src/screen_group.cpp @@ -23,30 +23,26 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "ScreenGroup"}; } class ScreenGroup::Impl : public RefBase { -public: - Impl(sptr info) - { - if (info == nullptr) { - WLOGFE("ScreenGroupInfo is nullptr."); - } - screenGroupInfo_ = info; - } +friend class ScreenGroup; +private: + Impl() = default; ~Impl() = default; - DEFINE_VAR_FUNC_GET_SET(sptr, ScreenGroupInfo, screenGroupInfo); + std::vector children_; + std::vector position_; + ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; }; -ScreenGroup::ScreenGroup(sptr info) - : Screen(info), pImpl_(new Impl(info)) -{ -} - -void ScreenGroup::UpdateScreenGroupInfo(sptr info) +ScreenGroup::ScreenGroup(const ScreenGroupInfo* info) + : Screen(info), pImpl_(new Impl()) { if (info == nullptr) { - WLOGFE("ScreenGroupInfo is nullptr."); + WLOGFE("info is nullptr."); + return; } - pImpl_->SetScreenGroupInfo(info); + pImpl_->children_ = info->children_; + pImpl_->position_ = info->position_; + pImpl_->combination_ = info->combination_; } ScreenGroup::~ScreenGroup() @@ -55,16 +51,16 @@ ScreenGroup::~ScreenGroup() ScreenCombination ScreenGroup::GetCombination() const { - return pImpl_->GetScreenGroupInfo()->GetCombination(); + return pImpl_->combination_; } -std::vector ScreenGroup::GetChildIds() const +std::vector ScreenGroup::GetChild() const { - return pImpl_->GetScreenGroupInfo()->GetChildren(); + return pImpl_->children_; } -std::vector ScreenGroup::GetChildPositions() const +std::vector ScreenGroup::GetChildPosition() const { - return pImpl_->GetScreenGroupInfo()->GetPosition(); + return pImpl_->position_; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen_manager.cpp b/dm/src/screen_manager.cpp index b81e640e..abbbee9d 100644 --- a/dm/src/screen_manager.cpp +++ b/dm/src/screen_manager.cpp @@ -43,7 +43,7 @@ public: void OnScreenConnect(sptr screenInfo) { - if (screenInfo == nullptr || screenInfo->GetScreenId() == SCREEN_ID_INVALID) { + if (screenInfo == nullptr || screenInfo->id_ == SCREEN_ID_INVALID) { WLOGFE("OnScreenConnect, screenInfo is invalid."); return; } @@ -52,7 +52,7 @@ public: return; } for (auto listener : pImpl_->screenListeners_) { - listener->OnConnect(screenInfo->GetScreenId()); + listener->OnConnect(screenInfo->id_); } }; @@ -84,8 +84,8 @@ public: WLOGFD("OnScreenChange. event %{public}u", event); std::vector screenIds; for (auto screenInfo : screenInfos) { - if (screenInfo->GetScreenId() != SCREEN_ID_INVALID) { - screenIds.push_back(screenInfo->GetScreenId()); + if (screenInfo->id_ != SCREEN_ID_INVALID) { + screenIds.push_back(screenInfo->id_); } } for (auto listener: pImpl_->screenListeners_) { @@ -108,17 +108,17 @@ ScreenManager::~ScreenManager() sptr ScreenManager::GetScreenById(ScreenId screenId) { - return SingletonContainer::Get().GetScreenById(screenId); + return SingletonContainer::Get().GetScreenById(screenId); } sptr ScreenManager::GetScreenGroupById(ScreenId screenId) { - return SingletonContainer::Get().GetScreenGroupById(screenId); + return SingletonContainer::Get().GetScreenGroupById(screenId); } std::vector> ScreenManager::GetAllScreens() { - return SingletonContainer::Get().GetAllScreens(); + return SingletonContainer::Get().GetAllScreens(); } bool ScreenManager::RegisterScreenListener(sptr listener) @@ -131,7 +131,7 @@ bool ScreenManager::RegisterScreenListener(sptr listener) pImpl_->screenListeners_.push_back(listener); if (screenManagerListener_ == nullptr) { screenManagerListener_ = new ScreenManagerListener(pImpl_); - SingletonContainer::Get().RegisterDisplayManagerAgent( + SingletonContainer::Get().RegisterDisplayManagerAgent( screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); } @@ -152,7 +152,7 @@ bool ScreenManager::UnregisterScreenListener(sptr listener) } pImpl_->screenListeners_.erase(iter); if (pImpl_->screenListeners_.empty() && screenManagerListener_ != nullptr) { - SingletonContainer::Get().UnregisterDisplayManagerAgent( + SingletonContainer::Get().UnregisterDisplayManagerAgent( screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); screenManagerListener_ = nullptr; @@ -172,7 +172,7 @@ ScreenId ScreenManager::MakeExpand(const std::vector& options) screenIds.emplace_back(option.screenId_); startPoints.emplace_back(Point(option.startX_, option.startY_)); } - DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); + DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); if (result != DMError::DM_OK) { return SCREEN_ID_INVALID; } @@ -184,7 +184,7 @@ ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector { WLOGFI("create mirror for screen: %{public}" PRIu64"", mainScreenId); // TODO: "record screen" should use another function, "MakeMirror" should return group id. - DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); + DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); if (result == DMError::DM_OK) { WLOGFI("create mirror success"); } @@ -193,16 +193,16 @@ ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector ScreenId ScreenManager::CreateVirtualScreen(VirtualScreenOption option) { - return SingletonContainer::Get().CreateVirtualScreen(option); + return SingletonContainer::Get().CreateVirtualScreen(option); } DMError ScreenManager::DestroyVirtualScreen(ScreenId screenId) { - return SingletonContainer::Get().DestroyVirtualScreen(screenId); + return SingletonContainer::Get().DestroyVirtualScreen(screenId); } DMError ScreenManager::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { - return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); + return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/test/unittest/mock_display_manager_adapter.h b/dm/test/unittest/mock_display_manager_adapter.h index 46ee9bc5..97dbef49 100644 --- a/dm/test/unittest/mock_display_manager_adapter.h +++ b/dm/test/unittest/mock_display_manager_adapter.h @@ -23,45 +23,25 @@ namespace OHOS { namespace Rosen { class MockDisplayManagerAdapter : public DisplayManagerAdapter { public: + MOCK_METHOD0(GetDefaultDisplayId, DisplayId()); + MOCK_METHOD1(GetDisplayById, sptr(DisplayId displayId)); + MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); + MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); + MOCK_METHOD1(GetDisplaySnapshot, std::shared_ptr(DisplayId displayId)); MOCK_METHOD0(Clear, void()); MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); - MOCK_METHOD0(GetDefaultDisplayId, DisplayId()); - MOCK_METHOD1(GetDisplayById, sptr(DisplayId displayId)); - MOCK_METHOD1(GetDisplaySnapshot, std::shared_ptr(DisplayId displayId)); - MOCK_METHOD1(WakeUpBegin, bool(PowerStateChangeReason reason)); MOCK_METHOD0(WakeUpEnd, bool()); MOCK_METHOD1(SuspendBegin, bool(PowerStateChangeReason reason)); MOCK_METHOD0(SuspendEnd, bool()); MOCK_METHOD2(SetScreenPowerForAll, bool(DisplayPowerState state, PowerStateChangeReason reason)); MOCK_METHOD1(SetDisplayState, bool(DisplayState state)); - MOCK_METHOD1(GetDisplayState, DisplayState(DisplayId displayId)); - MOCK_METHOD1(NotifyDisplayEvent, void(DisplayEvent event)); - MOCK_METHOD1(UpdateDisplayInfo, void(DisplayId displayId)); -}; - -class MockScreenManagerAdapter : public ScreenManagerAdapter { -public: - MOCK_METHOD0(Clear, void()); - MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, - DisplayManagerAgentType type)); - MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, - DisplayManagerAgentType type)); - MOCK_METHOD2(RequestRotation, bool(ScreenId screenId, Rotation rotation)); - MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); - MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); - MOCK_METHOD2(SetVirtualScreenSurface, DMError(ScreenId screenId, sptr surface)); - MOCK_METHOD1(GetScreenById, sptr(ScreenId screenId)); - MOCK_METHOD1(GetScreenGroupById, sptr(ScreenId screenId)); - MOCK_METHOD0(GetAllScreens, std::vector>()); - MOCK_METHOD2(MakeMirror, DMError(ScreenId mainScreenId, std::vector mirrorScreenId)); - MOCK_METHOD2(MakeExpand, DMError(std::vector screenId, std::vector startPoint)); + MOCK_METHOD1(GetDisplayState, DisplayState(uint64_t displayId)); MOCK_METHOD2(SetScreenActiveMode, bool(ScreenId screenId, uint32_t modeId)); - MOCK_METHOD1(UpdateScreenInfo, void(ScreenId screenId)); - + MOCK_METHOD2(MakeExpand, DMError(std::vector screenId, std::vector startPoint)); MOCK_METHOD2(GetScreenSupportedColorGamuts, DMError(ScreenId screenId, std::vector& colorGamuts)); MOCK_METHOD2(GetScreenColorGamut, DMError(ScreenId screenId, ScreenColorGamut& colorGamut)); MOCK_METHOD2(SetScreenColorGamut, DMError(ScreenId screenId, int32_t colorGamutIdx)); diff --git a/dm/test/unittest/screen_manager_test.cpp b/dm/test/unittest/screen_manager_test.cpp index eeafc8b3..d6da30be 100644 --- a/dm/test/unittest/screen_manager_test.cpp +++ b/dm/test/unittest/screen_manager_test.cpp @@ -22,7 +22,7 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { -using Mocker = SingletonMocker; +using Mocker = SingletonMocker; sptr ScreenManagerTest::defaultDisplay_ = nullptr; DisplayId ScreenManagerTest::defaultDisplayId_ = DISPLAY_ID_INVALD; diff --git a/dm/test/unittest/screen_test.cpp b/dm/test/unittest/screen_test.cpp index e6aebea0..23086993 100644 --- a/dm/test/unittest/screen_test.cpp +++ b/dm/test/unittest/screen_test.cpp @@ -22,7 +22,7 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { -using Mocker = SingletonMocker; +using Mocker = SingletonMocker; sptr ScreenTest::defaultDisplay_ = nullptr; ScreenId ScreenTest::defaultScreenId_ = SCREEN_ID_INVALID; diff --git a/dmserver/include/abstract_display.h b/dmserver/include/abstract_display.h index 79ba8b9c..3b505006 100644 --- a/dmserver/include/abstract_display.h +++ b/dmserver/include/abstract_display.h @@ -28,7 +28,7 @@ public: constexpr static int32_t DEFAULT_HIGHT = 1280; constexpr static float DEFAULT_VIRTUAL_PIXEL_RATIO = 1.0; constexpr static uint32_t DEFAULT_FRESH_RATE = 60; - AbstractDisplay(const DisplayInfo* info); + AbstractDisplay(const DisplayInfo& info); AbstractDisplay(DisplayId id, ScreenId screenId, int32_t width, int32_t height, uint32_t freshRate); ~AbstractDisplay() = default; static inline bool IsVertical(Rotation rotation) @@ -43,7 +43,7 @@ public: ScreenId GetAbstractScreenId() const; bool BindAbstractScreen(ScreenId dmsScreenId); bool BindAbstractScreen(sptr abstractDisplay); - sptr ConvertToDisplayInfo() const; + const sptr ConvertToDisplayInfo() const; void SetId(DisplayId displayId); void SetWidth(int32_t width); diff --git a/dmserver/include/abstract_screen.h b/dmserver/include/abstract_screen.h index cbf32a2a..c89d392d 100644 --- a/dmserver/include/abstract_screen.h +++ b/dmserver/include/abstract_screen.h @@ -46,7 +46,7 @@ public: sptr GetActiveScreenMode() const; std::vector> GetAbstractScreenModes() const; sptr GetGroup() const; - sptr ConvertToScreenInfo() const; + const sptr ConvertToScreenInfo() const; void RequestRotation(Rotation rotation); Rotation GetRotation() const; @@ -90,7 +90,7 @@ public: std::vector> GetChildren() const; std::vector GetChildrenPosition() const; size_t GetChildCount() const; - sptr ConvertToScreenGroupInfo() const; + const sptr ConvertToScreenGroupInfo() const; bool SetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config); ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; diff --git a/dmserver/include/display_manager_interface.h b/dmserver/include/display_manager_interface.h index 9e9c40f6..c4cb521b 100644 --- a/dmserver/include/display_manager_interface.h +++ b/dmserver/include/display_manager_interface.h @@ -68,7 +68,7 @@ public: }; virtual DisplayId GetDefaultDisplayId() = 0; - virtual sptr GetDisplayInfoById(DisplayId displayId) = 0; + virtual DisplayInfo GetDisplayInfoById(DisplayId displayId) = 0; virtual ScreenId CreateVirtualScreen(VirtualScreenOption option) = 0; virtual DMError DestroyVirtualScreen(ScreenId screenId) = 0; diff --git a/dmserver/include/display_manager_proxy.h b/dmserver/include/display_manager_proxy.h index 28d98a68..0d30ce4c 100644 --- a/dmserver/include/display_manager_proxy.h +++ b/dmserver/include/display_manager_proxy.h @@ -32,7 +32,7 @@ public: ~DisplayManagerProxy() {}; DisplayId GetDefaultDisplayId() override; - sptr GetDisplayInfoById(DisplayId displayId) override; + DisplayInfo GetDisplayInfoById(DisplayId displayId) override; ScreenId CreateVirtualScreen(VirtualScreenOption option) override; DMError DestroyVirtualScreen(ScreenId screenId) override; diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index 356521ba..ee3dc6d9 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -51,7 +51,7 @@ public: DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; DisplayId GetDefaultDisplayId() override; - sptr GetDisplayInfoById(DisplayId displayId) override; + DisplayInfo GetDisplayInfoById(DisplayId displayId) override; bool RequestRotation(ScreenId screenId, Rotation rotation) override; std::shared_ptr GetDispalySnapshot(DisplayId displayId) override; ScreenId GetRSScreenId(DisplayId displayId) const; diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index c425a631..e9ad85f9 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -24,16 +24,12 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractDisplay"}; } -AbstractDisplay::AbstractDisplay(const DisplayInfo* info) +AbstractDisplay::AbstractDisplay(const DisplayInfo& info) + : id_(info.id_), + width_(info.width_), + height_(info.height_), + freshRate_(info.freshRate_) { - if (info == nullptr) { - WLOGFE("DisplayInfo is nullptr"); - return; - } - id_ = info->GetDisplayId(); - width_ = info->GetWidth(); - height_ = info->GetHeight(); - freshRate_ = info->GetHeight(); } AbstractDisplay::AbstractDisplay(DisplayId id, ScreenId screenId, int32_t width, int32_t height, uint32_t freshRate) @@ -150,7 +146,7 @@ ScreenId AbstractDisplay::GetAbstractScreenId() const return screenId_; } -sptr AbstractDisplay::ConvertToDisplayInfo() const +const sptr AbstractDisplay::ConvertToDisplayInfo() const { sptr displayInfo = new DisplayInfo(); displayInfo->width_ = width_; diff --git a/dmserver/src/abstract_screen.cpp b/dmserver/src/abstract_screen.cpp index bddd68c8..fb124012 100644 --- a/dmserver/src/abstract_screen.cpp +++ b/dmserver/src/abstract_screen.cpp @@ -53,7 +53,7 @@ sptr AbstractScreen::GetGroup() const return DisplayManagerService::GetInstance().GetAbstractScreenController()->GetAbstractScreenGroup(groupDmsId_); } -sptr AbstractScreen::ConvertToScreenInfo() const +const sptr AbstractScreen::ConvertToScreenInfo() const { sptr info = new ScreenInfo(); FillScreenInfo(info); @@ -215,7 +215,7 @@ AbstractScreenGroup::~AbstractScreenGroup() abstractScreenMap_.clear(); } -sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const +const sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const { sptr screenGroupInfo = new ScreenGroupInfo(); FillScreenInfo(screenGroupInfo); diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index 3dfc287a..180dc4a4 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -52,12 +52,12 @@ DisplayId DisplayManagerProxy::GetDefaultDisplayId() return displayId; } -sptr DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) +DisplayInfo DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) { sptr remote = Remote(); if (remote == nullptr) { WLOGFW("GetDisplayInfoById: remote is nullptr"); - return nullptr; + return DisplayInfo(); } MessageParcel data; @@ -65,23 +65,23 @@ sptr DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) MessageOption option; if (!data.WriteInterfaceToken(GetDescriptor())) { WLOGFE("GetDisplayInfoById: WriteInterfaceToken failed"); - return nullptr; + return DisplayInfo(); } if (!data.WriteUint64(displayId)) { WLOGFW("GetDisplayInfoById: WriteUint64 displayId failed"); - return nullptr; + return DisplayInfo(); } if (remote->SendRequest(TRANS_ID_GET_DISPLAY_BY_ID, data, reply, option) != ERR_NONE) { WLOGFW("GetDisplayInfoById: SendRequest failed"); - return nullptr; + return DisplayInfo(); } sptr info = reply.ReadParcelable(); if (info == nullptr) { WLOGFW("DisplayManagerProxy::GetDisplayInfoById SendRequest nullptr."); - return nullptr; + return DisplayInfo(); } - return info; + return *info; } ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption) @@ -682,10 +682,9 @@ sptr DisplayManagerProxy::GetScreenInfoById(ScreenId screenId) WLOGFW("GetScreenInfoById SendRequest nullptr."); return nullptr; } - auto modes = info->GetModes(); - for (int i = 0; i < modes.size(); i++) { + for (int i = 0; i < info->modes_.size(); i++) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", - modes[i]->width_, modes[i]->height_, modes[i]->freshRate_); + info->modes_[i]->width_, info->modes_[i]->height_, info->modes_[i]->freshRate_); } return info; } diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index 047dbfee..0e3c34e0 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -89,14 +89,21 @@ DisplayId DisplayManagerService::GetDefaultDisplayId() return GetDisplayIdFromScreenId(screenId); } -sptr DisplayManagerService::GetDisplayInfoById(DisplayId displayId) +DisplayInfo DisplayManagerService::GetDisplayInfoById(DisplayId displayId) { + DisplayInfo displayInfo; sptr display = GetDisplayByDisplayId(displayId); if (display == nullptr) { WLOGFE("GetDisplayById: Get invalid display!"); - return nullptr; + return displayInfo; } - return display->ConvertToDisplayInfo(); + displayInfo.id_ = displayId; + displayInfo.width_ = display->GetWidth(); + displayInfo.height_ = display->GetHeight(); + displayInfo.freshRate_ = display->GetFreshRate(); + displayInfo.screenId_ = display->GetAbstractScreenId(); + displayInfo.rotation_ = display->GetRotation(); + return displayInfo; } sptr DisplayManagerService::GetAbstractDisplay(DisplayId displayId) diff --git a/dmserver/src/display_manager_service_inner.cpp b/dmserver/src/display_manager_service_inner.cpp index 8c84b84a..edaaa5cd 100644 --- a/dmserver/src/display_manager_service_inner.cpp +++ b/dmserver/src/display_manager_service_inner.cpp @@ -41,7 +41,7 @@ const sptr DisplayManagerServiceInner::GetDisplayById(DisplayId { sptr display = DisplayManagerService::GetInstance().GetAbstractDisplay(displayId); if (display == nullptr) { - auto displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + DisplayInfo displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); display = new AbstractDisplay(displayInfo); WLOGFE("GetDisplayById create new!\n"); } diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index 824fddaf..2504aef4 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -45,7 +45,7 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_DISPLAY_BY_ID: { DisplayId displayId = data.ReadUint64(); auto info = GetDisplayInfoById(displayId); - reply.WriteParcelable(info); + reply.WriteParcelable(&info); break; } case TRANS_ID_CREATE_VIRTUAL_SCREEN: { @@ -166,10 +166,9 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_SCREEN_INFO_BY_ID: { ScreenId screenId = static_cast(data.ReadUint64()); auto screenInfo = GetScreenInfoById(screenId); - auto modes = screenInfo->GetModes(); - for (int i = 0; i < modes.size(); i++) { + for (int i = 0; i < screenInfo->modes_.size(); i++) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", - modes[i]->width_, modes[i]->height_, modes[i]->freshRate_); + screenInfo->modes_[i]->width_, screenInfo->modes_[i]->height_, screenInfo->modes_[i]->freshRate_); } reply.WriteStrongParcelable(screenInfo); break; diff --git a/interfaces/innerkits/dm/display.h b/interfaces/innerkits/dm/display.h index 5846b76c..a71df544 100644 --- a/interfaces/innerkits/dm/display.h +++ b/interfaces/innerkits/dm/display.h @@ -27,22 +27,23 @@ typedef enum DisplayType { } DisplayType; class Display : public RefBase { -friend class DisplayManagerAdapter; public: + Display(const std::string& name, DisplayInfo* info); ~Display() = default; - Display(const Display&) = delete; - Display(Display&&) = delete; - Display& operator=(const Display&) = delete; - Display& operator=(Display&&) = delete; + DisplayId GetId() const; int32_t GetWidth() const; int32_t GetHeight() const; uint32_t GetFreshRate() const; ScreenId GetScreenId() const; float GetVirtualPixelRatio() const; + + void SetId(DisplayId displayId); + void SetWidth(int32_t width); + void SetHeight(int32_t height); + void SetFreshRate(uint32_t freshRate); + private: - Display(const std::string& name, sptr info); - void UpdateDisplayInfo(sptr); class Impl; sptr pImpl_; }; diff --git a/interfaces/innerkits/dm/screen.h b/interfaces/innerkits/dm/screen.h index baf1d56d..8c71c4f9 100644 --- a/interfaces/innerkits/dm/screen.h +++ b/interfaces/innerkits/dm/screen.h @@ -57,13 +57,9 @@ struct ExpandOption { }; class Screen : public RefBase { -friend class ScreenManagerAdapter; public: + Screen(const ScreenInfo* info); ~Screen(); - Screen(const Screen&) = delete; - Screen(Screen&&) = delete; - Screen& operator=(const Screen&) = delete; - Screen& operator=(Screen&&) = delete; bool IsGroup() const; ScreenId GetId() const; uint32_t GetWidth() const; @@ -85,9 +81,7 @@ public: DMError GetScreenGamutMap(ScreenGamutMap& gamutMap) const; DMError SetScreenGamutMap(ScreenGamutMap gamutMap); DMError SetScreenColorTransform(); -protected: - Screen(sptr info); - void UpdateScreenInfo(sptr screenInfo); + private: class Impl; sptr pImpl_; diff --git a/interfaces/innerkits/dm/screen_group.h b/interfaces/innerkits/dm/screen_group.h index bb879536..78377f88 100644 --- a/interfaces/innerkits/dm/screen_group.h +++ b/interfaces/innerkits/dm/screen_group.h @@ -29,20 +29,14 @@ enum class ScreenCombination : uint32_t { }; class ScreenGroup : public Screen { -friend class ScreenManagerAdapter; public: + ScreenGroup(const ScreenGroupInfo* info); ~ScreenGroup(); - ScreenGroup(const ScreenGroup&) = delete; - ScreenGroup(ScreenGroup&&) = delete; - ScreenGroup& operator=(const ScreenGroup&) = delete; - ScreenGroup& operator=(ScreenGroup&&) = delete; ScreenCombination GetCombination() const; - std::vector GetChildIds() const; - std::vector GetChildPositions() const; + std::vector GetChild() const; + std::vector GetChildPosition() const; private: - ScreenGroup(sptr info); - void UpdateScreenGroupInfo(sptr info); class Impl; sptr pImpl_; }; diff --git a/utils/include/class_var_defination.h b/utils/include/class_var_defination.h deleted file mode 100644 index 27bce64e..00000000 --- a/utils/include/class_var_defination.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2022 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 p ermissions and - * limitations under the License. - */ - -#ifndef OHOS_ROSEN_CLASS_VAR_DEFINATION_H -#define OHOS_ROSEN_CLASS_VAR_DEFINATION_H -namespace OHOS::Rosen { -#define DEFINE_VAR(type, memberName) \ -private: \ - type memberName##_; - -#define DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ -private: \ - type memberName##_ {defaultValue}; - -#define DEFINE_FUNC_GET(type, funcName, memberName) \ -public: \ - type Get##funcName() const \ - { \ - return memberName##_; \ - } - -#define DEFINE_FUNC_SET(type, funcName, memberName) \ -public: \ - void Set##funcName(type value) \ - { \ - memberName##_ = value; \ - } - -#define DEFINE_VAR_FUNC_GET(type, funcName, memberName) \ - DEFINE_VAR(type, memberName) \ - DEFINE_FUNC_GET(type, funcName, memberName) - -#define DEFINE_VAR_DEFAULT_FUNC_GET(type, funcName, memberName, defaultValue) \ - DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ - DEFINE_FUNC_GET(type, funcName, memberName) - -#define DEFINE_VAR_FUNC_GET_SET(type, funcName, memberName) \ - DEFINE_VAR(type, memberName) \ - DEFINE_FUNC_GET(type, funcName, memberName) \ - DEFINE_FUNC_SET(type, funcName, memberName) - -#define DEFINE_VAR_DEFAULT_FUNC_GET_SET(type, funcName, memberName, defaultValue) \ - DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ - DEFINE_FUNC_GET(type, funcName, memberName) \ - DEFINE_FUNC_SET(type, funcName, memberName) -} // namespace OHOS::Rosen -#endif // OHOS_ROSEN_CLASS_VAR_DEFINATION_H diff --git a/utils/include/display_info.h b/utils/include/display_info.h index e7ec23c9..0aab1010 100644 --- a/utils/include/display_info.h +++ b/utils/include/display_info.h @@ -18,34 +18,29 @@ #include -#include "class_var_defination.h" #include "display.h" #include "dm_common.h" namespace OHOS::Rosen { class DisplayInfo : public Parcelable { -friend class AbstractDisplay; public: + DisplayInfo() = default; ~DisplayInfo() = default; - DisplayInfo(const DisplayInfo&) = delete; - DisplayInfo(DisplayInfo&&) = delete; - DisplayInfo& operator=(const DisplayInfo&) = delete; - DisplayInfo& operator=(DisplayInfo&&) = delete; + + void Update(DisplayInfo* info); virtual bool Marshalling(Parcel& parcel) const override; static DisplayInfo *Unmarshalling(Parcel& parcel); - DEFINE_VAR_DEFAULT_FUNC_GET(DisplayId, DisplayId, id, DISPLAY_ID_INVALD); - DEFINE_VAR_DEFAULT_FUNC_GET(DisplayType, DisplayType, type, DisplayType::DEFAULT); - DEFINE_VAR_DEFAULT_FUNC_GET(int32_t, Width, width, 0); - DEFINE_VAR_DEFAULT_FUNC_GET(int32_t, Height, height, 0); - DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, FreshRate, freshRate, 0); - DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ScreenId, screenId, SCREEN_ID_INVALID); - DEFINE_VAR_DEFAULT_FUNC_GET(float, XDpi, xDpi, 0.0f); - DEFINE_VAR_DEFAULT_FUNC_GET(float, YDpi, yDpi, 0.0f); - DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); -private: - DisplayInfo() = default; + DisplayId id_ { DISPLAY_ID_INVALD }; + DisplayType type_ {DisplayType::DEFAULT }; + int32_t width_ { 0 }; + int32_t height_ { 0 }; + uint32_t freshRate_ { 0 }; + ScreenId screenId_ { SCREEN_ID_INVALID }; + float xDpi_ { 0.0 }; + float yDpi_ { 0.0 }; + Rotation rotation_ { Rotation::ROTATION_0 }; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H \ No newline at end of file diff --git a/utils/include/screen_group_info.h b/utils/include/screen_group_info.h index c1980182..6a9addbf 100644 --- a/utils/include/screen_group_info.h +++ b/utils/include/screen_group_info.h @@ -23,23 +23,20 @@ namespace OHOS::Rosen { class ScreenGroupInfo : public ScreenInfo { -friend class AbstractScreenGroup; public: + ScreenGroupInfo() = default; ~ScreenGroupInfo() = default; - ScreenGroupInfo(const ScreenGroupInfo&) = delete; - ScreenGroupInfo(ScreenGroupInfo&&) = delete; - ScreenGroupInfo& operator=(const ScreenGroupInfo&) = delete; - ScreenGroupInfo& operator=(ScreenGroupInfo&&) = delete; + + void Update(sptr info); virtual bool Marshalling(Parcel& parcel) const override; static ScreenGroupInfo* Unmarshalling(Parcel& parcel); - DEFINE_VAR_FUNC_GET(std::vector, Children, children); - DEFINE_VAR_FUNC_GET(std::vector, Position, position); - DEFINE_VAR_DEFAULT_FUNC_GET(ScreenCombination, Combination, combination, ScreenCombination::SCREEN_ALONE); -private: - ScreenGroupInfo() = default; - bool InnerUnmarshalling(Parcel& parcel); + std::vector children_; + std::vector position_; + ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; +protected: + ScreenGroupInfo* InnerUnmarshalling(Parcel& parcel); }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_SCREEN_GROUP_INFO_H \ No newline at end of file diff --git a/utils/include/screen_info.h b/utils/include/screen_info.h index 618a67ce..c39fad9d 100644 --- a/utils/include/screen_info.h +++ b/utils/include/screen_info.h @@ -18,34 +18,30 @@ #include -#include "class_var_defination.h" #include "screen.h" namespace OHOS::Rosen { class ScreenInfo : public Parcelable { -friend class AbstractScreen; public: + ScreenInfo() = default; ~ScreenInfo() = default; - ScreenInfo(const ScreenInfo&) = delete; - ScreenInfo(ScreenInfo&&) = delete; - ScreenInfo& operator=(const ScreenInfo&) = delete; - ScreenInfo& operator= (ScreenInfo&&) = delete; + + void Update(sptr info); virtual bool Marshalling(Parcel& parcel) const override; static ScreenInfo* Unmarshalling(Parcel& parcel); - DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ScreenId, id, SCREEN_ID_INVALID); - DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, VirtualWidth, virtualWidth, 0); - DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, VirtualHeight, virtualHeight, 0); - DEFINE_VAR_DEFAULT_FUNC_GET(float, VirtualPixelRatio, virtualPixelRatio, 0.0f); - DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ParentId, parent, 0); - DEFINE_VAR_DEFAULT_FUNC_GET(bool, CanHasChild, canHasChild, false); - DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); - DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, ModeId, modeId, 0); - DEFINE_VAR_FUNC_GET(std::vector>, Modes, modes); + ScreenId id_ { SCREEN_ID_INVALID }; + uint32_t virtualWidth_ { 0 }; + uint32_t virtualHeight_ { 0 }; + float virtualPixelRatio_ { 0.0 }; + ScreenId parent_ { 0 }; + bool canHasChild_ { false }; + Rotation rotation_ { Rotation::ROTATION_0 }; + uint32_t modeId_ { 0 }; + std::vector> modes_ {}; protected: - ScreenInfo() = default; - bool InnerUnmarshalling(Parcel& parcel); + ScreenInfo* InnerUnmarshalling(Parcel& parcel); }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H diff --git a/utils/src/display_info.cpp b/utils/src/display_info.cpp index ca033643..0ff79f31 100644 --- a/utils/src/display_info.cpp +++ b/utils/src/display_info.cpp @@ -16,6 +16,19 @@ #include "display_info.h" namespace OHOS::Rosen { +void DisplayInfo::Update(DisplayInfo* info) +{ + id_ = info->id_; + type_ = info->type_; + width_ = info->width_; + height_ = info->height_; + freshRate_ = info->freshRate_; + screenId_ = info->screenId_; + xDpi_ = info->xDpi_; + yDpi_ = info->yDpi_; + rotation_ = info->rotation_; +} + bool DisplayInfo::Marshalling(Parcel &parcel) const { return parcel.WriteUint64(id_) && parcel.WriteUint32(type_) && @@ -28,6 +41,9 @@ bool DisplayInfo::Marshalling(Parcel &parcel) const DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) { DisplayInfo *displayInfo = new DisplayInfo(); + if (displayInfo == nullptr) { + return nullptr; + } uint32_t type = (uint32_t)DisplayType::DEFAULT; uint32_t rotation; bool res = parcel.ReadUint64(displayInfo->id_) && parcel.ReadUint32(type) && @@ -36,11 +52,11 @@ DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) parcel.ReadFloat(displayInfo->xDpi_) && parcel.ReadFloat(displayInfo->yDpi_) && parcel.ReadUint32(rotation); if (!res) { - delete displayInfo; - return nullptr; + displayInfo = nullptr; + } else { + displayInfo->type_ = (DisplayType)type; + displayInfo->rotation_ = static_cast(rotation); } - displayInfo->type_ = (DisplayType)type; - displayInfo->rotation_ = static_cast(rotation); return displayInfo; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/utils/src/screen_group_info.cpp b/utils/src/screen_group_info.cpp index ed4e4122..56268c74 100644 --- a/utils/src/screen_group_info.cpp +++ b/utils/src/screen_group_info.cpp @@ -16,6 +16,16 @@ #include "screen_group_info.h" namespace OHOS::Rosen { +void ScreenGroupInfo::Update(sptr info) +{ + ScreenInfo::Update(info); + children_.clear(); + children_.insert(children_.begin(), info->children_.begin(), info->children_.end()); + position_.clear(); + position_.insert(position_.begin(), info->position_.begin(), info->position_.end()); + combination_ = info->combination_; +} + bool ScreenGroupInfo::Marshalling(Parcel &parcel) const { bool res = ScreenInfo::Marshalling(parcel) && parcel.WriteUint32((uint32_t)combination_) && @@ -38,34 +48,29 @@ bool ScreenGroupInfo::Marshalling(Parcel &parcel) const ScreenGroupInfo* ScreenGroupInfo::Unmarshalling(Parcel &parcel) { ScreenGroupInfo* screenGroupInfo = new ScreenGroupInfo(); - bool res = screenGroupInfo->InnerUnmarshalling(parcel); - if (res) { - return screenGroupInfo; - } - delete screenGroupInfo; - return nullptr; + return screenGroupInfo->InnerUnmarshalling(parcel); } -bool ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) +ScreenGroupInfo* ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) { uint32_t combination; if (!ScreenInfo::InnerUnmarshalling(parcel) || !parcel.ReadUint32(combination) || !parcel.ReadUInt64Vector(&children_)) { - return false; + return nullptr; } combination_ = (ScreenCombination) combination; uint32_t size; if (!parcel.ReadUint32(size)) { - return false; + return nullptr; } for (size_t i = 0; i < size; i++) { Point point; if (parcel.ReadInt32(point.posX_) && parcel.ReadInt32(point.posY_)) { position_.push_back(point); } else { - return false; + return nullptr; } } - return true; + return this; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/utils/src/screen_info.cpp b/utils/src/screen_info.cpp index 4e16e2a7..a3df26fe 100644 --- a/utils/src/screen_info.cpp +++ b/utils/src/screen_info.cpp @@ -16,6 +16,19 @@ #include "screen_info.h" namespace OHOS::Rosen { +void ScreenInfo::Update(sptr info) +{ + id_ = info->id_; + virtualWidth_ = info->virtualWidth_; + virtualHeight_ = info->virtualHeight_; + virtualPixelRatio_ = info->virtualPixelRatio_; + parent_ = info->parent_; + canHasChild_ = info->canHasChild_; + rotation_ = info->rotation_; + modeId_ = info->modeId_; + modes_ = info->modes_; +} + bool ScreenInfo::Marshalling(Parcel &parcel) const { bool res = parcel.WriteUint64(id_) && @@ -40,15 +53,10 @@ bool ScreenInfo::Marshalling(Parcel &parcel) const ScreenInfo* ScreenInfo::Unmarshalling(Parcel &parcel) { ScreenInfo* info = new ScreenInfo(); - bool res = info->InnerUnmarshalling(parcel); - if (res) { - return info; - } - delete info; - return nullptr; + return info->InnerUnmarshalling(parcel); } -bool ScreenInfo::InnerUnmarshalling(Parcel& parcel) +ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) { uint32_t size = 0; uint32_t rotation; @@ -58,7 +66,7 @@ bool ScreenInfo::InnerUnmarshalling(Parcel& parcel) parcel.ReadBool(canHasChild_) && parcel.ReadUint32(rotation) && parcel.ReadUint32(modeId_) && parcel.ReadUint32(size); if (!res1) { - return false; + return nullptr; } modes_.clear(); for (uint32_t modeIndex = 0; modeIndex < size; modeIndex++) { @@ -68,10 +76,10 @@ bool ScreenInfo::InnerUnmarshalling(Parcel& parcel) parcel.ReadUint32(mode->freshRate_)) { modes_.push_back(mode); } else { - return false; + return nullptr; } } rotation_ = static_cast(rotation); - return true; + return this; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/wmserver/src/input_window_monitor.cpp b/wmserver/src/input_window_monitor.cpp index 393659c4..f8ad19ac 100644 --- a/wmserver/src/input_window_monitor.cpp +++ b/wmserver/src/input_window_monitor.cpp @@ -163,7 +163,7 @@ void InputWindowMonitor::TraverseWindowNodes(const std::vector> void InputWindowMonitor::UpdateDisplayDirection(MMI::PhysicalDisplayInfo& physicalDisplayInfo, DisplayId displayId) { - Rotation rotation = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(displayId)->GetRotation(); + Rotation rotation = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(displayId)->rotation_; switch (rotation) { case Rotation::ROTATION_0: physicalDisplayInfo.direction = MMI::Direction0; From c9ae024f58c047eea69ca6cb25da3f136cc262b8 Mon Sep 17 00:00:00 2001 From: xingyanan Date: Mon, 21 Feb 2022 20:43:27 +0800 Subject: [PATCH 23/70] fix remove single split window mode do not resume bug Signed-off-by: xingyanan Change-Id: I8eb497e9a35f9aa22cd2913ddef77e5593925b2f Signed-off-by: xingyanan --- wmserver/src/window_node_container.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 776e34f8..2d90d055 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -913,23 +913,19 @@ WMError WindowNodeContainer::ExitSplitWindowMode(sptr& node) { WM_FUNCTION_TRACE(); WLOGFI("exit split window mode %{public}d", node->GetWindowId()); - if (pairedWindowMap_.find(node->GetWindowId()) != pairedWindowMap_.end()) { - WindowPairInfo info = pairedWindowMap_.at(node->GetWindowId()); - auto pairNode = info.pairNode_; + node->GetWindowProperty()->ResumeLastWindowMode(); + node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode()); + if (pairedWindowMap_.count(node->GetWindowId()) != 0) { + auto pairNode = pairedWindowMap_.at(node->GetWindowId()).pairNode_; pairNode->GetWindowProperty()->ResumeLastWindowMode(); pairNode->GetWindowToken()->UpdateWindowMode(pairNode->GetWindowMode()); - node->GetWindowProperty()->ResumeLastWindowMode(); - node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode()); pairedWindowMap_.erase(pairNode->GetWindowId()); pairedWindowMap_.erase(node->GetWindowId()); - WLOGFI("Split out, Id[%{public}d, %{public}d], Mode[%{public}d, %{public}d]", - node->GetWindowId(), pairNode->GetWindowId(), - node->GetWindowMode(), pairNode->GetWindowMode()); - } else { - WLOGFE("Split out, but can not find pair in map %{public}d", node->GetWindowId()); - return WMError::WM_OK; + WLOGFI("resume pair node mode, Id[%{public}d, %{public}d], Mode[%{public}d, %{public}d]", node->GetWindowId(), + pairNode->GetWindowId(), node->GetWindowMode(), pairNode->GetWindowMode()); } if (pairedWindowMap_.empty()) { + WLOGFI("send destroy msg to divider, Id: %{public}d", node->GetWindowId()); SingletonContainer::Get().SendMessage(INNER_WM_DESTROY_DIVIDER, displayId_); } ResetLayoutPolicy(); From ed99c2febc72ca75ac030234ef406c59495909c5 Mon Sep 17 00:00:00 2001 From: chenqinxin Date: Tue, 22 Feb 2022 10:56:36 +0800 Subject: [PATCH 24/70] =?UTF-8?q?=E4=BF=AE=E5=A4=8D2.21=E6=97=A5=E5=91=8A?= =?UTF-8?q?=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chenqinxin Change-Id: I6b0269a008ea2956800c8686d7e8e73956ae33dd --- dm/src/display_manager.cpp | 2 +- dm/src/zidl/display_manager_agent_proxy.cpp | 4 ++-- dmserver/src/abstract_display.cpp | 4 ++-- dmserver/src/abstract_display_controller.cpp | 3 ++- dmserver/src/abstract_screen.cpp | 2 +- dmserver/src/abstract_screen_controller.cpp | 8 +++---- dmserver/src/display_manager_proxy.cpp | 4 ++-- dmserver/src/display_manager_stub.cpp | 4 ++-- interfaces/innerkits/dm/screen.h | 2 +- .../napi/js_screen_manager.cpp | 2 +- .../window_napi/js_window_utils.cpp | 2 +- utils/include/window_helper.h | 10 ++++---- wm/src/input_transfer_station.cpp | 2 +- wm/src/window_impl.cpp | 24 +++++++++---------- wmserver/src/window_controller.cpp | 2 +- wmserver/src/window_manager_proxy.cpp | 4 ++-- wmserver/src/window_node_container.cpp | 2 +- 17 files changed, 42 insertions(+), 39 deletions(-) diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 370f56c3..b18dd5be 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -462,7 +462,7 @@ bool DisplayManager::SetDisplayState(DisplayState state, DisplayStateCallback ca DisplayManagerAgentType::DISPLAY_STATE_LISTENER); } - ret &= SingletonContainer::Get().SetDisplayState(state); + ret = ret && SingletonContainer::Get().SetDisplayState(state); if (!ret) { pImpl_->ClearDisplayStateCallback(); } diff --git a/dm/src/zidl/display_manager_agent_proxy.cpp b/dm/src/zidl/display_manager_agent_proxy.cpp index 6e71bc27..dd0bf836 100644 --- a/dm/src/zidl/display_manager_agent_proxy.cpp +++ b/dm/src/zidl/display_manager_agent_proxy.cpp @@ -130,9 +130,9 @@ void DisplayManagerAgentProxy::OnScreenChange( return; } - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { if (!data.WriteParcelable(screenInfos[i].GetRefPtr())) { - WLOGFE("Write screenInfos[%{public}d] size failed", i); + WLOGFE("Write screenInfos[%{public}zu] size failed", i); return; } } diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index e9ad85f9..10d73508 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -133,8 +133,8 @@ bool AbstractDisplay::BindAbstractScreen(sptr abstractScreen) id_, dmsScreenId); return false; } - width_ = info->width_; - height_ = info->height_; + width_ = static_cast(info->width_); + height_ = static_cast(info->height_); freshRate_ = info->freshRate_; screenId_ = dmsScreenId; WLOGD("display bound to screen. display:%{public}" PRIu64", screen:%{public}" PRIu64"", id_, dmsScreenId); diff --git a/dmserver/src/abstract_display_controller.cpp b/dmserver/src/abstract_display_controller.cpp index d54d6fca..9a38095f 100644 --- a/dmserver/src/abstract_display_controller.cpp +++ b/dmserver/src/abstract_display_controller.cpp @@ -296,7 +296,8 @@ void AbstractDisplayController::ProcessDisplaySizeChange(sptr ab bool AbstractDisplayController::UpdateDisplaySize(sptr absDisplay, sptr info) { - if (info->height_ == absDisplay->GetHeight() && info->width_ == absDisplay->GetWidth()) { + if (info->height_ == static_cast(absDisplay->GetHeight()) && + info->width_ == static_cast(absDisplay->GetWidth())) { WLOGI("keep display size. display:%{public}" PRIu64"", absDisplay->GetId()); return false; } diff --git a/dmserver/src/abstract_screen.cpp b/dmserver/src/abstract_screen.cpp index fb124012..1478e620 100644 --- a/dmserver/src/abstract_screen.cpp +++ b/dmserver/src/abstract_screen.cpp @@ -296,7 +296,7 @@ bool AbstractScreenGroup::AddChildren(std::vector>& dmsScre } bool res = true; for (size_t i = 0; i < size; i++) { - res &= AddChild(dmsScreens[i], startPoints[i]); + res = AddChild(dmsScreens[i], startPoints[i]) && res; } return res; } diff --git a/dmserver/src/abstract_screen_controller.cpp b/dmserver/src/abstract_screen_controller.cpp index ed327ffd..0c611ef3 100644 --- a/dmserver/src/abstract_screen_controller.cpp +++ b/dmserver/src/abstract_screen_controller.cpp @@ -312,8 +312,8 @@ bool AbstractScreenController::FillAbstractScreen(sptr& absScree } for (RSScreenModeInfo rsScreenModeInfo : allModes) { sptr info = new SupportedScreenModes(); - info->width_ = rsScreenModeInfo.GetScreenWidth(); - info->height_ = rsScreenModeInfo.GetScreenHeight(); + info->width_ = static_cast(rsScreenModeInfo.GetScreenWidth()); + info->height_ = static_cast(rsScreenModeInfo.GetScreenHeight()); info->freshRate_ = rsScreenModeInfo.GetScreenFreshRate(); absScreen->modes_.push_back(info); WLOGD("fill screen w/h:%{public}d/%{public}d", info->width_, info->height_); @@ -613,8 +613,8 @@ bool AbstractScreenController::SetScreenActiveMode(ScreenId screenId, uint32_t m return false; } std::lock_guard lock(mutex_); - uint32_t usedModeId = screen->activeIdx_; - screen->activeIdx_ = modeId; + uint32_t usedModeId = static_cast(screen->activeIdx_); + screen->activeIdx_ = static_cast(modeId); // add thread to process mode change sync event // should be called by OnRsScreenChange if rs implement corresponding event callback if (usedModeId != modeId) { diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index 180dc4a4..b036f988 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -682,9 +682,9 @@ sptr DisplayManagerProxy::GetScreenInfoById(ScreenId screenId) WLOGFW("GetScreenInfoById SendRequest nullptr."); return nullptr; } - for (int i = 0; i < info->modes_.size(); i++) { + for (auto& mode : info->modes_) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", - info->modes_[i]->width_, info->modes_[i]->height_, info->modes_[i]->freshRate_); + mode->width_, mode->height_, mode->freshRate_); } return info; } diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index 2504aef4..5801ef8c 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -166,9 +166,9 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_SCREEN_INFO_BY_ID: { ScreenId screenId = static_cast(data.ReadUint64()); auto screenInfo = GetScreenInfoById(screenId); - for (int i = 0; i < screenInfo->modes_.size(); i++) { + for (auto& mode : screenInfo->modes_) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", - screenInfo->modes_[i]->width_, screenInfo->modes_[i]->height_, screenInfo->modes_[i]->freshRate_); + mode->width_, mode->height_, mode->freshRate_); } reply.WriteStrongParcelable(screenInfo); break; diff --git a/interfaces/innerkits/dm/screen.h b/interfaces/innerkits/dm/screen.h index 8c71c4f9..e22215e6 100644 --- a/interfaces/innerkits/dm/screen.h +++ b/interfaces/innerkits/dm/screen.h @@ -30,7 +30,7 @@ class ScreenInfo; struct Point { int32_t posX_; int32_t posY_; - Point() {}; + Point() : posX_(0), posY_(0) {}; Point(int32_t posX, int32_t posY) : posX_(posX), posY_(posY) {}; }; diff --git a/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp b/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp index 40773b52..f6efc13c 100644 --- a/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp +++ b/interfaces/kits/napi/display_runtime/napi/js_screen_manager.cpp @@ -316,7 +316,7 @@ NativeValue* OnMakeExpand(NativeEngine& engine, NativeCallbackInfo& info) } uint32_t size = array->GetLength(); std::vector options; - for (auto i = 0; i < size; ++i) { + for (uint32_t i = 0; i < size; ++i) { NativeObject* object = ConvertNativeValueTo(array->GetElement(i)); ExpandOption expandOption; int32_t res = GetExpandOptionFromJs(engine, object, expandOption); diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp index 663b8198..e97f4a0b 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp @@ -75,7 +75,7 @@ static std::string GetHexColor(uint32_t color) std::string temp; ioss << std::setiosflags(std::ios::uppercase) << std::hex << color; ioss >> temp; - int count = RGBA_LENGTH - temp.length(); + int count = RGBA_LENGTH - static_cast(temp.length()); std::string tmpColor(count, '0'); tmpColor += temp; std::string finalColor("#"); diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index 9e822ae0..5ee5034d 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -96,10 +96,12 @@ public: // limit position by fixed width or height if (oriDstRect.posX_ != lastRect.posX_) { - dstRect.posX_ = oriDstRect.posX_ + oriDstRect.width_ - dstRect.width_; + dstRect.posX_ = oriDstRect.posX_ + static_cast(oriDstRect.width_) - + static_cast(dstRect.width_); } if (oriDstRect.posY_ != lastRect.posY_) { - dstRect.posY_ = oriDstRect.posY_ + oriDstRect.height_ - dstRect.height_; + dstRect.posY_ = oriDstRect.posY_ + static_cast(oriDstRect.height_) - + static_cast(dstRect.height_); } return dstRect; } @@ -107,9 +109,9 @@ public: static bool IsPointInWindow(int32_t pointPosX, int32_t pointPosY, Rect pointRect) { if ((pointPosX > pointRect.posX_) && - (pointPosX < static_cast(pointRect.posX_ + pointRect.width_)) && + (pointPosX < (pointRect.posX_ + static_cast(pointRect.width_))) && (pointPosY > pointRect.posY_) && - (pointPosY < static_cast(pointRect.posY_ + pointRect.height_))) { + (pointPosY < (pointRect.posY_ + static_cast(pointRect.height_)))) { return true; } return false; diff --git a/wm/src/input_transfer_station.cpp b/wm/src/input_transfer_station.cpp index 947eb949..f9d9e5c7 100644 --- a/wm/src/input_transfer_station.cpp +++ b/wm/src/input_transfer_station.cpp @@ -56,7 +56,7 @@ void InputEventListener::OnInputEvent(std::shared_ptr pointer WLOGE("OnInputEvent receive pointerEvent is nullptr"); return; } - uint32_t windowId = pointerEvent->GetAgentWindowId(); + uint32_t windowId = static_cast(pointerEvent->GetAgentWindowId()); auto channel = InputTransferStation::GetInstance().GetInputChannel(windowId); if (channel == nullptr) { WLOGE("OnInputEvent channel is nullptr"); diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index bd797a1a..2b43862c 100644 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -937,27 +937,27 @@ void WindowImpl::HandleDragEvent(int32_t posX, int32_t posY, int32_t pointId) Rect newRect = startPointRect_; if (startPointPosX_ <= startPointRect_.posX_) { if (diffX > static_cast(startPointRect_.width_)) { - diffX = startPointRect_.width_; + diffX = static_cast(startPointRect_.width_); } - newRect.posX_ += diffX; - newRect.width_ -= diffX; - } else if (startPointPosX_ >= static_cast(startPointRect_.posX_ + startPointRect_.width_)) { + newRect.posX_ += diffX; + newRect.width_ = static_cast(static_cast(newRect.width_) - diffX); + } else if (startPointPosX_ >= startPointRect_.posX_ + static_cast(startPointRect_.width_)) { if (diffX < 0 && (-diffX > static_cast(startPointRect_.width_))) { - diffX = -startPointRect_.width_; + diffX = -(static_cast(startPointRect_.width_)); } - newRect.width_ += diffX; + newRect.width_ = static_cast(static_cast(newRect.width_) + diffX); } if (startPointPosY_ <= startPointRect_.posY_) { if (diffY > static_cast(startPointRect_.height_)) { - diffY = startPointRect_.height_; + diffY = static_cast(startPointRect_.height_); } - newRect.posY_ += diffY; - newRect.height_ -= diffY; - } else if (startPointPosY_ >= static_cast(startPointRect_.posY_ + startPointRect_.height_)) { + newRect.posY_ += diffY; + newRect.height_ = static_cast(static_cast(newRect.height_) - diffY); + } else if (startPointPosY_ >= startPointRect_.posY_ + static_cast(startPointRect_.height_)) { if (diffY < 0 && (-diffY > static_cast(startPointRect_.height_))) { - diffY = -startPointRect_.height_; + diffY = -(static_cast(startPointRect_.height_)); } - newRect.height_ += diffY; + newRect.height_ = static_cast(static_cast(newRect.height_) + diffY); } auto res = Drag(newRect); if (res != WMError::WM_OK) { diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index efaf27a0..55412be7 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -282,7 +282,7 @@ void WindowController::ProcessDisplayChange(DisplayId displayId, DisplayStateCha windowRoot_->NotifyDisplayChange(abstractDisplay); // TODO: Remove 'sysBarWinId_' after SystemUI resize 'systembar' - uint32_t width = abstractDisplay->GetWidth(); + uint32_t width = static_cast(abstractDisplay->GetWidth()); uint32_t height = abstractDisplay->GetHeight() * SYSTEM_BAR_HEIGHT_RATIO; Rect newRect = { 0, 0, width, height }; ResizeRect(sysBarWinId_[WindowType::WINDOW_TYPE_STATUS_BAR], newRect, WindowSizeChangeReason::DRAG); diff --git a/wmserver/src/window_manager_proxy.cpp b/wmserver/src/window_manager_proxy.cpp index 1a1b9509..5f991b68 100644 --- a/wmserver/src/window_manager_proxy.cpp +++ b/wmserver/src/window_manager_proxy.cpp @@ -510,7 +510,7 @@ bool WindowManagerProxy::IsSupportWideGamut(uint32_t windowId) return false; } - int32_t ret = reply.ReadUint32(); + uint32_t ret = reply.ReadUint32(); return static_cast(ret); } @@ -555,7 +555,7 @@ ColorSpace WindowManagerProxy::GetColorSpace(uint32_t windowId) return ColorSpace::COLOR_SPACE_DEFAULT; } - int32_t ret = reply.ReadUint32(); + uint32_t ret = reply.ReadUint32(); return static_cast(ret); } diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index feeb28b5..b1a80264 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -558,7 +558,7 @@ void WindowNodeContainer::UpdateWindowStatus(const sptr& node, Windo } if (isNeedNotify) { sptr windowInfo = new WindowInfo(); - windowInfo->wid_ = node->GetWindowId(); + windowInfo->wid_ = static_cast(node->GetWindowId()); windowInfo->windowRect_ = node->GetLayoutRect(); windowInfo->focused_ = node->GetWindowId() == focusedWindow_; windowInfo->mode_ = node->GetWindowMode(); From 7ce96267244975ebc724f177acea90dae5df4404 Mon Sep 17 00:00:00 2001 From: jincanran Date: Tue, 22 Feb 2022 14:36:24 +0800 Subject: [PATCH 25/70] bugfix when window change mode from FULL_SCREEN to FLOATING Signed-off-by: jincanran Change-Id: I28cc3256e27280be3921e9350b112cf31dc64a99 Signed-off-by: jincanran --- interfaces/innerkits/wm/wm_common.h | 2 +- wmserver/src/window_layout_policy.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 5d515903..4b262814 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -153,7 +153,7 @@ struct SystemBarProperty { bool enable_; uint32_t backgroundColor_; uint32_t contentColor_; - SystemBarProperty() : enable_(true), backgroundColor_(SYSTEM_COLOR_WHITE), contentColor_(SYSTEM_COLOR_BLACK) {} + SystemBarProperty() : enable_(true), backgroundColor_(SYSTEM_COLOR_BLACK), contentColor_(SYSTEM_COLOR_WHITE) {} SystemBarProperty(bool enable, uint32_t background, uint32_t content) : enable_(enable), backgroundColor_(background), contentColor_(content) {} bool operator == (const SystemBarProperty& a) const diff --git a/wmserver/src/window_layout_policy.cpp b/wmserver/src/window_layout_policy.cpp index a3ccfb89..ded4d478 100644 --- a/wmserver/src/window_layout_policy.cpp +++ b/wmserver/src/window_layout_policy.cpp @@ -144,6 +144,7 @@ void WindowLayoutPolicy::RemoveWindowNode(sptr& node) LayoutWindowTree(); } Rect winRect = node->GetWindowProperty()->GetWindowRect(); + node->SetLayoutRect(winRect); node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); } From 0145973871dccf90d8e8ee36a05f288423ab101b Mon Sep 17 00:00:00 2001 From: xiaojianfeng Date: Tue, 22 Feb 2022 10:49:16 +0800 Subject: [PATCH 26/70] =?UTF-8?q?Revert=20"Revert=20"modify=20screenInfo?= =?UTF-8?q?=EF=BC=8C=20screengroupinfo=EF=BC=8C=20displayInfo=EF=BC=8C=20s?= =?UTF-8?q?creen=EF=BC=8C=20screengroup=EF=BC=8C=20display""?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 12460515d1b2c3f5108f9c9019b2c0e83e519afc. Signed-off-by: xiaojianfeng Change-Id: I1184ab3cd41d899759b83b1f8b865275bfd2db0b --- dm/include/display_manager_adapter.h | 94 +++++----- dm/src/display.cpp | 89 ++++------ dm/src/display_manager.cpp | 12 +- dm/src/display_manager_adapter.cpp | 164 +++++++++++------- dm/src/screen.cpp | 130 +++++--------- dm/src/screen_group.cpp | 36 ++-- dm/src/screen_manager.cpp | 28 +-- .../unittest/mock_display_manager_adapter.h | 34 +++- dm/test/unittest/screen_manager_test.cpp | 2 +- dm/test/unittest/screen_test.cpp | 2 +- dmserver/include/abstract_display.h | 4 +- dmserver/include/abstract_screen.h | 4 +- dmserver/include/display_manager_interface.h | 2 +- dmserver/include/display_manager_proxy.h | 2 +- dmserver/include/display_manager_service.h | 2 +- dmserver/src/abstract_display.cpp | 16 +- dmserver/src/abstract_screen.cpp | 4 +- dmserver/src/display_manager_proxy.cpp | 16 +- dmserver/src/display_manager_service.cpp | 13 +- .../src/display_manager_service_inner.cpp | 2 +- dmserver/src/display_manager_stub.cpp | 4 +- interfaces/innerkits/dm/display.h | 15 +- interfaces/innerkits/dm/screen.h | 10 +- interfaces/innerkits/dm/screen_group.h | 12 +- utils/include/class_var_defination.h | 59 +++++++ utils/include/class_var_definition.h | 59 +++++++ utils/include/display_info.h | 29 ++-- utils/include/screen_group_info.h | 19 +- utils/include/screen_info.h | 30 ++-- utils/src/display_info.cpp | 24 +-- utils/src/screen_group_info.cpp | 27 ++- utils/src/screen_info.cpp | 28 ++- wmserver/src/input_window_monitor.cpp | 2 +- 33 files changed, 547 insertions(+), 427 deletions(-) create mode 100644 utils/include/class_var_defination.h create mode 100644 utils/include/class_var_definition.h diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index aa129871..19fe9849 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -28,35 +28,34 @@ #include "singleton_delegator.h" namespace OHOS::Rosen { -class DMSDeathRecipient : public IRemoteObject::DeathRecipient { +class BaseAdapter { public: - virtual void OnRemoteDied(const wptr& wptrDeath) override; -}; - -class DisplayManagerAdapter { -WM_DECLARE_SINGLE_INSTANCE(DisplayManagerAdapter); -public: - virtual DisplayId GetDefaultDisplayId(); - virtual sptr GetDisplayById(DisplayId displayId); - - virtual ScreenId CreateVirtualScreen(VirtualScreenOption option); - virtual DMError DestroyVirtualScreen(ScreenId screenId); - virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); - virtual bool RequestRotation(ScreenId screenId, Rotation rotation); - virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); - - // colorspace, gamut - virtual DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts); - virtual DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut); - virtual DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx); - virtual DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap); - virtual DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap); - virtual DMError SetScreenColorTransform(ScreenId screenId); - virtual bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type); virtual bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type); + virtual void Clear(); +protected: + bool InitDMSProxyLocked(); + std::recursive_mutex mutex_; + sptr displayManagerServiceProxy_ = nullptr; + sptr dmsDeath_ = nullptr; +}; + +class DMSDeathRecipient : public IRemoteObject::DeathRecipient { +public: + DMSDeathRecipient(BaseAdapter& adapter); + virtual void OnRemoteDied(const wptr& wptrDeath) override; +private: + BaseAdapter& adapter_; +}; + +class DisplayManagerAdapter : public BaseAdapter { +WM_DECLARE_SINGLE_INSTANCE(DisplayManagerAdapter); +public: + virtual DisplayId GetDefaultDisplayId(); + virtual sptr GetDisplayById(DisplayId displayId); + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); virtual bool WakeUpBegin(PowerStateChangeReason reason); virtual bool WakeUpEnd(); virtual bool SuspendBegin(PowerStateChangeReason reason); @@ -65,28 +64,45 @@ public: virtual bool SetDisplayState(DisplayState state); virtual DisplayState GetDisplayState(DisplayId displayId); virtual void NotifyDisplayEvent(DisplayEvent event); - virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); - virtual void Clear(); - virtual DisplayInfo GetDisplayInfo(DisplayId displayId); - virtual sptr GetScreenInfo(ScreenId screenId); - virtual sptr GetScreenById(ScreenId screenId); - virtual sptr GetScreenGroupById(ScreenId screenId); - virtual std::vector> GetAllScreens(); - virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); - virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); - + virtual void UpdateDisplayInfo(DisplayId); private: - bool InitDMSProxyLocked(); + sptr GetDisplayInfo(DisplayId displayId); static inline SingletonDelegator delegator; - std::recursive_mutex mutex_; - sptr displayManagerServiceProxy_ = nullptr; - sptr dmsDeath_ = nullptr; std::map> displayMap_; + DisplayId defaultDisplayId_; +}; + +class ScreenManagerAdapter : public BaseAdapter { +WM_DECLARE_SINGLE_INSTANCE(ScreenManagerAdapter); +public: + virtual bool RequestRotation(ScreenId screenId, Rotation rotation); + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option); + virtual DMError DestroyVirtualScreen(ScreenId screenId); + virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); + virtual sptr GetScreenById(ScreenId screenId); + virtual sptr GetScreenGroupById(ScreenId screenId); + virtual std::vector> GetAllScreens(); + virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); + virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); + virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); + virtual void UpdateScreenInfo(ScreenId); + + // colorspace, gamut + virtual DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts); + virtual DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut); + virtual DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx); + virtual DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap); + virtual DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap); + virtual DMError SetScreenColorTransform(ScreenId screenId); +private: + sptr GetScreenInfo(ScreenId screenId); + + static inline SingletonDelegator delegator; + std::map> screenMap_; std::map> screenGroupMap_; - DisplayId defaultDisplayId_; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DM_DISPLAY_MANAGER_ADAPTER_H diff --git a/dm/src/display.cpp b/dm/src/display.cpp index faa6ebf7..2cc2f511 100644 --- a/dm/src/display.cpp +++ b/dm/src/display.cpp @@ -16,89 +16,65 @@ #include "display.h" #include "display_info.h" #include "display_manager_adapter.h" +#include "window_manager_hilog.h" namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "Display"}; +} class Display::Impl : public RefBase { -friend class Display; -private: - void UpdateDisplay(DisplayInfo& info); - - std::string name_; - DisplayId id_ { DISPLAY_ID_INVALD }; - int32_t width_ { 0 }; - int32_t height_ { 0 }; - uint32_t freshRate_ { 0 }; - ScreenId screenId_ {SCREEN_ID_INVALID}; - Rotation rotation_ { Rotation::ROTATION_0 }; +public: + Impl(const std::string& name, sptr info) + { + name_= name; + displayInfo_ = info; + } + ~Impl() = default; + DEFINE_VAR_FUNC_GET_SET(std::string, Name, name); + DEFINE_VAR_FUNC_GET_SET(sptr, DisplayInfo, displayInfo); }; -void Display::Impl::UpdateDisplay(DisplayInfo& info) +Display::Display(const std::string& name, sptr info) + : pImpl_(new Impl(name, info)) { - width_ = info.width_; - height_ = info.height_; - freshRate_ = info.freshRate_; - screenId_ = info.screenId_; - rotation_ = info.rotation_; -} - -Display::Display(const std::string& name, DisplayInfo* info) - : pImpl_(new Impl()) -{ - pImpl_->name_ = name; - pImpl_->id_ = info->id_; - pImpl_->width_ = info->width_; - pImpl_->height_ = info->height_; - pImpl_->freshRate_ = info->freshRate_; - pImpl_->screenId_ = info->screenId_; - pImpl_->rotation_ = info->rotation_; } DisplayId Display::GetId() const { - return pImpl_->id_; + return pImpl_->GetDisplayInfo()->GetDisplayId(); } int32_t Display::GetWidth() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(info); - return pImpl_->width_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetWidth(); } int32_t Display::GetHeight() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(info); - return pImpl_->height_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetHeight(); } uint32_t Display::GetFreshRate() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(info); - return pImpl_->freshRate_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetFreshRate(); } ScreenId Display::GetScreenId() const { - DisplayInfo info = SingletonContainer::Get().GetDisplayInfo(pImpl_->id_); - pImpl_->UpdateDisplay(info); - return pImpl_->screenId_; + SingletonContainer::Get().UpdateDisplayInfo(GetId()); + return pImpl_->GetDisplayInfo()->GetScreenId(); } -void Display::SetWidth(int32_t width) +void Display::UpdateDisplayInfo(sptr displayInfo) { - pImpl_->width_ = width; -} - -void Display::SetHeight(int32_t height) -{ - pImpl_->height_ = height; -} - -void Display::SetFreshRate(uint32_t freshRate) -{ - pImpl_->freshRate_ = freshRate; + if (displayInfo == nullptr) { + WLOGFE("displayInfo is invalid"); + return; + } + pImpl_->SetDisplayInfo(displayInfo); } float Display::GetVirtualPixelRatio() const @@ -110,9 +86,4 @@ float Display::GetVirtualPixelRatio() const return 2.0f; #endif } - -void Display::SetId(DisplayId id) -{ - pImpl_->id_ = id; -} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index b18dd5be..e1733f80 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -54,7 +54,7 @@ public: void OnDisplayCreate(sptr displayInfo) override { - if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { + if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayCreate, displayInfo is invalid."); return; } @@ -63,7 +63,7 @@ public: return; } for (auto listener : pImpl_->displayListeners_) { - listener->OnCreate(displayInfo->id_); + listener->OnCreate(displayInfo->GetDisplayId()); } }; @@ -84,7 +84,7 @@ public: void OnDisplayChange(const sptr displayInfo, DisplayChangeEvent event) override { - if (displayInfo == nullptr || displayInfo->id_ == DISPLAY_ID_INVALD) { + if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { WLOGFE("OnDisplayChange, displayInfo is invalid."); return; } @@ -92,9 +92,9 @@ public: WLOGFE("OnDisplayChange, impl is nullptr."); return; } - WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->id_, event); + WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->GetDisplayId(), event); for (auto listener : pImpl_->displayListeners_) { - listener->OnChange(displayInfo->id_, event); + listener->OnChange(displayInfo->GetDisplayId(), event); } }; private: @@ -380,7 +380,7 @@ void DisplayManager::NotifyDisplayChangedEvent(const sptr info, Dis WLOGI("NotifyDisplayChangedEvent event:%{public}u, size:%{public}zu", event, pImpl_->displayListeners_.size()); std::lock_guard lock(pImpl_->mutex_); for (auto& listener : pImpl_->displayListeners_) { - listener->OnChange(info->id_, event); + listener->OnChange(info->GetDisplayId(), event); } } diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 80ad19ba..2e58f1d6 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -26,6 +26,7 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAdapter"}; } WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerAdapter) +WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManagerAdapter) DisplayId DisplayManagerAdapter::GetDefaultDisplayId() { @@ -56,35 +57,34 @@ sptr DisplayManagerAdapter::GetDisplayById(DisplayId displayId) if (iter != displayMap_.end()) { // Update display in map // should be updated automatically - DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); - if (displayInfo.id_ == DISPLAY_ID_INVALD) { + auto displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + if (displayInfo == nullptr) { + WLOGFE("GetDisplayById: displayInfo is nullptr!"); + displayMap_.erase(iter); + return nullptr; + } + if (displayInfo->GetDisplayId() == DISPLAY_ID_INVALD) { WLOGFE("GetDisplayById: Get invalid displayInfo!"); + displayMap_.erase(iter); return nullptr; } sptr display = iter->second; - if (displayInfo.width_ != display->GetWidth()) { - display->SetWidth(displayInfo.width_); - WLOGFI("GetDisplayById: set new width %{public}d", display->GetWidth()); - } - if (displayInfo.height_ != display->GetHeight()) { - display->SetHeight(displayInfo.height_); - WLOGFI("GetDisplayById: set new height %{public}d", display->GetHeight()); - } - if (displayInfo.freshRate_ != display->GetFreshRate()) { - display->SetFreshRate(displayInfo.freshRate_); - WLOGFI("GetDisplayById: set new freshRate %{public}ud", display->GetFreshRate()); - } + display->UpdateDisplayInfo(displayInfo); return iter->second; } - DisplayInfo displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); - sptr display = new Display("", &displayInfo); + auto displayInfo = displayManagerServiceProxy_->GetDisplayInfoById(displayId); + if (displayInfo == nullptr) { + WLOGFE("GetDisplayById: displayInfo is nullptr!"); + return nullptr; + } + sptr display = new Display("", displayInfo); if (display->GetId() != DISPLAY_ID_INVALD) { displayMap_[display->GetId()] = display; } return display; } -bool DisplayManagerAdapter::RequestRotation(ScreenId screenId, Rotation rotation) +bool ScreenManagerAdapter::RequestRotation(ScreenId screenId, Rotation rotation) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -109,7 +109,7 @@ std::shared_ptr DisplayManagerAdapter::GetDisplaySnapshot(Displ return dispalySnapshot; } -DMError DisplayManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, +DMError ScreenManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) { std::lock_guard lock(mutex_); @@ -123,7 +123,7 @@ DMError DisplayManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, return ret; } -DMError DisplayManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +DMError ScreenManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) { std::lock_guard lock(mutex_); @@ -136,7 +136,7 @@ DMError DisplayManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColo return ret; } -DMError DisplayManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +DMError ScreenManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) { std::lock_guard lock(mutex_); @@ -149,7 +149,7 @@ DMError DisplayManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t co return ret; } -DMError DisplayManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +DMError ScreenManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) { std::lock_guard lock(mutex_); @@ -162,7 +162,7 @@ DMError DisplayManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutM return ret; } -DMError DisplayManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +DMError ScreenManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) { std::lock_guard lock(mutex_); @@ -175,7 +175,7 @@ DMError DisplayManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutM return ret; } -DMError DisplayManagerAdapter::SetScreenColorTransform(ScreenId screenId) +DMError ScreenManagerAdapter::SetScreenColorTransform(ScreenId screenId) { std::lock_guard lock(mutex_); @@ -188,7 +188,7 @@ DMError DisplayManagerAdapter::SetScreenColorTransform(ScreenId screenId) return ret; } -ScreenId DisplayManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) +ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) { if (!InitDMSProxyLocked()) { return SCREEN_ID_INVALID; @@ -197,7 +197,7 @@ ScreenId DisplayManagerAdapter::CreateVirtualScreen(VirtualScreenOption option) return displayManagerServiceProxy_->CreateVirtualScreen(option); } -DMError DisplayManagerAdapter::DestroyVirtualScreen(ScreenId screenId) +DMError ScreenManagerAdapter::DestroyVirtualScreen(ScreenId screenId) { if (!InitDMSProxyLocked()) { return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; @@ -206,7 +206,7 @@ DMError DisplayManagerAdapter::DestroyVirtualScreen(ScreenId screenId) return displayManagerServiceProxy_->DestroyVirtualScreen(screenId); } -DMError DisplayManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +DMError ScreenManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { if (!InitDMSProxyLocked()) { return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; @@ -215,7 +215,7 @@ DMError DisplayManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptrSetVirtualScreenSurface(screenId, surface); } -bool DisplayManagerAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, +bool BaseAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) { std::lock_guard lock(mutex_); @@ -225,7 +225,7 @@ bool DisplayManagerAdapter::RegisterDisplayManagerAgent(const sptrRegisterDisplayManagerAgent(displayManagerAgent, type); } -bool DisplayManagerAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, +bool BaseAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, DisplayManagerAgentType type) { std::lock_guard lock(mutex_); @@ -308,7 +308,7 @@ void DisplayManagerAdapter::NotifyDisplayEvent(DisplayEvent event) displayManagerServiceProxy_->NotifyDisplayEvent(event); } -bool DisplayManagerAdapter::InitDMSProxyLocked() +bool BaseAdapter::InitDMSProxyLocked() { if (!displayManagerServiceProxy_) { sptr systemAbilityManager = @@ -331,7 +331,7 @@ bool DisplayManagerAdapter::InitDMSProxyLocked() return false; } - dmsDeath_ = new DMSDeathRecipient(); + dmsDeath_ = new DMSDeathRecipient(*this); if (!dmsDeath_) { WLOGFE("Failed to create death Recipient ptr DMSDeathRecipient"); return false; @@ -344,6 +344,10 @@ bool DisplayManagerAdapter::InitDMSProxyLocked() return true; } +DMSDeathRecipient::DMSDeathRecipient(BaseAdapter& adapter) : adapter_(adapter) +{ +} + void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) { if (wptrDeath == nullptr) { @@ -356,11 +360,11 @@ void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) WLOGFE("object is null"); return; } - SingletonContainer::Get().Clear(); + adapter_.Clear(); return; } -void DisplayManagerAdapter::Clear() +void BaseAdapter::Clear() { std::lock_guard lock(mutex_); if ((displayManagerServiceProxy_ != nullptr) && (displayManagerServiceProxy_->AsObject() != nullptr)) { @@ -369,7 +373,7 @@ void DisplayManagerAdapter::Clear() displayManagerServiceProxy_ = nullptr; } -DMError DisplayManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +DMError ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -378,7 +382,7 @@ DMError DisplayManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vectorMakeMirror(mainScreenId, mirrorScreenId); } -sptr DisplayManagerAdapter::GetScreenInfo(ScreenId screenId) +sptr ScreenManagerAdapter::GetScreenInfo(ScreenId screenId) { if (screenId == SCREEN_ID_INVALID) { WLOGFE("screen id is invalid"); @@ -396,80 +400,76 @@ sptr DisplayManagerAdapter::GetScreenInfo(ScreenId screenId) return screenInfo; } -DisplayInfo DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) +sptr DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) { if (displayId == DISPLAY_ID_INVALD) { WLOGFE("screen id is invalid"); - return DisplayInfo(); + return nullptr; } std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); - return DisplayInfo(); + return nullptr; } return displayManagerServiceProxy_->GetDisplayInfoById(displayId); } -sptr DisplayManagerAdapter::GetScreenById(ScreenId screenId) +sptr ScreenManagerAdapter::GetScreenById(ScreenId screenId) { std::lock_guard lock(mutex_); - if (screenId == SCREEN_ID_INVALID) { - WLOGFE("screen id is invalid"); + sptr screenInfo = GetScreenInfo(screenId); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is null"); + screenMap_.erase(screenId); return nullptr; } auto iter = screenMap_.find(screenId); if (iter != screenMap_.end()) { WLOGFI("get screen in screen map"); + iter->second->UpdateScreenInfo(screenInfo); return iter->second; } - - if (!InitDMSProxyLocked()) { - WLOGFE("InitDMSProxyLocked failed!"); - return nullptr; - } - sptr screenInfo = displayManagerServiceProxy_->GetScreenInfoById(screenId); - if (screenInfo == nullptr) { - WLOGFE("screenInfo is null"); - return nullptr; - } - sptr screen = new Screen(screenInfo.GetRefPtr()); + sptr screen = new Screen(screenInfo); screenMap_.insert(std::make_pair(screenId, screen)); return screen; } -sptr DisplayManagerAdapter::GetScreenGroupById(ScreenId screenId) +sptr ScreenManagerAdapter::GetScreenGroupById(ScreenId screenId) { std::lock_guard lock(mutex_); if (screenId == SCREEN_ID_INVALID) { WLOGFE("screenGroup id is invalid"); return nullptr; } - auto iter = screenGroupMap_.find(screenId); - if (iter != screenGroupMap_.end()) { - WLOGFI("get screenGroup in screenGroup map"); - return iter->second; - } - if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); + screenGroupMap_.clear(); return nullptr; } sptr screenGroupInfo = displayManagerServiceProxy_->GetScreenGroupInfoById(screenId); if (screenGroupInfo == nullptr) { WLOGFE("screenGroupInfo is null"); + screenGroupMap_.erase(screenId); return nullptr; } - sptr screenGroup = new ScreenGroup(screenGroupInfo.GetRefPtr()); + auto iter = screenGroupMap_.find(screenId); + if (iter != screenGroupMap_.end()) { + WLOGFI("get screenGroup in screenGroup map"); + iter->second->UpdateScreenGroupInfo(screenGroupInfo); + return iter->second; + } + sptr screenGroup = new ScreenGroup(screenGroupInfo); screenGroupMap_.insert(std::make_pair(screenId, screenGroup)); return screenGroup; } -std::vector> DisplayManagerAdapter::GetAllScreens() +std::vector> ScreenManagerAdapter::GetAllScreens() { std::lock_guard lock(mutex_); std::vector> screens; if (!InitDMSProxyLocked()) { WLOGFE("InitDMSProxyLocked failed!"); + screenMap_.clear(); return screens; } std::vector> screenInfos = displayManagerServiceProxy_->GetAllScreenInfos(); @@ -478,12 +478,24 @@ std::vector> DisplayManagerAdapter::GetAllScreens() WLOGFE("screenInfo is null"); continue; } - screens.emplace_back(new Screen(info.GetRefPtr())); + auto iter = screenMap_.find(info->GetScreenId()); + if (iter != screenMap_.end()) { + WLOGFI("get screen in screen map"); + iter->second->UpdateScreenInfo(info); + screens.emplace_back(iter->second); + } else { + sptr screen = new Screen(info); + screens.emplace_back(screen); + } + } + screenMap_.clear(); + for (auto screen: screens) { + screenMap_.insert(std::make_pair(screen->GetId(), screen)); } return screens; } -DMError DisplayManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) +DMError ScreenManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -492,7 +504,7 @@ DMError DisplayManagerAdapter::MakeExpand(std::vector screenId, std::v return displayManagerServiceProxy_->MakeExpand(screenId, startPoint); } -bool DisplayManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) +bool ScreenManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { @@ -500,4 +512,30 @@ bool DisplayManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t mode } return displayManagerServiceProxy_->SetScreenActiveMode(screenId, modeId); } + +void ScreenManagerAdapter::UpdateScreenInfo(ScreenId screenId) +{ + auto screenInfo = GetScreenInfo(screenId); + if (screenInfo == nullptr) { + WLOGFE("screenInfo is invalid"); + return; + } + auto iter = screenMap_.find(screenId); + if (iter != screenMap_.end()) { + iter->second->UpdateScreenInfo(screenInfo); + } +} + +void DisplayManagerAdapter::UpdateDisplayInfo(DisplayId displayId) +{ + auto displayInfo = GetDisplayInfo(displayId); + if (displayInfo == nullptr) { + WLOGFE("displayInfo is invalid"); + return; + } + auto iter = displayMap_.find(displayId); + if (iter != displayMap_.end()) { + iter->second->UpdateDisplayInfo(displayInfo); + } +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen.cpp b/dm/src/screen.cpp index d4a227b3..a682d809 100644 --- a/dm/src/screen.cpp +++ b/dm/src/screen.cpp @@ -16,7 +16,6 @@ #include "screen.h" #include "display_manager_adapter.h" -#include "screen_group.h" #include "screen_info.h" #include "window_manager_hilog.h" @@ -25,55 +24,18 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "Screen"}; } class Screen::Impl : public RefBase { -friend class Screen; public: - Impl() = default; + Impl(sptr info) + { + screenInfo_ = info; + } ~Impl() = default; - void UpdateScreen(sptr info); - - ScreenId id_ { SCREEN_ID_INVALID }; - uint32_t virtualWidth_ { 0 }; - uint32_t virtualHeight_ { 0 }; - float virtualPixelRatio_ { 0.0 }; - ScreenId parent_ { SCREEN_ID_INVALID }; - bool canHasChild_ { false }; - uint32_t modeId_ { 0 }; - std::vector> modes_ {}; - Rotation rotation_ { Rotation::ROTATION_0 }; + DEFINE_VAR_FUNC_GET_SET(sptr, ScreenInfo, screenInfo); }; -void Screen::Impl::UpdateScreen(sptr info) +Screen::Screen(sptr info) + : pImpl_(new Impl(info)) { - if (info == nullptr) { - WLOGFE("info is nullptr."); - return; - } - virtualWidth_ = info->virtualWidth_; - virtualHeight_ = info->virtualHeight_; - virtualPixelRatio_ = info->virtualPixelRatio_; - parent_ = info->parent_; - canHasChild_ = info->canHasChild_; - modeId_ = info->modeId_; - modes_ = info->modes_; - rotation_ = info->rotation_; -} - -Screen::Screen(const ScreenInfo* info) - : pImpl_(new Impl()) -{ - if (info == nullptr) { - WLOGFE("info is nullptr."); - return; - } - pImpl_->id_ = info->id_; - pImpl_->virtualWidth_ = info->virtualWidth_; - pImpl_->virtualHeight_ = info->virtualHeight_; - pImpl_->virtualPixelRatio_ = info->virtualPixelRatio_; - pImpl_->parent_ = info->parent_; - pImpl_->canHasChild_ = info->canHasChild_; - pImpl_->modeId_ = info->modeId_; - pImpl_->modes_ = info->modes_; - pImpl_->rotation_ = info->rotation_; } Screen::~Screen() @@ -82,22 +44,20 @@ Screen::~Screen() bool Screen::IsGroup() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->canHasChild_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetCanHasChild(); } ScreenId Screen::GetId() const { - return pImpl_->id_; + return pImpl_->GetScreenInfo()->GetScreenId(); } uint32_t Screen::GetWidth() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - auto modeId = pImpl_->modeId_; - auto modes = pImpl_->modes_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + auto modeId = GetModeId(); + auto modes = GetSupportedModes(); if (modeId < 0 || modeId >= modes.size()) { return 0; } @@ -106,10 +66,9 @@ uint32_t Screen::GetWidth() const uint32_t Screen::GetHeight() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - auto modeId = pImpl_->modeId_; - auto modes = pImpl_->modes_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + auto modeId = GetModeId(); + auto modes = GetSupportedModes(); if (modeId < 0 || modeId >= modes.size()) { return 0; } @@ -118,93 +77,98 @@ uint32_t Screen::GetHeight() const uint32_t Screen::GetVirtualWidth() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->virtualWidth_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetVirtualWidth(); } uint32_t Screen::GetVirtualHeight() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->virtualHeight_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetVirtualHeight(); } float Screen::GetVirtualPixelRatio() const { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->virtualPixelRatio_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetVirtualPixelRatio(); } Rotation Screen::GetRotation() { - sptr info = SingletonContainer::Get().GetScreenInfo(pImpl_->id_); - pImpl_->UpdateScreen(info); - return pImpl_->rotation_; + SingletonContainer::Get().UpdateScreenInfo(GetId()); + return pImpl_->GetScreenInfo()->GetRotation(); } bool Screen::RequestRotation(Rotation rotation) { WLOGFD("rotation the screen"); - return SingletonContainer::Get().RequestRotation(pImpl_->id_, rotation); + return SingletonContainer::Get().RequestRotation(GetId(), rotation); } DMError Screen::GetScreenSupportedColorGamuts(std::vector& colorGamuts) const { - return SingletonContainer::Get().GetScreenSupportedColorGamuts(pImpl_->id_, colorGamuts); + return SingletonContainer::Get().GetScreenSupportedColorGamuts(GetId(), colorGamuts); } DMError Screen::GetScreenColorGamut(ScreenColorGamut& colorGamut) const { - return SingletonContainer::Get().GetScreenColorGamut(pImpl_->id_, colorGamut); + return SingletonContainer::Get().GetScreenColorGamut(GetId(), colorGamut); } DMError Screen::SetScreenColorGamut(int32_t colorGamutIdx) { - return SingletonContainer::Get().SetScreenColorGamut(pImpl_->id_, colorGamutIdx); + return SingletonContainer::Get().SetScreenColorGamut(GetId(), colorGamutIdx); } DMError Screen::GetScreenGamutMap(ScreenGamutMap& gamutMap) const { - return SingletonContainer::Get().GetScreenGamutMap(pImpl_->id_, gamutMap); + return SingletonContainer::Get().GetScreenGamutMap(GetId(), gamutMap); } DMError Screen::SetScreenGamutMap(ScreenGamutMap gamutMap) { - return SingletonContainer::Get().SetScreenGamutMap(pImpl_->id_, gamutMap); + return SingletonContainer::Get().SetScreenGamutMap(GetId(), gamutMap); } DMError Screen::SetScreenColorTransform() { - return SingletonContainer::Get().SetScreenColorTransform(pImpl_->id_); + return SingletonContainer::Get().SetScreenColorTransform(GetId()); } ScreenId Screen::GetParentId() const { - return pImpl_->parent_; + return pImpl_->GetScreenInfo()->GetParentId(); } uint32_t Screen::GetModeId() const { - return pImpl_->modeId_; + return pImpl_->GetScreenInfo()->GetModeId(); } std::vector> Screen::GetSupportedModes() const { - return pImpl_->modes_; + return pImpl_->GetScreenInfo()->GetModes(); } bool Screen::SetScreenActiveMode(uint32_t modeId) { - ScreenId screenId = pImpl_->id_; - if (modeId < 0 || modeId >= pImpl_->modes_.size()) { + ScreenId screenId = GetId(); + if (modeId >= GetSupportedModes().size()) { return false; } - if (SingletonContainer::Get().SetScreenActiveMode(screenId, modeId)) { - pImpl_->modeId_ = modeId; + if (SingletonContainer::Get().SetScreenActiveMode(screenId, modeId)) { + pImpl_->GetScreenInfo()->SetModeId(modeId); return true; } return false; } + +void Screen::UpdateScreenInfo(sptr screenInfo) +{ + if (screenInfo == nullptr) { + WLOGFE("ScreenInfo is invalid"); + return; + } + pImpl_->SetScreenInfo(screenInfo); +} } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen_group.cpp b/dm/src/screen_group.cpp index 91e17a8d..aa4e4924 100644 --- a/dm/src/screen_group.cpp +++ b/dm/src/screen_group.cpp @@ -23,26 +23,28 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "ScreenGroup"}; } class ScreenGroup::Impl : public RefBase { -friend class ScreenGroup; -private: - Impl() = default; +public: + Impl(sptr info) + { + screenGroupInfo_ = info; + } ~Impl() = default; - std::vector children_; - std::vector position_; - ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; + DEFINE_VAR_FUNC_GET_SET(sptr, ScreenGroupInfo, screenGroupInfo); }; -ScreenGroup::ScreenGroup(const ScreenGroupInfo* info) - : Screen(info), pImpl_(new Impl()) +ScreenGroup::ScreenGroup(sptr info) + : Screen(info), pImpl_(new Impl(info)) +{ +} + +void ScreenGroup::UpdateScreenGroupInfo(sptr info) { if (info == nullptr) { - WLOGFE("info is nullptr."); + WLOGFE("ScreenGroupInfo is nullptr."); return; } - pImpl_->children_ = info->children_; - pImpl_->position_ = info->position_; - pImpl_->combination_ = info->combination_; + pImpl_->SetScreenGroupInfo(info); } ScreenGroup::~ScreenGroup() @@ -51,16 +53,16 @@ ScreenGroup::~ScreenGroup() ScreenCombination ScreenGroup::GetCombination() const { - return pImpl_->combination_; + return pImpl_->GetScreenGroupInfo()->GetCombination(); } -std::vector ScreenGroup::GetChild() const +std::vector ScreenGroup::GetChildIds() const { - return pImpl_->children_; + return pImpl_->GetScreenGroupInfo()->GetChildren(); } -std::vector ScreenGroup::GetChildPosition() const +std::vector ScreenGroup::GetChildPositions() const { - return pImpl_->position_; + return pImpl_->GetScreenGroupInfo()->GetPosition(); } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/src/screen_manager.cpp b/dm/src/screen_manager.cpp index abbbee9d..b81e640e 100644 --- a/dm/src/screen_manager.cpp +++ b/dm/src/screen_manager.cpp @@ -43,7 +43,7 @@ public: void OnScreenConnect(sptr screenInfo) { - if (screenInfo == nullptr || screenInfo->id_ == SCREEN_ID_INVALID) { + if (screenInfo == nullptr || screenInfo->GetScreenId() == SCREEN_ID_INVALID) { WLOGFE("OnScreenConnect, screenInfo is invalid."); return; } @@ -52,7 +52,7 @@ public: return; } for (auto listener : pImpl_->screenListeners_) { - listener->OnConnect(screenInfo->id_); + listener->OnConnect(screenInfo->GetScreenId()); } }; @@ -84,8 +84,8 @@ public: WLOGFD("OnScreenChange. event %{public}u", event); std::vector screenIds; for (auto screenInfo : screenInfos) { - if (screenInfo->id_ != SCREEN_ID_INVALID) { - screenIds.push_back(screenInfo->id_); + if (screenInfo->GetScreenId() != SCREEN_ID_INVALID) { + screenIds.push_back(screenInfo->GetScreenId()); } } for (auto listener: pImpl_->screenListeners_) { @@ -108,17 +108,17 @@ ScreenManager::~ScreenManager() sptr ScreenManager::GetScreenById(ScreenId screenId) { - return SingletonContainer::Get().GetScreenById(screenId); + return SingletonContainer::Get().GetScreenById(screenId); } sptr ScreenManager::GetScreenGroupById(ScreenId screenId) { - return SingletonContainer::Get().GetScreenGroupById(screenId); + return SingletonContainer::Get().GetScreenGroupById(screenId); } std::vector> ScreenManager::GetAllScreens() { - return SingletonContainer::Get().GetAllScreens(); + return SingletonContainer::Get().GetAllScreens(); } bool ScreenManager::RegisterScreenListener(sptr listener) @@ -131,7 +131,7 @@ bool ScreenManager::RegisterScreenListener(sptr listener) pImpl_->screenListeners_.push_back(listener); if (screenManagerListener_ == nullptr) { screenManagerListener_ = new ScreenManagerListener(pImpl_); - SingletonContainer::Get().RegisterDisplayManagerAgent( + SingletonContainer::Get().RegisterDisplayManagerAgent( screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); } @@ -152,7 +152,7 @@ bool ScreenManager::UnregisterScreenListener(sptr listener) } pImpl_->screenListeners_.erase(iter); if (pImpl_->screenListeners_.empty() && screenManagerListener_ != nullptr) { - SingletonContainer::Get().UnregisterDisplayManagerAgent( + SingletonContainer::Get().UnregisterDisplayManagerAgent( screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); screenManagerListener_ = nullptr; @@ -172,7 +172,7 @@ ScreenId ScreenManager::MakeExpand(const std::vector& options) screenIds.emplace_back(option.screenId_); startPoints.emplace_back(Point(option.startX_, option.startY_)); } - DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); + DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); if (result != DMError::DM_OK) { return SCREEN_ID_INVALID; } @@ -184,7 +184,7 @@ ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector { WLOGFI("create mirror for screen: %{public}" PRIu64"", mainScreenId); // TODO: "record screen" should use another function, "MakeMirror" should return group id. - DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); + DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); if (result == DMError::DM_OK) { WLOGFI("create mirror success"); } @@ -193,16 +193,16 @@ ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector ScreenId ScreenManager::CreateVirtualScreen(VirtualScreenOption option) { - return SingletonContainer::Get().CreateVirtualScreen(option); + return SingletonContainer::Get().CreateVirtualScreen(option); } DMError ScreenManager::DestroyVirtualScreen(ScreenId screenId) { - return SingletonContainer::Get().DestroyVirtualScreen(screenId); + return SingletonContainer::Get().DestroyVirtualScreen(screenId); } DMError ScreenManager::SetVirtualScreenSurface(ScreenId screenId, sptr surface) { - return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); + return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/dm/test/unittest/mock_display_manager_adapter.h b/dm/test/unittest/mock_display_manager_adapter.h index 97dbef49..46ee9bc5 100644 --- a/dm/test/unittest/mock_display_manager_adapter.h +++ b/dm/test/unittest/mock_display_manager_adapter.h @@ -23,25 +23,45 @@ namespace OHOS { namespace Rosen { class MockDisplayManagerAdapter : public DisplayManagerAdapter { public: - MOCK_METHOD0(GetDefaultDisplayId, DisplayId()); - MOCK_METHOD1(GetDisplayById, sptr(DisplayId displayId)); - MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); - MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); - MOCK_METHOD1(GetDisplaySnapshot, std::shared_ptr(DisplayId displayId)); MOCK_METHOD0(Clear, void()); MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, DisplayManagerAgentType type)); + MOCK_METHOD0(GetDefaultDisplayId, DisplayId()); + MOCK_METHOD1(GetDisplayById, sptr(DisplayId displayId)); + MOCK_METHOD1(GetDisplaySnapshot, std::shared_ptr(DisplayId displayId)); + MOCK_METHOD1(WakeUpBegin, bool(PowerStateChangeReason reason)); MOCK_METHOD0(WakeUpEnd, bool()); MOCK_METHOD1(SuspendBegin, bool(PowerStateChangeReason reason)); MOCK_METHOD0(SuspendEnd, bool()); MOCK_METHOD2(SetScreenPowerForAll, bool(DisplayPowerState state, PowerStateChangeReason reason)); MOCK_METHOD1(SetDisplayState, bool(DisplayState state)); - MOCK_METHOD1(GetDisplayState, DisplayState(uint64_t displayId)); - MOCK_METHOD2(SetScreenActiveMode, bool(ScreenId screenId, uint32_t modeId)); + MOCK_METHOD1(GetDisplayState, DisplayState(DisplayId displayId)); + MOCK_METHOD1(NotifyDisplayEvent, void(DisplayEvent event)); + MOCK_METHOD1(UpdateDisplayInfo, void(DisplayId displayId)); +}; + +class MockScreenManagerAdapter : public ScreenManagerAdapter { +public: + MOCK_METHOD0(Clear, void()); + MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, + DisplayManagerAgentType type)); + MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, + DisplayManagerAgentType type)); + MOCK_METHOD2(RequestRotation, bool(ScreenId screenId, Rotation rotation)); + MOCK_METHOD1(CreateVirtualScreen, ScreenId(VirtualScreenOption option)); + MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); + MOCK_METHOD2(SetVirtualScreenSurface, DMError(ScreenId screenId, sptr surface)); + MOCK_METHOD1(GetScreenById, sptr(ScreenId screenId)); + MOCK_METHOD1(GetScreenGroupById, sptr(ScreenId screenId)); + MOCK_METHOD0(GetAllScreens, std::vector>()); + MOCK_METHOD2(MakeMirror, DMError(ScreenId mainScreenId, std::vector mirrorScreenId)); MOCK_METHOD2(MakeExpand, DMError(std::vector screenId, std::vector startPoint)); + MOCK_METHOD2(SetScreenActiveMode, bool(ScreenId screenId, uint32_t modeId)); + MOCK_METHOD1(UpdateScreenInfo, void(ScreenId screenId)); + MOCK_METHOD2(GetScreenSupportedColorGamuts, DMError(ScreenId screenId, std::vector& colorGamuts)); MOCK_METHOD2(GetScreenColorGamut, DMError(ScreenId screenId, ScreenColorGamut& colorGamut)); MOCK_METHOD2(SetScreenColorGamut, DMError(ScreenId screenId, int32_t colorGamutIdx)); diff --git a/dm/test/unittest/screen_manager_test.cpp b/dm/test/unittest/screen_manager_test.cpp index d6da30be..eeafc8b3 100644 --- a/dm/test/unittest/screen_manager_test.cpp +++ b/dm/test/unittest/screen_manager_test.cpp @@ -22,7 +22,7 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { -using Mocker = SingletonMocker; +using Mocker = SingletonMocker; sptr ScreenManagerTest::defaultDisplay_ = nullptr; DisplayId ScreenManagerTest::defaultDisplayId_ = DISPLAY_ID_INVALD; diff --git a/dm/test/unittest/screen_test.cpp b/dm/test/unittest/screen_test.cpp index 23086993..e6aebea0 100644 --- a/dm/test/unittest/screen_test.cpp +++ b/dm/test/unittest/screen_test.cpp @@ -22,7 +22,7 @@ using namespace testing::ext; namespace OHOS { namespace Rosen { -using Mocker = SingletonMocker; +using Mocker = SingletonMocker; sptr ScreenTest::defaultDisplay_ = nullptr; ScreenId ScreenTest::defaultScreenId_ = SCREEN_ID_INVALID; diff --git a/dmserver/include/abstract_display.h b/dmserver/include/abstract_display.h index 3b505006..79ba8b9c 100644 --- a/dmserver/include/abstract_display.h +++ b/dmserver/include/abstract_display.h @@ -28,7 +28,7 @@ public: constexpr static int32_t DEFAULT_HIGHT = 1280; constexpr static float DEFAULT_VIRTUAL_PIXEL_RATIO = 1.0; constexpr static uint32_t DEFAULT_FRESH_RATE = 60; - AbstractDisplay(const DisplayInfo& info); + AbstractDisplay(const DisplayInfo* info); AbstractDisplay(DisplayId id, ScreenId screenId, int32_t width, int32_t height, uint32_t freshRate); ~AbstractDisplay() = default; static inline bool IsVertical(Rotation rotation) @@ -43,7 +43,7 @@ public: ScreenId GetAbstractScreenId() const; bool BindAbstractScreen(ScreenId dmsScreenId); bool BindAbstractScreen(sptr abstractDisplay); - const sptr ConvertToDisplayInfo() const; + sptr ConvertToDisplayInfo() const; void SetId(DisplayId displayId); void SetWidth(int32_t width); diff --git a/dmserver/include/abstract_screen.h b/dmserver/include/abstract_screen.h index c89d392d..cbf32a2a 100644 --- a/dmserver/include/abstract_screen.h +++ b/dmserver/include/abstract_screen.h @@ -46,7 +46,7 @@ public: sptr GetActiveScreenMode() const; std::vector> GetAbstractScreenModes() const; sptr GetGroup() const; - const sptr ConvertToScreenInfo() const; + sptr ConvertToScreenInfo() const; void RequestRotation(Rotation rotation); Rotation GetRotation() const; @@ -90,7 +90,7 @@ public: std::vector> GetChildren() const; std::vector GetChildrenPosition() const; size_t GetChildCount() const; - const sptr ConvertToScreenGroupInfo() const; + sptr ConvertToScreenGroupInfo() const; bool SetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config); ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; diff --git a/dmserver/include/display_manager_interface.h b/dmserver/include/display_manager_interface.h index c4cb521b..9e9c40f6 100644 --- a/dmserver/include/display_manager_interface.h +++ b/dmserver/include/display_manager_interface.h @@ -68,7 +68,7 @@ public: }; virtual DisplayId GetDefaultDisplayId() = 0; - virtual DisplayInfo GetDisplayInfoById(DisplayId displayId) = 0; + virtual sptr GetDisplayInfoById(DisplayId displayId) = 0; virtual ScreenId CreateVirtualScreen(VirtualScreenOption option) = 0; virtual DMError DestroyVirtualScreen(ScreenId screenId) = 0; diff --git a/dmserver/include/display_manager_proxy.h b/dmserver/include/display_manager_proxy.h index 0d30ce4c..28d98a68 100644 --- a/dmserver/include/display_manager_proxy.h +++ b/dmserver/include/display_manager_proxy.h @@ -32,7 +32,7 @@ public: ~DisplayManagerProxy() {}; DisplayId GetDefaultDisplayId() override; - DisplayInfo GetDisplayInfoById(DisplayId displayId) override; + sptr GetDisplayInfoById(DisplayId displayId) override; ScreenId CreateVirtualScreen(VirtualScreenOption option) override; DMError DestroyVirtualScreen(ScreenId screenId) override; diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index ee3dc6d9..356521ba 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -51,7 +51,7 @@ public: DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; DisplayId GetDefaultDisplayId() override; - DisplayInfo GetDisplayInfoById(DisplayId displayId) override; + sptr GetDisplayInfoById(DisplayId displayId) override; bool RequestRotation(ScreenId screenId, Rotation rotation) override; std::shared_ptr GetDispalySnapshot(DisplayId displayId) override; ScreenId GetRSScreenId(DisplayId displayId) const; diff --git a/dmserver/src/abstract_display.cpp b/dmserver/src/abstract_display.cpp index 10d73508..de36fa69 100644 --- a/dmserver/src/abstract_display.cpp +++ b/dmserver/src/abstract_display.cpp @@ -24,12 +24,16 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractDisplay"}; } -AbstractDisplay::AbstractDisplay(const DisplayInfo& info) - : id_(info.id_), - width_(info.width_), - height_(info.height_), - freshRate_(info.freshRate_) +AbstractDisplay::AbstractDisplay(const DisplayInfo* info) { + if (info == nullptr) { + WLOGFE("DisplayInfo is nullptr"); + return; + } + id_ = info->GetDisplayId(); + width_ = info->GetWidth(); + height_ = info->GetHeight(); + freshRate_ = info->GetHeight(); } AbstractDisplay::AbstractDisplay(DisplayId id, ScreenId screenId, int32_t width, int32_t height, uint32_t freshRate) @@ -146,7 +150,7 @@ ScreenId AbstractDisplay::GetAbstractScreenId() const return screenId_; } -const sptr AbstractDisplay::ConvertToDisplayInfo() const +sptr AbstractDisplay::ConvertToDisplayInfo() const { sptr displayInfo = new DisplayInfo(); displayInfo->width_ = width_; diff --git a/dmserver/src/abstract_screen.cpp b/dmserver/src/abstract_screen.cpp index 1478e620..9428d044 100644 --- a/dmserver/src/abstract_screen.cpp +++ b/dmserver/src/abstract_screen.cpp @@ -53,7 +53,7 @@ sptr AbstractScreen::GetGroup() const return DisplayManagerService::GetInstance().GetAbstractScreenController()->GetAbstractScreenGroup(groupDmsId_); } -const sptr AbstractScreen::ConvertToScreenInfo() const +sptr AbstractScreen::ConvertToScreenInfo() const { sptr info = new ScreenInfo(); FillScreenInfo(info); @@ -215,7 +215,7 @@ AbstractScreenGroup::~AbstractScreenGroup() abstractScreenMap_.clear(); } -const sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const +sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const { sptr screenGroupInfo = new ScreenGroupInfo(); FillScreenInfo(screenGroupInfo); diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index b036f988..ec2a00a0 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -52,12 +52,12 @@ DisplayId DisplayManagerProxy::GetDefaultDisplayId() return displayId; } -DisplayInfo DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) +sptr DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) { sptr remote = Remote(); if (remote == nullptr) { WLOGFW("GetDisplayInfoById: remote is nullptr"); - return DisplayInfo(); + return nullptr; } MessageParcel data; @@ -65,23 +65,23 @@ DisplayInfo DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) MessageOption option; if (!data.WriteInterfaceToken(GetDescriptor())) { WLOGFE("GetDisplayInfoById: WriteInterfaceToken failed"); - return DisplayInfo(); + return nullptr; } if (!data.WriteUint64(displayId)) { WLOGFW("GetDisplayInfoById: WriteUint64 displayId failed"); - return DisplayInfo(); + return nullptr; } if (remote->SendRequest(TRANS_ID_GET_DISPLAY_BY_ID, data, reply, option) != ERR_NONE) { WLOGFW("GetDisplayInfoById: SendRequest failed"); - return DisplayInfo(); + return nullptr; } sptr info = reply.ReadParcelable(); if (info == nullptr) { WLOGFW("DisplayManagerProxy::GetDisplayInfoById SendRequest nullptr."); - return DisplayInfo(); + return nullptr; } - return *info; + return info; } ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption) @@ -682,7 +682,7 @@ sptr DisplayManagerProxy::GetScreenInfoById(ScreenId screenId) WLOGFW("GetScreenInfoById SendRequest nullptr."); return nullptr; } - for (auto& mode : info->modes_) { + for (auto& mode : info->GetModes()) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", mode->width_, mode->height_, mode->freshRate_); } diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index 0e3c34e0..047dbfee 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -89,21 +89,14 @@ DisplayId DisplayManagerService::GetDefaultDisplayId() return GetDisplayIdFromScreenId(screenId); } -DisplayInfo DisplayManagerService::GetDisplayInfoById(DisplayId displayId) +sptr DisplayManagerService::GetDisplayInfoById(DisplayId displayId) { - DisplayInfo displayInfo; sptr display = GetDisplayByDisplayId(displayId); if (display == nullptr) { WLOGFE("GetDisplayById: Get invalid display!"); - return displayInfo; + return nullptr; } - displayInfo.id_ = displayId; - displayInfo.width_ = display->GetWidth(); - displayInfo.height_ = display->GetHeight(); - displayInfo.freshRate_ = display->GetFreshRate(); - displayInfo.screenId_ = display->GetAbstractScreenId(); - displayInfo.rotation_ = display->GetRotation(); - return displayInfo; + return display->ConvertToDisplayInfo(); } sptr DisplayManagerService::GetAbstractDisplay(DisplayId displayId) diff --git a/dmserver/src/display_manager_service_inner.cpp b/dmserver/src/display_manager_service_inner.cpp index edaaa5cd..8c84b84a 100644 --- a/dmserver/src/display_manager_service_inner.cpp +++ b/dmserver/src/display_manager_service_inner.cpp @@ -41,7 +41,7 @@ const sptr DisplayManagerServiceInner::GetDisplayById(DisplayId { sptr display = DisplayManagerService::GetInstance().GetAbstractDisplay(displayId); if (display == nullptr) { - DisplayInfo displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + auto displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); display = new AbstractDisplay(displayInfo); WLOGFE("GetDisplayById create new!\n"); } diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index 5801ef8c..b76f231f 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -45,7 +45,7 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_DISPLAY_BY_ID: { DisplayId displayId = data.ReadUint64(); auto info = GetDisplayInfoById(displayId); - reply.WriteParcelable(&info); + reply.WriteParcelable(info); break; } case TRANS_ID_CREATE_VIRTUAL_SCREEN: { @@ -166,7 +166,7 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, case TRANS_ID_GET_SCREEN_INFO_BY_ID: { ScreenId screenId = static_cast(data.ReadUint64()); auto screenInfo = GetScreenInfoById(screenId); - for (auto& mode : screenInfo->modes_) { + for (auto& mode : screenInfo->GetModes()) { WLOGFI("info modes is width: %{public}u, height: %{public}u, freshRate: %{public}u", mode->width_, mode->height_, mode->freshRate_); } diff --git a/interfaces/innerkits/dm/display.h b/interfaces/innerkits/dm/display.h index a71df544..5846b76c 100644 --- a/interfaces/innerkits/dm/display.h +++ b/interfaces/innerkits/dm/display.h @@ -27,23 +27,22 @@ typedef enum DisplayType { } DisplayType; class Display : public RefBase { +friend class DisplayManagerAdapter; public: - Display(const std::string& name, DisplayInfo* info); ~Display() = default; - + Display(const Display&) = delete; + Display(Display&&) = delete; + Display& operator=(const Display&) = delete; + Display& operator=(Display&&) = delete; DisplayId GetId() const; int32_t GetWidth() const; int32_t GetHeight() const; uint32_t GetFreshRate() const; ScreenId GetScreenId() const; float GetVirtualPixelRatio() const; - - void SetId(DisplayId displayId); - void SetWidth(int32_t width); - void SetHeight(int32_t height); - void SetFreshRate(uint32_t freshRate); - private: + Display(const std::string& name, sptr info); + void UpdateDisplayInfo(sptr); class Impl; sptr pImpl_; }; diff --git a/interfaces/innerkits/dm/screen.h b/interfaces/innerkits/dm/screen.h index e22215e6..ed000dbb 100644 --- a/interfaces/innerkits/dm/screen.h +++ b/interfaces/innerkits/dm/screen.h @@ -57,9 +57,13 @@ struct ExpandOption { }; class Screen : public RefBase { +friend class ScreenManagerAdapter; public: - Screen(const ScreenInfo* info); ~Screen(); + Screen(const Screen&) = delete; + Screen(Screen&&) = delete; + Screen& operator=(const Screen&) = delete; + Screen& operator=(Screen&&) = delete; bool IsGroup() const; ScreenId GetId() const; uint32_t GetWidth() const; @@ -81,7 +85,9 @@ public: DMError GetScreenGamutMap(ScreenGamutMap& gamutMap) const; DMError SetScreenGamutMap(ScreenGamutMap gamutMap); DMError SetScreenColorTransform(); - +protected: + Screen(sptr info); + void UpdateScreenInfo(sptr screenInfo); private: class Impl; sptr pImpl_; diff --git a/interfaces/innerkits/dm/screen_group.h b/interfaces/innerkits/dm/screen_group.h index 78377f88..bb879536 100644 --- a/interfaces/innerkits/dm/screen_group.h +++ b/interfaces/innerkits/dm/screen_group.h @@ -29,14 +29,20 @@ enum class ScreenCombination : uint32_t { }; class ScreenGroup : public Screen { +friend class ScreenManagerAdapter; public: - ScreenGroup(const ScreenGroupInfo* info); ~ScreenGroup(); + ScreenGroup(const ScreenGroup&) = delete; + ScreenGroup(ScreenGroup&&) = delete; + ScreenGroup& operator=(const ScreenGroup&) = delete; + ScreenGroup& operator=(ScreenGroup&&) = delete; ScreenCombination GetCombination() const; - std::vector GetChild() const; - std::vector GetChildPosition() const; + std::vector GetChildIds() const; + std::vector GetChildPositions() const; private: + ScreenGroup(sptr info); + void UpdateScreenGroupInfo(sptr info); class Impl; sptr pImpl_; }; diff --git a/utils/include/class_var_defination.h b/utils/include/class_var_defination.h new file mode 100644 index 00000000..27bce64e --- /dev/null +++ b/utils/include/class_var_defination.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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 p ermissions and + * limitations under the License. + */ + +#ifndef OHOS_ROSEN_CLASS_VAR_DEFINATION_H +#define OHOS_ROSEN_CLASS_VAR_DEFINATION_H +namespace OHOS::Rosen { +#define DEFINE_VAR(type, memberName) \ +private: \ + type memberName##_; + +#define DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ +private: \ + type memberName##_ {defaultValue}; + +#define DEFINE_FUNC_GET(type, funcName, memberName) \ +public: \ + type Get##funcName() const \ + { \ + return memberName##_; \ + } + +#define DEFINE_FUNC_SET(type, funcName, memberName) \ +public: \ + void Set##funcName(type value) \ + { \ + memberName##_ = value; \ + } + +#define DEFINE_VAR_FUNC_GET(type, funcName, memberName) \ + DEFINE_VAR(type, memberName) \ + DEFINE_FUNC_GET(type, funcName, memberName) + +#define DEFINE_VAR_DEFAULT_FUNC_GET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_GET(type, funcName, memberName) + +#define DEFINE_VAR_FUNC_GET_SET(type, funcName, memberName) \ + DEFINE_VAR(type, memberName) \ + DEFINE_FUNC_GET(type, funcName, memberName) \ + DEFINE_FUNC_SET(type, funcName, memberName) + +#define DEFINE_VAR_DEFAULT_FUNC_GET_SET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_GET(type, funcName, memberName) \ + DEFINE_FUNC_SET(type, funcName, memberName) +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_CLASS_VAR_DEFINATION_H diff --git a/utils/include/class_var_definition.h b/utils/include/class_var_definition.h new file mode 100644 index 00000000..c69794d2 --- /dev/null +++ b/utils/include/class_var_definition.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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 p ermissions and + * limitations under the License. + */ + +#ifndef OHOS_ROSEN_CLASS_VAR_DEFINITION_H +#define OHOS_ROSEN_CLASS_VAR_DEFINITION_H +namespace OHOS::Rosen { +#define DEFINE_VAR(type, memberName) \ +private: \ + type memberName##_; + +#define DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ +private: \ + type memberName##_ {defaultValue}; + +#define DEFINE_FUNC_GET(type, funcName, memberName) \ +public: \ + type Get##funcName() const \ + { \ + return memberName##_; \ + } + +#define DEFINE_FUNC_SET(type, funcName, memberName) \ +public: \ + void Set##funcName(type value) \ + { \ + memberName##_ = value; \ + } + +#define DEFINE_VAR_FUNC_GET(type, funcName, memberName) \ + DEFINE_VAR(type, memberName) \ + DEFINE_FUNC_GET(type, funcName, memberName) + +#define DEFINE_VAR_DEFAULT_FUNC_GET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_GET(type, funcName, memberName) + +#define DEFINE_VAR_FUNC_GET_SET(type, funcName, memberName) \ + DEFINE_VAR(type, memberName) \ + DEFINE_FUNC_GET(type, funcName, memberName) \ + DEFINE_FUNC_SET(type, funcName, memberName) + +#define DEFINE_VAR_DEFAULT_FUNC_GET_SET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_GET(type, funcName, memberName) \ + DEFINE_FUNC_SET(type, funcName, memberName) +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_CLASS_VAR_DEFINITION_H diff --git a/utils/include/display_info.h b/utils/include/display_info.h index 0aab1010..ed542629 100644 --- a/utils/include/display_info.h +++ b/utils/include/display_info.h @@ -18,29 +18,34 @@ #include +#include "class_var_definition.h" #include "display.h" #include "dm_common.h" namespace OHOS::Rosen { class DisplayInfo : public Parcelable { +friend class AbstractDisplay; public: - DisplayInfo() = default; ~DisplayInfo() = default; - - void Update(DisplayInfo* info); + DisplayInfo(const DisplayInfo&) = delete; + DisplayInfo(DisplayInfo&&) = delete; + DisplayInfo& operator=(const DisplayInfo&) = delete; + DisplayInfo& operator=(DisplayInfo&&) = delete; virtual bool Marshalling(Parcel& parcel) const override; static DisplayInfo *Unmarshalling(Parcel& parcel); - DisplayId id_ { DISPLAY_ID_INVALD }; - DisplayType type_ {DisplayType::DEFAULT }; - int32_t width_ { 0 }; - int32_t height_ { 0 }; - uint32_t freshRate_ { 0 }; - ScreenId screenId_ { SCREEN_ID_INVALID }; - float xDpi_ { 0.0 }; - float yDpi_ { 0.0 }; - Rotation rotation_ { Rotation::ROTATION_0 }; + DEFINE_VAR_DEFAULT_FUNC_GET(DisplayId, DisplayId, id, DISPLAY_ID_INVALD); + DEFINE_VAR_DEFAULT_FUNC_GET(DisplayType, DisplayType, type, DisplayType::DEFAULT); + DEFINE_VAR_DEFAULT_FUNC_GET(int32_t, Width, width, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(int32_t, Height, height, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, FreshRate, freshRate, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ScreenId, screenId, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET(float, XDpi, xDpi, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET(float, YDpi, yDpi, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); +private: + DisplayInfo() = default; }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H \ No newline at end of file diff --git a/utils/include/screen_group_info.h b/utils/include/screen_group_info.h index 6a9addbf..c1980182 100644 --- a/utils/include/screen_group_info.h +++ b/utils/include/screen_group_info.h @@ -23,20 +23,23 @@ namespace OHOS::Rosen { class ScreenGroupInfo : public ScreenInfo { +friend class AbstractScreenGroup; public: - ScreenGroupInfo() = default; ~ScreenGroupInfo() = default; - - void Update(sptr info); + ScreenGroupInfo(const ScreenGroupInfo&) = delete; + ScreenGroupInfo(ScreenGroupInfo&&) = delete; + ScreenGroupInfo& operator=(const ScreenGroupInfo&) = delete; + ScreenGroupInfo& operator=(ScreenGroupInfo&&) = delete; virtual bool Marshalling(Parcel& parcel) const override; static ScreenGroupInfo* Unmarshalling(Parcel& parcel); - std::vector children_; - std::vector position_; - ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; -protected: - ScreenGroupInfo* InnerUnmarshalling(Parcel& parcel); + DEFINE_VAR_FUNC_GET(std::vector, Children, children); + DEFINE_VAR_FUNC_GET(std::vector, Position, position); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenCombination, Combination, combination, ScreenCombination::SCREEN_ALONE); +private: + ScreenGroupInfo() = default; + bool InnerUnmarshalling(Parcel& parcel); }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_SCREEN_GROUP_INFO_H \ No newline at end of file diff --git a/utils/include/screen_info.h b/utils/include/screen_info.h index c39fad9d..c8ec17ae 100644 --- a/utils/include/screen_info.h +++ b/utils/include/screen_info.h @@ -18,30 +18,34 @@ #include +#include "class_var_definition.h" #include "screen.h" namespace OHOS::Rosen { class ScreenInfo : public Parcelable { +friend class AbstractScreen; public: - ScreenInfo() = default; ~ScreenInfo() = default; - - void Update(sptr info); + ScreenInfo(const ScreenInfo&) = delete; + ScreenInfo(ScreenInfo&&) = delete; + ScreenInfo& operator=(const ScreenInfo&) = delete; + ScreenInfo& operator= (ScreenInfo&&) = delete; virtual bool Marshalling(Parcel& parcel) const override; static ScreenInfo* Unmarshalling(Parcel& parcel); - ScreenId id_ { SCREEN_ID_INVALID }; - uint32_t virtualWidth_ { 0 }; - uint32_t virtualHeight_ { 0 }; - float virtualPixelRatio_ { 0.0 }; - ScreenId parent_ { 0 }; - bool canHasChild_ { false }; - Rotation rotation_ { Rotation::ROTATION_0 }; - uint32_t modeId_ { 0 }; - std::vector> modes_ {}; + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ScreenId, id, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, VirtualWidth, virtualWidth, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(uint32_t, VirtualHeight, virtualHeight, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(float, VirtualPixelRatio, virtualPixelRatio, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenId, ParentId, parent, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(bool, CanHasChild, canHasChild, false); + DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, ModeId, modeId, 0); + DEFINE_VAR_FUNC_GET(std::vector>, Modes, modes); protected: - ScreenInfo* InnerUnmarshalling(Parcel& parcel); + ScreenInfo() = default; + bool InnerUnmarshalling(Parcel& parcel); }; } // namespace OHOS::Rosen #endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H diff --git a/utils/src/display_info.cpp b/utils/src/display_info.cpp index 0ff79f31..ca033643 100644 --- a/utils/src/display_info.cpp +++ b/utils/src/display_info.cpp @@ -16,19 +16,6 @@ #include "display_info.h" namespace OHOS::Rosen { -void DisplayInfo::Update(DisplayInfo* info) -{ - id_ = info->id_; - type_ = info->type_; - width_ = info->width_; - height_ = info->height_; - freshRate_ = info->freshRate_; - screenId_ = info->screenId_; - xDpi_ = info->xDpi_; - yDpi_ = info->yDpi_; - rotation_ = info->rotation_; -} - bool DisplayInfo::Marshalling(Parcel &parcel) const { return parcel.WriteUint64(id_) && parcel.WriteUint32(type_) && @@ -41,9 +28,6 @@ bool DisplayInfo::Marshalling(Parcel &parcel) const DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) { DisplayInfo *displayInfo = new DisplayInfo(); - if (displayInfo == nullptr) { - return nullptr; - } uint32_t type = (uint32_t)DisplayType::DEFAULT; uint32_t rotation; bool res = parcel.ReadUint64(displayInfo->id_) && parcel.ReadUint32(type) && @@ -52,11 +36,11 @@ DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) parcel.ReadFloat(displayInfo->xDpi_) && parcel.ReadFloat(displayInfo->yDpi_) && parcel.ReadUint32(rotation); if (!res) { - displayInfo = nullptr; - } else { - displayInfo->type_ = (DisplayType)type; - displayInfo->rotation_ = static_cast(rotation); + delete displayInfo; + return nullptr; } + displayInfo->type_ = (DisplayType)type; + displayInfo->rotation_ = static_cast(rotation); return displayInfo; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/utils/src/screen_group_info.cpp b/utils/src/screen_group_info.cpp index 56268c74..ed4e4122 100644 --- a/utils/src/screen_group_info.cpp +++ b/utils/src/screen_group_info.cpp @@ -16,16 +16,6 @@ #include "screen_group_info.h" namespace OHOS::Rosen { -void ScreenGroupInfo::Update(sptr info) -{ - ScreenInfo::Update(info); - children_.clear(); - children_.insert(children_.begin(), info->children_.begin(), info->children_.end()); - position_.clear(); - position_.insert(position_.begin(), info->position_.begin(), info->position_.end()); - combination_ = info->combination_; -} - bool ScreenGroupInfo::Marshalling(Parcel &parcel) const { bool res = ScreenInfo::Marshalling(parcel) && parcel.WriteUint32((uint32_t)combination_) && @@ -48,29 +38,34 @@ bool ScreenGroupInfo::Marshalling(Parcel &parcel) const ScreenGroupInfo* ScreenGroupInfo::Unmarshalling(Parcel &parcel) { ScreenGroupInfo* screenGroupInfo = new ScreenGroupInfo(); - return screenGroupInfo->InnerUnmarshalling(parcel); + bool res = screenGroupInfo->InnerUnmarshalling(parcel); + if (res) { + return screenGroupInfo; + } + delete screenGroupInfo; + return nullptr; } -ScreenGroupInfo* ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) +bool ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) { uint32_t combination; if (!ScreenInfo::InnerUnmarshalling(parcel) || !parcel.ReadUint32(combination) || !parcel.ReadUInt64Vector(&children_)) { - return nullptr; + return false; } combination_ = (ScreenCombination) combination; uint32_t size; if (!parcel.ReadUint32(size)) { - return nullptr; + return false; } for (size_t i = 0; i < size; i++) { Point point; if (parcel.ReadInt32(point.posX_) && parcel.ReadInt32(point.posY_)) { position_.push_back(point); } else { - return nullptr; + return false; } } - return this; + return true; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/utils/src/screen_info.cpp b/utils/src/screen_info.cpp index a3df26fe..4e16e2a7 100644 --- a/utils/src/screen_info.cpp +++ b/utils/src/screen_info.cpp @@ -16,19 +16,6 @@ #include "screen_info.h" namespace OHOS::Rosen { -void ScreenInfo::Update(sptr info) -{ - id_ = info->id_; - virtualWidth_ = info->virtualWidth_; - virtualHeight_ = info->virtualHeight_; - virtualPixelRatio_ = info->virtualPixelRatio_; - parent_ = info->parent_; - canHasChild_ = info->canHasChild_; - rotation_ = info->rotation_; - modeId_ = info->modeId_; - modes_ = info->modes_; -} - bool ScreenInfo::Marshalling(Parcel &parcel) const { bool res = parcel.WriteUint64(id_) && @@ -53,10 +40,15 @@ bool ScreenInfo::Marshalling(Parcel &parcel) const ScreenInfo* ScreenInfo::Unmarshalling(Parcel &parcel) { ScreenInfo* info = new ScreenInfo(); - return info->InnerUnmarshalling(parcel); + bool res = info->InnerUnmarshalling(parcel); + if (res) { + return info; + } + delete info; + return nullptr; } -ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) +bool ScreenInfo::InnerUnmarshalling(Parcel& parcel) { uint32_t size = 0; uint32_t rotation; @@ -66,7 +58,7 @@ ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) parcel.ReadBool(canHasChild_) && parcel.ReadUint32(rotation) && parcel.ReadUint32(modeId_) && parcel.ReadUint32(size); if (!res1) { - return nullptr; + return false; } modes_.clear(); for (uint32_t modeIndex = 0; modeIndex < size; modeIndex++) { @@ -76,10 +68,10 @@ ScreenInfo* ScreenInfo::InnerUnmarshalling(Parcel& parcel) parcel.ReadUint32(mode->freshRate_)) { modes_.push_back(mode); } else { - return nullptr; + return false; } } rotation_ = static_cast(rotation); - return this; + return true; } } // namespace OHOS::Rosen \ No newline at end of file diff --git a/wmserver/src/input_window_monitor.cpp b/wmserver/src/input_window_monitor.cpp index f8ad19ac..393659c4 100644 --- a/wmserver/src/input_window_monitor.cpp +++ b/wmserver/src/input_window_monitor.cpp @@ -163,7 +163,7 @@ void InputWindowMonitor::TraverseWindowNodes(const std::vector> void InputWindowMonitor::UpdateDisplayDirection(MMI::PhysicalDisplayInfo& physicalDisplayInfo, DisplayId displayId) { - Rotation rotation = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(displayId)->rotation_; + Rotation rotation = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(displayId)->GetRotation(); switch (rotation) { case Rotation::ROTATION_0: physicalDisplayInfo.direction = MMI::Direction0; From 3128155c4e41e6940052db544117a4d3e140ec60 Mon Sep 17 00:00:00 2001 From: xiaojianfeng Date: Tue, 22 Feb 2022 10:50:47 +0800 Subject: [PATCH 27/70] fix accessibility compile bug Signed-off-by: xiaojianfeng Change-Id: I725577ea065a39192b3cdf05f12c34d9651e095b --- dm/src/display.cpp | 4 ++++ interfaces/innerkits/dm/display.h | 6 ++++-- utils/include/display_info.h | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/dm/src/display.cpp b/dm/src/display.cpp index 2cc2f511..6051a673 100644 --- a/dm/src/display.cpp +++ b/dm/src/display.cpp @@ -39,6 +39,10 @@ Display::Display(const std::string& name, sptr info) { } +Display::~Display() +{ +} + DisplayId Display::GetId() const { return pImpl_->GetDisplayInfo()->GetDisplayId(); diff --git a/interfaces/innerkits/dm/display.h b/interfaces/innerkits/dm/display.h index 5846b76c..3d9ed5f9 100644 --- a/interfaces/innerkits/dm/display.h +++ b/interfaces/innerkits/dm/display.h @@ -29,7 +29,7 @@ typedef enum DisplayType { class Display : public RefBase { friend class DisplayManagerAdapter; public: - ~Display() = default; + ~Display(); Display(const Display&) = delete; Display(Display&&) = delete; Display& operator=(const Display&) = delete; @@ -40,8 +40,10 @@ public: uint32_t GetFreshRate() const; ScreenId GetScreenId() const; float GetVirtualPixelRatio() const; -private: + +protected: Display(const std::string& name, sptr info); +private: void UpdateDisplayInfo(sptr); class Impl; sptr pImpl_; diff --git a/utils/include/display_info.h b/utils/include/display_info.h index ed542629..f8c3843a 100644 --- a/utils/include/display_info.h +++ b/utils/include/display_info.h @@ -44,7 +44,7 @@ public: DEFINE_VAR_DEFAULT_FUNC_GET(float, XDpi, xDpi, 0.0f); DEFINE_VAR_DEFAULT_FUNC_GET(float, YDpi, yDpi, 0.0f); DEFINE_VAR_DEFAULT_FUNC_GET(Rotation, Rotation, rotation, Rotation::ROTATION_0); -private: +protected: DisplayInfo() = default; }; } // namespace OHOS::Rosen From 7c87cb3fc1bd1a30ea61af609079ec09c18ce56e Mon Sep 17 00:00:00 2001 From: xingyanan Date: Tue, 22 Feb 2022 17:06:04 +0800 Subject: [PATCH 28/70] divider window move bugfix Signed-off-by: xingyanan Change-Id: I67df8bdfac0ad10d90a913bf398655d728cdb7fb --- wmserver/src/window_layout_policy_cascade.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wmserver/src/window_layout_policy_cascade.cpp b/wmserver/src/window_layout_policy_cascade.cpp index 3854543b..8faa6d61 100644 --- a/wmserver/src/window_layout_policy_cascade.cpp +++ b/wmserver/src/window_layout_policy_cascade.cpp @@ -150,6 +150,8 @@ void WindowLayoutPolicyCascade::LimitMoveBounds(Rect& rect) rect.posY_ = limitRect_.posY_ + static_cast(limitRect_.height_ - minVerticalSplitH); } } + WLOGFI("limit divider move bounds:[%{public}d, %{public}d, %{public}u, %{public}u]", + rect.posX_, rect.posY_, rect.width_, rect.height_); } void WindowLayoutPolicyCascade::InitCascadeRect() @@ -212,16 +214,14 @@ void WindowLayoutPolicyCascade::UpdateLayoutRect(sptr& node) UpdateFloatingLayoutRect(limitRect, winRect); } } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + LimitMoveBounds(winRect); // limit divider pos first + } // Limit window to the maximum window size LimitWindowSize(node, displayRect_, winRect); - - if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { - LimitMoveBounds(winRect); - } - node->SetLayoutRect(winRect); CalcAndSetNodeHotZone(winRect, node); - if (IsLayoutChanged(lastRect, winRect)) { + if (IsLayoutChanged(lastRect, winRect) || node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason()); node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); } From 64ed663b5a8c7681aac36acb736f5166a15bfd3c Mon Sep 17 00:00:00 2001 From: BruceXuXu Date: Mon, 21 Feb 2022 20:03:29 +0800 Subject: [PATCH 29/70] use new vsync interface Signed-off-by: BruceXuXu Change-Id: I1e9f9fa6c55a263ca3fb7504a79464cf8a35ada2 --- wm/BUILD.gn | 2 +- wm/include/vsync_station.h | 5 +++-- wm/src/vsync_station.cpp | 26 +++++++++++++++----------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/wm/BUILD.gn b/wm/BUILD.gn index 42f9ce64..0cd6a568 100644 --- a/wm/BUILD.gn +++ b/wm/BUILD.gn @@ -72,7 +72,7 @@ ohos_shared_library("libwm") { "//foundation/windowmanager/utils:libwmutil", # vsync - "//foundation/graphic/standard:libvsync_client", + "//foundation/graphic/standard/rosen/modules/composer:libcomposer", ] external_deps = [ diff --git a/wm/include/vsync_station.h b/wm/include/vsync_station.h index 1c362f74..25a5c65b 100644 --- a/wm/include/vsync_station.h +++ b/wm/include/vsync_station.h @@ -23,7 +23,8 @@ #include #include -#include +#include +#include #include "wm_single_instance.h" @@ -44,7 +45,6 @@ public: void RequestVsync(CallbackType type, std::shared_ptr vsyncCallback); private: - FrameCallback callback_; VsyncStation() = default; static void OnVsync(int64_t nanoTimestamp, void* client); void VsyncCallbackInner(int64_t nanoTimestamp); @@ -56,6 +56,7 @@ private: {CallbackType::CALLBACK_INPUT, {}}, {CallbackType::CALLBACK_FRAME, {}}, }; + std::shared_ptr receiver_ = nullptr; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/src/vsync_station.cpp b/wm/src/vsync_station.cpp index 832d6172..a28b9378 100644 --- a/wm/src/vsync_station.cpp +++ b/wm/src/vsync_station.cpp @@ -14,6 +14,7 @@ */ #include +#include "transaction/rs_interfaces.h" #include "window_manager_hilog.h" @@ -33,21 +34,24 @@ void VsyncStation::RequestVsync(CallbackType type, std::shared_ptrsecond.insert(vsyncCallback); + if (mainHandler_ == nullptr) { auto runner = AppExecFwk::EventRunner::Create(VSYNC_THREAD_ID); mainHandler_ = std::make_shared(runner); + + auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance(); + while (receiver_ == nullptr) { + receiver_ = rsClient.CreateVSyncReceiver("WM_" + std::to_string(::getpid()), mainHandler_); + } + receiver_->Init(); } - if (!hasRequestedVsync_) { - mainHandler_->PostTask([this]() { - callback_.timestamp_ = 0; - callback_.userdata_ = this; - callback_.callback_ = OnVsync; - WLOGFI("request vsync start."); - VsyncError ret = VsyncHelper::Current()->RequestFrameCallback(callback_); - if (ret != VSYNC_ERROR_OK) { - WLOGFE("VsyncStation::RequestNextVsync fail: %{public}s", VsyncErrorStr(ret).c_str()); - } - }); + + if (!hasRequestedVsync_.load()) { + OHOS::Rosen::VSyncReceiver::FrameCallback fcb = { + .userData_ = this, + .callback_ = OnVsync, + }; + receiver_->RequestNextVSync(fcb); hasRequestedVsync_.store(true); } } From 41e34014332ddc9a4e6f8ab9ed2f457b0a6a04bb Mon Sep 17 00:00:00 2001 From: Grady Date: Mon, 21 Feb 2022 09:37:07 +0800 Subject: [PATCH 30/70] add ScreenRecord demo Signed-off-by: Grady Change-Id: Ic9f6f94bd615e8def87d33f36d62e94def46a472 --- snapshot/BUILD.gn | 26 ++++ snapshot/snapshot_virtual_screen.cpp | 97 +++++++++++++ utils/BUILD.gn | 3 + utils/include/surface_reader.h | 66 +++++++++ utils/include/surface_reader_handler.h | 34 +++++ utils/include/surface_reader_handler_impl.h | 39 +++++ utils/src/surface_reader.cpp | 152 ++++++++++++++++++++ utils/src/surface_reader_handler_impl.cpp | 54 +++++++ 8 files changed, 471 insertions(+) create mode 100644 snapshot/snapshot_virtual_screen.cpp create mode 100644 utils/include/surface_reader.h create mode 100644 utils/include/surface_reader_handler.h create mode 100644 utils/include/surface_reader_handler_impl.h create mode 100644 utils/src/surface_reader.cpp create mode 100644 utils/src/surface_reader_handler_impl.cpp diff --git a/snapshot/BUILD.gn b/snapshot/BUILD.gn index 859799ef..cbbddd66 100644 --- a/snapshot/BUILD.gn +++ b/snapshot/BUILD.gn @@ -43,6 +43,32 @@ ohos_executable("snapshot_display") { subsystem_name = "window" } +ohos_executable("snapshot_virtual_screen") { + install_enable = false + sources = [ + "snapshot_utils.cpp", + "snapshot_virtual_screen.cpp", + ] + + configs = [ ":snapshot_config" ] + + deps = [ + "//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client", + "//foundation/windowmanager/dm:libdm", + "//foundation/windowmanager/utils:libwmutil", + "//foundation/windowmanager/wm:libwm", + "//third_party/libpng:libpng", # png + ] + + external_deps = [ + "multimedia_image_standard:image_native", + "utils_base:utils", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + ## Build snapshot }}} group("test") { diff --git a/snapshot/snapshot_virtual_screen.cpp b/snapshot/snapshot_virtual_screen.cpp new file mode 100644 index 00000000..8d0e0b5b --- /dev/null +++ b/snapshot/snapshot_virtual_screen.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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 "snapshot_utils.h" +#include "screen_manager.h" +#include "surface_reader.h" +#include "surface_reader_handler_impl.h" + +using namespace OHOS; +using namespace OHOS::Rosen; +using namespace OHOS::Media; + +namespace { +const int SLEEP_US = 10 * 1000; // 10ms +const int MAX_SNAPSHOT_COUNT = 10; +const int MAX_WAIT_COUNT = 200; +const float DEFAULT_DENSITY = 2.0; +const std::string FILE_NAME = "/data/snapshot_virtual_screen"; +} + +static VirtualScreenOption InitOption(ScreenId mainId, SurfaceReader& surfaceReader) +{ + auto defaultScreen = ScreenManager::GetInstance().GetScreenById(mainId); + VirtualScreenOption option = { + .name_ = "virtualScreen", + .width_ = defaultScreen->GetWidth(), + .height_ = defaultScreen->GetHeight(), + .density_ = DEFAULT_DENSITY, + .surface_ = surfaceReader.GetSurface(), + .flags_ = 0, + .isForShot_ = true, + }; + return option; +} + +int main(int argc, char *argv[]) +{ + SurfaceReader surfaceReader; + sptr surfaceReaderHandler = new SurfaceReaderHandlerImpl(); + if (!surfaceReader.Init()) { + printf("surfaceReader init failed!\n"); + return 0; + } + surfaceReader.SetHandler(surfaceReaderHandler); + ScreenId mainId = static_cast(DisplayManager::GetInstance().GetDefaultDisplayId()); + VirtualScreenOption option = InitOption(mainId, surfaceReader); + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(option); + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + ScreenManager::GetInstance().MakeMirror(mainId, mirrorIds); + int fileIndex = 1; + auto startTime = time(nullptr); + while (time(nullptr) - startTime < MAX_SNAPSHOT_COUNT) { + int waitCount = 0; + while (!surfaceReaderHandler->IsImageOk()) { + waitCount++; + if (waitCount >= MAX_WAIT_COUNT) { + printf("wait image overtime\n"); + break; + } + usleep(SLEEP_US); + } + if (waitCount >= MAX_WAIT_COUNT) { + continue; + } + auto pixelMap = surfaceReaderHandler->GetPixelMap(); + bool ret = SnapShotUtils::WriteToPngWithPixelMap(FILE_NAME + std::to_string(fileIndex) + ".png", *pixelMap); + if (ret) { + printf("snapshot %" PRIu64 ", write to %s as png\n", + mainId, (FILE_NAME + std::to_string(fileIndex)).c_str()); + } else { + printf("snapshot %" PRIu64 " write to %s failed!\n", + mainId, (FILE_NAME + std::to_string(fileIndex)).c_str()); + } + surfaceReaderHandler->ResetFlag(); + fileIndex++; + } + ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId); + printf("DestroyVirtualScreen %" PRIu64 "\n", virtualScreenId); + return 0; +} \ No newline at end of file diff --git a/utils/BUILD.gn b/utils/BUILD.gn index cd42616a..d18856c9 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -34,6 +34,8 @@ ohos_shared_library("libwmutil") { "src/screen_group_info.cpp", "src/screen_info.cpp", "src/singleton_container.cpp", + "src/surface_reader.cpp", + "src/surface_reader_handler_impl.cpp", "src/window_property.cpp", "src/wm_trace.cpp", ] @@ -49,6 +51,7 @@ ohos_shared_library("libwmutil") { "graphic_standard:surface", "hilog_native:libhilog", "ipc:ipc_core", + "multimedia_image_standard:image_native", "utils_base:utils", ] diff --git a/utils/include/surface_reader.h b/utils/include/surface_reader.h new file mode 100644 index 00000000..49ea386c --- /dev/null +++ b/utils/include/surface_reader.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef SURFACE_READER_H +#define SURFACE_READER_H + +#include "refbase.h" + +#include + +#include "surface_reader_handler.h" + +namespace OHOS { +namespace Rosen { +class SurfaceReader { +public: + SurfaceReader(); + virtual ~SurfaceReader(); + + bool Init(); + void DeInit(); + + sptr GetSurface() const; + void SetHandler(sptr handler); +private: + class BufferListener : public IBufferConsumerListener { + public: + explicit BufferListener(SurfaceReader &surfaceReader): surfaceReader_(surfaceReader) + { + } + ~BufferListener() noexcept override = default; + void OnBufferAvailable() override + { + surfaceReader_.OnVsync(); + } + + private: + SurfaceReader &surfaceReader_; + }; + friend class BufferListener; + + void OnVsync(); + bool ProcessBuffer(const sptr &buf); + + sptr listener_ = nullptr; + sptr csurface_ = nullptr; // cosumer surface + sptr psurface_ = nullptr; // producer surface + sptr prevBuffer_ = nullptr; + sptr handler_ = nullptr; +}; +} +} + +#endif // SURFACE_READER_H diff --git a/utils/include/surface_reader_handler.h b/utils/include/surface_reader_handler.h new file mode 100644 index 00000000..016b356f --- /dev/null +++ b/utils/include/surface_reader_handler.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef SURFACE_READER_HANDLER_H +#define SURFACE_READER_HANDLER_H + +#include "pixel_map.h" + +namespace OHOS { +namespace Rosen { +class SurfaceReaderHandler : public RefBase { +public: + SurfaceReaderHandler() {} + virtual ~SurfaceReaderHandler() noexcept + { + } + virtual bool OnImageAvalible(sptr pixleMap) = 0; +}; +} +} + +#endif // IMAGE_READER_HANDLER_H diff --git a/utils/include/surface_reader_handler_impl.h b/utils/include/surface_reader_handler_impl.h new file mode 100644 index 00000000..359d6c8a --- /dev/null +++ b/utils/include/surface_reader_handler_impl.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef SURFACE_READER_HANDLER_IMPL_H +#define SURFACE_READER_HANDLER_IMPL_H + +#include +#include "surface_reader_handler.h" + +namespace OHOS { +namespace Rosen { +class SurfaceReaderHandlerImpl : public SurfaceReaderHandler { +public: + bool OnImageAvalible(sptr pixleMap) override; + bool IsImageOk(); + void ResetFlag(); + sptr GetPixelMap(); + +private: + bool flag_ = false; + sptr pixleMap_ = nullptr; + std::recursive_mutex mutex_; +}; +} +} + +#endif // SURFACE_READER_HANDLER_IMPL_H diff --git a/utils/src/surface_reader.cpp b/utils/src/surface_reader.cpp new file mode 100644 index 00000000..af49492a --- /dev/null +++ b/utils/src/surface_reader.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2022 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 "surface_reader.h" +#include "window_manager_hilog.h" +#include "unique_fd.h" + +#include + +using namespace OHOS::Media; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReader"}; +} // namespace +const int BPP = 4; // bytes per pixel + +SurfaceReader::SurfaceReader() +{ +} + +SurfaceReader::~SurfaceReader() +{ + if (csurface_ != nullptr) { + csurface_->UnregisterConsumerListener(); + } + psurface_ = nullptr; + csurface_ = nullptr; +} + +bool SurfaceReader::Init() +{ + csurface_ = Surface::CreateSurfaceAsConsumer(); + if (csurface_ == nullptr) { + return false; + } + + auto producer = csurface_->GetProducer(); + psurface_ = Surface::CreateSurfaceAsProducer(producer); + if (psurface_ == nullptr) { + return false; + } + + listener_ = new BufferListener(*this); + SurfaceError ret = csurface_->RegisterConsumerListener(listener_); + if (ret != SURFACE_ERROR_OK) { + return false; + } + return true; +} + +void SurfaceReader::OnVsync() +{ + WLOGFI("SurfaceReader::OnVsync"); + + sptr cbuffer = nullptr; + int32_t fence = -1; + int64_t timestamp = 0; + Rect damage; + auto sret = csurface_->AcquireBuffer(cbuffer, fence, timestamp, damage); + if (cbuffer == nullptr || sret != OHOS::SURFACE_ERROR_OK) { + WLOGFE("SurfaceReader::OnVsync: surface buffer is null"); + return; + } + + if (!ProcessBuffer(cbuffer)) { + WLOGFE("SurfaceReader::OnVsync: ProcessBuffer failed"); + return; + } + + if (cbuffer != prevBuffer_) { + if (prevBuffer_ != nullptr) { + SurfaceError ret = csurface_->ReleaseBuffer(prevBuffer_, -1); + if (ret != SURFACE_ERROR_OK) { + WLOGFE("SurfaceReader::OnVsync: release buffer error"); + return; + } + } + + prevBuffer_ = cbuffer; + } +} + +sptr SurfaceReader::GetSurface() const +{ + return psurface_; +} + +void SurfaceReader::SetHandler(sptr handler) +{ + handler_ = handler; +} + +bool SurfaceReader::ProcessBuffer(const sptr &buf) +{ + if (handler_ == nullptr) { + WLOGFE("SurfaceReaderHandler not set"); + return false; + } + + BufferHandle *bufferHandle = buf->GetBufferHandle(); + if (bufferHandle == nullptr) { + WLOGFE("bufferHandle nullptr"); + return false; + } + + uint32_t width = bufferHandle->width; + uint32_t height = bufferHandle->height; + uint32_t stride = bufferHandle->stride; + uint8_t *addr = (uint8_t *)buf->GetVirAddr(); + + auto data = (uint8_t *)malloc(width * height * BPP); + if (data == nullptr) { + WLOGFE("data malloc failed"); + return false; + } + for (uint32_t i = 0; i < height; i++) { + errno_t ret = memcpy_s(data + width * i * BPP, width * BPP, addr + stride * i, width * BPP); + if (ret != EOK) { + WLOGFE("memcpy failed"); + return false; + } + } + + sptr pixelMap = new PixelMap(); + ImageInfo info; + info.size.width = width; + info.size.height = height; + info.pixelFormat = PixelFormat::RGBA_8888; + info.colorSpace = ColorSpace::SRGB; + pixelMap->SetImageInfo(info); + + pixelMap->SetPixelsAddr(data, nullptr, width * height, AllocatorType::HEAP_ALLOC, nullptr); + + handler_->OnImageAvalible(pixelMap); + return true; +} +} +} \ No newline at end of file diff --git a/utils/src/surface_reader_handler_impl.cpp b/utils/src/surface_reader_handler_impl.cpp new file mode 100644 index 00000000..534c5fab --- /dev/null +++ b/utils/src/surface_reader_handler_impl.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 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 "surface_reader_handler_impl.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReaderHandlerImpl"}; +} // namespace +bool SurfaceReaderHandlerImpl::OnImageAvalible(sptr pixleMap) +{ + std::lock_guard locl(mutex_); + if (!flag_) { + flag_ = true; + pixleMap_ = pixleMap; + WLOGFI("Get an Image!"); + } + return true; +} + +bool SurfaceReaderHandlerImpl::IsImageOk() +{ + std::lock_guard lock(mutex_); + return flag_; +} + +void SurfaceReaderHandlerImpl::ResetFlag() +{ + std::lock_guard lock(mutex_); + if (flag_) { + flag_ = false; + } +} + +sptr SurfaceReaderHandlerImpl::GetPixelMap() +{ + return pixleMap_; +} +} +} \ No newline at end of file From cef57bd91df1045b507319670de283f3b9cc3644 Mon Sep 17 00:00:00 2001 From: xiaojianfeng Date: Tue, 22 Feb 2022 16:44:19 +0800 Subject: [PATCH 31/70] modify the makemirror reture para type Signed-off-by: xiaojianfeng Change-Id: Ib5cd6d5a3927d200be1ec3f987d25e09238aa245 --- dm/include/display_manager_adapter.h | 4 +-- dm/src/display_manager_adapter.cpp | 8 +++--- dm/src/screen_manager.cpp | 17 ++++++----- .../unittest/mock_display_manager_adapter.h | 4 +-- dm/test/unittest/screen_manager_test.cpp | 2 +- dmserver/include/display_manager_interface.h | 4 +-- dmserver/include/display_manager_proxy.h | 4 +-- dmserver/include/display_manager_service.h | 4 +-- dmserver/src/display_manager_proxy.cpp | 28 +++++++++---------- dmserver/src/display_manager_service.cpp | 26 +++++++++++------ dmserver/src/display_manager_stub.cpp | 8 +++--- 11 files changed, 59 insertions(+), 50 deletions(-) diff --git a/dm/include/display_manager_adapter.h b/dm/include/display_manager_adapter.h index 19fe9849..54a80632 100644 --- a/dm/include/display_manager_adapter.h +++ b/dm/include/display_manager_adapter.h @@ -84,8 +84,8 @@ public: virtual sptr GetScreenById(ScreenId screenId); virtual sptr GetScreenGroupById(ScreenId screenId); virtual std::vector> GetAllScreens(); - virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); - virtual DMError MakeExpand(std::vector screenId, std::vector startPoint); + virtual ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); + virtual ScreenId MakeExpand(std::vector screenId, std::vector startPoint); virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); virtual void UpdateScreenInfo(ScreenId); diff --git a/dm/src/display_manager_adapter.cpp b/dm/src/display_manager_adapter.cpp index 2e58f1d6..0976d9a8 100644 --- a/dm/src/display_manager_adapter.cpp +++ b/dm/src/display_manager_adapter.cpp @@ -373,11 +373,11 @@ void BaseAdapter::Clear() displayManagerServiceProxy_ = nullptr; } -DMError ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +ScreenId ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { - return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; + return SCREEN_ID_INVALID; } return displayManagerServiceProxy_->MakeMirror(mainScreenId, mirrorScreenId); } @@ -495,11 +495,11 @@ std::vector> ScreenManagerAdapter::GetAllScreens() return screens; } -DMError ScreenManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) +ScreenId ScreenManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) { std::lock_guard lock(mutex_); if (!InitDMSProxyLocked()) { - return DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED; + return SCREEN_ID_INVALID; } return displayManagerServiceProxy_->MakeExpand(screenId, startPoint); } diff --git a/dm/src/screen_manager.cpp b/dm/src/screen_manager.cpp index b81e640e..324d0d1a 100644 --- a/dm/src/screen_manager.cpp +++ b/dm/src/screen_manager.cpp @@ -172,23 +172,22 @@ ScreenId ScreenManager::MakeExpand(const std::vector& options) screenIds.emplace_back(option.screenId_); startPoints.emplace_back(Point(option.startX_, option.startY_)); } - DMError result = SingletonContainer::Get().MakeExpand(screenIds, startPoints); - if (result != DMError::DM_OK) { - return SCREEN_ID_INVALID; + ScreenId group = SingletonContainer::Get().MakeExpand(screenIds, startPoints); + if (group == SCREEN_ID_INVALID) { + WLOGFI("make expand failed"); } - WLOGFI("make expand success"); - return screenIds.front(); // default main screenId is the first element of screenIds + return group; } ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { WLOGFI("create mirror for screen: %{public}" PRIu64"", mainScreenId); // TODO: "record screen" should use another function, "MakeMirror" should return group id. - DMError result = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); - if (result == DMError::DM_OK) { - WLOGFI("create mirror success"); + ScreenId group = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); + if (group == SCREEN_ID_INVALID) { + WLOGFI("create mirror failed"); } - return SCREEN_ID_INVALID; + return group; } ScreenId ScreenManager::CreateVirtualScreen(VirtualScreenOption option) diff --git a/dm/test/unittest/mock_display_manager_adapter.h b/dm/test/unittest/mock_display_manager_adapter.h index 46ee9bc5..a2e66521 100644 --- a/dm/test/unittest/mock_display_manager_adapter.h +++ b/dm/test/unittest/mock_display_manager_adapter.h @@ -57,8 +57,8 @@ public: MOCK_METHOD1(GetScreenById, sptr(ScreenId screenId)); MOCK_METHOD1(GetScreenGroupById, sptr(ScreenId screenId)); MOCK_METHOD0(GetAllScreens, std::vector>()); - MOCK_METHOD2(MakeMirror, DMError(ScreenId mainScreenId, std::vector mirrorScreenId)); - MOCK_METHOD2(MakeExpand, DMError(std::vector screenId, std::vector startPoint)); + MOCK_METHOD2(MakeMirror, ScreenId(ScreenId mainScreenId, std::vector mirrorScreenId)); + MOCK_METHOD2(MakeExpand, ScreenId(std::vector screenId, std::vector startPoint)); MOCK_METHOD2(SetScreenActiveMode, bool(ScreenId screenId, uint32_t modeId)); MOCK_METHOD1(UpdateScreenInfo, void(ScreenId screenId)); diff --git a/dm/test/unittest/screen_manager_test.cpp b/dm/test/unittest/screen_manager_test.cpp index eeafc8b3..76056531 100644 --- a/dm/test/unittest/screen_manager_test.cpp +++ b/dm/test/unittest/screen_manager_test.cpp @@ -105,7 +105,7 @@ HWTEST_F(ScreenManagerTest, MakeExpand_001, Function | SmallTest | Level1) std::unique_ptr m = std::make_unique(); EXPECT_CALL(m->Mock(), CreateVirtualScreen(_)).Times(1).WillOnce(Return(virtualScreenId)); EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_OK)); - EXPECT_CALL(m->Mock(), MakeExpand(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + EXPECT_CALL(m->Mock(), MakeExpand(_, _)).Times(1).WillOnce(Return(0)); ScreenId vScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); std::vector options = {{validId, 0, 0}, {vScreenId, defaultWidth_, 0}}; ScreenId expansionId = ScreenManager::GetInstance().MakeExpand(options); diff --git a/dmserver/include/display_manager_interface.h b/dmserver/include/display_manager_interface.h index 9e9c40f6..0af471f2 100644 --- a/dmserver/include/display_manager_interface.h +++ b/dmserver/include/display_manager_interface.h @@ -99,8 +99,8 @@ public: virtual sptr GetScreenInfoById(ScreenId screenId) = 0; virtual sptr GetScreenGroupInfoById(ScreenId screenId) = 0; virtual std::vector> GetAllScreenInfos() = 0; - virtual DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) = 0; - virtual DMError MakeExpand(std::vector screenId, std::vector startPoint) = 0; + virtual ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) = 0; + virtual ScreenId MakeExpand(std::vector screenId, std::vector startPoint) = 0; virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId) = 0; }; } // namespace OHOS::Rosen diff --git a/dmserver/include/display_manager_proxy.h b/dmserver/include/display_manager_proxy.h index 28d98a68..746f7229 100644 --- a/dmserver/include/display_manager_proxy.h +++ b/dmserver/include/display_manager_proxy.h @@ -60,11 +60,11 @@ public: bool SetDisplayState(DisplayState state) override; DisplayState GetDisplayState(DisplayId displayId) override; void NotifyDisplayEvent(DisplayEvent event) override; - DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; + ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; sptr GetScreenInfoById(ScreenId screenId) override; sptr GetScreenGroupInfoById(ScreenId screenId) override; std::vector> GetAllScreenInfos() override; - DMError MakeExpand(std::vector screenId, std::vector startPoint) override; + ScreenId MakeExpand(std::vector screenId, std::vector startPoint) override; bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId) override; private: diff --git a/dmserver/include/display_manager_service.h b/dmserver/include/display_manager_service.h index 356521ba..bac8580b 100644 --- a/dmserver/include/display_manager_service.h +++ b/dmserver/include/display_manager_service.h @@ -82,11 +82,11 @@ public: sptr GetAbstractDisplay(DisplayId displayId); sptr GetAbstractScreenController(); sptr GetDisplayByDisplayId(DisplayId displayId) const; - DMError MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; + ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; sptr GetScreenInfoById(ScreenId screenId) override; sptr GetScreenGroupInfoById(ScreenId screenId) override; std::vector> GetAllScreenInfos() override; - DMError MakeExpand(std::vector screenId, std::vector startPoint) override; + ScreenId MakeExpand(std::vector screenId, std::vector startPoint) override; bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId) override; private: diff --git a/dmserver/src/display_manager_proxy.cpp b/dmserver/src/display_manager_proxy.cpp index ec2a00a0..d050ca2b 100644 --- a/dmserver/src/display_manager_proxy.cpp +++ b/dmserver/src/display_manager_proxy.cpp @@ -625,12 +625,12 @@ void DisplayManagerProxy::NotifyDisplayEvent(DisplayEvent event) } } -DMError DisplayManagerProxy::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +ScreenId DisplayManagerProxy::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) { sptr remote = Remote(); if (remote == nullptr) { WLOGFW("create mirror fail: remote is null"); - return DMError::DM_ERROR_REMOTE_CREATE_FAILED; + return SCREEN_ID_INVALID; } MessageParcel data; @@ -638,19 +638,19 @@ DMError DisplayManagerProxy::MakeMirror(ScreenId mainScreenId, std::vector(mainScreenId)) && data.WriteUInt64Vector(mirrorScreenId); if (!res) { WLOGFE("create mirror fail: data write failed"); - return DMError::DM_ERROR_WRITE_DATA_FAILED; + return SCREEN_ID_INVALID; } if (remote->SendRequest(TRANS_ID_SCREEN_MAKE_MIRROR, data, reply, option) != ERR_NONE) { WLOGFW("create mirror fail: SendRequest failed"); - return DMError::DM_ERROR_IPC_FAILED; + return SCREEN_ID_INVALID; } - return static_cast(reply.ReadInt32()); + return static_cast(reply.ReadUint64()); } sptr DisplayManagerProxy::GetScreenInfoById(ScreenId screenId) @@ -750,12 +750,12 @@ std::vector> DisplayManagerProxy::GetAllScreenInfos() return screenInfos; } -DMError DisplayManagerProxy::MakeExpand(std::vector screenId, std::vector startPoint) +ScreenId DisplayManagerProxy::MakeExpand(std::vector screenId, std::vector startPoint) { sptr remote = Remote(); if (remote == nullptr) { WLOGFW("MakeExpand: remote is null"); - return DMError::DM_ERROR_REMOTE_CREATE_FAILED; + return SCREEN_ID_INVALID; } MessageParcel data; @@ -763,28 +763,28 @@ DMError DisplayManagerProxy::MakeExpand(std::vector screenId, std::vec MessageOption option; if (!data.WriteInterfaceToken(GetDescriptor())) { WLOGFE("MakeExpand: WriteInterfaceToken failed"); - return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + return SCREEN_ID_INVALID; } if (!data.WriteUInt64Vector(screenId)) { WLOGFE("MakeExpand: write screenId failed"); - return DMError::DM_ERROR_WRITE_DATA_FAILED; + return SCREEN_ID_INVALID; } uint32_t num = startPoint.size(); if (!data.WriteUint32(num)) { WLOGFE("MakeExpand: write startPoint size failed"); - return DMError::DM_ERROR_WRITE_DATA_FAILED; + return SCREEN_ID_INVALID; } for (auto point: startPoint) { if (!(data.WriteInt32(point.posX_) && data.WriteInt32(point.posY_))) { WLOGFE("MakeExpand: write startPoint failed"); - return DMError::DM_ERROR_WRITE_DATA_FAILED; + return SCREEN_ID_INVALID; } } if (remote->SendRequest(TRANS_ID_SCREEN_MAKE_EXPAND, data, reply, option) != ERR_NONE) { WLOGFE("MakeExpand: SendRequest failed"); - return DMError::DM_ERROR_IPC_FAILED; + return SCREEN_ID_INVALID; } - return static_cast(reply.ReadInt32()); + return static_cast(reply.ReadUint64()); } bool DisplayManagerProxy::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) diff --git a/dmserver/src/display_manager_service.cpp b/dmserver/src/display_manager_service.cpp index 047dbfee..902280a4 100644 --- a/dmserver/src/display_manager_service.cpp +++ b/dmserver/src/display_manager_service.cpp @@ -380,7 +380,7 @@ void DisplayManagerService::SetShotScreen(ScreenId mainScreenId, std::vectorFlushImplicitTransaction(); } -DMError DisplayManagerService::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds) +ScreenId DisplayManagerService::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds) { WLOGFI("MakeMirror. mainScreenId :%{public}" PRIu64"", mainScreenId); abstractScreenController_->DumpScreenInfo(); @@ -396,16 +396,21 @@ DMError DisplayManagerService::MakeMirror(ScreenId mainScreenId, std::vectorMakeMirror(mainScreenId, allMirrorScreenIds)) { WLOGFE("make mirror failed."); - return DMError::DM_ERROR_NULLPTR; + return SCREEN_ID_INVALID; } abstractScreenController_->DumpScreenInfo(); - return DMError::DM_OK; + auto screen = abstractScreenController_->GetAbstractScreen(mainScreenId); + if (screen == nullptr || abstractScreenController_->GetAbstractScreenGroup(screen->groupDmsId_) == nullptr) { + WLOGFE("get screen group failed."); + return SCREEN_ID_INVALID; + } + return screen->groupDmsId_; } void DisplayManagerService::UpdateRSTree(DisplayId displayId, std::shared_ptr& surfaceNode, @@ -454,14 +459,14 @@ std::vector> DisplayManagerService::GetAllScreenInfos() return screenInfos; } -DMError DisplayManagerService::MakeExpand(std::vector expandScreenIds, std::vector startPoints) +ScreenId DisplayManagerService::MakeExpand(std::vector expandScreenIds, std::vector startPoints) { WLOGI("MakeExpand"); if (expandScreenIds.empty() || startPoints.empty() || expandScreenIds.size() != startPoints.size()) { WLOGFI("create expand fail, input params is invalid. " "screenId vector size :%{public}ud, startPoint vector size :%{public}ud", static_cast(expandScreenIds.size()), static_cast(startPoints.size())); - return DMError::DM_ERROR_INVALID_PARAM; + return SCREEN_ID_INVALID; } abstractScreenController_->DumpScreenInfo(); ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); @@ -484,10 +489,15 @@ DMError DisplayManagerService::MakeExpand(std::vector expandScreenIds, WM_SCOPED_TRACE("dms:MakeExpand"); if (!allExpandScreenIds.empty() && !abstractScreenController_->MakeExpand(allExpandScreenIds, startPoints)) { WLOGFE("make expand failed."); - return DMError::DM_ERROR_NULLPTR; + return SCREEN_ID_INVALID; } abstractScreenController_->DumpScreenInfo(); - return DMError::DM_OK; + auto screen = abstractScreenController_->GetAbstractScreen(allExpandScreenIds[0]); + if (screen == nullptr || abstractScreenController_->GetAbstractScreenGroup(screen->groupDmsId_) == nullptr) { + WLOGFE("get screen group failed."); + return SCREEN_ID_INVALID; + } + return screen->groupDmsId_; } bool DisplayManagerService::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) diff --git a/dmserver/src/display_manager_stub.cpp b/dmserver/src/display_manager_stub.cpp index b76f231f..ca880198 100644 --- a/dmserver/src/display_manager_stub.cpp +++ b/dmserver/src/display_manager_stub.cpp @@ -159,8 +159,8 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, WLOGE("fail to receive mirror screen in stub. screen:%{public}" PRIu64"", mainScreenId); break; } - DMError result = MakeMirror(mainScreenId, mirrorScreenId); - reply.WriteInt32(static_cast(result)); + ScreenId result = MakeMirror(mainScreenId, mirrorScreenId); + reply.WriteUint64(static_cast(result)); break; } case TRANS_ID_GET_SCREEN_INFO_BY_ID: { @@ -200,8 +200,8 @@ int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Point point { data.ReadInt32(), data.ReadInt32() }; startPoint.push_back(point); } - DMError result = MakeExpand(screenId, startPoint); - reply.WriteInt32(static_cast(result)); + ScreenId result = MakeExpand(screenId, startPoint); + reply.WriteUint64(static_cast(result)); break; } case TRANS_ID_SET_SCREEN_ACTIVE_MODE: { From fcead9e349d7c91b61cda19c65501679094940ee Mon Sep 17 00:00:00 2001 From: zhouyaoying Date: Tue, 22 Feb 2022 17:50:30 +0800 Subject: [PATCH 32/70] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhouyaoying Change-Id: Id6272913e4da19b9d3bb2e60d148d2f60e3e2210 --- OAT.xml | 1 + README.md | 715 -------------------------------------- README_zh.md | 345 ++---------------- figures/WindowManager.png | Bin 0 -> 109194 bytes figures/graphic.png | Bin 46331 -> 0 bytes 5 files changed, 24 insertions(+), 1037 deletions(-) delete mode 100644 README.md create mode 100644 figures/WindowManager.png delete mode 100644 figures/graphic.png diff --git a/OAT.xml b/OAT.xml index 03bcd02b..1f2feceb 100644 --- a/OAT.xml +++ b/OAT.xml @@ -62,6 +62,7 @@ Note:If the text contains special characters, please escape them according to th + diff --git a/README.md b/README.md deleted file mode 100644 index 622d01ba..00000000 --- a/README.md +++ /dev/null @@ -1,715 +0,0 @@ -# WidnowManager - -- [Introduction](#section1333751883213) -- [Directory Structure](#section1882912343) -- [Constraints](#section68982123611) -- [Compilation and Building](#section671864110372) -- [Available APIs](#section197399520386) - - [WindowManager](#section5851104093816) - - [Window](#section3483122273912) - - [SubWindow](#section96481249183913) - - [Surface](#section12366161544010) - - [SurfaceBuffer](#section12001640184711) - - [VsyncHelper](#section1392116294211) - -- [Usage](#section18359134910422) - - [Transferring a Producer Surface](#section193464304411) - - [Creating a Producer Surface](#section1276823075112) - - [Producing a SurfaceBuffer](#section614545716513) - - [Consuming a SurfaceBuffer](#section315285412535) - - [Adding Custom Data to a SurfaceBuffer](#section612412125616) - - [Registering a Vsync Callback Listener](#section1148115214576) - -- [\#EN-US\_TOPIC\_0000001105482134/section1939493174420](#section1939493174420) -- [Repositories Involved](#section6488145313) - -## Introduction - -The Graphics subsystem provides graphics and window management capabilities, which can be invoked by using Java or JS APIs. It can be used for UI development for all standard-system devices. - -The following figure shows the architecture of the Graphics subsystem. - -![](figures/graphic.png) - -- Surface - - Provides APIs for managing the graphics buffer and the efficient and convenient rotation buffer. - -- Vsync - - Provides APIs for managing registration and response of all vertical sync signals. - -- WindowManager - - Provides APIs for creating and managing windows. - -- WaylandProtocols - - Provides the communication protocols between the window manager and synthesizer. - -- Compositor - - Implements synthesis of layers. - -- Renderer - - Functions as the back-end rendering module of the synthesizer. - -- Wayland protocols - - Provides Wayland inter-process communication protocols. - -- Shell - - Provides multi-window capabilities. - -- Input Manger - - Functions as the multimodal input module that receives input events. - - -## Directory Structure - -``` -foundation/graphic/standard/ -├── frameworks # Framework code -│ ├── bootanimation # Boot Animation code -│ ├── surface # Surface code -│ ├── vsync # Vsync code -│ └── wm # WindowManager code -├── interfaces # External APIs -│ ├── innerkits # Native APIs -│ └── kits # JS APIs and NAPIs -└── utils # Utilities -``` - -## Constraints - -- Language version: C++ 11 or later - -## Compilation and Building - -The dependent APIs include the following: - -- graphic\_standard:libwms\_client -- graphic\_standard:libsurface -- graphic\_standard:libvsync\_client - -## Available APIs - -### WindowManager - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

API

-

Description

-

GetInstance

-

Obtains the pointer to a singleton WindowManager instance.

-

GetMaxWidth

-

Obtains the width of the screen.

-

GetMaxHeight

-

Obtains the height of the screen.

-

CreateWindow

-

Creates a standard window.

-

CreateSubWindow

-

Creates a child window.

-

StartShotScreen

-

Takes a screenshot.

-

StartShotWindow

-

Captures a window.

-

SwitchTop

-

Moves the specified window to the top.

-
- -### Window - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

API

-

Description

-

Show

-

Displays the current window.

-

Hide

-

Hides the current window.

-

Move

-

Moves the current window to a specified position.

-

SwitchTop

-

Moves the current window to the top.

-

ChangeWindowType

-

Changes the type of the current window.

-

ReSize

-

Resizes the current window.

-

Rotate

-

Rotates the current window.

-

RegistPointerButtonCb

-

Registers the callback for Button events of the mouse.

-

RegistPointerEnterCb

-

Registers the callback for Enter events of the mouse.

-

RegistPointerLeaveCb

-

Registers the callback for Leave events of the mouse.

-

RegistPointerMotionCb

-

Registers the callback for Motion events of the mouse.

-

RegistPointerAxisDiscreteCb

-

Registers the callback for AxisDiscrete events of the mouse.

-

RegistPointerAxisSourceCb

-

Registers the callback for AxisSource events of the mouse.

-

RegistPointerAxisStopCb

-

Registers the callback for AxisStop events of the mouse.

-

RegistPointerAxisCb

-

Registers the callback for Axis events of the mouse.

-

RegistTouchUpCb

-

Registers the callback for TouchUp events.

-

RegistTouchDownCb

-

Registers the callback for TouchDown events.

-

RegistTouchEmotionCb

-

Registers the callback for TouchEmotion events.

-

RegistTouchFrameCb

-

Registers the callback for TouchFrame events.

-

RegistTouchCancelCb

-

Registers the callback for TouchCancel events.

-

RegistTouchShapeCb

-

Registers the callback for TouchShape events.

-

RegistTouchOrientationCb

-

Registers the callback for TouchOrientation events.

-

RegistKeyboardKeyCb

-

Registers the callback for Key events of the keyboard.

-

RegistKeyboardKeyMapCb

-

Registers the callback for KeyMap events of the keyboard.

-

RegistKeyboardLeaveCb

-

Registers the callback for Leave events of the keyboard.

-

RegistKeyboardEnterCb

-

Registers the callback for Enter events of the keyboard.

-

RegistKeyboardRepeatInfoCb

-

Registers the callback for RepeatInfo events of the keyboard.

-
- -### SubWindow - - - - - - - - - - - - - -

API

-

Description

-

Move

-

Moves the current child window.

-

SetSubWindowSize

-

Sets the size of the current child window.

-
- -### Surface - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

API

-

Description

-

CreateSurfaceAsConsumer

-

Creates a surface for the buffer consumer.

-

CreateSurfaceAsProducer

-

Creates a surface for the buffer producer. Only production-related APIs can be used.

-

GetProducer

-

Obtains an internal IBufferProducer object of Surface.

-

RequestBuffer

-

Requests a SurfaceBuffer object to be produced.

-

CancelBuffer

-

Cancels a SurfaceBuffer object to be produced.

-

FlushBuffer

-

Flushes a produced SurfaceBuffer object with certain information.

-

AcquireBuffer

-

Requests a SurfaceBuffer object to be consumed.

-

ReleaseBuffer

-

Returns a consumed SurfaceBuffer object.

-

GetQueueSize

-

Obtains the number of concurrent buffers.

-

SetQueueSize

-

Sets the number of concurrent buffers.

-

SetDefaultWidthAndHeight

-

Sets the default width and height.

-

GetDefaultWidth

-

Obtains the default width.

-

GetDefaultHeight

-

Obtains the default height.

-

SetUserData

-

Stores string data, which will not be transferred through IPC.

-

GetUserData

-

Obtains string data.

-

RegisterConsumerListener

-

Registers a consumer listener to listen for buffer flush events.

-

UnregisterConsumerListener

-

Unregiseters a consumer listener.

-
- -### SurfaceBuffer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

API

-

Description

-

GetBufferHandle

-

Obtains the BufferHandle pointer to the SurfaceBuffer object.

-

GetWidth

-

Obtains the width of the SurfaceBuffer object.

-

GetHeight

-

Obtains the height of the SurfaceBuffer object.

-

GetFormat

-

Obtains the color format of the SurfaceBuffer object.

-

GetUsage

-

Obtains the usage of the SurfaceBuffer object.

-

GetPhyAddr

-

Obtains the physical address of the SurfaceBuffer object.

-

GetKey

-

Obtains the key of the SurfaceBuffer object.

-

GetVirAddr

-

Obtains the virtual address of the SurfaceBuffer object.

-

GetSize

-

Obtains the size of the SurfaceBuffer object.

-

SetInt32

-

Sets the 32-bit integer for the SurfaceBuffer object.

-

GetInt32

-

Obtains the 32-bit integer for the SurfaceBuffer object.

-

SetInt64

-

Sets the 64-bit integer for the SurfaceBuffer object.

-

GetInt64

-

Obtains the 64-bit integer for the SurfaceBuffer object.

-
- -### VsyncHelper - - - - - - - - - - - - - - - - -

API

-

Description

-

Current

-

Obtains the VsyncHelper object of the current runner.

-

VsyncHelper

-

Constructs a VsyncHelper object using an EventHandler object.

-

RequestFrameCallback

-

Registers a frame callback.

-
- -## Usage - -### Transferring a Producer Surface - -1. Named service - - Service registration: - - ``` - // Obtain a consumer surface. - sptr surface = Surface::CreateSurfaceAsConsumer(); - // Extract the producer object. - sptr producer = surface->GetProducer(); - // Register the service. - auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - sm->AddSystemAbility(IPC_SA_ID, producer->AsObject()); - ``` - - - Construction of a producer surface: - - ``` - // Obtain a producer object. - auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - sptr robj = sm->GetSystemAbility(IPC_SA_ID); - // Construct a surface. - sptr bp = iface_cast(robj); - sptr surface = Surface::CreateSurfaceAsProducer(bp); - ``` - - -2. Anonymous service - - Sending of a surface: - - ``` - // Obtain a consumer surface. - sptr surface = CreateSurfaceAsConsumer(); - // Extract the producer object. - sptr producer = surface->GetProducer(); - // Return the producer object to the client. - parcel.WriteRemoteObject(producer); - ``` - - - -### Creating a Producer Surface - -``` -// Obtain a producer object. -sptr remoteObject = parcel.ReadRemoteObject(); -// Construct a surface. -sptr bp = iface_cast(robj); -sptr surface = Surface::CreateSurfaceAsProducer(bp); -``` - -### Producing a SurfaceBuffer - -``` -// Prerequisite: a producer surface -BufferRequestConfig requestConfig = { - .width = 1920, // Screen width - .height = 1080, // Screen height - .strideAlignment = 8, // Stride alignment byte - .format = PIXEL_FMT_RGBA_8888, // Color format - .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, // Usage - .timeout = 0, // Delay -}; - -sptr buffer; -int32_t releaseFence; - -SurfaceError ret = surface->RequestBuffer(buffer, releaseFence, requestConfig); -if (ret != SURFACE_ERROR_OK) { - // failed -} - -BufferFlushConfig flushConfig = { - .damage = { // Redrawing buffer zone - .x = 0, // Horizontal coordinate of the start point - .y = 0, // Vertical coordinate of the start point - .w = buffer->GetWidth(), // Width of the buffer zone - .h = buffer->GetHeight(), // Height of the buffer zone - }, - .timestamp = 0 // Time displayed to consumers. Value 0 indicates the current time. -}; - -ret = surface->FlushBuffer(buffer, -1, flushConfig); -if (ret != SURFACE_ERROR_OK) { - // failed -} -``` - -### Consuming a SurfaceBuffer - -``` -// Prerequisite: a consumer surface -class TestConsumerListener : public IBufferConsumerListener { -public: - void OnBufferAvailable() override { - sptr buffer; - int32_t flushFence; - SurfaceError ret = surface->AcquireBuffer(buffer, flushFence, timestamp, damage); - if (ret != SURFACE_ERROR_OK) { - // failed - } - // ... - ret = surface->ReleaseBuffer(buffer, -1); - if (ret != SURFACE_ERROR_OK) { - // failed - } - } -}; - -sptr listener = new TestConsumerListener(); -SurfaceError ret = surface->RegisterConsumerListener(listener); -if (ret != SURFACE_ERROR_OK) { - // failed -} -``` - -### Adding Custom Data to a SurfaceBuffer - -``` -sptr buffer; -SurfaceError ret = buffer->SetInt32(1, 3); -if (ret != SURFACE_ERROR_OK) { -// failed -} - -int32_t val; -ret = buffer->GetInt32(1, val); -if (ret != SURFACE_ERROR_OK) { -// failed -} -``` - -### Registering a Vsync Callback Listener - -1. Construct a **VsyncHelper** object using **handler**. - - ``` - auto runner = AppExecFwk::EventRunner::Create(true); - auto handler = std::make_shared(runner); - auto helper = new VsyncHelper(handler); - runner->Run(); - - struct FrameCallback cb = { - .timestamp_ = 0, - .userdata_ = nullptr, - .callback_ = [](int64_t timestamp, void* userdata) { - }, - }; - - VsyncError ret = helper->RequestFrameCallback(cb); - if (ret != VSYNC_ERROR_OK) { - // failed - } - ``` - -2. Use **Current** in **handler**. - - ``` - auto runner = AppExecFwk::EventRunner::Create(true); - auto handler = std::make_shared(runner); - handler->PostTask([]() { - auto helper = VsyncHelper::Current(); - struct FrameCallback cb = { - .timestamp_ = 0, - .userdata_ = nullptr, - .callback_ = [](int64_t timestamp, void* userdata) { - }, - }; - VsyncError ret = helper->RequestFrameCallback(cb); - if (ret != VSYNC_ERROR_OK) { - // failed - } - }); - - runner->Run(); - ``` - - -## Repositories Involved - -Graphics subsystem - -**graphic\_standard** - -ace\_ace\_engine - -aafwk\_L2 - -multimedia\_media\_standard - -multimedia\_camera\_standard - diff --git a/README_zh.md b/README_zh.md index 87d4811f..77182df5 100644 --- a/README_zh.md +++ b/README_zh.md @@ -3,359 +3,60 @@ - [简介](#简介) - [目录](#目录) - [约束](#约束) -- [编译构建](#编译构建) - [接口说明](#接口说明) -- [使用说明](#使用说明) - [相关仓](#相关仓) ## 简介 -**Graphic子系统** 提供了图形接口能力和窗口管理接口能力, +**窗口子系统** 提供窗口管理和Display管理的基础能力,是系统图形界面显示所需的基础子系统 其主要的结构如下图所示: -![Graphic子系统架构图](./figures/graphic.png) +![窗口子系统架构图](./figures/WindowManager.png) -- **Surface** +- **Window Manager Client** - 图形缓冲区管理接口,负责管理图形缓冲区和高效便捷的轮转缓冲区。 + 应用进程窗口管理接口层,提供窗口对对象抽象和窗口管理接口,对接原能力和UI框架。 -- **Vsync** +- **Display Manager Client** - 垂直同步信号管理接口,负责管理所有垂直同步信号注册和响应。 + 应用进程Display管理接口层,提供Display信息抽象和Display管理接口。 -- **WindowManager** +- **Window Manager Server** - 窗口管理器接口,负责创建和管理窗口。 + 窗口管理服务,提供窗口布局、Z序控制、窗口树结构、窗口拖拽、窗口快照等能力,并提供窗口布局和焦点窗口给多模输入 -- **WaylandProtocols** - - 窗口管理器和合成器的通信协议。 - -- **Compositor** - - 合成器,负责合成各个图层。 - -- **Renderer** - - 合成器的后端渲染模块。 - -- **Wayland protocols** - - Wayland 进程间通信协议 - -- **Shell** - - 提供多窗口能力 - -- **Input Manger** - - 多模输入模块,负责接收事件输入 +- **Display Manager Server** + Display管理服务,提供Display信息、屏幕截图、屏幕亮灭和亮度处理控制,并处理Display与Screen映射关系 ## 目录 ``` -foundation/graphic/standard/ -├── frameworks # 框架代码目录 -│ ├── bootanimation # 开机动画目录 -│   ├── surface # Surface代码 -│   ├── vsync # Vsync代码 -│   └── wm # WindowManager代码 +foundation/windowmanager/ +├── dm # Dislplay Manager Client实现代码 +├── dmserver # Dislplay Manager Service实现代码 ├── interfaces # 对外接口存放目录 │   ├── innerkits # native接口存放目录 │   └── kits # js/napi接口存放目录 -└── utils # 小部件存放目录 +├── resources # 框架使用资源文件存放目录 +├── sa_profile # 系统服务配置文件 +├── snapshot # 截屏命令行工具实现代码 +├── utils # 工具类存放目录 +├── wm # Window Manager Client实现代码 +├── wmserver # Window Manager Service实现代码 ``` ## 约束 - 语言版本 - C++11或以上 -## 编译构建 -可以依赖的接口有: -- graphic_standard:libwms_client -- graphic_standard:libsurface -- graphic_standard:libvsync_client - ## 接口说明 -### WindowManager - -| 接口名 | 职责 | -|-----------------|-----------------------------| -| GetInstance | 获取WindowManager的单例指针 | -| GetMaxWidth | 获取当前屏幕宽度 | -| GetMaxHeight | 获取当前屏幕高度 | -| CreateWindow | 创建一个标准窗口 | -| CreateSubWindow | 创建一个子窗口 | -| StartShotScreen | 截屏操作 | -| StartShotWindow | 截取窗口操作 | -| SwitchTop | 将指定窗口调整至最上层显示 | - -### Window -| 接口名 | 职责 | -|-----------------------------|------------------------------| -| Show | 显示当前窗口 | -| Hide | 隐藏当前窗口 | -| Move | 移动当前窗口至指定位置 | -| SwitchTop | 将当前窗口调整到最上层显示 | -| ChangeWindowType | 更改当前窗口类型 | -| ReSize | 调整当前窗口至指定大小 | -| Rotate | 旋转当前窗口 | -| RegistPointerButtonCb | 注册鼠标Button事件回调 | -| RegistPointerEnterCb | 注册鼠标Enter事件回调 | -| RegistPointerLeaveCb | 注册鼠标Leave事件回调 | -| RegistPointerMotionCb | 注册鼠标Motion事件回调 | -| RegistPointerAxisDiscreteCb | 注册鼠标AxisDiscrete事件回调 | -| RegistPointerAxisSourceCb | 注册鼠标AxisSource事件回调 | -| RegistPointerAxisStopCb | 注册鼠标AxisStop事件回调 | -| RegistPointerAxisCb | 注册鼠标Axis事件回调 | -| RegistTouchUpCb | 注册TouchUp事件回调 | -| RegistTouchDownCb | 注册TouchDown事件回调 | -| RegistTouchEmotionCb | 注册TouchEmotion事件回调 | -| RegistTouchFrameCb | 注册TouchFrame事件回调 | -| RegistTouchCancelCb | 注册TouchCancel事件回调 | -| RegistTouchShapeCb | 注册TouchShape事件回调 | -| RegistTouchOrientationCb | 注册TouchOrientation事件回调 | -| RegistKeyboardKeyCb | 注册键盘Key事件回调 | -| RegistKeyboardKeyMapCb | 注册键盘KeyMap事件回调 | -| RegistKeyboardLeaveCb | 注册键盘Leave事件回调 | -| RegistKeyboardEnterCb | 注册键盘Enter事件回调 | -| RegistKeyboardRepeatInfoCb | 注册键盘RepeatInfo事件回调 | - -### SubWindow -| 接口名 | 职责 | -|------------------|--------------------| -| Move | 移动当前子窗口 | -| SetSubWindowSize | 调整当前子窗口位置 | - -### Surface -| 接口名 | 职责 | -|----------------------------|-------------------------------------------------------------------| -| CreateSurfaceAsConsumer | Buffer的消费者来使用该函数创建一个Surface | -| CreateSurfaceAsProducer | Buffer的生产者使用该函数创建一个Surface,只能使用与生产相关的接口 | -| GetProducer | 获得一个Surface内部的IBufferProducer对象 | -| RequestBuffer | 请求一个待生产的SurfaceBuffer对象 | -| CancelBuffer | 取消、归还一个待生产的SurfaceBuffer对象 | -| FlushBuffer | 归还一个生产好的SurfaceBuffer对象并携带一些信息 | -| AcquireBuffer | 请求一个待消费的SurfaceBuffer对象 | -| ReleaseBuffer | 归还一个已消费的SurfaceBuffer对象 | -| GetQueueSize | 获得当前同时能并存buffer的数量 | -| SetQueueSize | 设置当前同时能并存buffer的数量 | -| SetDefaultWidthAndHeight | 设置默认宽和高 | -| GetDefaultWidth | 获得默认宽度 | -| GetDefaultHeight | 获得默认高度 | -| SetUserData | 存贮字符串数据,不随着IPC传递 | -| GetUserData | 取出字符串数据 | -| RegisterConsumerListener | 注册一个消费监听器,监听Buffer的Flush事件 | -| UnregisterConsumerListener | 取消监听 | - -### SurfaceBuffer -| 接口名 | 职责 | -|-----------------|-------------------------------------| -| GetBufferHandle | 获得SurfaceBuffer的BufferHandle指针 | -| GetWidth | 获得SurfaceBuffer的宽度 | -| GetHeight | 获得SurfaceBuffer的高度 | -| GetFormat | 获得SurfaceBuffer的颜色格式 | -| GetUsage | 获得SurfaceBuffer的用途 | -| GetPhyAddr | 获得SurfaceBuffer的物理地址 | -| GetKey | 获得SurfaceBuffer的key | -| GetVirAddr | 获得SurfaceBuffer的虚拟地址 | -| GetSize | 获得SurfaceBuffer的文件句柄 | -| SetInt32 | 获得SurfaceBuffer的缓冲区大小 | -| GetInt32 | 设置SurfaceBuffer的32位整数 | -| SetInt64 | 获得SurfaceBuffer的32位整数 | -| GetInt64 | 设置SurfaceBuffer的64位整数 | - -### VsyncHelper -| 接口名 | 职责 | -|----------------------|-----------------------------------| -| Current | 获取当前runner对应的VsyncHelper | -| VsyncHelper | 用EventHandler对象构造VsyncHelper | -| RequestFrameCallback | 注册一个帧回调 | - -## 使用说明 - -### 具名服务-传递一个生产型Surface - -#### 注册 -```cpp -// 拿到一个消费型Surface -sptr surface = Surface::CreateSurfaceAsConsumer(); - -// 拿出里面的生产者对象 -sptr producer = surface->GetProducer(); - -// 注册服务 -auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); -sm->AddSystemAbility(IPC_SA_ID, producer->AsObject()); -``` - -#### 客户端获得生产型Surface -```cpp -// 获得远程对象 -auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); -sptr robj = sm->GetSystemAbility(IPC_SA_ID); - -// 构造Surface -sptr bp = iface_cast(robj); -sptr surface = Surface::CreateSurfaceAsProducer(bp); -``` - -### 匿名服务-传递一个生产型Surface -场景: 在一次IPC过程中 - -#### 发送 -```cpp -// 拿到一个消费型Surface -sptr surface = CreateSurfaceAsConsumer(); - -// 拿出里面的生产者对象 -sptr producer = surface->GetProducer(); - -// 返回给客户端 -parcel.WriteRemoteObject(producer); -``` - -#### 接受并获得生产型Surface -```cpp -// 获得远程对象 -sptr remoteObject = parcel.ReadRemoteObject(); - -// 构造Surface -sptr bp = iface_cast(robj); -sptr surface = Surface::CreateSurfaceAsProducer(bp); -``` - -### 生产一个SurfaceBuffer -条件: 一个生产型Surface - -```cpp -BufferRequestConfig requestConfig = { - .width = 1920, // 屏幕宽度 - .height = 1080, // 屏幕高度 - .strideAlignment = 8, // stride对齐字节 - .format = PIXEL_FMT_RGBA_8888, // 颜色格式 - .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, // 用法 - .timeout = 0, // 时延 -}; - -sptr buffer; -int32_t releaseFence; - -SurfaceError ret = surface->RequestBuffer(buffer, releaseFence, requestConfig); -if (ret != SURFACE_ERROR_OK) { - // failed -} - -BufferFlushConfig flushConfig = { - .damage = { // 重绘区域 - .x = 0, // 起点横坐标 - .y = 0, // 起点纵坐标 - .w = buffer->GetWidth(), // 区域宽度 - .h = buffer->GetHeight(), // 区域高度 - }, - .timestamp = 0 // 给消费者看的时间,0为使用当前时间 -}; - -ret = surface->FlushBuffer(buffer, -1, flushConfig); -if (ret != SURFACE_ERROR_OK) { - // failed -} -``` - -### 消费一个SurfaceBuffer -条件: 一个消费型Surface - -```cpp -class TestConsumerListener : public IBufferConsumerListener { -public: - void OnBufferAvailable() override { - sptr buffer; - int32_t flushFence; - - SurfaceError ret = surface->AcquireBuffer(buffer, flushFence, timestamp, damage); - if (ret != SURFACE_ERROR_OK) { - // failed - } - - // ... - - ret = surface->ReleaseBuffer(buffer, -1); - if (ret != SURFACE_ERROR_OK) { - // failed - } - } -}; - -sptr listener = new TestConsumerListener(); -SurfaceError ret = surface->RegisterConsumerListener(listener); -if (ret != SURFACE_ERROR_OK) { - // failed -} -``` - -### 给SurfaceBuffer带上自定义数据 -```cpp -sptr buffer; -SurfaceError ret = buffer->SetInt32(1, 3); -if (ret != SURFACE_ERROR_OK) { - // failed -} - -int32_t val; -ret = buffer->GetInt32(1, val); -if (ret != SURFACE_ERROR_OK) { - // failed -} -``` - -### 注册一个Vsync回调事件 -#### 用handler构造VsyncHelper -```cpp -auto runner = AppExecFwk::EventRunner::Create(true); -auto handler = std::make_shared(runner); -auto helper = new VsyncHelper(handler); -runner->Run(); - -struct FrameCallback cb = { - .timestamp_ = 0, - .userdata_ = nullptr, - .callback_ = [](int64_t timestamp, void* userdata) { - }, -}; - -VsyncError ret = helper->RequestFrameCallback(cb); -if (ret != VSYNC_ERROR_OK) { - // failed -} -``` - -#### 在handler里用Current -```cpp -auto runner = AppExecFwk::EventRunner::Create(true); -auto handler = std::make_shared(runner); -handler->PostTask([]() { - auto helper = VsyncHelper::Current(); - struct FrameCallback cb = { - .timestamp_ = 0, - .userdata_ = nullptr, - .callback_ = [](int64_t timestamp, void* userdata) { - }, - }; - - VsyncError ret = helper->RequestFrameCallback(cb); - if (ret != VSYNC_ERROR_OK) { - // failed - } -}); - -runner->Run(); -``` +- [Window](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-window.md) +- [Display](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-display.md) ## 相关仓 -- **graphic_standard** +- graphic_standard - ace_ace_engine - aafwk_standard -- multimedia_media_standard -- multimedia_camera_standard +- multimodalinput_input \ No newline at end of file diff --git a/figures/WindowManager.png b/figures/WindowManager.png new file mode 100644 index 0000000000000000000000000000000000000000..f4f96ea5b71b1f58a604451681981a1e2c3d10d3 GIT binary patch literal 109194 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%0D_XKEOy(oSXnKG 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