From 2b567d543a8864e5138fdd406801043f6ad152b1 Mon Sep 17 00:00:00 2001 From: ShaoboFeng Date: Mon, 29 May 2023 14:27:28 +0800 Subject: [PATCH] Initsinitial Version for window manager module, Fork from OpenHarmony 3.2 --- .../AppDemo/window/immersive/README_zh.md | 14 + .../AppDemo/window/immersive/build.gradle | 34 + .../window/immersive/entry/build.gradle | 21 + .../immersive/entry/src/main/config.json | 70 + .../entry/src/main/ets/MainAbility/app.ets | 23 + .../src/main/ets/MainAbility/pages/index.ets | 46 + .../main/resources/base/element/string.json | 12 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../screenshots/device/immersive.png | Bin 0 -> 15469 bytes .../AppDemo/window/immersive/settings.gradle | 1 + .../AbilityComponent/AppScope/app.json5 | 26 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../AbilityComponent/build-profile.json5 | 42 + .../entry/build-profile.json5 | 25 + .../AbilityComponent/entry/hvigorfile.js | 2 + .../AbilityComponent/entry/package.json | 14 + .../src/main/ets/Application/AbilityStage.ts | 22 + .../src/main/ets/MainAbility/MainAbility.ts | 49 + .../entry/src/main/ets/pages/index.ets | 33 + .../entry/src/main/module.json5 | 52 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../AbilityComponent/hvigorfile.js | 2 + .../AbilityComponent/package.json | 18 + .../window/windowExtension/README_zh.md | 14 + .../WindowExtension/AppScope/app.json5 | 26 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../WindowExtension/build-profile.json5 | 42 + .../WindowExtension/entry/build-profile.json5 | 25 + .../WindowExtension/entry/hvigorfile.js | 2 + .../WindowExtension/entry/package.json | 14 + .../src/main/ets/Application/AbilityStage.ts | 22 + .../src/main/ets/MainAbility/MainAbility.ts | 43 + .../ets/WindowExtAbility/WindowExtAbility.ts | 37 + .../ets/WindowExtAbility/pages/index1.ets | 77 + .../ets/WindowExtAbility/pages/second.ets | 52 + .../entry/src/main/module.json5 | 70 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 6 + .../WindowExtension/hvigorfile.js | 2 + .../WindowExtension/package.json | 18 + .../screenshot/device/Screenshot.jpg | Bin 0 -> 119203 bytes window_manager/LICENSE | 177 + window_manager/OAT.xml | 69 + window_manager/README.md | 2 + window_manager/bundle.json | 138 + window_manager/dm/BUILD.gn | 70 + .../dm/include/display_manager_adapter.h | 108 + .../include/display_manager_agent_default.h | 42 + .../zidl/display_manager_agent_interface.h | 65 + .../zidl/display_manager_agent_proxy.h | 45 + .../include/zidl/display_manager_agent_stub.h | 36 + window_manager/dm/src/display.cpp | 133 + window_manager/dm/src/display_manager.cpp | 869 ++++ .../dm/src/display_manager_adapter.cpp | 404 ++ window_manager/dm/src/screen.cpp | 216 + window_manager/dm/src/screen_group.cpp | 84 + window_manager/dm/src/screen_manager.cpp | 593 +++ .../src/zidl/display_manager_agent_proxy.cpp | 257 ++ .../src/zidl/display_manager_agent_stub.cpp | 128 + window_manager/dm/test/BUILD.gn | 17 + window_manager/dm/test/unittest/BUILD.gn | 171 + .../unittest/display_change_unit_test.cpp | 147 + .../unittest/display_manager_adapter_test.cpp | 227 + .../display_manager_agent_stub_test.cpp | 94 + .../dm/test/unittest/display_manager_test.cpp | 366 ++ .../test/unittest/display_power_unit_test.cpp | 291 ++ .../dm/test/unittest/display_test.cpp | 185 + .../dm/test/unittest/screen_group_test.cpp | 122 + .../dm/test/unittest/screen_manager_test.cpp | 432 ++ .../dm/test/unittest/screen_test.cpp | 233 ++ .../dm/test/unittest/screenshot_test.cpp | 94 + window_manager/dmserver/BUILD.gn | 97 + .../dmserver/include/abstract_display.h | 87 + .../include/abstract_display_controller.h | 82 + .../dmserver/include/abstract_screen.h | 111 + .../include/abstract_screen_controller.h | 153 + .../include/display_cutout_controller.h | 78 + .../dmserver/include/display_dumper.h | 60 + .../display_manager_agent_controller.h | 55 + .../dmserver/include/display_manager_config.h | 50 + .../include/display_manager_interface.h | 130 + .../dmserver/include/display_manager_proxy.h | 86 + .../include/display_manager_service.h | 133 + .../include/display_manager_service_inner.h | 59 + .../dmserver/include/display_manager_stub.h | 33 + .../include/display_power_controller.h | 51 + .../include/screen_rotation_controller.h | 101 + .../dmserver/include/sensor_connector.h | 84 + .../dmserver/src/abstract_display.cpp | 235 ++ .../src/abstract_display_controller.cpp | 678 +++ .../dmserver/src/abstract_screen.cpp | 476 +++ .../src/abstract_screen_controller.cpp | 1277 ++++++ .../src/display_cutout_controller.cpp | 324 ++ .../dmserver/src/display_dumper.cpp | 351 ++ .../src/display_manager_agent_controller.cpp | 193 + .../dmserver/src/display_manager_config.cpp | 228 + .../dmserver/src/display_manager_proxy.cpp | 1106 +++++ .../dmserver/src/display_manager_service.cpp | 709 ++++ .../src/display_manager_service_inner.cpp | 170 + .../dmserver/src/display_manager_stub.cpp | 346 ++ .../dmserver/src/display_power_controller.cpp | 103 + .../src/screen_rotation_controller.cpp | 437 ++ .../dmserver/src/sensor_connector.cpp | 237 ++ window_manager/dmserver/test/BUILD.gn | 17 + .../dmserver/test/unittest/BUILD.gn | 192 + .../abstract_display_controller_test.cpp | 508 +++ .../test/unittest/abstract_display_test.cpp | 97 + .../abstract_screen_controller_test.cpp | 601 +++ .../test/unittest/abstract_screen_test.cpp | 187 + .../display_cutout_controller_test.cpp | 257 ++ .../test/unittest/display_dumper_test.cpp | 350 ++ .../display_manager_agent_controller_test.cpp | 146 + .../unittest/display_manager_config_test.cpp | 167 + .../unittest/display_manager_proxy_test.cpp | 299 ++ .../unittest/display_manager_service_test.cpp | 395 ++ .../screen_rotation_controller_test.cpp | 557 +++ window_manager/etc/BUILD.gn | 36 + window_manager/etc/wms.para | 14 + window_manager/etc/wms.para.dac | 14 + .../extension/extension_connection/BUILD.gn | 61 + .../window_extension_client_stub_impl.h | 39 + .../zidl/window_extension_client_interface.h | 43 + .../zidl/window_extension_client_proxy.h | 38 + .../zidl/window_extension_client_stub.h | 34 + .../src/window_extension_client_stub_impl.cpp | 58 + .../src/window_extension_connection.cpp | 236 ++ .../zidl/window_extension_client_proxy.cpp | 107 + .../src/zidl/window_extension_client_stub.cpp | 70 + .../extension/window_extension/BUILD.gn | 104 + .../include/js_window_extension.h | 97 + .../include/js_window_extension_context.h | 42 + .../include/window_extension.h | 69 + .../include/window_extension_context.h | 50 + .../include/window_extension_module_loader.h | 37 + .../include/window_extension_stub_impl.h | 51 + .../include/zidl/window_extension_interface.h | 48 + .../include/zidl/window_extension_proxy.h | 40 + .../include/zidl/window_extension_stub.h | 34 + .../src/js_window_extension.cpp | 347 ++ .../src/js_window_extension_context.cpp | 162 + .../window_extension/src/window_extension.cpp | 67 + .../src/window_extension_context.cpp | 44 + .../src/window_extension_module_loader.cpp | 52 + .../src/window_extension_stub_impl.cpp | 114 + .../src/zidl/window_extension_proxy.cpp | 101 + .../src/zidl/window_extension_stub.cpp | 65 + .../extension/window_extension/test/BUILD.gn | 17 + .../window_extension/test/unittest/BUILD.gn | 79 + .../unittest/window_extension_proxy_test.cpp | 75 + window_manager/figures/WindowManager.png | Bin 0 -> 125465 bytes window_manager/figures/WindowManager_EN.png | Bin 0 -> 127072 bytes window_manager/hisysevent.yaml | 66 + window_manager/interfaces/innerkits/BUILD.gn | 36 + .../interfaces/innerkits/dm/display.h | 63 + .../interfaces/innerkits/dm/display_manager.h | 90 + .../innerkits/dm/display_property.h | 37 + .../interfaces/innerkits/dm/dm_common.h | 175 + .../interfaces/innerkits/dm/screen.h | 105 + .../interfaces/innerkits/dm/screen_group.h | 53 + .../interfaces/innerkits/dm/screen_manager.h | 84 + .../extension/window_extension_connection.h | 66 + .../interfaces/innerkits/wm/window.h | 481 +++ .../wm/window_accessibility_controller.h | 35 + .../interfaces/innerkits/wm/window_manager.h | 160 + .../interfaces/innerkits/wm/window_option.h | 97 + .../interfaces/innerkits/wm/window_scene.h | 167 + .../interfaces/innerkits/wm/wm_common.h | 446 ++ .../interfaces/kits/js/declaration/BUILD.gn | 29 + .../js/declaration/api/@ohos.display.d.ts | 291 ++ .../js/declaration/api/@ohos.screenshot.d.ts | 89 + window_manager/interfaces/kits/napi/BUILD.gn | 28 + .../interfaces/kits/napi/common/BUILD.gn | 61 + .../kits/napi/common/dm_napi_common.cpp | 129 + .../kits/napi/common/dm_napi_common.h | 150 + .../kits/napi/display_runtime/BUILD.gn | 60 + .../kits/napi/display_runtime/js_display.cpp | 224 + .../kits/napi/display_runtime/js_display.h | 56 + .../display_runtime/js_display_listener.cpp | 165 + .../display_runtime/js_display_listener.h | 50 + .../display_runtime/js_display_manager.cpp | 539 +++ .../napi/display_runtime/js_display_manager.h | 28 + .../display_runtime/js_display_module.cpp | 29 + .../kits/napi/screen_runtime/BUILD.gn | 57 + .../napi/screen_runtime/api/@ohos.screen.d.ts | 243 ++ .../napi/screen_runtime/napi/js_screen.cpp | 309 ++ .../kits/napi/screen_runtime/napi/js_screen.h | 47 + .../napi/js_screen_listener.cpp | 178 + .../screen_runtime/napi/js_screen_listener.h | 49 + .../screen_runtime/napi/js_screen_manager.cpp | 830 ++++ .../screen_runtime/napi/js_screen_manager.h | 28 + .../napi/screen_manager_module.cpp | 29 + .../interfaces/kits/napi/screenshot/BUILD.gn | 40 + .../screenshot/native_screenshot_module.cpp | 346 ++ .../screenshot/native_screenshot_module.h | 19 + .../napi/window_extension_ability/BUILD.gn | 54 + .../window_extension_ability.js | 30 + .../window_extension_ability_module.cpp | 56 + .../napi/window_extension_context/BUILD.gn | 54 + .../window_extension_context.js | 29 + .../window_extension_context_module.cpp | 56 + .../kits/napi/window_runtime/BUILD.gn | 140 + .../napi/window_runtime/api/@ohos.window.d.ts | 1393 +++++++ .../window_manager_napi/js_window_manager.cpp | 907 ++++ .../window_manager_napi/js_window_manager.h | 64 + .../window_manager_module.cpp | 29 + .../window_napi/js_transition_controller.cpp | 245 ++ .../window_napi/js_transition_controller.h | 54 + .../window_runtime/window_napi/js_window.cpp | 3694 +++++++++++++++++ .../window_runtime/window_napi/js_window.h | 208 + .../window_napi/js_window_listener.cpp | 297 ++ .../window_napi/js_window_listener.h | 81 + .../js_window_register_manager.cpp | 303 ++ .../window_napi/js_window_register_manager.h | 60 + .../window_napi/js_window_utils.cpp | 647 +++ .../window_napi/js_window_utils.h | 215 + .../window_runtime/window_stage_napi/BUILD.gn | 55 + .../window_stage_napi/js_window_stage.cpp | 578 +++ .../window_stage_napi/js_window_stage.h | 61 + .../window_stage_napi/window_stage.js | 66 + .../window_stage_napi/window_stage_module.cpp | 57 + window_manager/previewer/BUILD.gn | 133 + .../previewer/include/window_impl.h | 202 + .../previewer/include/window_scene.h | 57 + window_manager/previewer/mock/ability_info.h | 28 + .../previewer/mock/accesstoken_kit.h | 39 + window_manager/previewer/mock/axis_event.h | 27 + .../previewer/mock/bundle_constants.h | 30 + window_manager/previewer/mock/configuration.h | 33 + window_manager/previewer/mock/context.h | 37 + .../previewer/mock/context_container.h | 26 + window_manager/previewer/mock/event_handler.h | 55 + window_manager/previewer/mock/event_queue.h | 36 + window_manager/previewer/mock/event_runner.h | 57 + window_manager/previewer/mock/hilog_wrapper.h | 25 + .../previewer/mock/i_input_event_consumer.h | 35 + window_manager/previewer/mock/input_event.h | 41 + window_manager/previewer/mock/input_manager.h | 43 + .../previewer/mock/input_method_controller.h | 36 + window_manager/previewer/mock/ipc_skeleton.h | 33 + .../previewer/mock/iremote_object.h | 26 + .../mock/js_transition_controller.cpp | 36 + .../previewer/mock/js_transition_controller.h | 35 + .../mock/js_window_register_manager.cpp | 36 + .../mock/js_window_register_manager.h | 42 + window_manager/previewer/mock/key_event.h | 37 + .../previewer/mock/napi_remote_object.h | 30 + window_manager/previewer/mock/parcel.cpp | 99 + window_manager/previewer/mock/parcel.h | 82 + window_manager/previewer/mock/permission.cpp | 41 + window_manager/previewer/mock/permission.h | 32 + window_manager/previewer/mock/pixel_map.h | 27 + .../previewer/mock/pixel_map_napi.cpp | 44 + .../previewer/mock/pixel_map_napi.h | 39 + window_manager/previewer/mock/pointer_event.h | 103 + window_manager/previewer/mock/request_info.h | 38 + .../mock/transaction/rs_interfaces.h | 46 + window_manager/previewer/mock/ui/rs_node.cpp | 64 + window_manager/previewer/mock/ui/rs_node.h | 41 + .../previewer/mock/ui/rs_surface_node.h | 26 + window_manager/previewer/mock/ui/rs_vector4.h | 38 + window_manager/previewer/mock/ui_content.h | 123 + .../previewer/mock/vsync_receiver.h | 53 + window_manager/previewer/mock/window_info.h | 64 + .../previewer/mock/window_manager.h | 41 + .../previewer/mock/window_manager_hilog.h | 46 + window_manager/previewer/src/window_impl.cpp | 762 ++++ window_manager/previewer/src/window_scene.cpp | 115 + window_manager/resources/BUILD.gn | 19 + window_manager/resources/config/BUILD.gn | 46 + .../resources/config/build/BUILD.gn | 33 + .../config/other/display_manager_config.xml | 19 + .../config/other/window_manager_config.xml | 38 + .../config/rk3568/display_manager_config.xml | 57 + .../config/rk3568/window_manager_config.xml | 95 + window_manager/resources/media/BUILD.gn | 26 + .../resources/media/img/bg_place_holder.png | Bin 0 -> 3500 bytes window_manager/sa_profile/4606.xml | 27 + window_manager/sa_profile/4607.xml | 27 + window_manager/sa_profile/BUILD.gn | 22 + window_manager/snapshot/BUILD.gn | 73 + .../snapshot/include/snapshot_utils.h | 70 + .../snapshot/src/snapshot_display.cpp | 87 + .../snapshot/src/snapshot_utils.cpp | 453 ++ window_manager/snapshot/test/BUILD.gn | 17 + .../snapshot/test/unittest/BUILD.gn | 90 + .../test/unittest/snapshot_display_test.cpp | 235 ++ .../test/unittest/snapshot_utils_test.cpp | 325 ++ window_manager/test/BUILD.gn | 21 + .../test/common/mock/iremote_object_mocker.h | 129 + .../test/common/mock/mock_IWindow.h | 56 + .../mock/mock_RSIWindowAnimationController.h | 102 + .../mock/mock_display_manager_adapter.h | 81 + .../mock_rs_iwindow_animation_controller.h | 52 + .../test/common/mock/mock_static_call.h | 34 + .../test/common/mock/mock_uicontent.h | 82 + .../test/common/mock/mock_window_adapter.h | 56 + .../test/common/mock/singleton_mocker.h | 46 + window_manager/test/common/utils/BUILD.gn | 47 + .../common/utils/include/common_test_utils.h | 34 + .../utils/include/screen_manager_utils.h | 34 + .../include/screenshot_listener_future.h | 34 + ...tual_screen_group_change_listener_future.h | 34 + .../common/utils/src/common_test_utils.cpp | 108 + .../common/utils/src/screen_manager_utils.cpp | 40 + window_manager/test/demo/BUILD.gn | 118 + .../test/demo/demo_freeze_display.cpp | 47 + .../test/demo/demo_mirror_screen_listener.cpp | 45 + .../test/demo/demo_screenshot_listener.cpp | 40 + .../demo/demo_snapshot_virtual_screen.cpp | 101 + .../test/demo/demo_system_sub_window.cpp | 111 + window_manager/test/fuzztest/BUILD.gn | 29 + window_manager/test/fuzztest/dms/BUILD.gn | 23 + .../dms/displaymanager_fuzzer/BUILD.gn | 52 + .../dms/displaymanager_fuzzer/corpus/init | 14 + .../displaymanager_fuzzer.cpp | 188 + .../displaymanager_fuzzer.h | 21 + .../dms/displaymanager_fuzzer/project.xml | 25 + .../dms/displaymanageripc_fuzzer/BUILD.gn | 55 + .../dms/displaymanageripc_fuzzer/corpus/init | 14 + .../displaymanageripc_fuzzer.cpp | 230 + .../displaymanageripc_fuzzer.h | 21 + .../dms/displaymanageripc_fuzzer/project.xml | 25 + .../test/fuzztest/dms/screen_fuzzer/BUILD.gn | 55 + .../fuzztest/dms/screen_fuzzer/corpus/init | 14 + .../fuzztest/dms/screen_fuzzer/project.xml | 25 + .../dms/screen_fuzzer/screen_fuzzer.cpp | 186 + .../dms/screen_fuzzer/screen_fuzzer.h | 21 + .../dms/screenmanager_fuzzer/BUILD.gn | 52 + .../dms/screenmanager_fuzzer/corpus/init | 14 + .../dms/screenmanager_fuzzer/project.xml | 25 + .../screenmanager_fuzzer.cpp | 300 ++ .../screenmanager_fuzzer.h | 21 + window_manager/test/fuzztest/wms/BUILD.gn | 28 + .../test/fuzztest/wms/window_fuzzer/BUILD.gn | 82 + .../fuzztest/wms/window_fuzzer/corpus/init | 14 + .../fuzztest/wms/window_fuzzer/project.xml | 25 + .../wms/window_fuzzer/window_fuzzer.cpp | 424 ++ .../wms/window_fuzzer/window_fuzzer.h | 21 + .../fuzztest/wms/windowagent_fuzzer/BUILD.gn | 82 + .../wms/windowagent_fuzzer/corpus/init | 14 + .../wms/windowagent_fuzzer/project.xml | 25 + .../window_agent_fuzzer.cpp | 157 + .../windowagent_fuzzer/window_agent_fuzzer.h | 21 + .../wms/windowcontroller_fuzzer/BUILD.gn | 80 + .../wms/windowcontroller_fuzzer/corpus/init | 14 + .../wms/windowcontroller_fuzzer/project.xml | 25 + .../windowcontroller_fuzzer.cpp | 259 ++ .../windowcontroller_fuzzer.h | 21 + .../fuzztest/wms/windowipc_fuzzer/BUILD.gn | 61 + .../fuzztest/wms/windowipc_fuzzer/corpus/init | 14 + .../fuzztest/wms/windowipc_fuzzer/project.xml | 25 + .../wms/windowipc_fuzzer/windowipc_fuzzer.cpp | 184 + .../wms/windowipc_fuzzer/windowipc_fuzzer.h | 21 + .../wms/windowmanager_fuzzer/BUILD.gn | 54 + .../wms/windowmanager_fuzzer/corpus/init | 14 + .../wms/windowmanager_fuzzer/project.xml | 25 + .../windowmanager_fuzzer.cpp | 184 + .../windowmanager_fuzzer.h | 21 + .../fuzztest/wms/windowpair_fuzzer/BUILD.gn | 85 + .../wms/windowpair_fuzzer/corpus/init | 14 + .../wms/windowpair_fuzzer/project.xml | 25 + .../windowpair_fuzzer/windowpair_fuzzer.cpp | 135 + .../wms/windowpair_fuzzer/windowpair_fuzzer.h | 21 + .../fuzztest/wms/windowroot_fuzzer/BUILD.gn | 89 + .../wms/windowroot_fuzzer/corpus/init | 14 + .../wms/windowroot_fuzzer/project.xml | 25 + .../windowroot_fuzzer/windowroot_fuzzer.cpp | 364 ++ .../wms/windowroot_fuzzer/windowroot_fuzzer.h | 21 + .../fuzztest/wms/windowscene_fuzzer/BUILD.gn | 60 + .../wms/windowscene_fuzzer/corpus/init | 14 + .../wms/windowscene_fuzzer/project.xml | 25 + .../windowscene_fuzzer/windowscene_fuzzer.cpp | 192 + .../windowscene_fuzzer/windowscene_fuzzer.h | 21 + .../wms/windowutilmath_fuzzer/BUILD.gn | 61 + .../wms/windowutilmath_fuzzer/corpus/init | 14 + .../wms/windowutilmath_fuzzer/project.xml | 25 + .../windowutilmath_fuzzer.cpp | 190 + .../windowutilmath_fuzzer.h | 21 + window_manager/test/systemtest/BUILD.gn | 21 + window_manager/test/systemtest/dms/BUILD.gn | 140 + .../systemtest/dms/display_change_test.cpp | 416 ++ .../systemtest/dms/display_manager_test.cpp | 298 ++ .../systemtest/dms/display_minimal_test.cpp | 85 + .../systemtest/dms/display_power_test.cpp | 437 ++ .../systemtest/dms/display_test_utils.cpp | 138 + .../test/systemtest/dms/display_test_utils.h | 76 + .../test/systemtest/dms/screen_gamut_test.cpp | 274 ++ .../systemtest/dms/screen_manager_test.cpp | 812 ++++ .../test/systemtest/dms/screenshot_test.cpp | 249 ++ .../test/systemtest/extension/BUILD.gn | 58 + .../extension/extension_connection_test.cpp | 107 + window_manager/test/systemtest/wms/BUILD.gn | 304 ++ .../wms/window_animation_transition_test.cpp | 174 + .../wms/window_app_floating_window_test.cpp | 421 ++ .../wms/window_dialogwindow_test.cpp | 255 ++ .../wms/window_display_zoom_test.cpp | 274 ++ .../test/systemtest/wms/window_drag_test.cpp | 223 + .../systemtest/wms/window_effect_test.cpp | 203 + .../test/systemtest/wms/window_focus_test.cpp | 483 +++ .../test/systemtest/wms/window_gamut_test.cpp | 148 + .../systemtest/wms/window_immersive_test.cpp | 430 ++ .../wms/window_input_method_test.cpp | 122 + .../test/systemtest/wms/window_input_test.cpp | 173 + .../systemtest/wms/window_layout_test.cpp | 560 +++ .../wms/window_mode_support_info_test.cpp | 208 + .../systemtest/wms/window_move_drag_test.cpp | 320 ++ .../wms/window_multi_ability_test.cpp | 142 + .../wms/window_occupied_area_change_test.cpp | 187 + .../systemtest/wms/window_rotation_test.cpp | 329 ++ .../wms/window_split_immersive_test.cpp | 124 + .../test/systemtest/wms/window_split_test.cpp | 213 + .../systemtest/wms/window_subwindow_test.cpp | 434 ++ .../wms/window_systemsubwindow_test.cpp | 329 ++ .../test/systemtest/wms/window_test_utils.cpp | 476 +++ .../test/systemtest/wms/window_test_utils.h | 93 + .../wms/window_touch_outside_test.cpp | 188 + .../wms/window_visibility_info_test.cpp | 236 ++ window_manager/utils/BUILD.gn | 87 + .../utils/include/agent_death_recipient.h | 34 + window_manager/utils/include/atomic_map.h | 106 + .../utils/include/class_var_definition.h | 103 + .../utils/include/client_agent_container.h | 132 + window_manager/utils/include/cutout_info.h | 85 + .../utils/include/display_change_listener.h | 43 + window_manager/utils/include/display_info.h | 57 + window_manager/utils/include/future.h | 96 + .../utils/include/marshalling_helper.h | 121 + window_manager/utils/include/noncopyable.h | 42 + .../utils/include/perform_reporter.h | 47 + window_manager/utils/include/permission.h | 32 + .../utils/include/rsscreen_change_listener.h | 31 + .../utils/include/screen_group_info.h | 42 + window_manager/utils/include/screen_info.h | 57 + .../utils/include/screenshot_info.h | 39 + .../utils/include/singleton_container.h | 82 + .../utils/include/singleton_delegator.h | 55 + window_manager/utils/include/string_util.h | 29 + .../utils/include/surface_capture_future.h | 55 + window_manager/utils/include/surface_draw.h | 61 + window_manager/utils/include/surface_reader.h | 66 + .../utils/include/surface_reader_handler.h | 34 + .../include/surface_reader_handler_impl.h | 39 + window_manager/utils/include/sys_cap_util.h | 32 + window_manager/utils/include/window_helper.h | 528 +++ .../include/window_info_queried_listener.h | 28 + .../utils/include/window_manager_hilog.h | 52 + .../utils/include/window_property.h | 211 + .../utils/include/window_transition_info.h | 85 + .../utils/include/wm_common_inner.h | 356 ++ window_manager/utils/include/wm_math.h | 244 ++ .../utils/include/wm_occlusion_region.h | 268 ++ .../utils/include/wm_single_instance.h | 43 + .../utils/include/xml_config_base.h | 238 ++ .../utils/src/agent_death_recipient.cpp | 43 + window_manager/utils/src/cutout_info.cpp | 113 + window_manager/utils/src/display_info.cpp | 65 + window_manager/utils/src/perform_reporter.cpp | 114 + window_manager/utils/src/permission.cpp | 106 + .../utils/src/screen_group_info.cpp | 74 + window_manager/utils/src/screen_info.cpp | 91 + window_manager/utils/src/screenshot_info.cpp | 37 + .../utils/src/singleton_container.cpp | 99 + window_manager/utils/src/string_util.cpp | 29 + window_manager/utils/src/surface_draw.cpp | 420 ++ window_manager/utils/src/surface_reader.cpp | 159 + .../utils/src/surface_reader_handler_impl.cpp | 52 + window_manager/utils/src/sys_cap_util.cpp | 77 + window_manager/utils/src/window_property.cpp | 916 ++++ .../utils/src/window_transition_info.cpp | 250 ++ window_manager/utils/src/wm_math.cpp | 360 ++ .../utils/src/wm_occlusion_region.cpp | 324 ++ window_manager/utils/src/xml_config_base.cpp | 23 + window_manager/utils/test/BUILD.gn | 17 + window_manager/utils/test/unittest/BUILD.gn | 210 + .../utils/test/unittest/cutout_info_test.cpp | 66 + .../utils/test/unittest/display_info_test.cpp | 69 + .../test/unittest/perform_reporter_test.cpp | 136 + .../test/unittest/screen_group_info_test.cpp | 77 + .../utils/test/unittest/screen_info_test.cpp | 69 + .../utils/test/unittest/string_util_test.cpp | 65 + .../utils/test/unittest/surface_draw_test.cpp | 217 + .../utils/test/unittest/utils_all_test.cpp | 211 + .../test/unittest/window_helper_test.cpp | 259 ++ .../test/unittest/window_property_test.cpp | 198 + .../unittest/window_transition_info_test.cpp | 117 + .../utils/test/unittest/wm_math_test.cpp | 138 + .../unittest/wm_occlusion_region_test.cpp | 425 ++ window_manager/windowmanager_aafwk.gni | 31 + window_manager/wm/BUILD.gn | 134 + window_manager/wm/include/README.md | 1 + window_manager/wm/include/color_parser.h | 35 + .../wm/include/input_transfer_station.h | 58 + window_manager/wm/include/ressched_report.h | 156 + window_manager/wm/include/static_call.h | 40 + window_manager/wm/include/vsync_station.h | 72 + window_manager/wm/include/window_adapter.h | 88 + window_manager/wm/include/window_agent.h | 55 + .../wm/include/window_frame_trace.h | 51 + window_manager/wm/include/window_impl.h | 585 +++ .../wm/include/window_input_channel.h | 44 + .../wm/include/window_manager_agent.h | 38 + .../wm/include/zidl/window_interface.h | 77 + .../zidl/window_manager_agent_interface.h | 54 + .../include/zidl/window_manager_agent_proxy.h | 42 + .../include/zidl/window_manager_agent_stub.h | 34 + window_manager/wm/include/zidl/window_proxy.h | 56 + window_manager/wm/include/zidl/window_stub.h | 49 + window_manager/wm/src/README.md | 1 + window_manager/wm/src/color_parser.cpp | 67 + .../wm/src/input_transfer_station.cpp | 144 + window_manager/wm/src/static_call.cpp | 33 + window_manager/wm/src/vsync_station.cpp | 111 + window_manager/wm/src/window.cpp | 106 + .../src/window_accessibility_controller.cpp | 39 + window_manager/wm/src/window_adapter.cpp | 313 ++ window_manager/wm/src/window_agent.cpp | 233 ++ .../wm/src/window_frame_trace_impl.cpp | 73 + window_manager/wm/src/window_impl.cpp | 3225 ++++++++++++++ .../wm/src/window_input_channel.cpp | 108 + window_manager/wm/src/window_manager.cpp | 594 +++ .../wm/src/window_manager_agent.cpp | 49 + window_manager/wm/src/window_option.cpp | 224 + window_manager/wm/src/window_scene.cpp | 194 + .../src/zidl/window_manager_agent_proxy.cpp | 175 + .../wm/src/zidl/window_manager_agent_stub.cpp | 103 + window_manager/wm/src/zidl/window_proxy.cpp | 463 +++ window_manager/wm/src/zidl/window_stub.cpp | 157 + window_manager/wm/test/BUILD.gn | 17 + window_manager/wm/test/unittest/BUILD.gn | 214 + .../unittest/input_transfer_station_test.cpp | 85 + .../wm/test/unittest/window_effect_test.cpp | 235 ++ .../unittest/window_impl_listener_test.cpp | 138 + .../wm/test/unittest/window_impl_test.cpp | 3038 ++++++++++++++ .../unittest/window_input_channel_test.cpp | 86 + .../window_manager_agent_proxy_test.cpp | 122 + .../window_manager_agent_stub_test.cpp | 200 + .../wm/test/unittest/window_manager_test.cpp | 402 ++ .../wm/test/unittest/window_option_test.cpp | 366 ++ .../wm/test/unittest/window_proxy_test.cpp | 299 ++ .../wm/test/unittest/window_scene_test.cpp | 419 ++ .../wm/test/unittest/window_stub_test.cpp | 242 ++ .../wm/test/unittest/window_test.cpp | 133 + window_manager/wmserver/BUILD.gn | 122 + window_manager/wmserver/include/README.md | 1 + .../include/accessibility_connection.h | 49 + .../wmserver/include/animation_config.h | 44 + .../wmserver/include/avoid_area_controller.h | 72 + .../include/display_group_controller.h | 86 + .../wmserver/include/display_group_info.h | 58 + .../include/display_zoom_controller.h | 62 + .../wmserver/include/drag_controller.h | 109 + .../wmserver/include/freeze_controller.h | 42 + .../wmserver/include/inner_window.h | 73 + .../wmserver/include/input_window_monitor.h | 52 + .../wmserver/include/memory_guard.h | 27 + .../wmserver/include/minimize_app.h | 69 + .../wmserver/include/remote_animation.h | 108 + .../wmserver/include/starting_window.h | 52 + .../wmserver/include/window_common_event.h | 60 + .../wmserver/include/window_controller.h | 141 + .../wmserver/include/window_dumper.h | 52 + .../wmserver/include/window_inner_manager.h | 83 + .../wmserver/include/window_layout_policy.h | 134 + .../include/window_layout_policy_cascade.h | 84 + .../include/window_layout_policy_tile.h | 58 + .../include/window_manager_agent_controller.h | 48 + .../wmserver/include/window_manager_config.h | 53 + .../wmserver/include/window_manager_service.h | 197 + window_manager/wmserver/include/window_node.h | 168 + .../wmserver/include/window_node_container.h | 200 + .../include/window_node_state_machine.h | 103 + window_manager/wmserver/include/window_pair.h | 257 ++ window_manager/wmserver/include/window_root.h | 176 + .../window_snapshot/snapshot_controller.h | 47 + .../include/window_snapshot/snapshot_proxy.h | 37 + .../include/window_snapshot/snapshot_stub.h | 35 + .../wmserver/include/window_zorder_policy.h | 76 + .../wmserver/include/zidl/ressched_report.h | 44 + .../include/zidl/window_manager_interface.h | 116 + .../include/zidl/window_manager_proxy.h | 75 + .../include/zidl/window_manager_stub.h | 33 + window_manager/wmserver/src/README.md | 1 + .../wmserver/src/accessibility_connection.cpp | 162 + .../wmserver/src/avoid_area_controller.cpp | 362 ++ .../wmserver/src/display_group_controller.cpp | 523 +++ .../wmserver/src/display_group_info.cpp | 181 + .../wmserver/src/display_zoom_controller.cpp | 352 ++ .../wmserver/src/drag_controller.cpp | 483 +++ .../wmserver/src/freeze_controller.cpp | 90 + window_manager/wmserver/src/inner_window.cpp | 142 + .../wmserver/src/input_window_monitor.cpp | 259 ++ window_manager/wmserver/src/memory_guard.cpp | 42 + window_manager/wmserver/src/minimize_app.cpp | 179 + .../wmserver/src/remote_animation.cpp | 910 ++++ .../wmserver/src/starting_window.cpp | 247 ++ .../wmserver/src/window_common_event.cpp | 99 + .../wmserver/src/window_controller.cpp | 1471 +++++++ window_manager/wmserver/src/window_dumper.cpp | 286 ++ .../wmserver/src/window_inner_manager.cpp | 317 ++ .../wmserver/src/window_layout_policy.cpp | 1117 +++++ .../src/window_layout_policy_cascade.cpp | 671 +++ .../src/window_layout_policy_tile.cpp | 374 ++ .../src/window_manager_agent_controller.cpp | 86 + .../wmserver/src/window_manager_config.cpp | 292 ++ .../wmserver/src/window_manager_service.cpp | 1222 ++++++ window_manager/wmserver/src/window_node.cpp | 400 ++ .../wmserver/src/window_node_container.cpp | 2178 ++++++++++ .../src/window_node_state_machine.cpp | 158 + window_manager/wmserver/src/window_pair.cpp | 489 +++ window_manager/wmserver/src/window_root.cpp | 1763 ++++++++ .../window_snapshot/snapshot_controller.cpp | 71 + .../src/window_snapshot/snapshot_proxy.cpp | 53 + .../src/window_snapshot/snapshot_stub.cpp | 56 + .../wmserver/src/window_zorder_policy.cpp | 34 + .../wmserver/src/zidl/ressched_report.cpp | 57 + .../src/zidl/window_manager_proxy.cpp | 840 ++++ .../wmserver/src/zidl/window_manager_stub.cpp | 296 ++ window_manager/wmserver/test/BUILD.gn | 17 + .../wmserver/test/unittest/BUILD.gn | 372 ++ .../accessibility_connection_test.cpp | 147 + .../unittest/avoid_area_controller_test.cpp | 551 +++ .../display_group_controller_test.cpp | 858 ++++ .../test/unittest/display_group_info_test.cpp | 274 ++ .../test/unittest/drag_controller_test.cpp | 442 ++ .../unittest/input_window_monitor_test.cpp | 100 + .../test/unittest/minimize_app_test.cpp | 250 ++ .../test/unittest/remote_animation_test.cpp | 1039 +++++ .../test/unittest/starting_window_test.cpp | 420 ++ .../test/unittest/window_controller_test.cpp | 507 +++ .../window_display_zoom_controller_test.cpp | 88 + .../test/unittest/window_dumper_test.cpp | 192 + .../window_freeze_controller_test.cpp | 87 + .../unittest/window_inner_manager_test.cpp | 175 + .../unittest/window_inner_window_test.cpp | 116 + .../unittest/window_layout_policy_test.cpp | 1381 ++++++ .../unittest/window_manager_config_test.cpp | 254 ++ .../unittest/window_manager_proxy_test.cpp | 225 + .../unittest/window_manager_service_test.cpp | 272 ++ .../test/unittest/window_manager_stub_impl.h | 132 + .../unittest/window_manager_stub_test.cpp | 500 +++ .../unittest/window_node_container_test.cpp | 802 ++++ .../test/unittest/window_node_test.cpp | 868 ++++ .../test/unittest/window_pair_test.cpp | 1158 ++++++ .../test/unittest/window_root_test.cpp | 501 +++ .../test/unittest/window_snapshot_test.cpp | 152 + .../unittest/window_zorder_policy_test.cpp | 73 + 651 files changed, 113203 insertions(+) create mode 100644 window_manager/AppDemo/window/immersive/README_zh.md create mode 100644 window_manager/AppDemo/window/immersive/build.gradle create mode 100644 window_manager/AppDemo/window/immersive/entry/build.gradle create mode 100644 window_manager/AppDemo/window/immersive/entry/src/main/config.json create mode 100644 window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/app.ets create mode 100644 window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/pages/index.ets create mode 100644 window_manager/AppDemo/window/immersive/entry/src/main/resources/base/element/string.json create mode 100644 window_manager/AppDemo/window/immersive/entry/src/main/resources/base/media/icon.png create mode 100644 window_manager/AppDemo/window/immersive/screenshots/device/immersive.png create mode 100644 window_manager/AppDemo/window/immersive/settings.gradle create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/app.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/element/string.json create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/media/app_icon.png create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/build-profile.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/build-profile.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/hvigorfile.js create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/package.json create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/ets/Application/AbilityStage.ts create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/ets/pages/index.ets create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/module.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/resources/base/element/string.json create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/resources/base/media/icon.png create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/entry/src/main/resources/base/profile/main_pages.json create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/hvigorfile.js create mode 100644 window_manager/AppDemo/window/windowExtension/AbilityComponent/package.json create mode 100644 window_manager/AppDemo/window/windowExtension/README_zh.md create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/AppScope/app.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/AppScope/resources/base/element/string.json create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/AppScope/resources/base/media/app_icon.png create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/build-profile.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/build-profile.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/hvigorfile.js create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/package.json create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/Application/AbilityStage.ts create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/WindowExtAbility.ts create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/index1.ets create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/second.ets create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/module.json5 create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/element/string.json create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/media/icon.png create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/profile/main_pages.json create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/hvigorfile.js create mode 100644 window_manager/AppDemo/window/windowExtension/WindowExtension/package.json create mode 100644 window_manager/AppDemo/window/windowExtension/screenshot/device/Screenshot.jpg create mode 100644 window_manager/LICENSE create mode 100644 window_manager/OAT.xml create mode 100644 window_manager/bundle.json create mode 100644 window_manager/dm/BUILD.gn create mode 100644 window_manager/dm/include/display_manager_adapter.h create mode 100644 window_manager/dm/include/display_manager_agent_default.h create mode 100644 window_manager/dm/include/zidl/display_manager_agent_interface.h create mode 100644 window_manager/dm/include/zidl/display_manager_agent_proxy.h create mode 100644 window_manager/dm/include/zidl/display_manager_agent_stub.h create mode 100644 window_manager/dm/src/display.cpp create mode 100644 window_manager/dm/src/display_manager.cpp create mode 100644 window_manager/dm/src/display_manager_adapter.cpp create mode 100644 window_manager/dm/src/screen.cpp create mode 100644 window_manager/dm/src/screen_group.cpp create mode 100644 window_manager/dm/src/screen_manager.cpp create mode 100644 window_manager/dm/src/zidl/display_manager_agent_proxy.cpp create mode 100644 window_manager/dm/src/zidl/display_manager_agent_stub.cpp create mode 100644 window_manager/dm/test/BUILD.gn create mode 100644 window_manager/dm/test/unittest/BUILD.gn create mode 100644 window_manager/dm/test/unittest/display_change_unit_test.cpp create mode 100644 window_manager/dm/test/unittest/display_manager_adapter_test.cpp create mode 100644 window_manager/dm/test/unittest/display_manager_agent_stub_test.cpp create mode 100644 window_manager/dm/test/unittest/display_manager_test.cpp create mode 100644 window_manager/dm/test/unittest/display_power_unit_test.cpp create mode 100644 window_manager/dm/test/unittest/display_test.cpp create mode 100644 window_manager/dm/test/unittest/screen_group_test.cpp create mode 100644 window_manager/dm/test/unittest/screen_manager_test.cpp create mode 100644 window_manager/dm/test/unittest/screen_test.cpp create mode 100644 window_manager/dm/test/unittest/screenshot_test.cpp create mode 100644 window_manager/dmserver/BUILD.gn create mode 100644 window_manager/dmserver/include/abstract_display.h create mode 100644 window_manager/dmserver/include/abstract_display_controller.h create mode 100644 window_manager/dmserver/include/abstract_screen.h create mode 100644 window_manager/dmserver/include/abstract_screen_controller.h create mode 100644 window_manager/dmserver/include/display_cutout_controller.h create mode 100644 window_manager/dmserver/include/display_dumper.h create mode 100644 window_manager/dmserver/include/display_manager_agent_controller.h create mode 100644 window_manager/dmserver/include/display_manager_config.h create mode 100644 window_manager/dmserver/include/display_manager_interface.h create mode 100644 window_manager/dmserver/include/display_manager_proxy.h create mode 100644 window_manager/dmserver/include/display_manager_service.h create mode 100644 window_manager/dmserver/include/display_manager_service_inner.h create mode 100644 window_manager/dmserver/include/display_manager_stub.h create mode 100644 window_manager/dmserver/include/display_power_controller.h create mode 100644 window_manager/dmserver/include/screen_rotation_controller.h create mode 100644 window_manager/dmserver/include/sensor_connector.h create mode 100644 window_manager/dmserver/src/abstract_display.cpp create mode 100644 window_manager/dmserver/src/abstract_display_controller.cpp create mode 100644 window_manager/dmserver/src/abstract_screen.cpp create mode 100644 window_manager/dmserver/src/abstract_screen_controller.cpp create mode 100644 window_manager/dmserver/src/display_cutout_controller.cpp create mode 100644 window_manager/dmserver/src/display_dumper.cpp create mode 100644 window_manager/dmserver/src/display_manager_agent_controller.cpp create mode 100644 window_manager/dmserver/src/display_manager_config.cpp create mode 100644 window_manager/dmserver/src/display_manager_proxy.cpp create mode 100644 window_manager/dmserver/src/display_manager_service.cpp create mode 100644 window_manager/dmserver/src/display_manager_service_inner.cpp create mode 100644 window_manager/dmserver/src/display_manager_stub.cpp create mode 100644 window_manager/dmserver/src/display_power_controller.cpp create mode 100644 window_manager/dmserver/src/screen_rotation_controller.cpp create mode 100644 window_manager/dmserver/src/sensor_connector.cpp create mode 100644 window_manager/dmserver/test/BUILD.gn create mode 100644 window_manager/dmserver/test/unittest/BUILD.gn create mode 100644 window_manager/dmserver/test/unittest/abstract_display_controller_test.cpp create mode 100644 window_manager/dmserver/test/unittest/abstract_display_test.cpp create mode 100644 window_manager/dmserver/test/unittest/abstract_screen_controller_test.cpp create mode 100644 window_manager/dmserver/test/unittest/abstract_screen_test.cpp create mode 100644 window_manager/dmserver/test/unittest/display_cutout_controller_test.cpp create mode 100644 window_manager/dmserver/test/unittest/display_dumper_test.cpp create mode 100644 window_manager/dmserver/test/unittest/display_manager_agent_controller_test.cpp create mode 100644 window_manager/dmserver/test/unittest/display_manager_config_test.cpp create mode 100644 window_manager/dmserver/test/unittest/display_manager_proxy_test.cpp create mode 100644 window_manager/dmserver/test/unittest/display_manager_service_test.cpp create mode 100644 window_manager/dmserver/test/unittest/screen_rotation_controller_test.cpp create mode 100644 window_manager/etc/BUILD.gn create mode 100644 window_manager/etc/wms.para create mode 100644 window_manager/etc/wms.para.dac create mode 100644 window_manager/extension/extension_connection/BUILD.gn create mode 100644 window_manager/extension/extension_connection/include/window_extension_client_stub_impl.h create mode 100644 window_manager/extension/extension_connection/include/zidl/window_extension_client_interface.h create mode 100644 window_manager/extension/extension_connection/include/zidl/window_extension_client_proxy.h create mode 100644 window_manager/extension/extension_connection/include/zidl/window_extension_client_stub.h create mode 100644 window_manager/extension/extension_connection/src/window_extension_client_stub_impl.cpp create mode 100644 window_manager/extension/extension_connection/src/window_extension_connection.cpp create mode 100644 window_manager/extension/extension_connection/src/zidl/window_extension_client_proxy.cpp create mode 100644 window_manager/extension/extension_connection/src/zidl/window_extension_client_stub.cpp create mode 100644 window_manager/extension/window_extension/BUILD.gn create mode 100644 window_manager/extension/window_extension/include/js_window_extension.h create mode 100644 window_manager/extension/window_extension/include/js_window_extension_context.h create mode 100644 window_manager/extension/window_extension/include/window_extension.h create mode 100644 window_manager/extension/window_extension/include/window_extension_context.h create mode 100644 window_manager/extension/window_extension/include/window_extension_module_loader.h create mode 100644 window_manager/extension/window_extension/include/window_extension_stub_impl.h create mode 100644 window_manager/extension/window_extension/include/zidl/window_extension_interface.h create mode 100644 window_manager/extension/window_extension/include/zidl/window_extension_proxy.h create mode 100644 window_manager/extension/window_extension/include/zidl/window_extension_stub.h create mode 100644 window_manager/extension/window_extension/src/js_window_extension.cpp create mode 100644 window_manager/extension/window_extension/src/js_window_extension_context.cpp create mode 100644 window_manager/extension/window_extension/src/window_extension.cpp create mode 100644 window_manager/extension/window_extension/src/window_extension_context.cpp create mode 100644 window_manager/extension/window_extension/src/window_extension_module_loader.cpp create mode 100644 window_manager/extension/window_extension/src/window_extension_stub_impl.cpp create mode 100644 window_manager/extension/window_extension/src/zidl/window_extension_proxy.cpp create mode 100644 window_manager/extension/window_extension/src/zidl/window_extension_stub.cpp create mode 100644 window_manager/extension/window_extension/test/BUILD.gn create mode 100644 window_manager/extension/window_extension/test/unittest/BUILD.gn create mode 100644 window_manager/extension/window_extension/test/unittest/window_extension_proxy_test.cpp create mode 100644 window_manager/figures/WindowManager.png create mode 100644 window_manager/figures/WindowManager_EN.png create mode 100644 window_manager/hisysevent.yaml create mode 100644 window_manager/interfaces/innerkits/BUILD.gn create mode 100644 window_manager/interfaces/innerkits/dm/display.h create mode 100644 window_manager/interfaces/innerkits/dm/display_manager.h create mode 100644 window_manager/interfaces/innerkits/dm/display_property.h create mode 100644 window_manager/interfaces/innerkits/dm/dm_common.h create mode 100644 window_manager/interfaces/innerkits/dm/screen.h create mode 100644 window_manager/interfaces/innerkits/dm/screen_group.h create mode 100644 window_manager/interfaces/innerkits/dm/screen_manager.h create mode 100644 window_manager/interfaces/innerkits/extension/window_extension_connection.h create mode 100644 window_manager/interfaces/innerkits/wm/window.h create mode 100644 window_manager/interfaces/innerkits/wm/window_accessibility_controller.h create mode 100644 window_manager/interfaces/innerkits/wm/window_manager.h create mode 100644 window_manager/interfaces/innerkits/wm/window_option.h create mode 100644 window_manager/interfaces/innerkits/wm/window_scene.h create mode 100644 window_manager/interfaces/innerkits/wm/wm_common.h create mode 100644 window_manager/interfaces/kits/js/declaration/BUILD.gn create mode 100644 window_manager/interfaces/kits/js/declaration/api/@ohos.display.d.ts create mode 100644 window_manager/interfaces/kits/js/declaration/api/@ohos.screenshot.d.ts create mode 100644 window_manager/interfaces/kits/napi/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/common/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/common/dm_napi_common.cpp create mode 100644 window_manager/interfaces/kits/napi/common/dm_napi_common.h create mode 100644 window_manager/interfaces/kits/napi/display_runtime/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display.cpp create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display.h create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display_listener.cpp create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display_listener.h create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display_manager.cpp create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display_manager.h create mode 100644 window_manager/interfaces/kits/napi/display_runtime/js_display_module.cpp create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/api/@ohos.screen.d.ts create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.cpp create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.h create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.cpp create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.h create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.cpp create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.h create mode 100644 window_manager/interfaces/kits/napi/screen_runtime/napi/screen_manager_module.cpp create mode 100644 window_manager/interfaces/kits/napi/screenshot/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.cpp create mode 100644 window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.h create mode 100644 window_manager/interfaces/kits/napi/window_extension_ability/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability.js create mode 100644 window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability_module.cpp create mode 100644 window_manager/interfaces/kits/napi/window_extension_context/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/window_extension_context/window_extension_context.js create mode 100644 window_manager/interfaces/kits/napi/window_extension_context/window_extension_context_module.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/window_manager_module.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/BUILD.gn create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage.js create mode 100644 window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage_module.cpp create mode 100644 window_manager/previewer/BUILD.gn create mode 100644 window_manager/previewer/include/window_impl.h create mode 100644 window_manager/previewer/include/window_scene.h create mode 100644 window_manager/previewer/mock/ability_info.h create mode 100644 window_manager/previewer/mock/accesstoken_kit.h create mode 100644 window_manager/previewer/mock/axis_event.h create mode 100644 window_manager/previewer/mock/bundle_constants.h create mode 100644 window_manager/previewer/mock/configuration.h create mode 100644 window_manager/previewer/mock/context.h create mode 100644 window_manager/previewer/mock/context_container.h create mode 100644 window_manager/previewer/mock/event_handler.h create mode 100644 window_manager/previewer/mock/event_queue.h create mode 100644 window_manager/previewer/mock/event_runner.h create mode 100644 window_manager/previewer/mock/hilog_wrapper.h create mode 100644 window_manager/previewer/mock/i_input_event_consumer.h create mode 100644 window_manager/previewer/mock/input_event.h create mode 100644 window_manager/previewer/mock/input_manager.h create mode 100644 window_manager/previewer/mock/input_method_controller.h create mode 100644 window_manager/previewer/mock/ipc_skeleton.h create mode 100644 window_manager/previewer/mock/iremote_object.h create mode 100644 window_manager/previewer/mock/js_transition_controller.cpp create mode 100644 window_manager/previewer/mock/js_transition_controller.h create mode 100644 window_manager/previewer/mock/js_window_register_manager.cpp create mode 100644 window_manager/previewer/mock/js_window_register_manager.h create mode 100644 window_manager/previewer/mock/key_event.h create mode 100644 window_manager/previewer/mock/napi_remote_object.h create mode 100644 window_manager/previewer/mock/parcel.cpp create mode 100644 window_manager/previewer/mock/parcel.h create mode 100644 window_manager/previewer/mock/permission.cpp create mode 100644 window_manager/previewer/mock/permission.h create mode 100644 window_manager/previewer/mock/pixel_map.h create mode 100644 window_manager/previewer/mock/pixel_map_napi.cpp create mode 100644 window_manager/previewer/mock/pixel_map_napi.h create mode 100644 window_manager/previewer/mock/pointer_event.h create mode 100644 window_manager/previewer/mock/request_info.h create mode 100644 window_manager/previewer/mock/transaction/rs_interfaces.h create mode 100644 window_manager/previewer/mock/ui/rs_node.cpp create mode 100644 window_manager/previewer/mock/ui/rs_node.h create mode 100644 window_manager/previewer/mock/ui/rs_surface_node.h create mode 100644 window_manager/previewer/mock/ui/rs_vector4.h create mode 100644 window_manager/previewer/mock/ui_content.h create mode 100644 window_manager/previewer/mock/vsync_receiver.h create mode 100644 window_manager/previewer/mock/window_info.h create mode 100644 window_manager/previewer/mock/window_manager.h create mode 100644 window_manager/previewer/mock/window_manager_hilog.h create mode 100644 window_manager/previewer/src/window_impl.cpp create mode 100644 window_manager/previewer/src/window_scene.cpp create mode 100644 window_manager/resources/BUILD.gn create mode 100644 window_manager/resources/config/BUILD.gn create mode 100644 window_manager/resources/config/build/BUILD.gn create mode 100644 window_manager/resources/config/other/display_manager_config.xml create mode 100644 window_manager/resources/config/other/window_manager_config.xml create mode 100644 window_manager/resources/config/rk3568/display_manager_config.xml create mode 100644 window_manager/resources/config/rk3568/window_manager_config.xml create mode 100644 window_manager/resources/media/BUILD.gn create mode 100644 window_manager/resources/media/img/bg_place_holder.png create mode 100644 window_manager/sa_profile/4606.xml create mode 100644 window_manager/sa_profile/4607.xml create mode 100644 window_manager/sa_profile/BUILD.gn create mode 100644 window_manager/snapshot/BUILD.gn create mode 100644 window_manager/snapshot/include/snapshot_utils.h create mode 100644 window_manager/snapshot/src/snapshot_display.cpp create mode 100644 window_manager/snapshot/src/snapshot_utils.cpp create mode 100644 window_manager/snapshot/test/BUILD.gn create mode 100644 window_manager/snapshot/test/unittest/BUILD.gn create mode 100644 window_manager/snapshot/test/unittest/snapshot_display_test.cpp create mode 100644 window_manager/snapshot/test/unittest/snapshot_utils_test.cpp create mode 100644 window_manager/test/BUILD.gn create mode 100644 window_manager/test/common/mock/iremote_object_mocker.h create mode 100644 window_manager/test/common/mock/mock_IWindow.h create mode 100644 window_manager/test/common/mock/mock_RSIWindowAnimationController.h create mode 100644 window_manager/test/common/mock/mock_display_manager_adapter.h create mode 100644 window_manager/test/common/mock/mock_rs_iwindow_animation_controller.h create mode 100644 window_manager/test/common/mock/mock_static_call.h create mode 100644 window_manager/test/common/mock/mock_uicontent.h create mode 100644 window_manager/test/common/mock/mock_window_adapter.h create mode 100644 window_manager/test/common/mock/singleton_mocker.h create mode 100644 window_manager/test/common/utils/BUILD.gn create mode 100644 window_manager/test/common/utils/include/common_test_utils.h create mode 100644 window_manager/test/common/utils/include/screen_manager_utils.h create mode 100644 window_manager/test/common/utils/include/screenshot_listener_future.h create mode 100644 window_manager/test/common/utils/include/virtual_screen_group_change_listener_future.h create mode 100644 window_manager/test/common/utils/src/common_test_utils.cpp create mode 100644 window_manager/test/common/utils/src/screen_manager_utils.cpp create mode 100644 window_manager/test/demo/BUILD.gn create mode 100644 window_manager/test/demo/demo_freeze_display.cpp create mode 100644 window_manager/test/demo/demo_mirror_screen_listener.cpp create mode 100644 window_manager/test/demo/demo_screenshot_listener.cpp create mode 100644 window_manager/test/demo/demo_snapshot_virtual_screen.cpp create mode 100644 window_manager/test/demo/demo_system_sub_window.cpp create mode 100644 window_manager/test/fuzztest/BUILD.gn create mode 100644 window_manager/test/fuzztest/dms/BUILD.gn create mode 100644 window_manager/test/fuzztest/dms/displaymanager_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/dms/displaymanager_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.h create mode 100644 window_manager/test/fuzztest/dms/displaymanager_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.h create mode 100644 window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/dms/screen_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/dms/screen_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/dms/screen_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.h create mode 100644 window_manager/test/fuzztest/dms/screenmanager_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/dms/screenmanager_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/dms/screenmanager_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/window_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/window_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/window_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowagent_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowagent_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowagent_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowcontroller_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowcontroller_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowcontroller_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowipc_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowipc_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowipc_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowmanager_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowmanager_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowmanager_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowpair_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowpair_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowpair_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowroot_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowroot_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowroot_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowscene_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowscene_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowscene_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.h create mode 100644 window_manager/test/fuzztest/wms/windowutilmath_fuzzer/BUILD.gn create mode 100644 window_manager/test/fuzztest/wms/windowutilmath_fuzzer/corpus/init create mode 100644 window_manager/test/fuzztest/wms/windowutilmath_fuzzer/project.xml create mode 100644 window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.cpp create mode 100644 window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.h create mode 100644 window_manager/test/systemtest/BUILD.gn create mode 100644 window_manager/test/systemtest/dms/BUILD.gn create mode 100644 window_manager/test/systemtest/dms/display_change_test.cpp create mode 100644 window_manager/test/systemtest/dms/display_manager_test.cpp create mode 100644 window_manager/test/systemtest/dms/display_minimal_test.cpp create mode 100644 window_manager/test/systemtest/dms/display_power_test.cpp create mode 100644 window_manager/test/systemtest/dms/display_test_utils.cpp create mode 100644 window_manager/test/systemtest/dms/display_test_utils.h create mode 100644 window_manager/test/systemtest/dms/screen_gamut_test.cpp create mode 100644 window_manager/test/systemtest/dms/screen_manager_test.cpp create mode 100644 window_manager/test/systemtest/dms/screenshot_test.cpp create mode 100644 window_manager/test/systemtest/extension/BUILD.gn create mode 100644 window_manager/test/systemtest/extension/extension_connection_test.cpp create mode 100644 window_manager/test/systemtest/wms/BUILD.gn create mode 100644 window_manager/test/systemtest/wms/window_animation_transition_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_app_floating_window_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_dialogwindow_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_display_zoom_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_drag_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_effect_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_focus_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_gamut_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_immersive_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_input_method_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_input_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_layout_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_mode_support_info_test.cpp create mode 100755 window_manager/test/systemtest/wms/window_move_drag_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_multi_ability_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_occupied_area_change_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_rotation_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_split_immersive_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_split_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_subwindow_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_systemsubwindow_test.cpp create mode 100755 window_manager/test/systemtest/wms/window_test_utils.cpp create mode 100644 window_manager/test/systemtest/wms/window_test_utils.h create mode 100644 window_manager/test/systemtest/wms/window_touch_outside_test.cpp create mode 100644 window_manager/test/systemtest/wms/window_visibility_info_test.cpp create mode 100644 window_manager/utils/BUILD.gn create mode 100644 window_manager/utils/include/agent_death_recipient.h create mode 100644 window_manager/utils/include/atomic_map.h create mode 100644 window_manager/utils/include/class_var_definition.h create mode 100644 window_manager/utils/include/client_agent_container.h create mode 100644 window_manager/utils/include/cutout_info.h create mode 100644 window_manager/utils/include/display_change_listener.h create mode 100644 window_manager/utils/include/display_info.h create mode 100644 window_manager/utils/include/future.h create mode 100644 window_manager/utils/include/marshalling_helper.h create mode 100644 window_manager/utils/include/noncopyable.h create mode 100644 window_manager/utils/include/perform_reporter.h create mode 100644 window_manager/utils/include/permission.h create mode 100644 window_manager/utils/include/rsscreen_change_listener.h create mode 100644 window_manager/utils/include/screen_group_info.h create mode 100644 window_manager/utils/include/screen_info.h create mode 100644 window_manager/utils/include/screenshot_info.h create mode 100644 window_manager/utils/include/singleton_container.h create mode 100644 window_manager/utils/include/singleton_delegator.h create mode 100644 window_manager/utils/include/string_util.h create mode 100644 window_manager/utils/include/surface_capture_future.h create mode 100644 window_manager/utils/include/surface_draw.h create mode 100644 window_manager/utils/include/surface_reader.h create mode 100644 window_manager/utils/include/surface_reader_handler.h create mode 100644 window_manager/utils/include/surface_reader_handler_impl.h create mode 100644 window_manager/utils/include/sys_cap_util.h create mode 100644 window_manager/utils/include/window_helper.h create mode 100644 window_manager/utils/include/window_info_queried_listener.h create mode 100644 window_manager/utils/include/window_manager_hilog.h create mode 100644 window_manager/utils/include/window_property.h create mode 100644 window_manager/utils/include/window_transition_info.h create mode 100644 window_manager/utils/include/wm_common_inner.h create mode 100644 window_manager/utils/include/wm_math.h create mode 100644 window_manager/utils/include/wm_occlusion_region.h create mode 100644 window_manager/utils/include/wm_single_instance.h create mode 100644 window_manager/utils/include/xml_config_base.h create mode 100644 window_manager/utils/src/agent_death_recipient.cpp create mode 100644 window_manager/utils/src/cutout_info.cpp create mode 100644 window_manager/utils/src/display_info.cpp create mode 100644 window_manager/utils/src/perform_reporter.cpp create mode 100644 window_manager/utils/src/permission.cpp create mode 100644 window_manager/utils/src/screen_group_info.cpp create mode 100644 window_manager/utils/src/screen_info.cpp create mode 100644 window_manager/utils/src/screenshot_info.cpp create mode 100644 window_manager/utils/src/singleton_container.cpp create mode 100644 window_manager/utils/src/string_util.cpp create mode 100644 window_manager/utils/src/surface_draw.cpp create mode 100644 window_manager/utils/src/surface_reader.cpp create mode 100644 window_manager/utils/src/surface_reader_handler_impl.cpp create mode 100644 window_manager/utils/src/sys_cap_util.cpp create mode 100644 window_manager/utils/src/window_property.cpp create mode 100644 window_manager/utils/src/window_transition_info.cpp create mode 100644 window_manager/utils/src/wm_math.cpp create mode 100644 window_manager/utils/src/wm_occlusion_region.cpp create mode 100644 window_manager/utils/src/xml_config_base.cpp create mode 100644 window_manager/utils/test/BUILD.gn create mode 100644 window_manager/utils/test/unittest/BUILD.gn create mode 100644 window_manager/utils/test/unittest/cutout_info_test.cpp create mode 100644 window_manager/utils/test/unittest/display_info_test.cpp create mode 100644 window_manager/utils/test/unittest/perform_reporter_test.cpp create mode 100644 window_manager/utils/test/unittest/screen_group_info_test.cpp create mode 100644 window_manager/utils/test/unittest/screen_info_test.cpp create mode 100644 window_manager/utils/test/unittest/string_util_test.cpp create mode 100644 window_manager/utils/test/unittest/surface_draw_test.cpp create mode 100644 window_manager/utils/test/unittest/utils_all_test.cpp create mode 100644 window_manager/utils/test/unittest/window_helper_test.cpp create mode 100644 window_manager/utils/test/unittest/window_property_test.cpp create mode 100644 window_manager/utils/test/unittest/window_transition_info_test.cpp create mode 100644 window_manager/utils/test/unittest/wm_math_test.cpp create mode 100644 window_manager/utils/test/unittest/wm_occlusion_region_test.cpp create mode 100644 window_manager/windowmanager_aafwk.gni create mode 100644 window_manager/wm/BUILD.gn create mode 100644 window_manager/wm/include/README.md create mode 100644 window_manager/wm/include/color_parser.h create mode 100644 window_manager/wm/include/input_transfer_station.h create mode 100644 window_manager/wm/include/ressched_report.h create mode 100644 window_manager/wm/include/static_call.h create mode 100644 window_manager/wm/include/vsync_station.h create mode 100644 window_manager/wm/include/window_adapter.h create mode 100644 window_manager/wm/include/window_agent.h create mode 100644 window_manager/wm/include/window_frame_trace.h create mode 100644 window_manager/wm/include/window_impl.h create mode 100644 window_manager/wm/include/window_input_channel.h create mode 100644 window_manager/wm/include/window_manager_agent.h create mode 100644 window_manager/wm/include/zidl/window_interface.h create mode 100644 window_manager/wm/include/zidl/window_manager_agent_interface.h create mode 100644 window_manager/wm/include/zidl/window_manager_agent_proxy.h create mode 100644 window_manager/wm/include/zidl/window_manager_agent_stub.h create mode 100644 window_manager/wm/include/zidl/window_proxy.h create mode 100644 window_manager/wm/include/zidl/window_stub.h create mode 100644 window_manager/wm/src/README.md create mode 100644 window_manager/wm/src/color_parser.cpp create mode 100644 window_manager/wm/src/input_transfer_station.cpp create mode 100644 window_manager/wm/src/static_call.cpp create mode 100644 window_manager/wm/src/vsync_station.cpp create mode 100644 window_manager/wm/src/window.cpp create mode 100644 window_manager/wm/src/window_accessibility_controller.cpp create mode 100644 window_manager/wm/src/window_adapter.cpp create mode 100644 window_manager/wm/src/window_agent.cpp create mode 100644 window_manager/wm/src/window_frame_trace_impl.cpp create mode 100755 window_manager/wm/src/window_impl.cpp create mode 100644 window_manager/wm/src/window_input_channel.cpp create mode 100644 window_manager/wm/src/window_manager.cpp create mode 100644 window_manager/wm/src/window_manager_agent.cpp create mode 100644 window_manager/wm/src/window_option.cpp create mode 100644 window_manager/wm/src/window_scene.cpp create mode 100644 window_manager/wm/src/zidl/window_manager_agent_proxy.cpp create mode 100644 window_manager/wm/src/zidl/window_manager_agent_stub.cpp create mode 100644 window_manager/wm/src/zidl/window_proxy.cpp create mode 100644 window_manager/wm/src/zidl/window_stub.cpp create mode 100644 window_manager/wm/test/BUILD.gn create mode 100644 window_manager/wm/test/unittest/BUILD.gn create mode 100644 window_manager/wm/test/unittest/input_transfer_station_test.cpp create mode 100644 window_manager/wm/test/unittest/window_effect_test.cpp create mode 100644 window_manager/wm/test/unittest/window_impl_listener_test.cpp create mode 100644 window_manager/wm/test/unittest/window_impl_test.cpp create mode 100644 window_manager/wm/test/unittest/window_input_channel_test.cpp create mode 100644 window_manager/wm/test/unittest/window_manager_agent_proxy_test.cpp create mode 100644 window_manager/wm/test/unittest/window_manager_agent_stub_test.cpp create mode 100644 window_manager/wm/test/unittest/window_manager_test.cpp create mode 100644 window_manager/wm/test/unittest/window_option_test.cpp create mode 100644 window_manager/wm/test/unittest/window_proxy_test.cpp create mode 100644 window_manager/wm/test/unittest/window_scene_test.cpp create mode 100644 window_manager/wm/test/unittest/window_stub_test.cpp create mode 100644 window_manager/wm/test/unittest/window_test.cpp create mode 100644 window_manager/wmserver/BUILD.gn create mode 100644 window_manager/wmserver/include/README.md create mode 100644 window_manager/wmserver/include/accessibility_connection.h create mode 100644 window_manager/wmserver/include/animation_config.h create mode 100644 window_manager/wmserver/include/avoid_area_controller.h create mode 100644 window_manager/wmserver/include/display_group_controller.h create mode 100644 window_manager/wmserver/include/display_group_info.h create mode 100644 window_manager/wmserver/include/display_zoom_controller.h create mode 100644 window_manager/wmserver/include/drag_controller.h create mode 100644 window_manager/wmserver/include/freeze_controller.h create mode 100644 window_manager/wmserver/include/inner_window.h create mode 100644 window_manager/wmserver/include/input_window_monitor.h create mode 100644 window_manager/wmserver/include/memory_guard.h create mode 100644 window_manager/wmserver/include/minimize_app.h create mode 100644 window_manager/wmserver/include/remote_animation.h create mode 100644 window_manager/wmserver/include/starting_window.h create mode 100644 window_manager/wmserver/include/window_common_event.h create mode 100644 window_manager/wmserver/include/window_controller.h create mode 100644 window_manager/wmserver/include/window_dumper.h create mode 100644 window_manager/wmserver/include/window_inner_manager.h create mode 100644 window_manager/wmserver/include/window_layout_policy.h create mode 100644 window_manager/wmserver/include/window_layout_policy_cascade.h create mode 100644 window_manager/wmserver/include/window_layout_policy_tile.h create mode 100644 window_manager/wmserver/include/window_manager_agent_controller.h create mode 100644 window_manager/wmserver/include/window_manager_config.h create mode 100644 window_manager/wmserver/include/window_manager_service.h create mode 100644 window_manager/wmserver/include/window_node.h create mode 100644 window_manager/wmserver/include/window_node_container.h create mode 100644 window_manager/wmserver/include/window_node_state_machine.h create mode 100644 window_manager/wmserver/include/window_pair.h create mode 100644 window_manager/wmserver/include/window_root.h create mode 100644 window_manager/wmserver/include/window_snapshot/snapshot_controller.h create mode 100644 window_manager/wmserver/include/window_snapshot/snapshot_proxy.h create mode 100644 window_manager/wmserver/include/window_snapshot/snapshot_stub.h create mode 100644 window_manager/wmserver/include/window_zorder_policy.h create mode 100644 window_manager/wmserver/include/zidl/ressched_report.h create mode 100644 window_manager/wmserver/include/zidl/window_manager_interface.h create mode 100644 window_manager/wmserver/include/zidl/window_manager_proxy.h create mode 100644 window_manager/wmserver/include/zidl/window_manager_stub.h create mode 100644 window_manager/wmserver/src/README.md create mode 100644 window_manager/wmserver/src/accessibility_connection.cpp create mode 100644 window_manager/wmserver/src/avoid_area_controller.cpp create mode 100644 window_manager/wmserver/src/display_group_controller.cpp create mode 100644 window_manager/wmserver/src/display_group_info.cpp create mode 100644 window_manager/wmserver/src/display_zoom_controller.cpp create mode 100644 window_manager/wmserver/src/drag_controller.cpp create mode 100644 window_manager/wmserver/src/freeze_controller.cpp create mode 100644 window_manager/wmserver/src/inner_window.cpp create mode 100644 window_manager/wmserver/src/input_window_monitor.cpp create mode 100644 window_manager/wmserver/src/memory_guard.cpp create mode 100644 window_manager/wmserver/src/minimize_app.cpp create mode 100644 window_manager/wmserver/src/remote_animation.cpp create mode 100644 window_manager/wmserver/src/starting_window.cpp create mode 100644 window_manager/wmserver/src/window_common_event.cpp create mode 100644 window_manager/wmserver/src/window_controller.cpp create mode 100644 window_manager/wmserver/src/window_dumper.cpp create mode 100644 window_manager/wmserver/src/window_inner_manager.cpp create mode 100644 window_manager/wmserver/src/window_layout_policy.cpp create mode 100644 window_manager/wmserver/src/window_layout_policy_cascade.cpp create mode 100644 window_manager/wmserver/src/window_layout_policy_tile.cpp create mode 100644 window_manager/wmserver/src/window_manager_agent_controller.cpp create mode 100644 window_manager/wmserver/src/window_manager_config.cpp create mode 100644 window_manager/wmserver/src/window_manager_service.cpp create mode 100644 window_manager/wmserver/src/window_node.cpp create mode 100644 window_manager/wmserver/src/window_node_container.cpp create mode 100644 window_manager/wmserver/src/window_node_state_machine.cpp create mode 100644 window_manager/wmserver/src/window_pair.cpp create mode 100644 window_manager/wmserver/src/window_root.cpp create mode 100644 window_manager/wmserver/src/window_snapshot/snapshot_controller.cpp create mode 100644 window_manager/wmserver/src/window_snapshot/snapshot_proxy.cpp create mode 100644 window_manager/wmserver/src/window_snapshot/snapshot_stub.cpp create mode 100644 window_manager/wmserver/src/window_zorder_policy.cpp create mode 100644 window_manager/wmserver/src/zidl/ressched_report.cpp create mode 100644 window_manager/wmserver/src/zidl/window_manager_proxy.cpp create mode 100644 window_manager/wmserver/src/zidl/window_manager_stub.cpp create mode 100644 window_manager/wmserver/test/BUILD.gn create mode 100644 window_manager/wmserver/test/unittest/BUILD.gn create mode 100644 window_manager/wmserver/test/unittest/accessibility_connection_test.cpp create mode 100644 window_manager/wmserver/test/unittest/avoid_area_controller_test.cpp create mode 100644 window_manager/wmserver/test/unittest/display_group_controller_test.cpp create mode 100644 window_manager/wmserver/test/unittest/display_group_info_test.cpp create mode 100644 window_manager/wmserver/test/unittest/drag_controller_test.cpp create mode 100644 window_manager/wmserver/test/unittest/input_window_monitor_test.cpp create mode 100644 window_manager/wmserver/test/unittest/minimize_app_test.cpp create mode 100644 window_manager/wmserver/test/unittest/remote_animation_test.cpp create mode 100644 window_manager/wmserver/test/unittest/starting_window_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_controller_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_display_zoom_controller_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_dumper_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_freeze_controller_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_inner_manager_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_inner_window_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_layout_policy_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_manager_config_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_manager_proxy_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_manager_service_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_manager_stub_impl.h create mode 100644 window_manager/wmserver/test/unittest/window_manager_stub_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_node_container_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_node_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_pair_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_root_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_snapshot_test.cpp create mode 100644 window_manager/wmserver/test/unittest/window_zorder_policy_test.cpp diff --git a/window_manager/AppDemo/window/immersive/README_zh.md b/window_manager/AppDemo/window/immersive/README_zh.md new file mode 100644 index 0000000..0e5a478 --- /dev/null +++ b/window_manager/AppDemo/window/immersive/README_zh.md @@ -0,0 +1,14 @@ +# immersive + +### 简介 + +本示例适用于介绍如何获取窗口并进入全屏模式。 + +### 使用说明 + +启动应用后点击immersive按钮进入全屏。 + +### 约束与限制 + +本示例仅支持在标准系统上运行。 + diff --git a/window_manager/AppDemo/window/immersive/build.gradle b/window_manager/AppDemo/window/immersive/build.gradle new file mode 100644 index 0000000..31e1deb --- /dev/null +++ b/window_manager/AppDemo/window/immersive/build.gradle @@ -0,0 +1,34 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 +ohos { + compileSdkVersion 8 + supportSystem "standard" +} + +buildscript { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + } + dependencies { + classpath 'com.huawei.ohos:hap:3.0.5.2' + classpath 'com.huawei.ohos:decctest:1.2.7.2' + } +} + +allprojects { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + } +} diff --git a/window_manager/AppDemo/window/immersive/entry/build.gradle b/window_manager/AppDemo/window/immersive/entry/build.gradle new file mode 100644 index 0000000..c40c1f0 --- /dev/null +++ b/window_manager/AppDemo/window/immersive/entry/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'com.huawei.ohos.hap' +//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 +ohos { + compileSdkVersion 8 + defaultConfig { + compatibleSdkVersion 7 + } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testImplementation 'junit:junit:4.13.1' +} diff --git a/window_manager/AppDemo/window/immersive/entry/src/main/config.json b/window_manager/AppDemo/window/immersive/entry/src/main/config.json new file mode 100644 index 0000000..1c46aae --- /dev/null +++ b/window_manager/AppDemo/window/immersive/entry/src/main/config.json @@ -0,0 +1,70 @@ +{ + "app": { + "bundleName": "ohos.samples.immersive", + "vendor": "example", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.myapplication", + "name": ".MyApplication", + "mainAbility": ".MainAbility", + "srcPath": "", + "deviceType": [ + "tablet", + "default", + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry", + "installationFree": false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "visible": true, + "srcPath": "MainAbility", + "name": ".MainAbility", + "srcLanguage": "ets", + "icon": "$media:icon", + "description": "$string:description_mainability", + "formsEnabled": false, + "label": "$string:entry_MainAbility", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "mode": { + "syntax": "ets", + "type": "pageAbility" + }, + "pages": [ + "pages/index", + "pages/second" + ], + "name": ".MainAbility", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} diff --git a/window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/app.ets b/window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/app.ets new file mode 100644 index 0000000..2eb18d6 --- /dev/null +++ b/window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/app.ets @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export default { + onCreate() { + console.info('Application onCreate') + }, + onDestroy() { + console.info('Application onDestroy') + }, +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/pages/index.ets b/window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/pages/index.ets new file mode 100644 index 0000000..ab68299 --- /dev/null +++ b/window_manager/AppDemo/window/immersive/entry/src/main/ets/MainAbility/pages/index.ets @@ -0,0 +1,46 @@ +/* + * 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. + */ +import router from '@system.router'; +import window from '@ohos.window' +@Entry +@Component +struct Index { + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('immersive') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(async () => { + try { + const win = await window.getTopWindow() + await win.setFullScreen(true) + } catch (err) { + console.log(`setFullScreen fail, code = ${err.code}`) + } + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/immersive/entry/src/main/resources/base/element/string.json b/window_manager/AppDemo/window/immersive/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..8df972c --- /dev/null +++ b/window_manager/AppDemo/window/immersive/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "entry_MainAbility", + "value": "entry_MainAbility" + }, + { + "name": "description_mainability", + "value": "eTS_Empty Ability" + } + ] +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/immersive/entry/src/main/resources/base/media/icon.png b/window_manager/AppDemo/window/immersive/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 literal 0 HcmV?d00001 diff --git a/window_manager/AppDemo/window/immersive/settings.gradle b/window_manager/AppDemo/window/immersive/settings.gradle new file mode 100644 index 0000000..28d595f --- /dev/null +++ b/window_manager/AppDemo/window/immersive/settings.gradle @@ -0,0 +1 @@ +include ':entry' diff --git a/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/app.json5 b/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/app.json5 new file mode 100644 index 0000000..8efbc0a --- /dev/null +++ b/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/app.json5 @@ -0,0 +1,26 @@ +/* + * 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. + */ + +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true + } +} diff --git a/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/element/string.json b/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/element/string.json new file mode 100644 index 0000000..d71e5ea --- /dev/null +++ b/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/media/app_icon.png b/window_manager/AppDemo/window/windowExtension/AbilityComponent/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 { + window.getProperties().then((pro) => { + console.log("WindowExtension " + JSON.stringify(pro)); + }) + window.show(); + }) + } + + onConnect(want) { + console.info('JSWindowExtension onConnect ' + want.abilityName); + } + + onDisconnect(want) { + console.info('JSWindowExtension onDisconnect ' + want.abilityName); + } +}; \ No newline at end of file diff --git a/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/index1.ets b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/index1.ets new file mode 100644 index 0000000..e301f29 --- /dev/null +++ b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/index1.ets @@ -0,0 +1,77 @@ +/* + * 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. + */ + +@Entry +@Component +struct Index { + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('hello world') + .fontSize(50) + .fontWeight(FontWeight.Bold) + + Button() { + Text('button1') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + console.log("WindowExtensionAbility, button1:"); + }) + + TextInput() { + + }.type(InputType.Number) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFC') + + + Button() { + Text('button2') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + console.log("WindowExtensionAbility, button2:"); + }) + + Button() { + Text('button3') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + console.log("WindowExtensionAbility, button3:"); + }) + } + .width('100%') + .height('100%') + .backgroundColor(1234) + } +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/second.ets b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/second.ets new file mode 100644 index 0000000..84a9e72 --- /dev/null +++ b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/ets/WindowExtAbility/pages/second.ets @@ -0,0 +1,52 @@ +/* + * 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. + */ + +import router from '@system.router'; + +@Entry +@Component +struct Second { + private content: string = "Second Page~~" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text(`${this.content}`) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('back to index') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + router.back() + }) + + TextInput() { + }.type(InputType.Number) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFC') + + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/module.json5 b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/module.json5 new file mode 100644 index 0000000..c8070a5 --- /dev/null +++ b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/module.json5 @@ -0,0 +1,70 @@ +/* + * 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. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:entry_desc", + "mainElement": "MainAbility", + "deviceTypes": [ + "phone", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "uiSyntax": "ets", + "abilities": [ + { + "name": "MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:MainAbility_desc", + "icon": "$media:icon", + "label": "$string:MainAbility_label", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "WindowExtAbility", + "srcEntrance": "./ets/WindowExtAbility/WindowExtAbility.ts", + "icon": "$media:icon", + "description": "WindowExtension", + "type": "window", + "permissions": [], + "visible": true, + "skills": [ + { + "actions": [], + "entities": [], + "uris": [] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/element/string.json b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..dddf912 --- /dev/null +++ b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "description" + }, + { + "name": "MainAbility_desc", + "value": "description" + }, + { + "name": "MainAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/media/icon.png b/window_manager/AppDemo/window/windowExtension/WindowExtension/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 + + + + + LICENSE + + + + + + + + + + + diff --git a/window_manager/README.md b/window_manager/README.md index d3f1e22..42bebac 100644 --- a/window_manager/README.md +++ b/window_manager/README.md @@ -2,3 +2,5 @@ #### 介绍 window_manager目录是 ft engine 的窗口管理部分。 + +本模块基于OpenHarmony-3.2-Release。将在openEuler做适配,同时抽象出FT协议的基本接口。 diff --git a/window_manager/bundle.json b/window_manager/bundle.json new file mode 100644 index 0000000..4a10bbe --- /dev/null +++ b/window_manager/bundle.json @@ -0,0 +1,138 @@ +{ + "name": "@ohos/window_manager", + "description": "library for window", + "version": "3.1", + "license": "Apache License 2.0", + "publishAs": "code-segment", + "segment": { + "destPath": "foundation/window/window_manager" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "window_manager", + "subsystem": "window", + "syscap": ["SystemCapability.WindowManager.WindowManager.Core"], + "features": [ + "window_manager_feature_coverage = false", + "window_manager_feature_subscribe_motion" + ], + "adapted_system_type": [ "standard" ], + "rom": "8000KB", + "ram": "8000KB", + "hisysevent_config": [ + "//foundation/window/window_manager/hisysevent.yaml" + ], + "deps": { + "components": [ + "imf", + "sensor", + "ability_base", + "graphic_standard", + "hisysevent_native", + "ability_runtime", + "napi", + "common_event_service", + "hilog_native", + "access_token", + "init", + "bundle_framework", + "hiviewdfx_hilog_native", + "ipc", + "power_manager", + "utils_base", + "hitrace_native", + "resource_management", + "samgr", + "input", + "safwk", + "display_manager", + "config_policy", + "ace_engine", + "multimedia_image_framework" + ], + "third_party": [ + "flutter", + "libxml2", + "libjpeg-turbo" + ] + }, + "build": { + "group_type": { + "base_group": [ + "//foundation/window/window_manager/snapshot:snapshot_display", + "//foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi:windowstage", + "//foundation/window/window_manager/interfaces/kits/napi:napi_packages", + "//foundation/window/window_manager/resources:window_resources" + ], + "fwk_group": [ + "//foundation/window/window_manager/interfaces/kits/js/declaration:window", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/extension/extension_connection:libwindow_extension_client", + "//foundation/window/window_manager/extension/window_extension:libwindow_extension", + "//foundation/window/window_manager/extension/window_extension:window_extension_module", + "//foundation/window/window_manager/wm:libwm", + "//foundation/window/window_manager/utils:libwmutil" + ], + "service_group": [ + "//foundation/window/window_manager/sa_profile:wms_sa_profile", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/wmserver:libwms" + ] + }, + "inner_kits": [ + { + "type": "so", + "name": "//foundation/window/window_manager/wm:libwm", + "header": { + "header_files": [ + "window.h", + "window_accessibility_controller.h", + "window_manager.h", + "window_option.h", + "window_scene.h", + "wm_common.h" + ], + "header_base": "//foundation/window/window_manager/interfaces/innerkits/wm" + } + }, + { + "type": "so", + "name": "//foundation/window/window_manager/dm:libdm", + "header": { + "header_files": [ + "display.h", + "display_manager.h", + "display_property.h", + "dm_common.h", + "screen.h", + "screen_group.h", + "screen_manager.h" + ], + "header_base": "//foundation/window/window_manager/interfaces/innerkits/dm" + } + }, + { + "type": "so", + "name": "//foundation/window/window_manager/extension/extension_connection:libwindow_extension_client", + "header": { + "header_files": [ + "window_extension_connection.h" + ], + "header_base": "//foundation/window/window_manager/interfaces/innerkits/extension" + } + } + ], + "test": [ + "//foundation/window/window_manager/dm:test", + "//foundation/window/window_manager/dmserver:test", + "//foundation/window/window_manager/snapshot:test", + "//foundation/window/window_manager/utils:test", + "//foundation/window/window_manager/wm:test", + "//foundation/window/window_manager/wmserver:test", + "//foundation/window/window_manager/test:test", + "//foundation/window/window_manager/extension/window_extension:test" + ] + } + } + } diff --git a/window_manager/dm/BUILD.gn b/window_manager/dm/BUILD.gn new file mode 100644 index 0000000..65b3bd5 --- /dev/null +++ b/window_manager/dm/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") + +config("libdm_private_config") { + include_dirs = [ + "include", + "../dmserver/include", + ] +} + +config("libdm_public_config") { + include_dirs = [ + "../interfaces/innerkits/dm", + "../utils/include", + ] +} + +## Build libdm.so +ohos_shared_library("libdm") { + sources = [ + "../dmserver/src/display_manager_proxy.cpp", + "src/display.cpp", + "src/display_manager.cpp", + "src/display_manager_adapter.cpp", + "src/screen.cpp", + "src/screen_group.cpp", + "src/screen_manager.cpp", + "src/zidl/display_manager_agent_stub.cpp", + ] + + configs = [ + ":libdm_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + public_configs = [ ":libdm_public_config" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/utils:libwmutil", + ] + + external_deps = [ + "c_utils:utils", + "hilog_native:libhilog", + "ipc:ipc_core", + "multimedia_image_framework:image_native", + "samgr:samgr_proxy", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/dm/include/display_manager_adapter.h b/window_manager/dm/include/display_manager_adapter.h new file mode 100644 index 0000000..282628e --- /dev/null +++ b/window_manager/dm/include/display_manager_adapter.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DM_DISPLAY_MANAGER_ADAPTER_H +#define FOUNDATION_DM_DISPLAY_MANAGER_ADAPTER_H + +#include +#include +#include + +#include "display.h" +#include "screen.h" +#include "screen_group.h" +#include "dm_common.h" +#include "display_manager_interface.h" +#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 InitDMSProxy(); + std::recursive_mutex mutex_; + sptr displayManagerServiceProxy_ = nullptr; + sptr dmsDeath_ = nullptr; + bool isProxyValid_ { false }; +}; + +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 sptr GetDefaultDisplayInfo(); + virtual sptr GetDisplayInfoByScreenId(ScreenId screenId); + virtual std::vector GetAllDisplayIds(); + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId); + virtual DMError HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow); + virtual bool WakeUpBegin(PowerStateChangeReason reason); + virtual bool WakeUpEnd(); + virtual bool SuspendBegin(PowerStateChangeReason reason); + virtual bool SuspendEnd(); + virtual bool SetDisplayState(DisplayState state); + virtual DisplayState GetDisplayState(DisplayId displayId); + virtual void NotifyDisplayEvent(DisplayEvent event); + virtual bool SetFreeze(std::vector displayIds, bool isFreeze); + virtual sptr GetDisplayInfo(DisplayId displayId); + virtual sptr GetCutoutInfo(DisplayId displayId); +private: + static inline SingletonDelegator delegator; +}; + +class ScreenManagerAdapter : public BaseAdapter { +WM_DECLARE_SINGLE_INSTANCE(ScreenManagerAdapter); +public: + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent); + virtual DMError DestroyVirtualScreen(ScreenId screenId); + virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); + virtual bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason); + virtual ScreenPowerState GetScreenPower(ScreenId dmsScreenId); + virtual bool SetOrientation(ScreenId screenId, Orientation orientation); + virtual sptr GetScreenGroupInfoById(ScreenId screenId); + virtual std::vector> GetAllScreenInfos(); + virtual ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); + virtual ScreenId MakeExpand(std::vector screenId, std::vector startPoint); + virtual void RemoveVirtualScreenFromGroup(std::vector); + virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); + virtual sptr GetScreenInfo(ScreenId screenId); + virtual bool SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio); + virtual void SetScreenRotationLocked(bool isLocked); + virtual bool IsScreenRotationLocked(); + + // 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: + static inline SingletonDelegator delegator; +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DM_DISPLAY_MANAGER_ADAPTER_H diff --git a/window_manager/dm/include/display_manager_agent_default.h b/window_manager/dm/include/display_manager_agent_default.h new file mode 100644 index 0000000..d29011e --- /dev/null +++ b/window_manager/dm/include/display_manager_agent_default.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-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 MASTER_DISPLAY_MANAGER_AGENT_DEFAULT_H +#define MASTER_DISPLAY_MANAGER_AGENT_DEFAULT_H + +#include + +namespace OHOS { +namespace Rosen { +class DisplayManagerAgentDefault : public DisplayManagerAgentStub { +public: + DisplayManagerAgentDefault() = default; + ~DisplayManagerAgentDefault() = default; + + void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) override {}; + void NotifyDisplayStateChanged(DisplayId id, DisplayState state) override {}; + void OnScreenConnect(sptr) override {}; + void OnScreenDisconnect(ScreenId) override {}; + void OnScreenChange(const sptr&, ScreenChangeEvent) override {}; + void OnScreenGroupChange(const std::string& trigger, + const std::vector>&, ScreenGroupChangeEvent) override {}; + void OnDisplayCreate(sptr) override {}; + void OnDisplayDestroy(DisplayId) override {}; + void OnDisplayChange(const sptr, DisplayChangeEvent) override {}; + void OnScreenshot(sptr) override {}; +}; +} +} +#endif // MASTER_DISPLAY_MANAGER_AGENT_DEFAULT_H diff --git a/window_manager/dm/include/zidl/display_manager_agent_interface.h b/window_manager/dm/include/zidl/display_manager_agent_interface.h new file mode 100644 index 0000000..957fed4 --- /dev/null +++ b/window_manager/dm/include/zidl/display_manager_agent_interface.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-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_ROSEN_DISPLAY_MANAGER_AGENT_INTERFACE_H +#define OHOS_ROSEN_DISPLAY_MANAGER_AGENT_INTERFACE_H + +#include +#include "display_info.h" +#include "dm_common.h" +#include "screen_info.h" +#include "screenshot_info.h" + +namespace OHOS { +namespace Rosen { +enum class DisplayManagerAgentType : uint32_t { + DISPLAY_POWER_EVENT_LISTENER, + DISPLAY_STATE_LISTENER, + SCREEN_EVENT_LISTENER, + DISPLAY_EVENT_LISTENER, + SCREENSHOT_EVENT_LISTENER, +}; + +class IDisplayManagerAgent : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.IDisplayManagerAgent"); + + enum { + TRANS_ID_NOTIFY_DISPLAY_POWER_EVENT = 1, + TRANS_ID_NOTIFY_DISPLAY_STATE_CHANGED, + TRANS_ID_ON_SCREEN_CONNECT, + TRANS_ID_ON_SCREEN_DISCONNECT, + TRANS_ID_ON_SCREEN_CHANGED, + TRANS_ID_ON_SCREENGROUP_CHANGED, + TRANS_ID_ON_DISPLAY_CONNECT, + TRANS_ID_ON_DISPLAY_DISCONNECT, + TRANS_ID_ON_DISPLAY_CHANGED, + TRANS_ID_ON_SCREEN_SHOT, + }; + virtual void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) = 0; + virtual void NotifyDisplayStateChanged(DisplayId id, DisplayState state) = 0; + virtual void OnScreenConnect(sptr) = 0; + virtual void OnScreenDisconnect(ScreenId) = 0; + virtual void OnScreenChange(const sptr&, ScreenChangeEvent) = 0; + virtual void OnScreenGroupChange(const std::string& trigger, + const std::vector>&, ScreenGroupChangeEvent) = 0; + virtual void OnDisplayCreate(sptr) = 0; + virtual void OnDisplayDestroy(DisplayId) = 0; + virtual void OnDisplayChange(sptr, DisplayChangeEvent) = 0; + virtual void OnScreenshot(sptr) = 0; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_DISPLAY_MANAGER_AGENT_INTERFACE_H \ No newline at end of file diff --git a/window_manager/dm/include/zidl/display_manager_agent_proxy.h b/window_manager/dm/include/zidl/display_manager_agent_proxy.h new file mode 100644 index 0000000..b1a298c --- /dev/null +++ b/window_manager/dm/include/zidl/display_manager_agent_proxy.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-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_ROSEN_DISPLAY_MANAGER_AGRNT_PROXY_H +#define OHOS_ROSEN_DISPLAY_MANAGER_AGRNT_PROXY_H + +#include +#include "display_manager_agent_interface.h" + +namespace OHOS { +namespace Rosen { +class DisplayManagerAgentProxy : public IRemoteProxy { +public: + explicit DisplayManagerAgentProxy(const sptr& impl) : IRemoteProxy(impl) {}; + ~DisplayManagerAgentProxy() = default; + + virtual void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) override; + virtual void NotifyDisplayStateChanged(DisplayId id, DisplayState state) override; + virtual void OnScreenConnect(sptr) override; + virtual void OnScreenDisconnect(ScreenId) override; + virtual void OnScreenChange(const sptr&, ScreenChangeEvent) override; + virtual void OnScreenGroupChange(const std::string& trigger, + const std::vector>&, ScreenGroupChangeEvent) override; + virtual void OnDisplayCreate(sptr) override; + virtual void OnDisplayDestroy(DisplayId) override; + virtual void OnDisplayChange(sptr, DisplayChangeEvent) override; + virtual void OnScreenshot(sptr) override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_DISPLAY_MANAGER_AGRNT_PROXY_H \ No newline at end of file diff --git a/window_manager/dm/include/zidl/display_manager_agent_stub.h b/window_manager/dm/include/zidl/display_manager_agent_stub.h new file mode 100644 index 0000000..0a59cd5 --- /dev/null +++ b/window_manager/dm/include/zidl/display_manager_agent_stub.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-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_ROSEN_DISPLAY_MANAGER_AGENT_STUB_H +#define OHOS_ROSEN_DISPLAY_MANAGER_AGENT_STUB_H + + +#include +#include +#include +#include +#include "display_manager_agent_interface.h" + +namespace OHOS::Rosen { +class DisplayManagerAgentStub : public IRemoteStub { +public: + DisplayManagerAgentStub() = default; + ~DisplayManagerAgentStub() = default; + + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption& option) override; +}; +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_DISPLAY_MANAGER_AGENT_STUB_H \ No newline at end of file diff --git a/window_manager/dm/src/display.cpp b/window_manager/dm/src/display.cpp new file mode 100644 index 0000000..ed32119 --- /dev/null +++ b/window_manager/dm/src/display.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-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 "display.h" + +#include +#include +#include + +#include "class_var_definition.h" +#include "display_info.h" +#include "display_manager_adapter.h" +#include "singleton_container.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 { +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_WITH_LOCK(sptr, DisplayInfo, displayInfo); +}; + +Display::Display(const std::string& name, sptr info) + : pImpl_(new Impl(name, info)) +{ +} + +Display::~Display() +{ +} + +DisplayId Display::GetId() const +{ + return pImpl_->GetDisplayInfo()->GetDisplayId(); +} + +std::string Display::GetName() const +{ + return pImpl_->GetDisplayInfo()->GetName(); +} + +int32_t Display::GetWidth() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetWidth(); +} + +int32_t Display::GetHeight() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetHeight(); +} + +uint32_t Display::GetRefreshRate() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetRefreshRate(); +} + +ScreenId Display::GetScreenId() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetScreenId(); +} + +Rotation Display::GetRotation() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetRotation(); +} + +Orientation Display::GetOrientation() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetOrientation(); +} + +void Display::UpdateDisplayInfo(sptr displayInfo) const +{ + if (displayInfo == nullptr) { + WLOGFE("displayInfo is invalid"); + return; + } + pImpl_->SetDisplayInfo(displayInfo); +} + +void Display::UpdateDisplayInfo() const +{ + auto displayInfo = SingletonContainer::Get().GetDisplayInfo(GetId()); + UpdateDisplayInfo(displayInfo); +} + +float Display::GetVirtualPixelRatio() const +{ + UpdateDisplayInfo(); + return pImpl_->GetDisplayInfo()->GetVirtualPixelRatio(); +} + +int Display::GetDpi() const +{ + return static_cast(GetVirtualPixelRatio() * DOT_PER_INCH); +} + +sptr Display::GetDisplayInfo() const +{ + return pImpl_->GetDisplayInfo(); +} + +sptr Display::GetCutoutInfo() const +{ + return SingletonContainer::Get().GetCutoutInfo(GetId()); +} +} // namespace OHOS::Rosen diff --git a/window_manager/dm/src/display_manager.cpp b/window_manager/dm/src/display_manager.cpp new file mode 100644 index 0000000..051ad7f --- /dev/null +++ b/window_manager/dm/src/display_manager.cpp @@ -0,0 +1,869 @@ +/* + * Copyright (c) 2021-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 "display_manager.h" + +#include +#include +#include + +#include "display_manager_adapter.h" +#include "display_manager_agent_default.h" +#include "dm_common.h" +#include "screen_manager.h" +#include "singleton_delegator.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManager"}; + const static uint32_t MAX_DISPLAY_SIZE = 32; + const static uint32_t MAX_INTERVAL_US = 5000; +} +WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManager) + +class DisplayManager::Impl : public RefBase { +public: + Impl(std::recursive_mutex& mutex) : mutex_(mutex) {} + ~Impl(); + static inline SingletonDelegator delegator; + bool CheckRectValid(const Media::Rect& rect, int32_t oriHeight, int32_t oriWidth) const; + bool CheckSizeValid(const Media::Size& size, int32_t oriHeight, int32_t oriWidth) const; + sptr GetDefaultDisplay(); + sptr GetDefaultDisplaySync(); + sptr GetDisplayById(DisplayId displayId); + DMError HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow); + bool RegisterDisplayListener(sptr listener); + bool UnregisterDisplayListener(sptr listener); + bool SetDisplayState(DisplayState state, DisplayStateCallback callback); + bool RegisterDisplayPowerEventListener(sptr listener); + bool UnregisterDisplayPowerEventListener(sptr listener); + bool RegisterScreenshotListener(sptr listener); + bool UnregisterScreenshotListener(sptr listener); + sptr GetDisplayByScreenId(ScreenId screenId); + void OnRemoteDied(); +private: + void ClearDisplayStateCallback(); + void NotifyScreenshot(sptr info); + void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status); + void NotifyDisplayStateChanged(DisplayId id, DisplayState state); + void NotifyDisplayChangedEvent(sptr info, DisplayChangeEvent event); + void NotifyDisplayCreate(sptr info); + void NotifyDisplayDestroy(DisplayId); + void NotifyDisplayChange(sptr displayInfo); + bool UpdateDisplayInfoLocked(sptr); + void Clear(); + + DisplayId defaultDisplayId_ = DISPLAY_ID_INVALID; + std::map> displayMap_; + DisplayStateCallback displayStateCallback_; + std::recursive_mutex& mutex_; + std::set> displayListeners_; + std::set> powerEventListeners_; + std::set> screenshotListeners_; + class DisplayManagerListener; + sptr displayManagerListener_; + class DisplayManagerAgent; + sptr displayStateAgent_; + sptr powerEventListenerAgent_; + class DisplayManagerScreenshotAgent; + sptr screenshotListenerAgent_; +}; + +class DisplayManager::Impl::DisplayManagerListener : public DisplayManagerAgentDefault { +public: + explicit DisplayManagerListener(sptr impl) : pImpl_(impl) + { + } + + void OnDisplayCreate(sptr displayInfo) override + { + if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALID) { + WLOGFE("OnDisplayCreate, displayInfo is invalid."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("OnDisplayCreate, impl is nullptr."); + return; + } + pImpl_->NotifyDisplayCreate(displayInfo); + std::set> displayListeners; + { + std::lock_guard lock(pImpl_->mutex_); + displayListeners = pImpl_->displayListeners_; + } + for (auto listener : displayListeners) { + listener->OnCreate(displayInfo->GetDisplayId()); + } + }; + + void OnDisplayDestroy(DisplayId displayId) override + { + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("OnDisplayDestroy, displayId is invalid."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("OnDisplayDestroy, impl is nullptr."); + return; + } + pImpl_->NotifyDisplayDestroy(displayId); + std::set> displayListeners; + { + std::lock_guard lock(pImpl_->mutex_); + displayListeners = pImpl_->displayListeners_; + } + for (auto listener : displayListeners) { + listener->OnDestroy(displayId); + } + }; + + void OnDisplayChange(sptr displayInfo, DisplayChangeEvent event) override + { + if (displayInfo == nullptr || displayInfo->GetDisplayId() == DISPLAY_ID_INVALID) { + WLOGFE("OnDisplayChange, displayInfo is invalid."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("OnDisplayChange, impl is nullptr."); + return; + } + WLOGD("OnDisplayChange. display %{public}" PRIu64", event %{public}u", displayInfo->GetDisplayId(), event); + pImpl_->NotifyDisplayChange(displayInfo); + std::set> displayListeners; + { + std::lock_guard lock(pImpl_->mutex_); + displayListeners = pImpl_->displayListeners_; + } + for (auto listener : displayListeners) { + listener->OnChange(displayInfo->GetDisplayId()); + } + }; +private: + sptr pImpl_; +}; + +class DisplayManager::Impl::DisplayManagerAgent : public DisplayManagerAgentDefault { +public: + explicit DisplayManagerAgent(sptr impl) : pImpl_(impl) + { + } + ~DisplayManagerAgent() = default; + + virtual void NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) override + { + pImpl_->NotifyDisplayPowerEvent(event, status); + } + + virtual void NotifyDisplayStateChanged(DisplayId id, DisplayState state) override + { + pImpl_->NotifyDisplayStateChanged(id, state); + } +private: + sptr pImpl_; +}; + +class DisplayManager::Impl::DisplayManagerScreenshotAgent : public DisplayManagerAgentDefault { +public: + explicit DisplayManagerScreenshotAgent(sptr impl) : pImpl_(impl) + { + } + ~DisplayManagerScreenshotAgent() = default; + + virtual void OnScreenshot(sptr info) override + { + pImpl_->NotifyScreenshot(info); + } +private: + sptr pImpl_; +}; + +bool DisplayManager::Impl::CheckRectValid(const Media::Rect& rect, int32_t oriHeight, int32_t oriWidth) const +{ + if (rect.left < 0) { + return false; + } + if (rect.top < 0) { + return false; + } + if (rect.width < 0) { + return false; + } + if (rect.height < 0) { + return false; + } + if (rect.width + rect.left > oriWidth) { + return false; + } + if (rect.height + rect.top > oriHeight) { + return false; + } + return true; +} + +bool DisplayManager::Impl::CheckSizeValid(const Media::Size& size, int32_t oriHeight, int32_t oriWidth) const +{ + if (size.width < 0) { + return false; + } + if (size.height < 0) { + return false; + } + if (size.width > MAX_RESOLUTION_SIZE_SCREENSHOT) { + return false; + } + if (size.height > MAX_RESOLUTION_SIZE_SCREENSHOT) { + return false; + } + return true; +} + +void DisplayManager::Impl::ClearDisplayStateCallback() +{ + std::lock_guard lock(mutex_); + displayStateCallback_ = nullptr; + if (displayStateAgent_ != nullptr) { + SingletonContainer::Get().UnregisterDisplayManagerAgent(displayStateAgent_, + DisplayManagerAgentType::DISPLAY_STATE_LISTENER); + displayStateAgent_ = nullptr; + } +} + +void DisplayManager::Impl::Clear() +{ + std::lock_guard lock(mutex_); + bool res = true; + if (displayManagerListener_ != nullptr) { + res = SingletonContainer::Get().UnregisterDisplayManagerAgent( + displayManagerListener_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); + } + displayManagerListener_ = nullptr; + if (!res) { + WLOGFW("UnregisterDisplayManagerAgent DISPLAY_EVENT_LISTENER failed !"); + } + res = true; + if (powerEventListenerAgent_ != nullptr) { + res = SingletonContainer::Get().UnregisterDisplayManagerAgent( + powerEventListenerAgent_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER); + } + powerEventListenerAgent_ = nullptr; + if (!res) { + WLOGFW("UnregisterDisplayManagerAgent DISPLAY_POWER_EVENT_LISTENER failed !"); + } + ClearDisplayStateCallback(); +} + +DisplayManager::Impl::~Impl() +{ + Clear(); +} + +DisplayManager::DisplayManager() : pImpl_(new Impl(mutex_)) +{ +} + +DisplayManager::~DisplayManager() +{ + std::lock_guard lock(mutex_); + destroyed_ = true; +} + +DisplayId DisplayManager::GetDefaultDisplayId() +{ + auto info = SingletonContainer::Get().GetDefaultDisplayInfo(); + if (info == nullptr) { + return DISPLAY_ID_INVALID; + } + return info->GetDisplayId(); +} + +sptr DisplayManager::Impl::GetDefaultDisplay() +{ + auto displayInfo = SingletonContainer::Get().GetDefaultDisplayInfo(); + if (displayInfo == nullptr) { + return nullptr; + } + auto displayId = displayInfo->GetDisplayId(); + std::lock_guard lock(mutex_); + if (!UpdateDisplayInfoLocked(displayInfo)) { + displayMap_.erase(displayId); + return nullptr; + } + return displayMap_[displayId]; +} + +sptr DisplayManager::Impl::GetDefaultDisplaySync() +{ + static std::chrono::steady_clock::time_point lastRequestTime = std::chrono::steady_clock::now(); + auto currentTime = std::chrono::steady_clock::now(); + auto interval = std::chrono::duration_cast(currentTime - lastRequestTime).count(); + if (defaultDisplayId_ != DISPLAY_ID_INVALID && interval < MAX_INTERVAL_US) { + std::lock_guard lock(mutex_); + auto iter = displayMap_.find(defaultDisplayId_); + if (iter != displayMap_.end()) { + return displayMap_[defaultDisplayId_]; + } + } + + auto displayInfo = SingletonContainer::Get().GetDefaultDisplayInfo(); + if (displayInfo == nullptr) { + return nullptr; + } + auto displayId = displayInfo->GetDisplayId(); + std::lock_guard lock(mutex_); + if (!UpdateDisplayInfoLocked(displayInfo)) { + displayMap_.erase(displayId); + return nullptr; + } + lastRequestTime = currentTime; + defaultDisplayId_ = displayId; + return displayMap_[displayId]; +} + +sptr DisplayManager::Impl::GetDisplayById(DisplayId displayId) +{ + auto displayInfo = SingletonContainer::Get().GetDisplayInfo(displayId); + std::lock_guard lock(mutex_); + if (!UpdateDisplayInfoLocked(displayInfo)) { + displayMap_.erase(displayId); + return nullptr; + } + return displayMap_[displayId]; +} + +sptr DisplayManager::GetDisplayById(DisplayId displayId) +{ + std::lock_guard lock(mutex_); + if (destroyed_) { + return nullptr; + } + return pImpl_->GetDisplayById(displayId); +} + +sptr DisplayManager::GetDisplayByScreen(ScreenId screenId) +{ + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("screenId is invalid."); + return nullptr; + } + sptr display = pImpl_->GetDisplayByScreenId(screenId); + if (display == nullptr) { + WLOGFE("get display by screenId failed. screen %{public}" PRIu64"", screenId); + } + return display; +} + +sptr DisplayManager::Impl::GetDisplayByScreenId(ScreenId screenId) +{ + sptr displayInfo = SingletonContainer::Get().GetDisplayInfoByScreenId(screenId); + if (displayInfo == nullptr) { + WLOGFE("get display by screenId: displayInfo is null"); + return nullptr; + } + DisplayId displayId = displayInfo->GetDisplayId(); + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("get display by screenId: invalid displayInfo"); + return nullptr; + } + + std::lock_guard lock(mutex_); + if (!UpdateDisplayInfoLocked(displayInfo)) { + displayMap_.erase(displayId); + return nullptr; + } + return displayMap_[displayId]; +} + +std::shared_ptr DisplayManager::GetScreenshot(DisplayId displayId) +{ + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("displayId invalid!"); + return nullptr; + } + std::shared_ptr screenShot = + SingletonContainer::Get().GetDisplaySnapshot(displayId); + if (screenShot == nullptr) { + WLOGFE("DisplayManager::GetScreenshot failed!"); + return nullptr; + } + + return screenShot; +} + +std::shared_ptr DisplayManager::GetScreenshot(DisplayId displayId, const Media::Rect &rect, + const Media::Size &size, int rotation) +{ + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("displayId invalid!"); + return nullptr; + } + + std::shared_ptr screenShot = + SingletonContainer::Get().GetDisplaySnapshot(displayId); + if (screenShot == nullptr) { + WLOGFE("DisplayManager::GetScreenshot failed!"); + return nullptr; + } + + // check parameters + int32_t oriHeight = screenShot->GetHeight(); + int32_t oriWidth = screenShot->GetWidth(); + if (!pImpl_->CheckRectValid(rect, oriHeight, oriWidth)) { + WLOGFE("rect invalid! left %{public}d, top %{public}d, w %{public}d, h %{public}d", + rect.left, rect.top, rect.width, rect.height); + return nullptr; + } + if (!pImpl_->CheckSizeValid(size, oriHeight, oriWidth)) { + WLOGFE("size invalid! w %{public}d, h %{public}d", rect.width, rect.height); + return nullptr; + } + + // create crop dest pixelmap + Media::InitializationOptions opt; + opt.size.width = size.width; + opt.size.height = size.height; + opt.scaleMode = Media::ScaleMode::FIT_TARGET_SIZE; + opt.editable = false; + auto pixelMap = Media::PixelMap::Create(*screenShot, rect, opt); + if (pixelMap == nullptr) { + WLOGFE("Media::PixelMap::Create failed!"); + return nullptr; + } + std::shared_ptr dstScreenshot(pixelMap.release()); + + return dstScreenshot; +} + +sptr DisplayManager::GetDefaultDisplay() +{ + return pImpl_->GetDefaultDisplay(); +} + +sptr DisplayManager::GetDefaultDisplaySync() +{ + return pImpl_->GetDefaultDisplaySync(); +} + +std::vector DisplayManager::GetAllDisplayIds() +{ + return SingletonContainer::Get().GetAllDisplayIds(); +} + +std::vector> DisplayManager::GetAllDisplays() +{ + std::vector> res; + auto displayIds = GetAllDisplayIds(); + for (auto displayId: displayIds) { + const sptr display = GetDisplayById(displayId); + if (display != nullptr) { + res.emplace_back(display); + } else { + WLOGFE("DisplayManager::GetAllDisplays display %" PRIu64" nullptr!", displayId); + } + } + return res; +} + +DMError DisplayManager::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + return pImpl_->HasPrivateWindow(displayId, hasPrivateWindow); +} + +DMError DisplayManager::Impl::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + return SingletonContainer::Get().HasPrivateWindow(displayId, hasPrivateWindow); +} + +bool DisplayManager::Impl::RegisterDisplayListener(sptr listener) +{ + std::lock_guard lock(mutex_); + bool ret = true; + if (displayManagerListener_ == nullptr) { + displayManagerListener_ = new DisplayManagerListener(this); + ret = SingletonContainer::Get().RegisterDisplayManagerAgent( + displayManagerListener_, + DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); + } + if (!ret) { + WLOGFW("RegisterDisplayManagerAgent failed !"); + displayManagerListener_ = nullptr; + } else { + displayListeners_.insert(listener); + } + return ret; +} + +bool DisplayManager::RegisterDisplayListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("RegisterDisplayListener listener is nullptr."); + return false; + } + return pImpl_->RegisterDisplayListener(listener); +} + +bool DisplayManager::Impl::UnregisterDisplayListener(sptr listener) +{ + std::lock_guard lock(mutex_); + auto iter = std::find(displayListeners_.begin(), displayListeners_.end(), listener); + if (iter == displayListeners_.end()) { + WLOGFE("could not find this listener"); + return false; + } + displayListeners_.erase(iter); + bool ret = true; + if (displayListeners_.empty() && displayManagerListener_ != nullptr) { + ret = SingletonContainer::Get().UnregisterDisplayManagerAgent( + displayManagerListener_, + DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); + displayManagerListener_ = nullptr; + } + return ret; +} + +bool DisplayManager::UnregisterDisplayListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("UnregisterDisplayListener listener is nullptr."); + return false; + } + return pImpl_->UnregisterDisplayListener(listener); +} + +bool DisplayManager::Impl::RegisterDisplayPowerEventListener(sptr listener) +{ + std::lock_guard lock(mutex_); + bool ret = true; + if (powerEventListenerAgent_ == nullptr) { + powerEventListenerAgent_ = new DisplayManagerAgent(this); + ret = SingletonContainer::Get().RegisterDisplayManagerAgent( + powerEventListenerAgent_, + DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER); + } + if (!ret) { + WLOGFW("RegisterDisplayManagerAgent failed !"); + powerEventListenerAgent_ = nullptr; + } else { + powerEventListeners_.insert(listener); + } + WLOGFD("RegisterDisplayPowerEventListener end"); + return ret; +} + +bool DisplayManager::RegisterDisplayPowerEventListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("listener is nullptr"); + return false; + } + return pImpl_->RegisterDisplayPowerEventListener(listener); +} + +bool DisplayManager::Impl::UnregisterDisplayPowerEventListener(sptr listener) +{ + std::lock_guard lock(mutex_); + auto iter = std::find(powerEventListeners_.begin(), powerEventListeners_.end(), listener); + if (iter == powerEventListeners_.end()) { + WLOGFE("could not find this listener"); + return false; + } + powerEventListeners_.erase(iter); + bool ret = true; + if (powerEventListeners_.empty() && powerEventListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterDisplayManagerAgent( + powerEventListenerAgent_, + DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER); + powerEventListenerAgent_ = nullptr; + } + WLOGFD("UnregisterDisplayPowerEventListener end"); + return ret; +} + +bool DisplayManager::UnregisterDisplayPowerEventListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("listener is nullptr"); + return false; + } + return pImpl_->UnregisterDisplayPowerEventListener(listener); +} + +bool DisplayManager::Impl::RegisterScreenshotListener(sptr listener) +{ + std::lock_guard lock(mutex_); + bool ret = true; + if (screenshotListenerAgent_ == nullptr) { + screenshotListenerAgent_ = new DisplayManagerScreenshotAgent(this); + ret = SingletonContainer::Get().RegisterDisplayManagerAgent( + screenshotListenerAgent_, + DisplayManagerAgentType::SCREENSHOT_EVENT_LISTENER); + } + if (!ret) { + WLOGFW("RegisterDisplayManagerAgent failed !"); + screenshotListenerAgent_ = nullptr; + } else { + screenshotListeners_.insert(listener); + } + return ret; +} + +bool DisplayManager::RegisterScreenshotListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("RegisterScreenshotListener listener is nullptr."); + return false; + } + return pImpl_->RegisterScreenshotListener(listener); +} + +bool DisplayManager::Impl::UnregisterScreenshotListener(sptr listener) +{ + std::lock_guard lock(mutex_); + auto iter = std::find(screenshotListeners_.begin(), screenshotListeners_.end(), listener); + if (iter == screenshotListeners_.end()) { + WLOGFE("could not find this listener"); + return false; + } + screenshotListeners_.erase(iter); + bool ret = true; + if (screenshotListeners_.empty() && screenshotListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterDisplayManagerAgent( + screenshotListenerAgent_, + DisplayManagerAgentType::SCREENSHOT_EVENT_LISTENER); + screenshotListenerAgent_ = nullptr; + } + return ret; +} + +bool DisplayManager::UnregisterScreenshotListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("UnregisterScreenshotListener listener is nullptr."); + return false; + } + return pImpl_->UnregisterScreenshotListener(listener); +} + +void DisplayManager::Impl::NotifyScreenshot(sptr info) +{ + WLOGFD("NotifyScreenshot trigger:[%{public}s] displayId:%{public}" PRIu64" size:%{public}zu", + info->GetTrigger().c_str(), info->GetDisplayId(), screenshotListeners_.size()); + std::set> screenshotListeners; + { + std::lock_guard lock(mutex_); + screenshotListeners = screenshotListeners_; + } + for (auto& listener : screenshotListeners) { + listener->OnScreenshot(*info); + } +} + +void DisplayManager::Impl::NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) +{ + WLOGFD("NotifyDisplayPowerEvent event:%{public}u, status:%{public}u, size:%{public}zu", event, status, + powerEventListeners_.size()); + std::set> powerEventListeners; + { + std::lock_guard lock(mutex_); + powerEventListeners = powerEventListeners_; + } + for (auto& listener : powerEventListeners) { + listener->OnDisplayPowerEvent(event, status); + } +} + +void DisplayManager::Impl::NotifyDisplayStateChanged(DisplayId id, DisplayState state) +{ + WLOGFD("state:%{public}u", state); + DisplayStateCallback displayStateCallback; + { + std::lock_guard lock(mutex_); + displayStateCallback = displayStateCallback_; + } + if (displayStateCallback) { + displayStateCallback(state); + ClearDisplayStateCallback(); + return; + } + WLOGFW("callback_ target is not set!"); +} + +void DisplayManager::Impl::NotifyDisplayCreate(sptr info) +{ + std::lock_guard lock(mutex_); + UpdateDisplayInfoLocked(info); +} + +void DisplayManager::Impl::NotifyDisplayDestroy(DisplayId displayId) +{ + WLOGFD("displayId:%{public}" PRIu64".", displayId); + std::lock_guard lock(mutex_); + displayMap_.erase(displayId); +} + +void DisplayManager::Impl::NotifyDisplayChange(sptr displayInfo) +{ + std::lock_guard lock(mutex_); + UpdateDisplayInfoLocked(displayInfo); +} + +bool DisplayManager::Impl::UpdateDisplayInfoLocked(sptr displayInfo) +{ + if (displayInfo == nullptr) { + WLOGFE("displayInfo is null"); + return false; + } + DisplayId displayId = displayInfo->GetDisplayId(); + WLOGFD("displayId:%{public}" PRIu64".", displayId); + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("displayId is invalid."); + return false; + } + auto iter = displayMap_.find(displayId); + if (iter != displayMap_.end() && iter->second != nullptr) { + WLOGFD("get screen in screen map"); + iter->second->UpdateDisplayInfo(displayInfo); + return true; + } + sptr display = new Display("", displayInfo); + displayMap_[displayId] = display; + return true; +} + +bool DisplayManager::WakeUpBegin(PowerStateChangeReason reason) +{ + WLOGFD("WakeUpBegin start, reason:%{public}u", reason); + return SingletonContainer::Get().WakeUpBegin(reason); +} + +bool DisplayManager::WakeUpEnd() +{ + WLOGFD("WakeUpEnd start"); + return SingletonContainer::Get().WakeUpEnd(); +} + +bool DisplayManager::SuspendBegin(PowerStateChangeReason reason) +{ + // dms->wms notify other windows to hide + WLOGFD("SuspendBegin start, reason:%{public}u", reason); + return SingletonContainer::Get().SuspendBegin(reason); +} + +bool DisplayManager::SuspendEnd() +{ + WLOGFD("SuspendEnd start"); + return SingletonContainer::Get().SuspendEnd(); +} + +bool DisplayManager::Impl::SetDisplayState(DisplayState state, DisplayStateCallback callback) +{ + WLOGFD("state:%{public}u", state); + bool ret = true; + { + std::lock_guard lock(mutex_); + if (displayStateCallback_ != nullptr || callback == nullptr) { + WLOGFI("previous callback not called or callback invalid"); + return false; + } + displayStateCallback_ = callback; + + if (displayStateAgent_ == nullptr) { + displayStateAgent_ = new DisplayManagerAgent(this); + ret = SingletonContainer::Get().RegisterDisplayManagerAgent( + displayStateAgent_, + DisplayManagerAgentType::DISPLAY_STATE_LISTENER); + } + } + ret = ret && SingletonContainer::Get().SetDisplayState(state); + if (!ret) { + ClearDisplayStateCallback(); + } + return ret; +} + +bool DisplayManager::SetDisplayState(DisplayState state, DisplayStateCallback callback) +{ + return pImpl_->SetDisplayState(state, callback); +} + +DisplayState DisplayManager::GetDisplayState(DisplayId displayId) +{ + return SingletonContainer::Get().GetDisplayState(displayId); +} + +bool DisplayManager::SetScreenBrightness(uint64_t screenId, uint32_t level) +{ + WLOGFD("screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); + RSInterfaces::GetInstance().SetScreenBacklight(screenId, level); + return true; +} + +uint32_t DisplayManager::GetScreenBrightness(uint64_t screenId) const +{ + uint32_t level = static_cast(RSInterfaces::GetInstance().GetScreenBacklight(screenId)); + WLOGFD("screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); + return level; +} + +void DisplayManager::NotifyDisplayEvent(DisplayEvent event) +{ + // Unlock event dms->wms restore other hidden windows + WLOGFD("DisplayEvent:%{public}u", event); + SingletonContainer::Get().NotifyDisplayEvent(event); +} + +bool DisplayManager::Freeze(std::vector displayIds) +{ + WLOGFD("freeze display"); + if (displayIds.size() == 0) { + WLOGFE("freeze display fail, num of display is 0"); + return false; + } + if (displayIds.size() > MAX_DISPLAY_SIZE) { + WLOGFE("freeze display fail, displayIds size is bigger than %{public}u.", MAX_DISPLAY_SIZE); + return false; + } + return SingletonContainer::Get().SetFreeze(displayIds, true); +} + +bool DisplayManager::Unfreeze(std::vector displayIds) +{ + WLOGFD("unfreeze display"); + if (displayIds.size() == 0) { + WLOGFE("unfreeze display fail, num of display is 0"); + return false; + } + if (displayIds.size() > MAX_DISPLAY_SIZE) { + WLOGFE("unfreeze display fail, displayIds size is bigger than %{public}u.", MAX_DISPLAY_SIZE); + return false; + } + return SingletonContainer::Get().SetFreeze(displayIds, false); +} + +void DisplayManager::Impl::OnRemoteDied() +{ + WLOGFI("dms is died"); + std::lock_guard lock(mutex_); + displayManagerListener_ = nullptr; + displayStateAgent_ = nullptr; + powerEventListenerAgent_ = nullptr; + screenshotListenerAgent_ = nullptr; +} + +void DisplayManager::OnRemoteDied() +{ + pImpl_->OnRemoteDied(); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dm/src/display_manager_adapter.cpp b/window_manager/dm/src/display_manager_adapter.cpp new file mode 100644 index 0000000..84f774b --- /dev/null +++ b/window_manager/dm/src/display_manager_adapter.cpp @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2021-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 "display_manager_adapter.h" + +#include +#include +#include + +#include "display_manager.h" +#include "screen_manager.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAdapter"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerAdapter) +WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManagerAdapter) + +#define INIT_PROXY_CHECK_RETURN(ret) \ + do { \ + if (!InitDMSProxy()) { \ + WLOGFE("InitDMSProxy failed!"); \ + return ret; \ + } \ + } while (false) + +sptr DisplayManagerAdapter::GetDefaultDisplayInfo() +{ + INIT_PROXY_CHECK_RETURN(nullptr); + + return displayManagerServiceProxy_->GetDefaultDisplayInfo(); +} + +sptr DisplayManagerAdapter::GetDisplayInfoByScreenId(ScreenId screenId) +{ + INIT_PROXY_CHECK_RETURN(nullptr); + + return displayManagerServiceProxy_->GetDisplayInfoByScreen(screenId); +} + +std::shared_ptr DisplayManagerAdapter::GetDisplaySnapshot(DisplayId displayId) +{ + INIT_PROXY_CHECK_RETURN(nullptr); + + return displayManagerServiceProxy_->GetDisplaySnapshot(displayId); +} + +DMError ScreenManagerAdapter::GetScreenSupportedColorGamuts(ScreenId screenId, + std::vector& colorGamuts) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->GetScreenSupportedColorGamuts(screenId, colorGamuts); +} + +DMError ScreenManagerAdapter::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->GetScreenColorGamut(screenId, colorGamut); +} + +DMError ScreenManagerAdapter::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->SetScreenColorGamut(screenId, colorGamutIdx); +} + +DMError ScreenManagerAdapter::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->GetScreenGamutMap(screenId, gamutMap); +} + +DMError ScreenManagerAdapter::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->SetScreenGamutMap(screenId, gamutMap); +} + +DMError ScreenManagerAdapter::SetScreenColorTransform(ScreenId screenId) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->SetScreenColorTransform(screenId); +} + +ScreenId ScreenManagerAdapter::CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) +{ + INIT_PROXY_CHECK_RETURN(SCREEN_ID_INVALID); + + WLOGFI("DisplayManagerAdapter::CreateVirtualScreen"); + return displayManagerServiceProxy_->CreateVirtualScreen(option, displayManagerAgent->AsObject()); +} + +DMError ScreenManagerAdapter::DestroyVirtualScreen(ScreenId screenId) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + WLOGFI("DisplayManagerAdapter::DestroyVirtualScreen"); + return displayManagerServiceProxy_->DestroyVirtualScreen(screenId); +} + +DMError ScreenManagerAdapter::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + WLOGFI("DisplayManagerAdapter::SetVirtualScreenSurface"); + return displayManagerServiceProxy_->SetVirtualScreenSurface(screenId, surface); +} + +void ScreenManagerAdapter::SetScreenRotationLocked(bool isLocked) +{ + INIT_PROXY_CHECK_RETURN(); + WLOGFI("DisplayManagerAdapter::SetScreenRotationLocked"); + displayManagerServiceProxy_->SetScreenRotationLocked(isLocked); +} + +bool ScreenManagerAdapter::IsScreenRotationLocked() +{ + INIT_PROXY_CHECK_RETURN(false); + WLOGFI("DisplayManagerAdapter::IsScreenRotationLocked"); + return displayManagerServiceProxy_->IsScreenRotationLocked(); +} + +bool ScreenManagerAdapter::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) +{ + INIT_PROXY_CHECK_RETURN(false); + return displayManagerServiceProxy_->SetScreenPowerForAll(state, reason); +} + +ScreenPowerState ScreenManagerAdapter::GetScreenPower(ScreenId dmsScreenId) +{ + INIT_PROXY_CHECK_RETURN(ScreenPowerState::INVALID_STATE); + return displayManagerServiceProxy_->GetScreenPower(dmsScreenId); +} + +bool ScreenManagerAdapter::SetOrientation(ScreenId screenId, Orientation orientation) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->SetOrientation(screenId, orientation); +} + +bool BaseAdapter::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->RegisterDisplayManagerAgent(displayManagerAgent, type); +} + +bool BaseAdapter::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->UnregisterDisplayManagerAgent(displayManagerAgent, type); +} + +bool DisplayManagerAdapter::WakeUpBegin(PowerStateChangeReason reason) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->WakeUpBegin(reason); +} + +bool DisplayManagerAdapter::WakeUpEnd() +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->WakeUpEnd(); +} + +bool DisplayManagerAdapter::SuspendBegin(PowerStateChangeReason reason) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->SuspendBegin(reason); +} + +bool DisplayManagerAdapter::SuspendEnd() +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->SuspendEnd(); +} + +bool DisplayManagerAdapter::SetDisplayState(DisplayState state) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->SetDisplayState(state); +} + +DisplayState DisplayManagerAdapter::GetDisplayState(DisplayId displayId) +{ + INIT_PROXY_CHECK_RETURN(DisplayState::UNKNOWN); + + return displayManagerServiceProxy_->GetDisplayState(displayId); +} + +void DisplayManagerAdapter::NotifyDisplayEvent(DisplayEvent event) +{ + INIT_PROXY_CHECK_RETURN(); + + displayManagerServiceProxy_->NotifyDisplayEvent(event); +} + +bool DisplayManagerAdapter::SetFreeze(std::vector displayIds, bool isFreeze) +{ + INIT_PROXY_CHECK_RETURN(false); + return displayManagerServiceProxy_->SetFreeze(displayIds, isFreeze); +} + +bool BaseAdapter::InitDMSProxy() +{ + std::lock_guard lock(mutex_); + if (!isProxyValid_) { + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + WLOGFE("Failed to get system ability mgr."); + return false; + } + + sptr remoteObject + = systemAbilityManager->GetSystemAbility(DISPLAY_MANAGER_SERVICE_SA_ID); + if (!remoteObject) { + WLOGFE("Failed to get display manager service."); + return false; + } + + displayManagerServiceProxy_ = iface_cast(remoteObject); + if ((!displayManagerServiceProxy_) || (!displayManagerServiceProxy_->AsObject())) { + WLOGFE("Failed to get system display manager services"); + return false; + } + + dmsDeath_ = new(std::nothrow) DMSDeathRecipient(*this); + if (dmsDeath_ == nullptr) { + WLOGFE("Failed to create death Recipient ptr DMSDeathRecipient"); + return false; + } + if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(dmsDeath_)) { + WLOGFE("Failed to add death recipient"); + return false; + } + isProxyValid_ = true; + } + return true; +} + +DMSDeathRecipient::DMSDeathRecipient(BaseAdapter& adapter) : adapter_(adapter) +{ +} + +void DMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) +{ + if (wptrDeath == nullptr) { + WLOGFE("wptrDeath is null"); + return; + } + + sptr object = wptrDeath.promote(); + if (!object) { + WLOGFE("object is null"); + return; + } + WLOGFI("dms OnRemoteDied"); + adapter_.Clear(); + SingletonContainer::Get().OnRemoteDied(); + SingletonContainer::Get().OnRemoteDied(); + return; +} + +void BaseAdapter::Clear() +{ + if ((displayManagerServiceProxy_ != nullptr) && (displayManagerServiceProxy_->AsObject() != nullptr)) { + displayManagerServiceProxy_->AsObject()->RemoveDeathRecipient(dmsDeath_); + } + std::lock_guard lock(mutex_); + isProxyValid_ = false; +} + +ScreenId ScreenManagerAdapter::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +{ + INIT_PROXY_CHECK_RETURN(SCREEN_ID_INVALID); + + return displayManagerServiceProxy_->MakeMirror(mainScreenId, mirrorScreenId); +} + +sptr ScreenManagerAdapter::GetScreenInfo(ScreenId screenId) +{ + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("screen id is invalid"); + return nullptr; + } + INIT_PROXY_CHECK_RETURN(nullptr); + + sptr screenInfo = displayManagerServiceProxy_->GetScreenInfoById(screenId); + return screenInfo; +} + +std::vector DisplayManagerAdapter::GetAllDisplayIds() +{ + INIT_PROXY_CHECK_RETURN(std::vector()); + + return displayManagerServiceProxy_->GetAllDisplayIds(); +} + +DMError DisplayManagerAdapter::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + INIT_PROXY_CHECK_RETURN(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED); + + return displayManagerServiceProxy_->HasPrivateWindow(displayId, hasPrivateWindow); +} + +sptr DisplayManagerAdapter::GetDisplayInfo(DisplayId displayId) +{ + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("screen id is invalid"); + return nullptr; + } + INIT_PROXY_CHECK_RETURN(nullptr); + + return displayManagerServiceProxy_->GetDisplayInfoById(displayId); +} + +sptr DisplayManagerAdapter::GetCutoutInfo(DisplayId displayId) +{ + WLOGFI("DisplayManagerAdapter::GetCutoutInfo"); + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("screen id is invalid"); + return nullptr; + } + INIT_PROXY_CHECK_RETURN(nullptr); + return displayManagerServiceProxy_->GetCutoutInfo(displayId); +} + +sptr ScreenManagerAdapter::GetScreenGroupInfoById(ScreenId screenId) +{ + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("screenGroup id is invalid"); + return nullptr; + } + INIT_PROXY_CHECK_RETURN(nullptr); + + return displayManagerServiceProxy_->GetScreenGroupInfoById(screenId); +} + +std::vector> ScreenManagerAdapter::GetAllScreenInfos() +{ + INIT_PROXY_CHECK_RETURN(std::vector>()); + + return displayManagerServiceProxy_->GetAllScreenInfos(); +} + +ScreenId ScreenManagerAdapter::MakeExpand(std::vector screenId, std::vector startPoint) +{ + INIT_PROXY_CHECK_RETURN(SCREEN_ID_INVALID); + + return displayManagerServiceProxy_->MakeExpand(screenId, startPoint); +} + +void ScreenManagerAdapter::RemoveVirtualScreenFromGroup(std::vector screens) +{ + INIT_PROXY_CHECK_RETURN(); + + displayManagerServiceProxy_->RemoveVirtualScreenFromGroup(screens); +} + +bool ScreenManagerAdapter::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->SetScreenActiveMode(screenId, modeId); +} + +bool ScreenManagerAdapter::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) +{ + INIT_PROXY_CHECK_RETURN(false); + + return displayManagerServiceProxy_->SetVirtualPixelRatio(screenId, virtualPixelRatio); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dm/src/screen.cpp b/window_manager/dm/src/screen.cpp new file mode 100644 index 0000000..35aa7a1 --- /dev/null +++ b/window_manager/dm/src/screen.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2021-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 "screen.h" + +#include +#include +#include + +#include "class_var_definition.h" +#include "display_manager_adapter.h" +#include "screen_info.h" +#include "singleton_container.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "Screen"}; +} +class Screen::Impl : public RefBase { +public: + explicit Impl(sptr info) + { + screenInfo_ = info; + } + ~Impl() = default; + DEFINE_VAR_FUNC_GET_SET_WITH_LOCK(sptr, ScreenInfo, screenInfo); +}; + +Screen::Screen(sptr info) + : pImpl_(new Impl(info)) +{ +} + +Screen::~Screen() +{ +} + +bool Screen::IsGroup() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetIsScreenGroup(); +} + +std::string Screen::GetName() const +{ + return pImpl_->GetScreenInfo()->GetName(); +} + +ScreenId Screen::GetId() const +{ + return pImpl_->GetScreenInfo()->GetScreenId(); +} + +uint32_t Screen::GetWidth() const +{ + auto modeId = GetModeId(); + auto modes = GetSupportedModes(); + if (modeId < 0 || modeId >= modes.size()) { + return 0; + } + return modes[modeId]->width_; +} + +uint32_t Screen::GetHeight() const +{ + UpdateScreenInfo(); + auto modeId = GetModeId(); + auto modes = GetSupportedModes(); + if (modeId < 0 || modeId >= modes.size()) { + return 0; + } + return modes[modeId]->height_; +} + +uint32_t Screen::GetVirtualWidth() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetVirtualWidth(); +} + +uint32_t Screen::GetVirtualHeight() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetVirtualHeight(); +} + +float Screen::GetVirtualPixelRatio() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetVirtualPixelRatio(); +} + +Rotation Screen::GetRotation() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetRotation(); +} + +Orientation Screen::GetOrientation() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetOrientation(); +} + +bool Screen::IsReal() const +{ + return pImpl_->GetScreenInfo()->GetType() == ScreenType::REAL; +} + +bool Screen::SetOrientation(Orientation orientation) const +{ + WLOGFD("set orientation %{public}u", orientation); + return SingletonContainer::Get().SetOrientation(GetId(), orientation); +} + +DMError Screen::GetScreenSupportedColorGamuts(std::vector& colorGamuts) const +{ + return SingletonContainer::Get().GetScreenSupportedColorGamuts(GetId(), colorGamuts); +} + +DMError Screen::GetScreenColorGamut(ScreenColorGamut& colorGamut) const +{ + return SingletonContainer::Get().GetScreenColorGamut(GetId(), colorGamut); +} + +DMError Screen::SetScreenColorGamut(int32_t colorGamutIdx) +{ + return SingletonContainer::Get().SetScreenColorGamut(GetId(), colorGamutIdx); +} + +DMError Screen::GetScreenGamutMap(ScreenGamutMap& gamutMap) const +{ + return SingletonContainer::Get().GetScreenGamutMap(GetId(), gamutMap); +} + +DMError Screen::SetScreenGamutMap(ScreenGamutMap gamutMap) +{ + return SingletonContainer::Get().SetScreenGamutMap(GetId(), gamutMap); +} + +DMError Screen::SetScreenColorTransform() +{ + return SingletonContainer::Get().SetScreenColorTransform(GetId()); +} + +ScreenId Screen::GetParentId() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetParentId(); +} + +uint32_t Screen::GetModeId() const +{ + UpdateScreenInfo(); + return pImpl_->GetScreenInfo()->GetModeId(); +} + +std::vector> Screen::GetSupportedModes() const +{ + return pImpl_->GetScreenInfo()->GetModes(); +} + +bool Screen::SetScreenActiveMode(uint32_t modeId) +{ + ScreenId screenId = GetId(); + if (modeId >= GetSupportedModes().size()) { + return false; + } + return SingletonContainer::Get().SetScreenActiveMode(screenId, modeId); +} + +void Screen::UpdateScreenInfo(sptr info) const +{ + if (info == nullptr) { + WLOGFE("ScreenInfo is invalid"); + return; + } + pImpl_->SetScreenInfo(info); +} + +void Screen::UpdateScreenInfo() const +{ + auto screenInfo = SingletonContainer::Get().GetScreenInfo(GetId()); + UpdateScreenInfo(screenInfo); +} + +bool Screen::SetDensityDpi(uint32_t dpi) const +{ + if (dpi > DOT_PER_INCH_MAXIMUM_VALUE || dpi < DOT_PER_INCH_MINIMUM_VALUE) { + WLOGE("Invalid input dpi value, valid input range for DPI is %{public}u ~ %{public}u", + DOT_PER_INCH_MINIMUM_VALUE, DOT_PER_INCH_MAXIMUM_VALUE); + return false; + } + // Calculate display density, Density = Dpi / 160. + float density = static_cast(dpi) / 160; // 160 is the coefficient between density and dpi. + return SingletonContainer::Get().SetVirtualPixelRatio(GetId(), density); +} + +sptr Screen::GetScreenInfo() const +{ + return pImpl_->GetScreenInfo(); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dm/src/screen_group.cpp b/window_manager/dm/src/screen_group.cpp new file mode 100644 index 0000000..93dd8d0 --- /dev/null +++ b/window_manager/dm/src/screen_group.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021-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 "screen_group.h" + +#include + +#include "class_var_definition.h" +#include "display_manager_adapter.h" +#include "screen_group_info.h" +#include "screen_info.h" +#include "singleton_container.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenGroup"}; +} +class ScreenGroup::Impl : public RefBase { +public: + explicit Impl(sptr info) + { + screenGroupInfo_ = info; + } + ~Impl() = default; + + DEFINE_VAR_FUNC_GET_SET_WITH_LOCK(sptr, ScreenGroupInfo, screenGroupInfo); +}; + +ScreenGroup::ScreenGroup(sptr info) + : Screen(info), pImpl_(new Impl(info)) +{ +} + +void ScreenGroup::UpdateScreenGroupInfo(sptr info) const +{ + if (info == nullptr) { + WLOGFE("ScreenGroupInfo is nullptr."); + return; + } + Screen::UpdateScreenInfo(info); + pImpl_->SetScreenGroupInfo(info); +} + +void ScreenGroup::UpdateScreenGroupInfo() const +{ + auto screenInfo = SingletonContainer::Get().GetScreenGroupInfoById(GetId()); + UpdateScreenGroupInfo(screenInfo); +} + +ScreenGroup::~ScreenGroup() +{ +} + +ScreenCombination ScreenGroup::GetCombination() const +{ + UpdateScreenGroupInfo(); + return pImpl_->GetScreenGroupInfo()->GetCombination(); +} + +std::vector ScreenGroup::GetChildIds() const +{ + UpdateScreenGroupInfo(); + return pImpl_->GetScreenGroupInfo()->GetChildren(); +} + +std::vector ScreenGroup::GetChildPositions() const +{ + UpdateScreenGroupInfo(); + return pImpl_->GetScreenGroupInfo()->GetPosition(); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dm/src/screen_manager.cpp b/window_manager/dm/src/screen_manager.cpp new file mode 100644 index 0000000..e584d54 --- /dev/null +++ b/window_manager/dm/src/screen_manager.cpp @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2021-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 "screen_manager.h" + +#include +#include + +#include + +#include "display_manager_adapter.h" +#include "display_manager_agent_default.h" +#include "singleton_delegator.h" +#include "window_manager_hilog.h" + + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenManager"}; + const static uint32_t MAX_SCREEN_SIZE = 32; +} +class ScreenManager::Impl : public RefBase { +public: + Impl() = default; + ~Impl(); + static inline SingletonDelegator delegator; + ScreenId CreateVirtualScreen(VirtualScreenOption option); + sptr GetScreen(ScreenId screenId); + sptr GetScreenGroup(ScreenId screenId); + std::vector> GetAllScreens(); + bool RegisterScreenListener(sptr listener); + bool UnregisterScreenListener(sptr listener); + bool RegisterScreenGroupListener(sptr listener); + bool UnregisterScreenGroupListener(sptr listener); + bool RegisterVirtualScreenGroupListener(sptr listener); + bool UnregisterVirtualScreenGroupListener(sptr listener); + void OnRemoteDied(); + +private: + void NotifyScreenConnect(sptr info); + void NotifyScreenDisconnect(ScreenId); + void NotifyScreenChange(const sptr& screenInfo); + void NotifyScreenChange(const std::vector>& screenInfos); + bool UpdateScreenInfoLocked(sptr); + bool RegisterDisplayManagerAgent(); + bool UnregisterDisplayManagerAgent(); + bool isAllListenersRemoved() const; + + class ScreenManagerListener; + sptr screenManagerListener_; + std::map> screenMap_; + std::map> screenGroupMap_; + std::recursive_mutex mutex_; + std::set> screenListeners_; + std::set> screenGroupListeners_; + std::set> virtualScreenGroupListeners_; + sptr virtualScreenAgent_ = nullptr; +}; + +class ScreenManager::Impl::ScreenManagerListener : public DisplayManagerAgentDefault { +public: + ScreenManagerListener(sptr impl) : pImpl_(impl) + { + } + + void OnScreenConnect(sptr screenInfo) + { + if (screenInfo == nullptr || screenInfo->GetScreenId() == SCREEN_ID_INVALID) { + WLOGFE("OnScreenConnect, screenInfo is invalid."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("OnScreenConnect, impl is nullptr."); + return; + } + pImpl_->NotifyScreenConnect(screenInfo); + std::lock_guard lock(pImpl_->mutex_); + for (auto listener : pImpl_->screenListeners_) { + listener->OnConnect(screenInfo->GetScreenId()); + } + }; + + void OnScreenDisconnect(ScreenId screenId) + { + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("OnScreenDisconnect, screenId is invalid."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("OnScreenDisconnect, impl is nullptr."); + return; + } + pImpl_->NotifyScreenDisconnect(screenId); + std::lock_guard lock(pImpl_->mutex_); + for (auto listener : pImpl_->screenListeners_) { + listener->OnDisconnect(screenId); + } + }; + + void OnScreenChange(const sptr& screenInfo, ScreenChangeEvent event) + { + if (screenInfo == nullptr) { + WLOGFE("OnScreenChange, screenInfo is null."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("OnScreenChange, impl is nullptr."); + return; + } + WLOGFD("OnScreenChange. event %{public}u", event); + pImpl_->NotifyScreenChange(screenInfo); + std::lock_guard lock(pImpl_->mutex_); + for (auto listener: pImpl_->screenListeners_) { + listener->OnChange(screenInfo->GetScreenId()); + } + }; + + void OnScreenGroupChange(const std::string& trigger, const std::vector>& screenInfos, + ScreenGroupChangeEvent groupEvent) + { + if (screenInfos.empty()) { + WLOGFE("screenInfos is empty."); + return; + } + if (pImpl_ == nullptr) { + WLOGFE("impl is nullptr."); + return; + } + WLOGFD("trigger %{public}s, event %{public}u", trigger.c_str(), groupEvent); + pImpl_->NotifyScreenChange(screenInfos); + std::vector screenIds; + for (auto screenInfo : screenInfos) { + if (screenInfo->GetScreenId() != SCREEN_ID_INVALID) { + screenIds.push_back(screenInfo->GetScreenId()); + } + } + std::lock_guard lock(pImpl_->mutex_); + for (auto listener: pImpl_->screenGroupListeners_) { + listener->OnChange(screenIds, groupEvent); + } + NotifyVirtualScreenGroupChanged(screenInfos[0], trigger, screenIds, groupEvent); + }; +private: + void NotifyVirtualScreenGroupChanged(sptr screenInfo, + const std::string trigger, std::vector& ids, ScreenGroupChangeEvent groupEvent) + { + // check for invalid scene + if (pImpl_->virtualScreenGroupListeners_.size() <= 0) { + WLOGFW("no virtual screnn group listeners"); + return; + } + if (screenInfo->GetType() != ScreenType::VIRTUAL) { + WLOGFW("not virtual screen type: %{public}u", screenInfo->GetType()); + return; + } + + // get the parent of screen + ScreenId parent = groupEvent == ScreenGroupChangeEvent::ADD_TO_GROUP ? + screenInfo->GetParentId() : screenInfo->GetLastParentId(); + WLOGFD("parentId=[%{public}llu], lastParentId=[%{public}llu]", (unsigned long long)screenInfo->GetParentId(), + (unsigned long long)screenInfo->GetLastParentId()); + if (parent == INVALID_SCREEN_ID) { + WLOGFE("parentId is invalid"); + return; + } + auto screenGroup = pImpl_->GetScreenGroup(parent); + if (screenGroup == nullptr) { + WLOGFE("screenGroup is null"); + return; + } + + // notify mirror + ScreenCombination comb = screenGroup->GetCombination(); + WLOGFD("comb %{public}u", comb); + IVirtualScreenGroupListener::ChangeInfo changeInfo = {groupEvent, trigger, ids}; + for (auto listener: pImpl_->virtualScreenGroupListeners_) { + if (comb == ScreenCombination::SCREEN_MIRROR) { + listener->OnMirrorChange(changeInfo); + } + } + } + sptr pImpl_; +}; + +WM_IMPLEMENT_SINGLE_INSTANCE(ScreenManager) + +ScreenManager::ScreenManager() +{ + pImpl_ = new Impl(); +} + +ScreenManager::~ScreenManager() +{ +} + +ScreenManager::Impl::~Impl() +{ + std::lock_guard lock(mutex_); + UnregisterDisplayManagerAgent(); +} + +sptr ScreenManager::Impl::GetScreen(ScreenId screenId) +{ + auto screenInfo = SingletonContainer::Get().GetScreenInfo(screenId); + std::lock_guard lock(mutex_); + if (!UpdateScreenInfoLocked(screenInfo)) { + screenMap_.erase(screenId); + return nullptr; + } + return screenMap_[screenId]; +} + +sptr ScreenManager::GetScreenById(ScreenId screenId) +{ + return pImpl_->GetScreen(screenId); +} + +sptr ScreenManager::Impl::GetScreenGroup(ScreenId screenId) +{ + auto screenGroupInfo = SingletonContainer::Get().GetScreenGroupInfoById(screenId); + std::lock_guard lock(mutex_); + if (screenGroupInfo == nullptr) { + WLOGFE("screenGroupInfo is null"); + screenGroupMap_.erase(screenId); + return nullptr; + } + auto iter = screenGroupMap_.find(screenId); + if (iter != screenGroupMap_.end() && iter->second != nullptr) { + WLOGFI("get screenGroup in screenGroup map"); + iter->second->UpdateScreenGroupInfo(screenGroupInfo); + return iter->second; + } + sptr screenGroup = new ScreenGroup(screenGroupInfo); + screenGroupMap_[screenId] = screenGroup; + return screenGroup; +} + +sptr ScreenManager::GetScreenGroup(ScreenId screenId) +{ + return pImpl_->GetScreenGroup(screenId); +} + +std::vector> ScreenManager::Impl::GetAllScreens() +{ + auto screenInfos = SingletonContainer::Get().GetAllScreenInfos(); + std::vector> screens; + std::lock_guard lock(mutex_); + for (auto info: screenInfos) { + if (UpdateScreenInfoLocked(info)) { + screens.emplace_back(screenMap_[info->GetScreenId()]); + } + } + screenMap_.clear(); + for (auto screen: screens) { + screenMap_.insert(std::make_pair(screen->GetId(), screen)); + } + return screens; +} + +std::vector> ScreenManager::GetAllScreens() +{ + return pImpl_->GetAllScreens(); +} + +bool ScreenManager::Impl::RegisterScreenListener(sptr listener) +{ + std::lock_guard lock(mutex_); + bool regSucc = RegisterDisplayManagerAgent(); + if (regSucc) { + screenListeners_.insert(listener); + } + return regSucc; +} + +bool ScreenManager::RegisterScreenListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("RegisterScreenListener listener is nullptr."); + return false; + } + return pImpl_->RegisterScreenListener(listener); +} + +bool ScreenManager::Impl::UnregisterScreenListener(sptr listener) +{ + std::lock_guard lock(mutex_); + auto iter = std::find(screenListeners_.begin(), screenListeners_.end(), listener); + if (iter == screenListeners_.end()) { + WLOGFE("could not find this listener"); + return false; + } + screenListeners_.erase(iter); + return isAllListenersRemoved() ? UnregisterDisplayManagerAgent() : true; +} + +bool ScreenManager::UnregisterScreenListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("UnregisterScreenListener listener is nullptr."); + return false; + } + return pImpl_->UnregisterScreenListener(listener); +} + +bool ScreenManager::Impl::RegisterScreenGroupListener(sptr listener) +{ + std::lock_guard lock(mutex_); + bool regSucc = RegisterDisplayManagerAgent(); + if (regSucc) { + screenGroupListeners_.insert(listener); + } + return regSucc; +} + +bool ScreenManager::RegisterScreenGroupListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("RegisterScreenGroupListener listener is nullptr."); + return false; + } + return pImpl_->RegisterScreenGroupListener(listener); +} + +bool ScreenManager::Impl::UnregisterScreenGroupListener(sptr listener) +{ + std::lock_guard lock(mutex_); + auto iter = std::find(screenGroupListeners_.begin(), screenGroupListeners_.end(), listener); + if (iter == screenGroupListeners_.end()) { + WLOGFE("could not find this listener"); + return false; + } + screenGroupListeners_.erase(iter); + return isAllListenersRemoved() ? UnregisterDisplayManagerAgent() : true; +} + +bool ScreenManager::UnregisterScreenGroupListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("UnregisterScreenGroupListener listener is nullptr."); + return false; + } + return pImpl_->UnregisterScreenGroupListener(listener); +} + +bool ScreenManager::Impl::RegisterVirtualScreenGroupListener(sptr listener) +{ + std::lock_guard lock(mutex_); + bool regSucc = RegisterDisplayManagerAgent(); + if (regSucc) { + virtualScreenGroupListeners_.insert(listener); + } + return regSucc; +} + +bool ScreenManager::RegisterVirtualScreenGroupListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("RegisterVirtualScreenGroupListener listener is nullptr."); + return false; + } + return pImpl_->RegisterVirtualScreenGroupListener(listener); +} + +bool ScreenManager::Impl::UnregisterVirtualScreenGroupListener(sptr listener) +{ + std::lock_guard lock(mutex_); + auto iter = std::find(virtualScreenGroupListeners_.begin(), virtualScreenGroupListeners_.end(), listener); + if (iter == virtualScreenGroupListeners_.end()) { + WLOGFE("could not find this listener"); + return false; + } + virtualScreenGroupListeners_.erase(iter); + return isAllListenersRemoved() ? UnregisterDisplayManagerAgent() : true; +} + +bool ScreenManager::UnregisterVirtualScreenGroupListener(sptr listener) +{ + if (listener == nullptr) { + WLOGFE("UnregisterVirtualScreenGroupListener listener is nullptr."); + return false; + } + return pImpl_->UnregisterVirtualScreenGroupListener(listener); +} + +bool ScreenManager::Impl::RegisterDisplayManagerAgent() +{ + bool regSucc = true; + if (screenManagerListener_ == nullptr) { + screenManagerListener_ = new ScreenManagerListener(this); + bool regSucc = SingletonContainer::Get().RegisterDisplayManagerAgent( + screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + if (!regSucc) { + screenManagerListener_ = nullptr; + WLOGFW("RegisterDisplayManagerAgent failed !"); + } + } + return regSucc; +} + +bool ScreenManager::Impl::UnregisterDisplayManagerAgent() +{ + bool unRegSucc = true; + if (screenManagerListener_ != nullptr) { + unRegSucc = SingletonContainer::Get().UnregisterDisplayManagerAgent( + screenManagerListener_, DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + screenManagerListener_ = nullptr; + if (!unRegSucc) { + WLOGFW("UnregisterDisplayManagerAgent failed!"); + } + } + return unRegSucc; +} + +ScreenId ScreenManager::MakeExpand(const std::vector& options) +{ + WLOGFI("Make expand"); + if (options.empty()) { + return SCREEN_ID_INVALID; + } + if (options.size() > MAX_SCREEN_SIZE) { + WLOGFW("Make expand failed. The options size is bigger than %{public}u.", MAX_SCREEN_SIZE); + return SCREEN_ID_INVALID; + } + std::vector screenIds; + std::vector startPoints; + for (auto& option: options) { + if (std::find(screenIds.begin(), screenIds.end(), option.screenId_) != screenIds.end()) { + continue; + } + screenIds.emplace_back(option.screenId_); + startPoints.emplace_back(Point(option.startX_, option.startY_)); + } + ScreenId group = SingletonContainer::Get().MakeExpand(screenIds, startPoints); + if (group == SCREEN_ID_INVALID) { + WLOGFI("Make expand failed"); + } + return group; +} + +ScreenId ScreenManager::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +{ + WLOGFI("Make mirror for screen: %{public}" PRIu64"", mainScreenId); + if (mirrorScreenId.size() > MAX_SCREEN_SIZE) { + WLOGFW("Make Mirror failed. The mirrorScreenId size is bigger than %{public}u.", MAX_SCREEN_SIZE); + return SCREEN_ID_INVALID; + } + ScreenId group = SingletonContainer::Get().MakeMirror(mainScreenId, mirrorScreenId); + if (group == SCREEN_ID_INVALID) { + WLOGFI("create mirror failed"); + } + return group; +} + +DMError ScreenManager::RemoveVirtualScreenFromGroup(std::vector screens) +{ + WLOGFI("screens.size=%{public}llu", (unsigned long long)screens.size()); + if (screens.empty()) { + WLOGFW("RemoveVirtualScreenFromGroup failed. screens is empty."); + return DMError::DM_ERROR_INVALID_PARAM; + } + if (screens.size() > MAX_SCREEN_SIZE) { + WLOGFW("RemoveVirtualScreenFromGroup failed. The screens size is bigger than %{public}u.", MAX_SCREEN_SIZE); + return DMError::DM_ERROR_INVALID_PARAM; + } + SingletonContainer::Get().RemoveVirtualScreenFromGroup(screens); + return DMError::DM_OK; +} + +ScreenId ScreenManager::CreateVirtualScreen(VirtualScreenOption option) +{ + return pImpl_->CreateVirtualScreen(option); +} + +ScreenId ScreenManager::Impl::CreateVirtualScreen(VirtualScreenOption option) +{ + // After the process creating the virtual screen is killed, DMS needs to delete the virtual screen + if (virtualScreenAgent_ == nullptr) { + virtualScreenAgent_ = new DisplayManagerAgentDefault(); + } + return SingletonContainer::Get().CreateVirtualScreen(option, virtualScreenAgent_); +} + +DMError ScreenManager::DestroyVirtualScreen(ScreenId screenId) +{ + return SingletonContainer::Get().DestroyVirtualScreen(screenId); +} + +DMError ScreenManager::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + return SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface); +} + +bool ScreenManager::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) +{ + WLOGFI("state:%{public}u, reason:%{public}u", state, reason); + return SingletonContainer::Get().SetScreenPowerForAll(state, reason); +} + +ScreenPowerState ScreenManager::GetScreenPower(ScreenId dmsScreenId) +{ + return SingletonContainer::Get().GetScreenPower(dmsScreenId); +} + +DMError ScreenManager::SetScreenRotationLocked(bool isLocked) +{ + SingletonContainer::Get().SetScreenRotationLocked(isLocked); + return DMError::DM_OK; +} + +bool ScreenManager::IsScreenRotationLocked() +{ + return SingletonContainer::Get().IsScreenRotationLocked(); +} + +void ScreenManager::Impl::NotifyScreenConnect(sptr info) +{ + std::lock_guard lock(mutex_); + UpdateScreenInfoLocked(info); +} + +void ScreenManager::Impl::NotifyScreenDisconnect(ScreenId screenId) +{ + WLOGFI("screenId:%{public}" PRIu64".", screenId); + std::lock_guard lock(mutex_); + screenMap_.erase(screenId); +} + +void ScreenManager::Impl::NotifyScreenChange(const sptr& screenInfo) +{ + std::lock_guard lock(mutex_); + UpdateScreenInfoLocked(screenInfo); +} + +void ScreenManager::Impl::NotifyScreenChange(const std::vector>& screenInfos) +{ + std::lock_guard lock(mutex_); + for (auto screenInfo : screenInfos) { + UpdateScreenInfoLocked(screenInfo); + } +} + +bool ScreenManager::Impl::UpdateScreenInfoLocked(sptr screenInfo) +{ + if (screenInfo == nullptr) { + WLOGFE("displayInfo is null"); + return false; + } + ScreenId screenId = screenInfo->GetScreenId(); + WLOGFI("screenId:%{public}" PRIu64".", screenId); + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("displayId is invalid."); + return false; + } + auto iter = screenMap_.find(screenId); + if (iter != screenMap_.end() && iter->second != nullptr) { + WLOGFI("get screen in screen map"); + iter->second->UpdateScreenInfo(screenInfo); + return true; + } + sptr screen = new Screen(screenInfo); + screenMap_[screenId] = screen; + return true; +} + +bool ScreenManager::Impl::isAllListenersRemoved() const +{ + return screenListeners_.empty() && screenGroupListeners_.empty() && virtualScreenGroupListeners_.empty(); +} + +void ScreenManager::Impl::OnRemoteDied() +{ + WLOGFI("dms is died"); + std::lock_guard lock(mutex_); + screenManagerListener_ = nullptr; + virtualScreenAgent_ = nullptr; +} + +void ScreenManager::OnRemoteDied() +{ + pImpl_->OnRemoteDied(); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dm/src/zidl/display_manager_agent_proxy.cpp b/window_manager/dm/src/zidl/display_manager_agent_proxy.cpp new file mode 100644 index 0000000..550c833 --- /dev/null +++ b/window_manager/dm/src/zidl/display_manager_agent_proxy.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2021-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 "zidl/display_manager_agent_proxy.h" +#include +#include "marshalling_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAgentProxy"}; +} + +void DisplayManagerAgentProxy::NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUint32(static_cast(event))) { + WLOGFE("Write event failed"); + return; + } + + if (!data.WriteUint32(static_cast(status))) { + WLOGFE("Write status failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_NOTIFY_DISPLAY_POWER_EVENT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::NotifyDisplayStateChanged(DisplayId id, DisplayState state) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUint32(static_cast(state))) { + WLOGFE("Write DisplayState failed"); + return; + } + + if (!data.WriteUint64(static_cast(id))) { + WLOGFE("Write displayId failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_NOTIFY_DISPLAY_STATE_CHANGED, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnScreenConnect(sptr screenInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(screenInfo.GetRefPtr())) { + WLOGFE("Write ScreenInfo failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_SCREEN_CONNECT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnScreenDisconnect(ScreenId screenId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUint64(screenId)) { + WLOGFE("Write ScreenId failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_SCREEN_DISCONNECT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnScreenChange(const sptr& screenInfo, ScreenChangeEvent event) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(screenInfo.GetRefPtr())) { + WLOGFE("Write screenInfo failed"); + return; + } + + if (!data.WriteUint32(static_cast(event))) { + WLOGFE("Write ScreenChangeEvent failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_SCREEN_CHANGED, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnScreenGroupChange(const std::string& trigger, + const std::vector>& screenInfos, ScreenGroupChangeEvent event) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteString(trigger)) { + WLOGFE("Write trigger failed"); + return; + } + + if (!MarshallingHelper::MarshallingVectorParcelableObj(data, screenInfos)) { + WLOGFE("Write screenInfos failed"); + return; + } + + if (!data.WriteUint32(static_cast(event))) { + WLOGFE("Write ScreenGroupChangeEvent failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_SCREENGROUP_CHANGED, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnDisplayCreate(sptr displayInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(displayInfo.GetRefPtr())) { + WLOGFE("Write DisplayInfo failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_DISPLAY_CONNECT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnDisplayDestroy(DisplayId displayId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUint64(displayId)) { + WLOGFE("Write DisplayId failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_DISPLAY_DISCONNECT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnDisplayChange(sptr displayInfo, DisplayChangeEvent event) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(displayInfo.GetRefPtr())) { + WLOGFE("Write DisplayInfo failed"); + return; + } + + if (!data.WriteUint32(static_cast(event))) { + WLOGFE("Write DisplayChangeEvent failed"); + return; + } + + if (Remote()->SendRequest(TRANS_ID_ON_DISPLAY_CHANGED, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void DisplayManagerAgentProxy::OnScreenshot(sptr snapshotInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteParcelable(snapshotInfo.GetRefPtr())) { + WLOGFE("Write ScreenshotInfo failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_ON_SCREEN_SHOT, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} +} // namespace Rosen +} // namespace OHOS + diff --git a/window_manager/dm/src/zidl/display_manager_agent_stub.cpp b/window_manager/dm/src/zidl/display_manager_agent_stub.cpp new file mode 100644 index 0000000..20416dd --- /dev/null +++ b/window_manager/dm/src/zidl/display_manager_agent_stub.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021-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 "zidl/display_manager_agent_stub.h" + +#include + +#include "display_info.h" +#include "dm_common.h" +#include "marshalling_helper.h" +#include "screen_info.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAgentStub"}; +} + +int32_t DisplayManagerAgentStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + WLOGFI("code:%{public}u", code); + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + switch (code) { + case TRANS_ID_NOTIFY_DISPLAY_POWER_EVENT: { + DisplayPowerEvent event = static_cast(data.ReadUint32()); + EventStatus status = static_cast(data.ReadUint32()); + NotifyDisplayPowerEvent(event, status); + break; + } + case TRANS_ID_NOTIFY_DISPLAY_STATE_CHANGED: { + DisplayState state = static_cast(data.ReadUint32()); + DisplayId id = static_cast(data.ReadUint64()); + NotifyDisplayStateChanged(id, state); + break; + } + case TRANS_ID_ON_SCREEN_CONNECT: { + sptr screenInfo = data.ReadParcelable(); + OnScreenConnect(screenInfo); + break; + } + case TRANS_ID_ON_SCREEN_DISCONNECT: { + ScreenId screenId; + if (!data.ReadUint64(screenId)) { + WLOGFE("Read ScreenId failed"); + return -1; + } + OnScreenDisconnect(screenId); + break; + } + case TRANS_ID_ON_SCREEN_CHANGED: { + sptr screenInfo = data.ReadParcelable(); + uint32_t event; + if (!data.ReadUint32(event)) { + WLOGFE("Read ScreenChangeEvent failed"); + return -1; + } + OnScreenChange(screenInfo, static_cast(event)); + break; + } + case TRANS_ID_ON_SCREENGROUP_CHANGED: { + std::string trigger; + if (!data.ReadString(trigger)) { + WLOGFE("Read trigger failed"); + return -1; + } + std::vector> screenInfos; + if (!MarshallingHelper::UnmarshallingVectorParcelableObj(data, screenInfos)) { + WLOGFE("Read ScreenInfo failed"); + return -1; + } + uint32_t event; + if (!data.ReadUint32(event)) { + WLOGFE("Read ScreenChangeEvent failed"); + return -1; + } + OnScreenGroupChange(trigger, screenInfos, static_cast(event)); + break; + } + case TRANS_ID_ON_DISPLAY_CONNECT: { + sptr displayInfo = data.ReadParcelable(); + OnDisplayCreate(displayInfo); + break; + } + case TRANS_ID_ON_DISPLAY_DISCONNECT: { + DisplayId displayId; + if (!data.ReadUint64(displayId)) { + WLOGFE("Read DisplayId failed"); + return -1; + } + OnDisplayDestroy(displayId); + break; + } + case TRANS_ID_ON_DISPLAY_CHANGED: { + sptr displayInfo = data.ReadParcelable(); + uint32_t event; + if (!data.ReadUint32(event)) { + WLOGFE("Read DisplayChangeEvent failed"); + return -1; + } + OnDisplayChange(displayInfo, static_cast(event)); + break; + } + case TRANS_ID_ON_SCREEN_SHOT: { + sptr snapshotInfo = data.ReadParcelable(); + OnScreenshot(snapshotInfo); + break; + } + default: + break; + } + return 0; +} +} // namespace OHOS::Rosen diff --git a/window_manager/dm/test/BUILD.gn b/window_manager/dm/test/BUILD.gn new file mode 100644 index 0000000..0abe745 --- /dev/null +++ b/window_manager/dm/test/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright (c) 2021-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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/dm/test/unittest/BUILD.gn b/window_manager/dm/test/unittest/BUILD.gn new file mode 100644 index 0000000..90603df --- /dev/null +++ b/window_manager/dm/test/unittest/BUILD.gn @@ -0,0 +1,171 @@ +# Copyright (c) 2021-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. + +import("//build/test.gni") + +module_out_path = "window_manager/dm" + +group("unittest") { + testonly = true + + deps = [ + ":dm_display_change_unit_test", + ":dm_display_manager_adapter_test", + ":dm_display_manager_agent_stub_test", + ":dm_display_manager_test", + ":dm_display_power_unit_test", + ":dm_display_test", + ":dm_screen_group_test", + ":dm_screen_manager_test", + ":dm_screen_test", + ":dm_screenshot_test", + ] +} + +ohos_unittest("dm_display_test") { + module_out_path = module_out_path + + sources = [ "display_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_display_change_unit_test") { + module_out_path = module_out_path + + sources = [ "display_change_unit_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_display_power_unit_test") { + module_out_path = module_out_path + + sources = [ "display_power_unit_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_screenshot_test") { + module_out_path = module_out_path + + sources = [ "screenshot_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_screen_manager_test") { + module_out_path = module_out_path + + include_dirs = [ "//foundation/window/window_manager/dm/src" ] + + sources = [ "screen_manager_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_screen_test") { + module_out_path = module_out_path + + sources = [ "screen_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_screen_group_test") { + module_out_path = module_out_path + + sources = [ "screen_group_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_display_manager_adapter_test") { + module_out_path = module_out_path + + sources = [ "display_manager_adapter_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_display_manager_test") { + module_out_path = module_out_path + + include_dirs = [ "//foundation/window/window_manager/dm/src" ] + + sources = [ "display_manager_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +ohos_unittest("dm_display_manager_agent_stub_test") { + module_out_path = module_out_path + + sources = [ "display_manager_agent_stub_test.cpp" ] + + deps = [ ":dm_unittest_common" ] +} + +## Build dm_unittest_common.a {{{ +config("dm_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/dm/include/zidl", + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/snapshot", + "//foundation/window/window_manager/test/common/mock", + "//foundation/window/window_manager/test/common/utils/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/test/common/utils/include", + "//foundation/window/window_manager/utils/include", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client", # RSSurface + ] +} + +ohos_static_library("dm_unittest_common") { + visibility = [ ":*" ] + testonly = true + + public_configs = [ + ":dm_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//commonlibrary/c_utils/base:utils", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/multimedia/image_framework/interfaces/innerkits:image_native", # PixelMap + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/snapshot:snapshot_display", + "//foundation/window/window_manager/test/common/utils:libtestutil", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + "//third_party/libjpeg-turbo:turbojpeg_static", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "hilog_native:libhilog", + "ipc:ipc_core", + ] + subsystem_name = "window" + part_name = "window_manager" +} +## Build wm_unittest_common.a }}} diff --git a/window_manager/dm/test/unittest/display_change_unit_test.cpp b/window_manager/dm/test/unittest/display_change_unit_test.cpp new file mode 100644 index 0000000..8c5ef83 --- /dev/null +++ b/window_manager/dm/test/unittest/display_change_unit_test.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021-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 "display_info.h" +#include "display_manager.h" +#include "mock_display_manager_adapter.h" +#include "screen_manager.h" +#include "screen_manager/rs_screen_mode_info.h" +#include "singleton_mocker.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayChangeUnitTest"}; +using Mocker = SingletonMocker; + +class DisplayChangeEventListener : public DisplayManager::IDisplayListener { +public: + virtual void OnCreate(DisplayId displayId) {} + + virtual void OnDestroy(DisplayId displayId) {} + + virtual void OnChange(DisplayId displayId) {} +}; + +class DisplayChangeUnitTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + bool ScreenSizeEqual(const sptr screen, const sptr curInfo); + bool DisplaySizeEqual(const sptr display, const sptr curInfo); + static DisplayId defaultDisplayId_; + static ScreenId defaultScreenId_; + sptr listener_ = new DisplayChangeEventListener(); +}; +DisplayId DisplayChangeUnitTest::defaultDisplayId_ = DISPLAY_ID_INVALID; +ScreenId DisplayChangeUnitTest::defaultScreenId_ = SCREEN_ID_INVALID; + +void DisplayChangeUnitTest::SetUpTestCase() +{ + defaultDisplayId_ = DisplayManager::GetInstance().GetDefaultDisplayId(); + sptr defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultDisplayId_); + if (defaultDisplay != nullptr) { + defaultScreenId_ = defaultDisplay->GetScreenId(); + } +} + +void DisplayChangeUnitTest::TearDownTestCase() +{ +} + +void DisplayChangeUnitTest::SetUp() +{ +} + +void DisplayChangeUnitTest::TearDown() +{ +} + +bool DisplayChangeUnitTest::DisplaySizeEqual(const sptr display, const sptr curInfo) +{ + uint32_t dWidth = static_cast(display->GetWidth()); + uint32_t dHeight = static_cast(display->GetHeight()); + WLOGI("DisplaySizeEqual:: DisplaySize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u", + dWidth, dHeight, curInfo->width_, curInfo->height_); + return ((curInfo->width_ == dWidth) && (curInfo->height_ == dHeight)); +} + +namespace { +/** + * @tc.name: RegisterDisplayChangeListener01 + * @tc.desc: Register and Unregister displayChangeListener with valid listener and check return true + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeUnitTest, RegisterDisplayChangeListener01, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) + .Times(1).WillOnce(Return(true)); + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(listener_); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) + .Times(1).WillOnce(Return(true)); + ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener_); + ASSERT_EQ(true, ret); +} + +/** + * @tc.name: RegisterDisplayChangeListener02 + * @tc.desc: Register and Unregister displayChangeListener with nullptr and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeUnitTest, RegisterDisplayChangeListener02, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) + .Times(0); + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(nullptr); + ASSERT_EQ(false, ret); + + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) + .Times(0); + ret = DisplayManager::GetInstance().UnregisterDisplayListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener03 + * @tc.desc: Register and Unregister displayChangeListener when ipc fails and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeUnitTest, RegisterDisplayChangeListener03, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) + .Times(1).WillOnce(Return(false)); + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(listener_); + ASSERT_EQ(false, ret); + + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_EVENT_LISTENER)) + .Times(0); + ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener_); + ASSERT_EQ(false, ret); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dm/test/unittest/display_manager_adapter_test.cpp b/window_manager/dm/test/unittest/display_manager_adapter_test.cpp new file mode 100644 index 0000000..096a77b --- /dev/null +++ b/window_manager/dm/test/unittest/display_manager_adapter_test.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2022-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 "display_manager_adapter.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayManagerAdapterTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void DisplayManagerAdapterTest::SetUpTestCase() +{ +} + +void DisplayManagerAdapterTest::TearDownTestCase() +{ +} + +void DisplayManagerAdapterTest::SetUp() +{ +} + +void DisplayManagerAdapterTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetDisplayInfo + * @tc.desc: test nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetDisplayInfo, Function | SmallTest | Level2) +{ + sptr info = SingletonContainer::Get().GetDisplayInfo(DISPLAY_ID_INVALID); + ASSERT_EQ(info, nullptr); +} + +/** + * @tc.name: GetCutoutInfo + * @tc.desc: test nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetCutoutInfo, Function | SmallTest | Level2) +{ + sptr info = SingletonContainer::Get().GetCutoutInfo(DISPLAY_ID_INVALID); + ASSERT_EQ(info, nullptr); +} + +/** + * @tc.name: GetScreenSupportedColorGamuts + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetScreenSupportedColorGamuts, Function | SmallTest | Level2) +{ + std::vector colorGamuts; + SingletonContainer::Get().GetScreenSupportedColorGamuts(0, colorGamuts); +} + +/** + * @tc.name: SetScreenColorGamut + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, SetScreenColorGamut, Function | SmallTest | Level2) +{ + std::vector colorGamuts; + DMError err = SingletonContainer::Get().SetScreenColorGamut(0, -1); + ASSERT_EQ(err, DMError::DM_ERROR_RENDER_SERVICE_FAILED); +} + +/** + * @tc.name: GetScreenColorGamut + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetScreenColorGamut, Function | SmallTest | Level2) +{ + ScreenColorGamut colorGamut; + DMError err = SingletonContainer::Get().GetScreenColorGamut(0, colorGamut); + ASSERT_EQ(err, DMError::DM_ERROR_RENDER_SERVICE_FAILED); +} + +/** + * @tc.name: GetScreenGamutMap + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetScreenGamutMap, Function | SmallTest | Level2) +{ + ScreenGamutMap gamutMap; + DMError err = SingletonContainer::Get().GetScreenGamutMap(0, gamutMap); + ASSERT_EQ(err, DMError::DM_ERROR_RENDER_SERVICE_FAILED); +} + +/** + * @tc.name: SetScreenGamutMap + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, SetScreenGamutMap, Function | SmallTest | Level2) +{ + DMError err = SingletonContainer::Get().SetScreenGamutMap(0, GAMUT_MAP_CONSTANT); + ASSERT_EQ(err, DMError::DM_ERROR_RENDER_SERVICE_FAILED); +} + +/** + * @tc.name: SetScreenColorTransform + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, SetScreenColorTransform, Function | SmallTest | Level2) +{ + DMError err = SingletonContainer::Get().SetScreenColorTransform(0); + ASSERT_EQ(err, DMError::DM_OK); +} + +/** + * @tc.name: SetFreeze + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, SetFreeze, Function | SmallTest | Level2) +{ + std::vector displayIds; + bool ret = SingletonContainer::Get().SetFreeze(displayIds, false); + ASSERT_TRUE(ret); +} + +/** + * @tc.name: GetScreenGroupInfoById + * @tc.desc: test nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetScreenGroupInfoById, Function | SmallTest | Level2) +{ + auto info = SingletonContainer::Get().GetScreenGroupInfoById(SCREEN_ID_INVALID); + ASSERT_EQ(info, nullptr); +} + +/** + * @tc.name: GetScreenInfo + * @tc.desc: test nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, GetScreenInfo, Function | SmallTest | Level2) +{ + sptr info = SingletonContainer::Get().GetScreenInfo(SCREEN_ID_INVALID); + ASSERT_EQ(info, nullptr); +} + +/** + * @tc.name: OnRemoteDied + * @tc.desc: test nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, OnRemoteDied, Function | SmallTest | Level2) +{ + sptr dmsDeath_ = nullptr; + dmsDeath_ = new(std::nothrow) DMSDeathRecipient(SingletonContainer::Get()); + dmsDeath_->OnRemoteDied(nullptr); +} + +/** + * @tc.name: OnRemoteDied01 + * @tc.desc: test nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, OnRemoteDied01, Function | SmallTest | Level2) +{ + sptr dmsDeath_ = nullptr; + dmsDeath_ = new(std::nothrow) DMSDeathRecipient(SingletonContainer::Get()); + SingletonContainer::Get().InitDMSProxy(); + sptr obj = SingletonContainer::Get().displayManagerServiceProxy_->AsObject(); + wptr wptrDeath = obj; + dmsDeath_->OnRemoteDied(wptrDeath); +} + +/** + * @tc.name: Clear + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, Clear, Function | SmallTest | Level2) +{ + SingletonContainer::Get().InitDMSProxy(); + SingletonContainer::Get().Clear(); + ASSERT_FALSE(SingletonContainer::Get().isProxyValid_); +} + +/** + * @tc.name: Clear01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAdapterTest, Clear01, Function | SmallTest | Level2) +{ + SingletonContainer::Get().InitDMSProxy(); + SingletonContainer::Get().displayManagerServiceProxy_ = nullptr; + SingletonContainer::Get().Clear(); + ASSERT_FALSE(SingletonContainer::Get().isProxyValid_); +} +} +} +} \ No newline at end of file diff --git a/window_manager/dm/test/unittest/display_manager_agent_stub_test.cpp b/window_manager/dm/test/unittest/display_manager_agent_stub_test.cpp new file mode 100644 index 0000000..bd48651 --- /dev/null +++ b/window_manager/dm/test/unittest/display_manager_agent_stub_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022-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 "display_manager_agent_stub.h" +#include "display_manager_agent_default.h" + + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { + +class DisplayManagerAgentStubTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr stub_; +}; + +void DisplayManagerAgentStubTest::SetUpTestCase() +{ +} + +void DisplayManagerAgentStubTest::TearDownTestCase() +{ +} + +void DisplayManagerAgentStubTest::SetUp() +{ + stub_ = new DisplayManagerAgentDefault(); +} + +void DisplayManagerAgentStubTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnRemoteRequest01 + * @tc.desc: TRANS_ID_ON_DISPLAY_CONNECT + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentStubTest, OnRemoteRequest01, Function | SmallTest | Level1) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(DisplayManagerAgentStub::GetDescriptor()); + sptr displayInfo; + data.WriteParcelable(displayInfo.GetRefPtr()); + uint32_t code = static_cast(IDisplayManagerAgent::TRANS_ID_ON_DISPLAY_CONNECT); + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest02 + * @tc.desc: TRANS_ID_ON_DISPLAY_DISCONNECT + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentStubTest, OnRemoteRequest02, Function | SmallTest | Level1) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(DisplayManagerAgentStub::GetDescriptor()); + DisplayId displayId = 0; + data.WriteUint64(displayId); + uint32_t code = static_cast(IDisplayManagerAgent::TRANS_ID_ON_DISPLAY_DISCONNECT); + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dm/test/unittest/display_manager_test.cpp b/window_manager/dm/test/unittest/display_manager_test.cpp new file mode 100644 index 0000000..d896abe --- /dev/null +++ b/window_manager/dm/test/unittest/display_manager_test.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2022-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 "display_manager.h" +#include "window.h" + +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" +#include "display_manager.cpp" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class DmMockScreenshotListener : public DisplayManager::IScreenshotListener { +public: + void OnScreenshot(const ScreenshotInfo info) override {} +}; +class DmMockDisplayListener : public DisplayManager::IDisplayListener { +public: + void OnCreate(DisplayId) override {} + void OnDestroy(DisplayId) override {} + void OnChange(DisplayId) override {} +}; +class DisplayManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void DisplayManagerTest::SetUpTestCase() +{ +} + +void DisplayManagerTest::TearDownTestCase() +{ +} + +void DisplayManagerTest::SetUp() +{ +} + +void DisplayManagerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Freeze01 + * @tc.desc: success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, Freeze01, Function | SmallTest | Level1) +{ + std::vector displayIds; + displayIds.push_back(0); + bool ret = DisplayManager::GetInstance().Freeze(displayIds); + ASSERT_TRUE(ret); +} + +/** + * @tc.name: Freeze02 + * @tc.desc: test Freeze displayIds exceed the maximum + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, Freeze02, Function | SmallTest | Level1) +{ + std::vector displayIds; + for (uint32_t i = 0; i < 33; i++) { // MAX_DISPLAY_SIZE + 1 + displayIds.push_back(i); + } + + bool ret = DisplayManager::GetInstance().Freeze(displayIds); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: Freeze03 + * @tc.desc: test Freeze displayIds empty + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, Freeze03, Function | SmallTest | Level1) +{ + std::vector displayIds; + bool ret = DisplayManager::GetInstance().Freeze(displayIds); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: Unfreeze01 + * @tc.desc: success + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, Unfreeze01, Function | SmallTest | Level1) +{ + std::vector displayIds; + displayIds.push_back(0); + bool ret = DisplayManager::GetInstance().Unfreeze(displayIds); + ASSERT_TRUE(ret); +} + +/** + * @tc.name: Unfreeze02 + * @tc.desc: test Freeze displayIds exceed the maximum + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, Unfreeze02, Function | SmallTest | Level1) +{ + std::vector displayIds; + for (uint32_t i = 0; i < 33; i++) { // MAX_DISPLAY_SIZE + 1 + displayIds.push_back(i); + } + + bool ret = DisplayManager::GetInstance().Unfreeze(displayIds); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: Unfreeze03 + * @tc.desc: test Freeze displayIds empty + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, Unfreeze03, Function | SmallTest | Level1) +{ + std::vector displayIds; + bool ret = DisplayManager::GetInstance().Unfreeze(displayIds); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: RegisterScreenshotListener01 + * @tc.desc: test RegisterScreenshotListener with null listener + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, RegisterScreenshotListener01, Function | SmallTest | Level1) +{ + bool ret = DisplayManager::GetInstance().RegisterScreenshotListener(nullptr); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: RegisterScreenshotListener02 + * @tc.desc: test RegisterScreenshotListener with null listener + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, RegisterScreenshotListener02, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(false)); + sptr listener = new DmMockScreenshotListener(); + bool ret = DisplayManager::GetInstance().RegisterScreenshotListener(listener); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: UnregisterScreenshotListener01 + * @tc.desc: test UnregisterScreenshotListener with null listener + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, UnregisterScreenshotListener01, Function | SmallTest | Level1) +{ + bool ret = DisplayManager::GetInstance().UnregisterScreenshotListener(nullptr); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: OnDisplayCreate01 + * @tc.desc: OnDisplayCreate + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, OnDisplayCreate01, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockDisplayListener(); + DisplayManager::GetInstance().RegisterDisplayListener(listener); + auto displayManagerListener = DisplayManager::GetInstance().pImpl_->displayManagerListener_; + ASSERT_NE(displayManagerListener, nullptr); + displayManagerListener->OnDisplayCreate(nullptr); + sptr displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(DISPLAY_ID_INVALID); + displayManagerListener->OnDisplayCreate(displayInfo); + displayInfo->SetDisplayId(0); + displayManagerListener->OnDisplayCreate(displayInfo); + ASSERT_NE(displayManagerListener->pImpl_, nullptr); + displayManagerListener->pImpl_ = nullptr; + displayManagerListener->OnDisplayCreate(displayInfo); + DisplayManager::GetInstance().pImpl_->displayManagerListener_ = nullptr; +} + +/** + * @tc.name: OnDisplayDestroy + * @tc.desc: OnDisplayDestroy + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, OnDisplayDestroy, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockDisplayListener(); + DisplayManager::GetInstance().RegisterDisplayListener(listener); + auto displayManagerListener = DisplayManager::GetInstance().pImpl_->displayManagerListener_; + ASSERT_NE(displayManagerListener, nullptr); + displayManagerListener->OnDisplayDestroy(DISPLAY_ID_INVALID); + displayManagerListener->OnDisplayDestroy(0); + displayManagerListener->pImpl_ = nullptr; + displayManagerListener->OnDisplayDestroy(1); + DisplayManager::GetInstance().pImpl_->displayManagerListener_ = nullptr; +} + +/** + * @tc.name: OnDisplayChange + * @tc.desc: OnDisplayChange + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, OnDisplayChange, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockDisplayListener(); + DisplayManager::GetInstance().RegisterDisplayListener(listener); + auto displayManagerListener = DisplayManager::GetInstance().pImpl_->displayManagerListener_; + ASSERT_NE(displayManagerListener, nullptr); + DisplayChangeEvent event = DisplayChangeEvent::DISPLAY_SIZE_CHANGED; + displayManagerListener->OnDisplayChange(nullptr, event); + sptr displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(DISPLAY_ID_INVALID); + displayManagerListener->OnDisplayChange(displayInfo, event); + displayInfo->SetDisplayId(0); + displayManagerListener->OnDisplayChange(displayInfo, event); + ASSERT_NE(displayManagerListener->pImpl_, nullptr); + displayManagerListener->pImpl_ = nullptr; + displayManagerListener->OnDisplayChange(displayInfo, event); + DisplayManager::GetInstance().pImpl_->displayManagerListener_ = nullptr; +} + +/** + * @tc.name: CheckRectValid + * @tc.desc: CheckRectValid all + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, CheckRectValid, Function | SmallTest | Level1) +{ + int32_t oriHeight = 500; + int32_t oriWidth = 500; + Media::Rect rect = {.left = 1, .top = 1, .width = 1, .height = 1}; + bool ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_TRUE(ret); + rect.left = -1; + ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_FALSE(ret); + rect.left = 1; + rect.top = -1; + ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_FALSE(ret); + rect.top = 1; + rect.width = -1; + ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_FALSE(ret); + rect.width = 1; + rect.height = -1; + ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_FALSE(ret); + rect.width = 500; + rect.height = 1; + ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_FALSE(ret); + rect.width = 1; + rect.height = 500; + ret = DisplayManager::GetInstance().pImpl_->CheckRectValid(rect, oriHeight, oriWidth); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: CheckSizeValid + * @tc.desc: CheckSizeValid all + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, CheckSizeValid, Function | SmallTest | Level1) +{ + int32_t oriHeight = 500; + int32_t oriWidth = 500; + Media::Size size = {.width = 1, .height = 1}; + bool ret = DisplayManager::GetInstance().pImpl_->CheckSizeValid(size, oriHeight, oriWidth); + ASSERT_TRUE(ret); + size.width = -1; + ret = DisplayManager::GetInstance().pImpl_->CheckSizeValid(size, oriHeight, oriWidth); + ASSERT_FALSE(ret); + size.width = 1; + size.height = -1; + ret = DisplayManager::GetInstance().pImpl_->CheckSizeValid(size, oriHeight, oriWidth); + ASSERT_FALSE(ret); + size.width = DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT + 1; + size.height = 1; + ret = DisplayManager::GetInstance().pImpl_->CheckSizeValid(size, oriHeight, oriWidth); + ASSERT_FALSE(ret); + size.width = DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT; + size.height = DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT + 1; + ret = DisplayManager::GetInstance().pImpl_->CheckSizeValid(size, oriHeight, oriWidth); + ASSERT_FALSE(ret); +} + +/** + * @tc.name: ImplGetDefaultDisplay01 + * @tc.desc: Impl GetDefaultDisplay nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, ImplGetDefaultDisplay01, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), GetDefaultDisplayInfo()).Times(1).WillOnce(Return(nullptr)); + sptr display = DisplayManager::GetInstance().pImpl_->GetDefaultDisplay(); + ASSERT_EQ(display, nullptr); +} + +/** + * @tc.name: GetDisplayByScreen + * @tc.desc: for interface coverage & check GetDisplayByScreen + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, GetDisplayByScreen, Function | SmallTest | Level1) +{ + auto& displayManager = DisplayManager::GetInstance(); + sptr display = displayManager.GetDisplayByScreen(SCREEN_ID_INVALID); + ASSERT_EQ(display, nullptr); + + sptr displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(DISPLAY_ID_INVALID); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), GetDisplayInfoByScreenId(_)).Times(1).WillOnce(Return(displayInfo)); + display = displayManager.GetDisplayByScreen(1); + ASSERT_EQ(display, nullptr); +} + +/** + * @tc.name: ImplGetDefaultDisplaySync + * @tc.desc: Impl GetDefaultDisplaySync nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerTest, ImplGetDefaultDisplaySync, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), GetDefaultDisplayInfo()).Times(1).WillOnce(Return(nullptr)); + sptr display = DisplayManager::GetInstance().GetDefaultDisplaySync(); + ASSERT_EQ(display, nullptr); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dm/test/unittest/display_power_unit_test.cpp b/window_manager/dm/test/unittest/display_power_unit_test.cpp new file mode 100644 index 0000000..08d3fed --- /dev/null +++ b/window_manager/dm/test/unittest/display_power_unit_test.cpp @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2021-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 "display_manager.h" +#include "screen_manager.h" +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; + +class DisplayPowerEventListener : public IDisplayPowerEventListener { +public: + virtual void OnDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) {} +}; + +class DisplayPowerUnitTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static inline sptr listener_ = new DisplayPowerEventListener(); + static inline DisplayId defaultId_ = 0; + static inline uint32_t brightnessLevel_ = 80; + static inline uint32_t invalidBrightnessLevel_ = 1000000000; + static inline ScreenPowerState initialPowerState_; + static inline DisplayState initialState_; +}; + +void DisplayPowerUnitTest::SetUpTestCase() +{ +} + +void DisplayPowerUnitTest::TearDownTestCase() +{ +} + +void DisplayPowerUnitTest::SetUp() +{ + initialPowerState_ = ScreenManager::GetInstance().GetScreenPower(defaultId_); + initialState_ = DisplayManager::GetInstance().GetDisplayState(defaultId_); +} + +void DisplayPowerUnitTest::TearDown() +{ + ScreenManager::GetInstance().SetScreenPowerForAll(initialPowerState_, PowerStateChangeReason::POWER_BUTTON); + DisplayStateCallback callback; + DisplayManager::GetInstance().SetDisplayState(initialState_, callback); +} + +namespace { +/** + * @tc.name: register_display_power_event_listener_001 + * @tc.desc: call Register/UnregisterDisplayPowerEventListener with a valid listener and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, register_display_power_event_listener_001, Function | SmallTest | Level2) +{ + Mocker m; + + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(1).WillOnce(Return(true)); + bool ret = DisplayManager::GetInstance().RegisterDisplayPowerEventListener(listener_); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(1).WillOnce(Return(true)); + ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener_); + ASSERT_EQ(true, ret); +} + +/** + * @tc.name: register_display_power_event_listener_002 + * @tc.desc: call Register/UnregisterDisplayPowerEventListener with nullptr and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, register_display_power_event_listener_002, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(0); + bool ret = DisplayManager::GetInstance().RegisterDisplayPowerEventListener(nullptr); + ASSERT_EQ(false, ret); + + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(0); + ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: register_display_power_event_listener_003 + * @tc.desc: call Register/UnregisterDisplayPowerEventListener with ipc failed and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, register_display_power_event_listener_003, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(1).WillOnce(Return(false)); + bool ret = DisplayManager::GetInstance().RegisterDisplayPowerEventListener(listener_); + ASSERT_EQ(false, ret); + + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(0); + ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener_); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: unregister_display_power_event_listener_001 + * @tc.desc: call UnregisterDisplayPowerEventListener with a listener never registered and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, unregister_display_power_event_listener_001, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(0); + bool ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener_); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: unregister_display_power_event_listener_002 + * @tc.desc: call UnregisterDisplayPowerEventListener with nullptr and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, unregister_display_power_event_listener_002, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), UnregisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER)) + .Times(0); + bool ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: wake_up_begin_001 + * @tc.desc: call WakeUpBegin and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, wake_up_begin_001, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), WakeUpBegin(PowerStateChangeReason::POWER_BUTTON)).Times(1).WillOnce(Return(true));; + bool ret = DisplayManager::GetInstance().WakeUpBegin(PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), WakeUpBegin(PowerStateChangeReason::POWER_BUTTON)).Times(1).WillOnce(Return(false));; + ret = DisplayManager::GetInstance().WakeUpBegin(PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: wake_up_end_001 + * @tc.desc: call WakeUpEnd and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, wake_up_end_001, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), WakeUpEnd()).Times(1).WillOnce(Return(true)); + bool ret = DisplayManager::GetInstance().WakeUpEnd(); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), WakeUpEnd()).Times(1).WillOnce(Return(false)); + ret = DisplayManager::GetInstance().WakeUpEnd(); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: suspend_begin_001 + * @tc.desc: call SuspendBegin and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerUnitTest, suspend_begin_001, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), SuspendBegin(PowerStateChangeReason::POWER_BUTTON)).Times(1).WillOnce(Return(true));; + bool ret = DisplayManager::GetInstance().SuspendBegin(PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), SuspendBegin(PowerStateChangeReason::POWER_BUTTON)).Times(1).WillOnce(Return(false));; + ret = DisplayManager::GetInstance().SuspendBegin(PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(false, ret); +} + +/** +* @tc.name: suspend_end_001 +* @tc.desc: call SuspendEnd and check return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerUnitTest, suspend_end_001, Function | SmallTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), SuspendEnd()).Times(1).WillOnce(Return(true)); + bool ret = DisplayManager::GetInstance().SuspendEnd(); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), SuspendEnd()).Times(1).WillOnce(Return(false)); + ret = DisplayManager::GetInstance().SuspendEnd(); + ASSERT_EQ(false, ret); +} + +/** +* @tc.name: set_screen_brightness_001 +* @tc.desc: Call SetScreenBrightness with a valid value and check the GetScreenBrightness return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerUnitTest, set_screen_brightness_001, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().SetScreenBrightness(defaultId_, brightnessLevel_); + ASSERT_EQ(true, ret); +} + +/** +* @tc.name: set_screen_power_for_all_001 +* @tc.desc: Call SetScreenPowerForAll with valid value and check the GetScreenPower return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerUnitTest, set_screen_power_for_all_001, Function | MediumTest | Level2) +{ + SingletonMocker m; + EXPECT_CALL(m.Mock(), GetScreenPower(_)).Times(1).WillOnce(Return(ScreenPowerState::POWER_OFF)); + EXPECT_CALL(m.Mock(), SetScreenPowerForAll(_, PowerStateChangeReason::POWER_BUTTON)) + .Times(1).WillOnce(Return(true)); + + bool ret = ScreenManager::GetInstance().SetScreenPowerForAll(ScreenPowerState::POWER_OFF, + PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + + ScreenPowerState state = ScreenManager::GetInstance().GetScreenPower(defaultId_); + ASSERT_EQ(state, ScreenPowerState::POWER_OFF); +} + +/** +* @tc.name: set_display_state_001 +* @tc.desc: Call SetDisplayState with valid value and check the GetDisplayState return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerUnitTest, set_display_state_001, Function | MediumTest | Level2) +{ + DisplayState stateToSet = (initialState_ == DisplayState::OFF ? DisplayState::ON : DisplayState::OFF); + Mocker m; + EXPECT_CALL(m.Mock(), RegisterDisplayManagerAgent(_, DisplayManagerAgentType::DISPLAY_STATE_LISTENER)) + .Times(1).WillOnce(Return(true)); + EXPECT_CALL(m.Mock(), SetDisplayState(stateToSet)).Times(1).WillOnce(Return(true)); + DisplayStateCallback callback = [](DisplayState state) {}; + bool ret = DisplayManager::GetInstance().SetDisplayState(stateToSet, callback); + ASSERT_EQ(true, ret); + + EXPECT_CALL(m.Mock(), GetDisplayState(defaultId_)).Times(1).WillOnce(Return(stateToSet)); + DisplayState state = DisplayManager::GetInstance().GetDisplayState(defaultId_); + ASSERT_EQ(state, stateToSet); +} + +/** +* @tc.name: set_display_state_002 +* @tc.desc: Call SetDisplayState with invalid callback and check the GetDisplayState return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerUnitTest, set_display_state_002, Function | MediumTest | Level2) +{ + Mocker m; + EXPECT_CALL(m.Mock(), SetDisplayState(_)).Times(0); + DisplayState stateToSet = (initialState_ == DisplayState::OFF ? DisplayState::ON : DisplayState::OFF); + bool ret = DisplayManager::GetInstance().SetDisplayState(stateToSet, nullptr); + ASSERT_EQ(false, ret); +} +} +} +} \ No newline at end of file diff --git a/window_manager/dm/test/unittest/display_test.cpp b/window_manager/dm/test/unittest/display_test.cpp new file mode 100644 index 0000000..c9cc305 --- /dev/null +++ b/window_manager/dm/test/unittest/display_test.cpp @@ -0,0 +1,185 @@ +/* + * 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 "display_manager.h" +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" +#include "display_cutout_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class DisplayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static sptr defaultDisplay_; + static DisplayId defaultDisplayId_; +}; +sptr DisplayTest::defaultDisplay_ = nullptr; +DisplayId DisplayTest::defaultDisplayId_ = DISPLAY_ID_INVALID; + +void DisplayTest::SetUpTestCase() +{ + defaultDisplay_ = DisplayManager::GetInstance().GetDefaultDisplay(); + defaultDisplayId_ = static_cast(defaultDisplay_->GetId()); +} + +void DisplayTest::TearDownTestCase() +{ + defaultDisplay_ = nullptr; +} + +void DisplayTest::SetUp() +{ +} + +void DisplayTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetCutoutInfo01 + * @tc.desc: GetCutoutInfo with valid defaultDisplayId and return success + * @tc.type: FUNC + * @tc.require: issueI5K0JP + */ +HWTEST_F(DisplayTest, GetCutoutInfo01, Function | SmallTest | Level1) +{ + auto cutoutInfo = defaultDisplay_->GetCutoutInfo(); + ASSERT_NE(nullptr, cutoutInfo); +} + +/** + * @tc.name: UpdateDisplayInfo01 + * @tc.desc: UpdateDisplayInfo with nullptr + * @tc.type: FUNC + * @tc.require: issueI5K0JP + */ +HWTEST_F(DisplayTest, UpdateDisplayInfo01, Function | SmallTest | Level1) +{ + defaultDisplay_->UpdateDisplayInfo(nullptr); +} + +/** + * @tc.name: GetName + * @tc.desc: UpdateDisplayInfo with nullptr + * @tc.type: FUNC + * @tc.require: issueI5K0JP + */ +HWTEST_F(DisplayTest, GetName, Function | SmallTest | Level1) +{ + defaultDisplay_->GetName(); + defaultDisplay_->GetDpi(); +} + +/** + * @tc.name: SetWaterfallCompression01 + * @tc.desc: Set waterfall compression related values with valid input. + * @tc.type: FUNC + * @tc.require: issueI5P8CI + */ +HWTEST_F(DisplayTest, SetWaterfallCompression01, Function | SmallTest | Level1) +{ + bool isWaterfallDisplayOrigin = DisplayCutoutController::IsWaterfallDisplay(); + DisplayCutoutController::SetIsWaterfallDisplay(true); + bool isCompressionEnableOrigin = + DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal(); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(true); + uint32_t testSizeOrigin = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal(); + uint32_t testSize = 20; + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSize); + ASSERT_EQ(true, DisplayCutoutController::IsWaterfallDisplay()); + ASSERT_EQ(true, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + ASSERT_EQ(testSize, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSizeOrigin); + ASSERT_EQ(testSizeOrigin, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(isCompressionEnableOrigin); + ASSERT_EQ(isWaterfallDisplayOrigin, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + DisplayCutoutController::SetIsWaterfallDisplay(isWaterfallDisplayOrigin); + ASSERT_EQ(isWaterfallDisplayOrigin, DisplayCutoutController::IsWaterfallDisplay()); +} + +/** + * @tc.name: SetWaterfallCompression02 + * @tc.desc: Set waterfall compression related values with invalid input. + * @tc.type: FUNC + * @tc.require: issueI5P8CI + */ +HWTEST_F(DisplayTest, SetWaterfallCompression02, Function | SmallTest | Level1) +{ + bool isWaterfallDisplayOrigin = DisplayCutoutController::IsWaterfallDisplay(); + DisplayCutoutController::SetIsWaterfallDisplay(true); + bool isCompressionEnableOrigin = + DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal(); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(true); + uint32_t testSizeOrigin = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal(); + + DisplayCutoutController::SetIsWaterfallDisplay(false); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(true); + ASSERT_EQ(false, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + + uint32_t testSize = 20; + DisplayCutoutController::SetIsWaterfallDisplay(true); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(false); + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSize); + ASSERT_EQ(0, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + + DisplayCutoutController::SetIsWaterfallDisplay(false); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(false); + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSize); + ASSERT_EQ(0, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSizeOrigin); + ASSERT_EQ(testSizeOrigin, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(isCompressionEnableOrigin); + ASSERT_EQ(isWaterfallDisplayOrigin, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + DisplayCutoutController::SetIsWaterfallDisplay(isWaterfallDisplayOrigin); + ASSERT_EQ(isWaterfallDisplayOrigin, DisplayCutoutController::IsWaterfallDisplay()); +} +/** + * @tc.name: GetName01 + * @tc.desc: GetName function cover + * @tc.type: FUNC + */ +HWTEST_F(DisplayTest, GetName01, Function | SmallTest | Level1) +{ + auto name = defaultDisplay_->GetName(); + ASSERT_EQ("display_0", name); +} + +/** + * @tc.name: GetDpi01 + * @tc.desc: GetDpi function cover + * @tc.type: FUNC + */ +HWTEST_F(DisplayTest, GetDpi01, Function | SmallTest | Level1) +{ + auto dpi = defaultDisplay_->GetDpi(); + + auto vpr = defaultDisplay_->GetVirtualPixelRatio(); + ASSERT_EQ(vpr * DOT_PER_INCH, dpi); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dm/test/unittest/screen_group_test.cpp b/window_manager/dm/test/unittest/screen_group_test.cpp new file mode 100644 index 0000000..e9ca0ac --- /dev/null +++ b/window_manager/dm/test/unittest/screen_group_test.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021-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 "screen_group.h" +#include "screen_manager.h" +#include "screen_group_info.h" +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class ScreenGroupTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr group_; +}; + + +void ScreenGroupTest::SetUpTestCase() +{ +} + +void ScreenGroupTest::TearDownTestCase() +{ +} + +void ScreenGroupTest::SetUp() +{ + group_ = ScreenManager::GetInstance().GetScreenGroup(0); +} + +void ScreenGroupTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: UpdateScreenGroupInfo02 + * @tc.desc: test InterfaceToken check failed + * @tc.type: FUNC + */ +HWTEST_F(ScreenGroupTest, UpdateScreenGroupInfo02, Function | SmallTest | Level2) +{ + sptr screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + sptr screenGroup = new ScreenGroup(screenGroupInfo); + SingletonMocker m; + EXPECT_CALL(m.Mock(), GetScreenGroupInfoById(_)).Times(1).WillOnce(Return(nullptr)); + ScreenCombination comb = screenGroup->GetCombination(); + ASSERT_EQ(ScreenCombination::SCREEN_ALONE, comb); +} + +/** + * @tc.name: UpdateScreenGroupInfo01 + * @tc.desc: test InterfaceToken check success + * @tc.type: FUNC + */ +HWTEST_F(ScreenGroupTest, UpdateScreenGroupInfo01, Function | SmallTest | Level2) +{ + sptr screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + sptr screenGroup = new ScreenGroup(screenGroupInfo); + screenGroupInfo->combination_ = ScreenCombination::SCREEN_EXPAND; + SingletonMocker m; + EXPECT_CALL(m.Mock(), GetScreenGroupInfoById(_)).Times(1).WillOnce(Return(screenGroupInfo)); + ScreenCombination comb = screenGroup->GetCombination(); + ASSERT_EQ(ScreenCombination::SCREEN_EXPAND, comb); +} + +/** + * @tc.name: UpdateScreenGroupInfo03 + * @tc.desc: test InterfaceToken check success + * @tc.type: FUNC + */ +HWTEST_F(ScreenGroupTest, UpdateScreenGroupInfo03, Function | SmallTest | Level2) +{ + sptr screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + sptr screenGroup = new ScreenGroup(screenGroupInfo); + std::vector position; + position.emplace_back(0, 0); + screenGroupInfo->position_ = position; + SingletonMocker m; + EXPECT_CALL(m.Mock(), GetScreenGroupInfoById(_)).Times(1).WillOnce(Return(screenGroupInfo)); + std::vector pos = screenGroup->GetChildPositions(); + ASSERT_EQ(position.size(), pos.size()); +} +/** + * @tc.name: GetChildIds + * @tc.desc: for interface coverage & check GetChildIds + * @tc.type: FUNC + */ +HWTEST_F(ScreenGroupTest, GetChildIds, Function | SmallTest | Level2) +{ + sptr screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + sptr screenGroup = new ScreenGroup(screenGroupInfo); + auto result = screenGroup->GetChildIds(); + ASSERT_TRUE(result.empty()); + + screenGroupInfo->children_.emplace_back(1); + result = screenGroup->GetChildIds(); + ASSERT_EQ(result.size(), 1); +} +} +} +} \ No newline at end of file diff --git a/window_manager/dm/test/unittest/screen_manager_test.cpp b/window_manager/dm/test/unittest/screen_manager_test.cpp new file mode 100644 index 0000000..ca72f86 --- /dev/null +++ b/window_manager/dm/test/unittest/screen_manager_test.cpp @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2021-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 "display_manager.h" +#include "screen_manager.h" +#include "screen_manager_utils.h" +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" +#include "screen_manager.cpp" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class DmMockScreenListener : public ScreenManager::IScreenListener { +public: + void OnConnect(ScreenId) override {} + void OnDisconnect(ScreenId) override {} + void OnChange(ScreenId) override {} +}; + +class TestScreenGroupListener : public ScreenManager::IScreenGroupListener { +public: + void OnChange(const std::vector&, ScreenGroupChangeEvent) override {}; +}; + +class TestIVirtualScreenGroupListener : public ScreenManager::IVirtualScreenGroupListener { +public: + void OnMirrorChange(const ChangeInfo& info) override {}; +}; +class ScreenManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + const std::string defaultName_ = "virtualScreen01"; + const float defaultDensity_ = 2.0; + const int32_t defaultFlags_ = 0; + static sptr defaultDisplay_; + static uint32_t defaultWidth_; + static uint32_t defaultHeight_; +}; +sptr ScreenManagerTest::defaultDisplay_ = nullptr; +uint32_t ScreenManagerTest::defaultWidth_ = 480; +uint32_t ScreenManagerTest::defaultHeight_ = 320; + +void ScreenManagerTest::SetUpTestCase() +{ + defaultDisplay_ = DisplayManager::GetInstance().GetDefaultDisplay(); + defaultWidth_ = defaultDisplay_->GetWidth(); + defaultHeight_ = defaultDisplay_->GetHeight(); +} + +void ScreenManagerTest::TearDownTestCase() +{ +} + +void ScreenManagerTest::SetUp() +{ +} + +void ScreenManagerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: CreateAndDestroy01 + * @tc.desc: CreateVirtualScreen with invalid option and return invalid screen id + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, CreateAndDestroy01, Function | SmallTest | Level1) +{ + VirtualScreenOption wrongOption = {defaultName_, defaultWidth_, defaultHeight_, + defaultDensity_, nullptr, defaultFlags_}; + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(SCREEN_ID_INVALID)); + EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); + ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(wrongOption); + DMError ret = ScreenManager::GetInstance().DestroyVirtualScreen(id); + ASSERT_EQ(SCREEN_ID_INVALID, id); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, ret); +} + +/** + * @tc.name: CreateAndDestroy02 + * @tc.desc: CreateVirtualScreen with valid option and return valid screen id + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, CreateAndDestroy02, Function | SmallTest | Level1) +{ + ScreenManagerUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + VirtualScreenOption defaultOption = {defaultName_, defaultWidth_, defaultHeight_, + defaultDensity_, utils.psurface_, defaultFlags_}; + ScreenId validId = 0; + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(validId)); + EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_OK)); + ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); + DMError ret = ScreenManager::GetInstance().DestroyVirtualScreen(id); + ASSERT_EQ(validId, id); + ASSERT_EQ(DMError::DM_OK, ret); +} + +/** + * @tc.name: MakeExpand_001 + * @tc.desc: Create a virtual screen as expansion of default screen, return default screen id + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, MakeExpand_001, Function | SmallTest | Level1) +{ + ScreenManagerUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + VirtualScreenOption defaultOption = {defaultName_, defaultWidth_, defaultHeight_, + defaultDensity_, utils.psurface_, defaultFlags_}; + ScreenId validId = 0; // default srceenId(0) + ScreenId virtualScreenId = 1; // VirtualScreen is the second screen(1) + 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(0)); + ScreenId vScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); + std::vector options = {{validId, 0, 0}, {vScreenId, defaultWidth_, 0}}; + ScreenId expansionId = ScreenManager::GetInstance().MakeExpand(options); + ASSERT_EQ(expansionId, validId); + DMError ret = ScreenManager::GetInstance().DestroyVirtualScreen(vScreenId); + ASSERT_EQ(vScreenId, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ret); +} + +/** + * @tc.name: MakeExpand_002 + * @tc.desc: Makepand with empty ExpandOption, return SCREEN_ID_INVALID + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, MakeExpand_002, Function | SmallTest | Level1) +{ + ScreenId invalidId = SCREEN_ID_INVALID; + std::vector options = {}; + ScreenId expansionId = ScreenManager::GetInstance().MakeExpand(options); + ASSERT_EQ(expansionId, invalidId); +} + +/** + * @tc.name: SetSurface01 + * @tc.desc: SetVirtualScreenSurface with valid option and return success + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, SetSurface01, Function | SmallTest | Level1) +{ + ScreenManagerUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + VirtualScreenOption defaultOption = {defaultName_, defaultWidth_, defaultHeight_, + defaultDensity_, nullptr, defaultFlags_}; + ScreenId validId = 0; + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(validId)); + EXPECT_CALL(m->Mock(), SetVirtualScreenSurface(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_OK)); + ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); + DMError surfaceRes = ScreenManager::GetInstance().SetVirtualScreenSurface(id, utils.psurface_); + DMError destroyRes = ScreenManager::GetInstance().DestroyVirtualScreen(id); + ASSERT_EQ(validId, id); + ASSERT_EQ(DMError::DM_OK, surfaceRes); + ASSERT_EQ(DMError::DM_OK, destroyRes); +} + +/** + * @tc.name: SetSurface02 + * @tc.desc: SetVirtualScreenSurface with invalid option and return failed + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, SetSurface02, Function | SmallTest | Level1) +{ + ScreenManagerUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + VirtualScreenOption defaultOption = {defaultName_, defaultWidth_, defaultHeight_, + defaultDensity_, nullptr, defaultFlags_}; + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateVirtualScreen(_, _)).Times(1).WillOnce(Return(SCREEN_ID_INVALID)); + EXPECT_CALL(m->Mock(), SetVirtualScreenSurface(_, _)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); + EXPECT_CALL(m->Mock(), DestroyVirtualScreen(_)).Times(1).WillOnce(Return(DMError::DM_ERROR_INVALID_PARAM)); + ScreenId id = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption); + DMError surfaceRes = ScreenManager::GetInstance().SetVirtualScreenSurface(id, utils.psurface_); + DMError destroyRes = ScreenManager::GetInstance().DestroyVirtualScreen(id); + ASSERT_EQ(SCREEN_ID_INVALID, id); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, surfaceRes); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, destroyRes); +} + +/** + * @tc.name: OnScreenConnect01 + * @tc.desc: OnScreenConnect + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, OnScreenConnect01, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockScreenListener(); + ScreenManager::GetInstance().RegisterScreenListener(listener); + auto screenManagerListener = ScreenManager::GetInstance().pImpl_->screenManagerListener_; + ASSERT_NE(screenManagerListener, nullptr); + screenManagerListener->OnScreenConnect(nullptr); + sptr screenInfo = new ScreenInfo(); + screenInfo->SetScreenId(SCREEN_ID_INVALID); + screenManagerListener->OnScreenConnect(screenInfo); + screenInfo->SetScreenId(0); + screenManagerListener->OnScreenConnect(screenInfo); + ASSERT_NE(screenManagerListener->pImpl_, nullptr); + screenManagerListener->pImpl_ = nullptr; + screenManagerListener->OnScreenConnect(screenInfo); + ScreenManager::GetInstance().pImpl_->screenManagerListener_ = nullptr; +} + +/** + * @tc.name: OnScreenDisconnect01 + * @tc.desc: OnScreenDisconnect + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, OnScreenDisconnect01, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockScreenListener(); + ScreenManager::GetInstance().RegisterScreenListener(listener); + auto screenManagerListener = ScreenManager::GetInstance().pImpl_->screenManagerListener_; + ASSERT_NE(screenManagerListener, nullptr); + screenManagerListener->OnScreenDisconnect(SCREEN_ID_INVALID); + ASSERT_NE(screenManagerListener->pImpl_, nullptr); + screenManagerListener->pImpl_ = nullptr; + screenManagerListener->OnScreenDisconnect(0); + ScreenManager::GetInstance().pImpl_->screenManagerListener_ = nullptr; +} + +/** + * @tc.name: OnScreenChange01 + * @tc.desc: OnScreenChange + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, OnScreenChange01, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockScreenListener(); + ScreenManager::GetInstance().RegisterScreenListener(listener); + auto screenManagerListener = ScreenManager::GetInstance().pImpl_->screenManagerListener_; + ASSERT_NE(screenManagerListener, nullptr); + screenManagerListener->OnScreenChange(nullptr, ScreenChangeEvent::UPDATE_ORIENTATION); + ASSERT_NE(screenManagerListener->pImpl_, nullptr); + sptr screenInfo = new ScreenInfo(); + screenManagerListener->pImpl_ = nullptr; + screenManagerListener->OnScreenChange(screenInfo, ScreenChangeEvent::UPDATE_ORIENTATION); + ScreenManager::GetInstance().pImpl_->screenManagerListener_ = nullptr; +} + +/** + * @tc.name: OnScreenGroupChange01 + * @tc.desc: OnScreenGroupChange + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, OnScreenGroupChange01, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + sptr listener = new DmMockScreenListener(); + ScreenManager::GetInstance().RegisterScreenListener(listener); + auto screenManagerListener = ScreenManager::GetInstance().pImpl_->screenManagerListener_; + ASSERT_NE(screenManagerListener, nullptr); + std::string trigger; + std::vector> screenInfos; + ScreenGroupChangeEvent groupEvent = ScreenGroupChangeEvent::CHANGE_GROUP; + screenManagerListener->OnScreenGroupChange(trigger, screenInfos, groupEvent); + ASSERT_NE(screenManagerListener->pImpl_, nullptr); + sptr screenInfo = new ScreenInfo(); + screenInfo->SetScreenId(1); + sptr screenInfo2 = new ScreenInfo(); + screenInfos.emplace_back(screenInfo); + screenInfos.emplace_back(screenInfo2); + screenManagerListener->OnScreenGroupChange(trigger, screenInfos, groupEvent); + screenManagerListener->pImpl_ = nullptr; + screenManagerListener->OnScreenGroupChange(trigger, screenInfos, groupEvent); + ScreenManager::GetInstance().pImpl_->screenManagerListener_ = nullptr; +} +/** + * @tc.name: RemoveVirtualScreenFromGroup + * @tc.desc: for interface coverage & check func RemoveVirtualScreenFromGroup + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, RemoveVirtualScreenFromGroup, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + std::vector testScreens(33, 1); + auto result = ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(testScreens); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, result); + + testScreens.clear(); + result = ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(testScreens); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, result); + + testScreens.emplace_back(static_cast(1)); + EXPECT_CALL(m->Mock(), RemoveVirtualScreenFromGroup(_)).Times(1); + result = ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(testScreens); + ASSERT_EQ(DMError::DM_OK, result); +} +/** + * @tc.name: SetScreenRotationLocked + * @tc.desc: for interface coverage & check SetScreenRotationLocked + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, SetScreenRotationLocked, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), SetScreenRotationLocked(_)).Times(1); + auto result = ScreenManager::GetInstance().SetScreenRotationLocked(true); + ASSERT_EQ(DMError::DM_OK, result); +} + +/** + * @tc.name: IsScreenRotationLocked + * @tc.desc: for interface coverage & check IsScreenRotationLocked + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, IsScreenRotationLocked, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), IsScreenRotationLocked()).Times(1).WillOnce(Return(true)); + auto result = ScreenManager::GetInstance().IsScreenRotationLocked(); + ASSERT_EQ(true, result); + EXPECT_CALL(m->Mock(), IsScreenRotationLocked()).Times(1).WillOnce(Return(false)); + result = ScreenManager::GetInstance().IsScreenRotationLocked(); + ASSERT_EQ(false, result); +} + +/** + * @tc.name: RegisterScreenGroupListener + * @tc.desc: for interface coverage and + * check RegisterScreenGroupListener & UnregisterScreenGroupListener + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, RegisterScreenGroupListener, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + auto& screenManager = ScreenManager::GetInstance(); + auto result = screenManager.RegisterScreenGroupListener(nullptr); + ASSERT_EQ(false, result); + + sptr listener = new (std::nothrow)TestScreenGroupListener(); + if (screenManager.pImpl_->screenManagerListener_ == nullptr) { + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + } + result = screenManager.RegisterScreenGroupListener(listener); + ASSERT_EQ(true, result); + + result = screenManager.UnregisterScreenGroupListener(nullptr); + ASSERT_EQ(false, result); + + auto sizeScreen = screenManager.pImpl_->screenListeners_.size(); + auto sizeScreenGroup = screenManager.pImpl_->screenGroupListeners_.size(); + auto sizeVirtualScreen = screenManager.pImpl_->virtualScreenGroupListeners_.size(); + if (sizeScreenGroup > 1) { + result = screenManager.UnregisterScreenGroupListener(listener); + ASSERT_EQ(true, result); + } else if (sizeScreenGroup == 1) { + if (sizeScreen == 0 && sizeVirtualScreen == 0) { + EXPECT_CALL(m->Mock(), UnregisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + } + result = screenManager.UnregisterScreenGroupListener(listener); + ASSERT_EQ(true, result); + } +} +/** + * @tc.name: RegisterVirtualScreenGroupListener + * @tc.desc: for interface coverage and + * check RegisterVirtualScreenGroupListener & UnregisterVirtualScreenGroupListener + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, RegisterVirtualScreenGroupListener, Function | SmallTest | Level1) +{ + std::unique_ptr m = std::make_unique(); + auto& screenManager = ScreenManager::GetInstance(); + auto result = screenManager.RegisterVirtualScreenGroupListener(nullptr); + ASSERT_EQ(false, result); + + sptr listener = new (std::nothrow)TestIVirtualScreenGroupListener(); + if (screenManager.pImpl_->screenManagerListener_ == nullptr) { + EXPECT_CALL(m->Mock(), RegisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + } + result = screenManager.RegisterVirtualScreenGroupListener(listener); + ASSERT_EQ(true, result); + + result = screenManager.UnregisterVirtualScreenGroupListener(nullptr); + ASSERT_EQ(false, result); + + auto sizeScreen = screenManager.pImpl_->screenListeners_.size(); + auto sizeScreenGroup = screenManager.pImpl_->screenGroupListeners_.size(); + auto sizeVirtualScreen = screenManager.pImpl_->virtualScreenGroupListeners_.size(); + + if (sizeVirtualScreen > 1) { + result = screenManager.UnregisterVirtualScreenGroupListener(listener); + ASSERT_EQ(true, result); + } else if (sizeVirtualScreen == 1) { + if (sizeScreen == 0 && sizeScreenGroup == 0) { + EXPECT_CALL(m->Mock(), UnregisterDisplayManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + } + result = screenManager.UnregisterVirtualScreenGroupListener(listener); + ASSERT_EQ(true, result); + } +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dm/test/unittest/screen_test.cpp b/window_manager/dm/test/unittest/screen_test.cpp new file mode 100644 index 0000000..4327c1e --- /dev/null +++ b/window_manager/dm/test/unittest/screen_test.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2021-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 "display_manager.h" +#include "screen_manager.h" +#include "screen_manager_utils.h" +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class ScreenTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static sptr defaultDisplay_; + static ScreenId defaultScreenId_; + static sptr screen_; +}; +sptr ScreenTest::defaultDisplay_ = nullptr; +ScreenId ScreenTest::defaultScreenId_ = SCREEN_ID_INVALID; +sptr ScreenTest::screen_ = nullptr; + +void ScreenTest::SetUpTestCase() +{ + defaultDisplay_ = DisplayManager::GetInstance().GetDefaultDisplay(); + defaultScreenId_ = static_cast(defaultDisplay_->GetId()); + screen_ = ScreenManager::GetInstance().GetScreenById(defaultScreenId_); +} + +void ScreenTest::TearDownTestCase() +{ + defaultDisplay_ = nullptr; + screen_ = nullptr; +} + +void ScreenTest::SetUp() +{ +} + +void ScreenTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetBasicProperty01 + * @tc.desc: Basic property getter test + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, GetBasicProperty01, Function | SmallTest | Level1) +{ + ASSERT_GT(screen_->GetName().size(), 0); + ASSERT_GT(screen_->GetWidth(), 0); + ASSERT_GT(screen_->GetHeight(), 0); + ASSERT_GT(screen_->GetVirtualWidth(), 0); + ASSERT_GT(screen_->GetVirtualHeight(), 0); + ASSERT_GT(screen_->GetVirtualPixelRatio(), 0); + ASSERT_EQ(screen_->GetRotation(), Rotation::ROTATION_0); + ASSERT_EQ(screen_->IsReal(), true); + ASSERT_NE(screen_->GetScreenInfo(), nullptr); +} + +/** + * @tc.name: SetScreenActiveMode01 + * @tc.desc: SetScreenActiveMode with valid modeId and return success + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, SetScreenActiveMode01, Function | SmallTest | Level1) +{ + auto supportedModes = screen_->GetSupportedModes(); + ASSERT_GT(supportedModes.size(), 0); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), SetScreenActiveMode(_, _)).Times(1).WillOnce(Return(true)); + bool res = screen_->SetScreenActiveMode(supportedModes.size() - 1); + ASSERT_EQ(true, res); +} + +/** + * @tc.name: SetScreenActiveMode02 + * @tc.desc: SetScreenActiveMode with valid modeId and return failed + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, SetScreenActiveMode02, Function | SmallTest | Level1) +{ + auto supportedModes = screen_->GetSupportedModes(); + ASSERT_GT(supportedModes.size(), 0); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), SetScreenActiveMode(_, _)).Times(1).WillOnce(Return(false)); + bool res = screen_->SetScreenActiveMode(supportedModes.size() - 1); + ASSERT_EQ(false, res); +} + +/** + * @tc.name: GetScreenSupportedColorGamuts01 + * @tc.desc: GetScreenSupportedColorGamuts + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, GetScreenSupportedColorGamuts01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), GetScreenSupportedColorGamuts(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + std::vector colorGamuts; + auto res = screen_->GetScreenSupportedColorGamuts(colorGamuts); + ASSERT_EQ(DMError::DM_OK, res); +} + +/** + * @tc.name: GetScreenColorGamut01 + * @tc.desc: GetScreenColorGamut + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, GetScreenColorGamut01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), GetScreenColorGamut(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + ScreenColorGamut colorGamut = ScreenColorGamut::COLOR_GAMUT_SRGB; + auto res = screen_->GetScreenColorGamut(colorGamut); + ASSERT_EQ(DMError::DM_OK, res); +} + +/** + * @tc.name: SetScreenColorGamut01 + * @tc.desc: SetScreenColorGamut + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, SetScreenColorGamut01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), SetScreenColorGamut(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + ScreenColorGamut colorGamut = ScreenColorGamut::COLOR_GAMUT_SRGB; + auto res = screen_->SetScreenColorGamut(colorGamut); + ASSERT_EQ(DMError::DM_OK, res); +} + +/** + * @tc.name: GetScreenGamutMap01 + * @tc.desc: GetScreenGamutMap + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, GetScreenGamutMap01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), GetScreenGamutMap(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + ScreenGamutMap gamutMap = ScreenGamutMap::GAMUT_MAP_CONSTANT; + auto res = screen_->GetScreenGamutMap(gamutMap); + ASSERT_EQ(DMError::DM_OK, res); +} + +/** + * @tc.name: SetScreenGamutMap01 + * @tc.desc: SetScreenGamutMap + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, SetScreenGamutMap01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), SetScreenGamutMap(_, _)).Times(1).WillOnce(Return(DMError::DM_OK)); + ScreenGamutMap gamutMap = ScreenGamutMap::GAMUT_MAP_CONSTANT; + auto res = screen_->SetScreenGamutMap(gamutMap); + ASSERT_EQ(DMError::DM_OK, res); +} + +/** + * @tc.name: SetScreenColorTransform01 + * @tc.desc: SetScreenColorTransform + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, SetScreenColorTransform01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), SetScreenColorTransform(_)).Times(1).WillOnce(Return(DMError::DM_OK)); + auto res = screen_->SetScreenColorTransform(); + ASSERT_EQ(DMError::DM_OK, res); +} + +/** + * @tc.name: IsGroup + * @tc.desc: for interface coverage and check IsGroup + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, IsGroup, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr screenInfo = screen_->GetScreenInfo(); + screenInfo->SetIsScreenGroup(true); + EXPECT_CALL(m->Mock(), GetScreenInfo(_)).Times(1).WillOnce(Return(screenInfo)); + ASSERT_EQ(true, screen_->IsGroup()); + screenInfo->SetIsScreenGroup(false); + EXPECT_CALL(m->Mock(), GetScreenInfo(_)).Times(1).WillOnce(Return(screenInfo)); + ASSERT_EQ(false, screen_->IsGroup()); +} + +/** + * @tc.name: GetParentId + * @tc.desc: for interface coverage and check GetParentId + * @tc.type: FUNC + */ +HWTEST_F(ScreenTest, GetParentId, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr screenInfo = screen_->GetScreenInfo(); + screenInfo->SetParentId(0); + EXPECT_CALL(m->Mock(), GetScreenInfo(_)).Times(1).WillOnce(Return(screenInfo)); + ASSERT_EQ(0, screen_->GetParentId()); + screenInfo->SetParentId(SCREEN_ID_INVALID); + EXPECT_CALL(m->Mock(), GetScreenInfo(_)).Times(1).WillOnce(Return(screenInfo)); + ASSERT_EQ(SCREEN_ID_INVALID, screen_->GetParentId()); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dm/test/unittest/screenshot_test.cpp b/window_manager/dm/test/unittest/screenshot_test.cpp new file mode 100644 index 0000000..182fed0 --- /dev/null +++ b/window_manager/dm/test/unittest/screenshot_test.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021-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 "png.h" +#include "display_manager.h" +#include "pixel_map.h" + +#include + +#include "mock_display_manager_adapter.h" +#include "singleton_mocker.h" +#include "common_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class ScreenshotTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; +void ScreenshotTest::SetUpTestCase() +{ + CommonTestUtils::InjectTokenInfoByHapName(0, "com.ohos.systemui", 0); +} + +void ScreenshotTest::TearDownTestCase() +{ +} + +void ScreenshotTest::SetUp() +{ +} + +void ScreenshotTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetScreenshot_default + * @tc.desc: SetWindowRect/GetWindowRect + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, GetScreenshot_default, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), GetDefaultDisplayInfo()).Times(1).WillOnce(Return(nullptr)); + + DisplayManager::GetInstance().GetDefaultDisplayId(); + + EXPECT_CALL(m->Mock(), GetDisplaySnapshot(_)).Times(1).WillOnce(Return(nullptr)); + + ASSERT_EQ(nullptr, DisplayManager::GetInstance().GetScreenshot(0)); +} + +HWTEST_F(ScreenshotTest, GetScreenshot_01, Function | MediumTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), GetDefaultDisplayInfo()).Times(1).WillOnce(Return(nullptr)); + DisplayManager::GetInstance().GetDefaultDisplayId(); + + EXPECT_CALL(m->Mock(), GetDisplaySnapshot(_)).Times(1).WillOnce(Return(CommonTestUtils::CreatePixelMap())); + auto screenshot = DisplayManager::GetInstance().GetScreenshot(0); + ASSERT_NE(nullptr, screenshot); + + uint32_t width = screenshot->GetWidth(); + uint32_t height = screenshot->GetHeight(); + ASSERT_EQ(width, CommonTestUtils::TEST_IMAGE_WIDTH); + ASSERT_EQ(height, CommonTestUtils::TEST_IMAGE_HEIGHT); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/BUILD.gn b/window_manager/dmserver/BUILD.gn new file mode 100644 index 0000000..a245f5b --- /dev/null +++ b/window_manager/dmserver/BUILD.gn @@ -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. + +import("//build/ohos.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +## Build libdms.so +config("libdms_private_config") { + include_dirs = [ + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + ] +} + +config("libdms_public_config") { + include_dirs = [ "include" ] +} + +ohos_shared_library("libdms") { + sources = [ + "../dm/src/zidl/display_manager_agent_proxy.cpp", + "src/abstract_display.cpp", + "src/abstract_display_controller.cpp", + "src/abstract_screen.cpp", + "src/abstract_screen_controller.cpp", + "src/display_cutout_controller.cpp", + "src/display_dumper.cpp", + "src/display_manager_agent_controller.cpp", + "src/display_manager_config.cpp", + "src/display_manager_service.cpp", + "src/display_manager_service_inner.cpp", + "src/display_manager_stub.cpp", + "src/display_power_controller.cpp", + "src/screen_rotation_controller.cpp", + "src/sensor_connector.cpp", + ] + + configs = [ + ":libdms_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + public_configs = [ ":libdms_public_config" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/resourceschedule/resource_schedule_service/soc_perf:socperf_client", + "//foundation/window/window_manager/utils:libwmutil", + "//third_party/libxml2:libxml2", + ] + + external_deps = [ + "c_utils:utils", + "config_policy:configpolicy_util", + "eventhandler:libeventhandler", + "graphic_standard:surface", + "hilog_native:libhilog", + "hitrace_native:hitrace_meter", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "sensor:sensor_interface_native", + ] + + include_dirs = [ "//third_party/flutter/skia/src" ] + + defines = [] + if (window_manager_feature_subscribe_motion) { + if (defined(global_parts_info) && defined(global_parts_info.msdp_motion)) { + external_deps += [ "motion:motion_interface_native" ] + defines += [ "WM_SUBSCRIBE_MOTION_ENABLE" ] + } + } + + if (is_standard_system) { + external_deps += [ "init:libbegetutil" ] + } else { + external_deps += [ "init_lite:libbegetutil" ] + } + + part_name = "window_manager" + subsystem_name = "window" +} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/dmserver/include/abstract_display.h b/window_manager/dmserver/include/abstract_display.h new file mode 100644 index 0000000..59dfd76 --- /dev/null +++ b/window_manager/dmserver/include/abstract_display.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_H +#define FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_H + +#include + +#include "abstract_screen.h" +#include "display_info.h" + +namespace OHOS::Rosen { +enum class FreezeFlag : uint32_t { + FREEZING, + UNFREEZING, +}; + +class AbstractDisplay : public RefBase { +public: + constexpr static int32_t DEFAULT_WIDTH = 720; + 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(DisplayId id, std::string name, sptr& info, sptr& absScreen); + WM_DISALLOW_COPY_AND_MOVE(AbstractDisplay); + ~AbstractDisplay() = default; + static inline bool IsVertical(Rotation rotation) + { + return (rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180); + } + DisplayId GetId() const; + int32_t GetOffsetX() const; + int32_t GetOffsetY() const; + int32_t GetWidth() const; + int32_t GetHeight() const; + uint32_t GetRefreshRate() const; + float GetVirtualPixelRatio() const; + ScreenId GetAbstractScreenId() const; + ScreenId GetAbstractScreenGroupId() const; + bool BindAbstractScreen(sptr abstractDisplay); + sptr ConvertToDisplayInfo() const; + Rotation GetRotation() const; + Orientation GetOrientation() const; + FreezeFlag GetFreezeFlag() const; + + void SetId(DisplayId displayId); + void SetOffsetX(int32_t offsetX); + void SetOffsetY(int32_t offsetY); + void SetWidth(int32_t width); + void SetHeight(int32_t height); + void SetOffset(int32_t offsetX, int32_t offsetY); + void SetRefreshRate(uint32_t refreshRate); + void SetVirtualPixelRatio(float virtualPixelRatio); + void SetOrientation(Orientation orientation); + bool RequestRotation(Rotation rotation); + void SetFreezeFlag(FreezeFlag); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(bool, WaterfallDisplayCompressionStatus, waterfallDisplayCompressionStatus, false); +private: + DisplayId id_ { DISPLAY_ID_INVALID }; + std::string name_ { "" }; + ScreenId screenId_ { SCREEN_ID_INVALID }; + ScreenId screenGroupId_ { SCREEN_ID_INVALID }; + int32_t offsetX_ { 0 }; + int32_t offsetY_ { 0 }; + int32_t width_ { 0 }; + int32_t height_ { 0 }; + uint32_t refreshRate_ { 0 }; + float virtualPixelRatio_ { 1.0 }; + Rotation rotation_ { Rotation::ROTATION_0 }; + Orientation orientation_ { Orientation::UNSPECIFIED }; + FreezeFlag freezeFlag_ { FreezeFlag::UNFREEZING }; + DEFINE_VAR_DEFAULT_FUNC_SET(DisplayState, DisplayState, displayState, DisplayState::UNKNOWN); +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_H \ No newline at end of file diff --git a/window_manager/dmserver/include/abstract_display_controller.h b/window_manager/dmserver/include/abstract_display_controller.h new file mode 100644 index 0000000..694ceaf --- /dev/null +++ b/window_manager/dmserver/include/abstract_display_controller.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_CONTROLLER_H +#define FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_CONTROLLER_H + +#include "abstract_screen_controller.h" + +#include +#include +#include +#include + +#include "screen.h" +#include "abstract_display.h" +#include "display_change_listener.h" +#include "future.h" + +namespace OHOS::Rosen { +class AbstractDisplayController : public RefBase { +using DisplayStateChangeListener = std::function, + const std::map>&, DisplayStateChangeType)>; +public: + AbstractDisplayController(std::recursive_mutex& mutex, DisplayStateChangeListener); + ~AbstractDisplayController(); + WM_DISALLOW_COPY_AND_MOVE(AbstractDisplayController); + + void Init(sptr abstractScreenController); + ScreenId GetDefaultScreenId(); + RSScreenModeInfo GetScreenActiveMode(ScreenId id); + + std::shared_ptr GetScreenSnapshot(DisplayId displayId); + sptr GetAbstractDisplay(DisplayId displayId) const; + sptr GetAbstractDisplayByScreen(ScreenId screenId) const; + std::vector GetAllDisplayIds() const; + void SetFreeze(std::vector displayIds, bool isFreeze); + +private: + void OnAbstractScreenConnect(sptr absScreen); + void OnAbstractScreenDisconnect(sptr absScreen); + void OnAbstractScreenChange(sptr absScreen, DisplayChangeEvent event); + void ProcessDisplayUpdateOrientation(sptr absScreen); + void ProcessDisplaySizeChange(sptr absScreen); + void ProcessVirtualPixelRatioChange(sptr absScreen); + void ProcessDisplayRotationChange(sptr absScreen); + void ProcessDisplayCompression(sptr absScreen); + sptr GetAbstractDisplayByAbsScreen(sptr absScreen); + void BindAloneScreenLocked(sptr absScreen); + void AddScreenToMirrorLocked(sptr absScreen); + void AddScreenToExpandLocked(sptr absScreen); + std::map> GetAllDisplayInfoOfGroup(sptr info); + DisplayId ProcessNormalScreenDisconnected( + sptr absScreen, sptr screenGroup, sptr& absDisplay); + DisplayId ProcessExpandScreenDisconnected( + sptr absScreen, sptr screenGroup, sptr& absDisplay); + bool UpdateDisplaySize(sptr absDisplay, sptr info); + void SetDisplayStateChangeListener(sptr abstractDisplay, DisplayStateChangeType type); + DisplayId GetDefaultDisplayId(); + + std::recursive_mutex& mutex_; + std::atomic displayCount_ { 0 }; + sptr dummyDisplay_; + std::map> abstractDisplayMap_; + sptr abstractScreenController_; + sptr abstractScreenCallback_; + OHOS::Rosen::RSInterfaces& rsInterface_; + DisplayStateChangeListener displayStateChangeListener_; +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_ABSTRACT_DISPLAY_CONTROLLER_H \ No newline at end of file diff --git a/window_manager/dmserver/include/abstract_screen.h b/window_manager/dmserver/include/abstract_screen.h new file mode 100644 index 0000000..d216894 --- /dev/null +++ b/window_manager/dmserver/include/abstract_screen.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_ABSTRACT_SCREEN_H +#define FOUNDATION_DMSERVER_ABSTRACT_SCREEN_H + + +#include +#include +#include +#include +#include +#include + +#include "noncopyable.h" +#include "screen.h" +#include "screen_group.h" +#include "screen_group_info.h" +#include "screen_info.h" + +namespace OHOS::Rosen { +class AbstractScreenGroup; +class AbstractScreenController; +class AbstractScreen : public RefBase { +public: + AbstractScreen(sptr, const std::string& name, ScreenId dmsId, ScreenId rsId); + AbstractScreen() = delete; + WM_DISALLOW_COPY_AND_MOVE(AbstractScreen); + ~AbstractScreen(); + sptr GetActiveScreenMode() const; + std::vector> GetAbstractScreenModes() const; + sptr GetGroup() const; + sptr ConvertToScreenInfo() const; + bool SetOrientation(Orientation orientation); + Rotation CalcRotation(Orientation orientation) const; + bool SetVirtualPixelRatio(float virtualPixelRatio); + float GetVirtualPixelRatio() const; + + void UpdateRSTree(std::shared_ptr& surfaceNode, bool isAdd); + void UpdateDisplayGroupRSTree(std::shared_ptr& surfaceNode, NodeId parentNodeId, bool isAdd); + void InitRSDisplayNode(RSDisplayNodeConfig& config, Point& startPoint); + ScreenId GetScreenGroupId() const; + + // colorspace, gamut + DMError GetScreenSupportedColorGamuts(std::vector& colorGamuts); + DMError GetScreenColorGamut(ScreenColorGamut& colorGamut); + DMError SetScreenColorGamut(int32_t colorGamutIdx); + DMError GetScreenGamutMap(ScreenGamutMap& gamutMap); + DMError SetScreenGamutMap(ScreenGamutMap gamutMap); + DMError SetScreenColorTransform(); + + const std::string name_; + const ScreenId dmsId_; + const ScreenId rsId_; + bool isScreenGroup_ { false }; + std::shared_ptr rsDisplayNode_; + RSDisplayNodeConfig rSDisplayNodeConfig_; + ScreenId groupDmsId_ { SCREEN_ID_INVALID }; + ScreenId lastGroupDmsId_ { SCREEN_ID_INVALID }; + ScreenType type_ { ScreenType::REAL }; + int32_t activeIdx_ { 0 }; + std::vector> modes_ = {}; + float virtualPixelRatio_ = { 1.0 }; + Orientation orientation_ { Orientation::UNSPECIFIED }; + Rotation rotation_ { Rotation::ROTATION_0 }; + Orientation screenRequestedOrientation_ { Orientation::UNSPECIFIED }; +protected: + void FillScreenInfo(sptr) const; + const sptr screenController_; +}; + +class AbstractScreenGroup : public AbstractScreen { +public: + AbstractScreenGroup(sptr, ScreenId dmsId, ScreenId rsId, std::string name, + ScreenCombination combination); + AbstractScreenGroup() = delete; + WM_DISALLOW_COPY_AND_MOVE(AbstractScreenGroup); + ~AbstractScreenGroup(); + + bool AddChild(sptr& dmsScreen, Point& startPoint); + bool AddChildren(std::vector>& dmsScreens, std::vector& startPoints); + bool RemoveChild(sptr& dmsScreen); + bool HasChild(ScreenId childScreen) const; + std::vector> GetChildren() const; + std::vector GetChildrenPosition() const; + Point GetChildPosition(ScreenId screenId) const; + size_t GetChildCount() const; + sptr ConvertToScreenGroupInfo() const; + + ScreenCombination combination_ { ScreenCombination::SCREEN_ALONE }; + ScreenId mirrorScreenId_ { SCREEN_ID_INVALID }; + +private: + bool GetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config); + + std::map, Point>> abstractScreenMap_; +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_ABSTRACT_SCREEN_H \ No newline at end of file diff --git a/window_manager/dmserver/include/abstract_screen_controller.h b/window_manager/dmserver/include/abstract_screen_controller.h new file mode 100644 index 0000000..f4cd5d4 --- /dev/null +++ b/window_manager/dmserver/include/abstract_screen_controller.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_ABSTRACT_SCREEN_CONTROLLER_H +#define FOUNDATION_DMSERVER_ABSTRACT_SCREEN_CONTROLLER_H + +#include +#include + +#include +#include +#include +#include + +#include "abstract_screen.h" +#include "agent_death_recipient.h" +#include "display_manager_agent_controller.h" +#include "dm_common.h" +#include "rsscreen_change_listener.h" +#include "screen.h" +#include "zidl/display_manager_agent_interface.h" + +namespace OHOS::Rosen { +class AbstractScreenController : public RefBase { +using OnAbstractScreenConnectCb = std::function)>; +using OnAbstractScreenChangeCb = std::function, DisplayChangeEvent event)>; +public: + struct AbstractScreenCallback : public RefBase { + OnAbstractScreenConnectCb onConnect_; + OnAbstractScreenConnectCb onDisconnect_; + OnAbstractScreenChangeCb onChange_; + }; + + explicit AbstractScreenController(std::recursive_mutex& mutex); + ~AbstractScreenController(); + WM_DISALLOW_COPY_AND_MOVE(AbstractScreenController); + + void Init(); + std::vector GetAllScreenIds() const; + uint32_t GetRSScreenNum() const; + sptr GetAbstractScreen(ScreenId dmsScreenId) const; + std::vector GetAllValidScreenIds(const std::vector& screenIds) const; + sptr GetAbstractScreenGroup(ScreenId dmsScreenId); + ScreenId GetDefaultAbstractScreenId(); + ScreenId ConvertToRsScreenId(ScreenId dmsScreenId) const; + ScreenId ConvertToDmsScreenId(ScreenId rsScreenId) const; + void RegisterAbstractScreenCallback(sptr cb); + void RegisterRSScreenChangeListener(const sptr& listener); + ScreenId CreateVirtualScreen(VirtualScreenOption option, const sptr& displayManagerAgent); + DMError DestroyVirtualScreen(ScreenId screenId); + DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); + void SetBuildInDefaultOrientation(Orientation orientation); + bool SetOrientation(ScreenId screenId, Orientation orientation, bool isFromWindow); + bool SetRotation(ScreenId screenId, Rotation rotationAfter, bool isFromWindow); + + bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId); + const std::shared_ptr& GetRSDisplayNodeByScreenId(ScreenId dmsScreenId) const; + void UpdateRSTree(ScreenId dmsScreenId, ScreenId parentScreenId, std::shared_ptr& surfaceNode, + bool isAdd, bool isMultiDisplay); + bool MakeMirror(ScreenId, std::vector screens); + bool MakeExpand(std::vector screenIds, std::vector startPoints); + void RemoveVirtualScreenFromGroup(std::vector screens); + bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) const; + ScreenPowerState GetScreenPower(ScreenId dmsScreenId) const; + bool SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio); + + // colorspace, gamut + DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts); + DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut); + DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx); + DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap); + DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap); + DMError SetScreenColorTransform(ScreenId screenId); + +private: + static inline bool IsVertical(Rotation rotation) + { + return (rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180); + } + void SetScreenRotateAnimation(sptr& screen, ScreenId screenId, Rotation rotationAfter); + void RegisterRsScreenConnectionChangeListener(); + void OnRsScreenConnectionChange(ScreenId rsScreenId, ScreenEvent screenEvent); + bool OnRemoteDied(const sptr& agent); + void ProcessScreenConnected(ScreenId rsScreenId); + sptr InitAndGetScreen(ScreenId rsScreenId); + void ProcessScreenDisconnected(ScreenId rsScreenId); + bool InitAbstractScreenModesInfo(sptr& absScreen); + sptr InitVirtualScreen(ScreenId dmsScreenId, ScreenId rsId, VirtualScreenOption option); + sptr AddToGroupLocked(sptr newScreen); + sptr RemoveFromGroupLocked(sptr newScreen); + bool RemoveChildFromGroup(sptr, sptr); + bool CheckScreenInScreenGroup(sptr newScreen) const; + sptr AddAsFirstScreenLocked(sptr newScreen); + sptr AddAsSuccedentScreenLocked(sptr newScreen); + void ProcessScreenModeChanged(ScreenId dmsScreenId); + void ChangeScreenGroup(sptr group, const std::vector& screens, + const std::vector& startPoints, bool filterScreen, ScreenCombination combination); + void AddScreenToGroup(sptr, const std::vector&, + const std::vector&, std::map&); + void NotifyScreenConnected(sptr) const; + void NotifyScreenDisconnected(ScreenId screenId) const; + void NotifyScreenChanged(sptr screenInfo, ScreenChangeEvent event) const; + void NotifyScreenGroupChanged(const sptr& screenInfo, ScreenGroupChangeEvent event) const; + void NotifyScreenGroupChanged(const std::vector>& screenInfo, ScreenGroupChangeEvent event) const; + + class ScreenIdManager { + public: + ScreenIdManager() = default; + ~ScreenIdManager() = default; + WM_DISALLOW_COPY_AND_MOVE(ScreenIdManager); + ScreenId CreateAndGetNewScreenId(ScreenId rsScreenId); + bool DeleteScreenId(ScreenId dmsScreenId); + bool HasDmsScreenId(ScreenId dmsScreenId) const; + bool HasRsScreenId(ScreenId dmsScreenId) const; + bool ConvertToRsScreenId(ScreenId, ScreenId&) const; + ScreenId ConvertToRsScreenId(ScreenId) const; + bool ConvertToDmsScreenId(ScreenId, ScreenId&) const; + ScreenId ConvertToDmsScreenId(ScreenId) const; + uint32_t GetRSScreenNum() const; + private: + std::atomic dmsScreenCount_ {0}; + std::map rs2DmsScreenIdMap_; + std::map dms2RsScreenIdMap_; + }; + + std::recursive_mutex& mutex_; + OHOS::Rosen::RSInterfaces& rsInterface_; + ScreenIdManager screenIdManager_; + std::map> dmsScreenMap_; + std::map> dmsScreenGroupMap_; + std::map, std::vector> screenAgentMap_; + sptr deathRecipient_ { nullptr }; + sptr abstractScreenCallback_; + sptr rSScreenChangeListener_; + std::shared_ptr controllerHandler_; + std::atomic defaultRsScreenId_ {SCREEN_ID_INVALID }; + Orientation buildInDefaultOrientation_ { Orientation::UNSPECIFIED }; + bool isExpandCombination_ = false; +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_ABSTRACT_SCREEN_CONTROLLER_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_cutout_controller.h b/window_manager/dmserver/include/display_cutout_controller.h new file mode 100644 index 0000000..ad9343b --- /dev/null +++ b/window_manager/dmserver/include/display_cutout_controller.h @@ -0,0 +1,78 @@ +/* + * 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_ROSEN_DISPLAY_CUTOUT_CONTROLLER_H +#define OHOS_ROSEN_DISPLAY_CUTOUT_CONTROLLER_H + +#include +#include +#include +#include + +#include "include/core/SkPath.h" +#include "include/core/SkMatrix.h" +#include "include/core/SkPathMeasure.h" +#include "include/utils/SkParsePath.h" + +#include "cutout_info.h" +#include "dm_common.h" +#include "noncopyable.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +class DisplayCutoutController : public RefBase { +public: + DisplayCutoutController() {}; + virtual ~DisplayCutoutController() = default; + + void SetCutoutSvgPath(DisplayId displayId, const std::string& svgPath); + sptr GetCutoutInfo(DisplayId displayId); + + // For built-in display + void SetBuiltInDisplayCutoutSvgPath(const std::string& svgPath); + static void SetIsWaterfallDisplay(bool isWaterfallDisplay); + static bool IsWaterfallDisplay(); + void SetCurvedScreenBoundary(std::vector curvedScreenBoundary); + + // For waterfall display curved area compression. + static void SetWaterfallAreaCompressionEnableWhenHorzontal(bool isEnable); + static void SetWaterfallAreaCompressionSizeWhenHorizontal(uint32_t size); + static bool IsWaterfallAreaCompressionEnableWhenHorizontal(); + static uint32_t GetWaterfallAreaCompressionSizeWhenHorizontal(); +private: + DMRect CalcCutoutBoundingRect(std::string svgPath); + void CheckBoundingRectsBoundary(DisplayId displayId, std::vector& boundingRects); + void CalcBuiltInDisplayWaterfallRects(); + void CalcBuiltInDisplayWaterfallRectsByRotation(Rotation rotation, uint32_t displayHeight, uint32_t displayWidth); + void TransferBoundingRectsByRotation(DisplayId displayId, std::vector& boundingRects); + DMRect CreateWaterfallRect(uint32_t left, uint32_t top, uint32_t width, uint32_t height); + + // Raw data + std::map> svgPaths_; + static bool isWaterfallDisplay_; + std::vector curvedScreenBoundary_; // Order: left top right bottom + + // Calulated data + WaterfallDisplayAreaRects waterfallDisplayAreaRects_ = {}; + std::map> boundingRects_; + + // For waterfall display curved area compression. + static bool isWaterfallAreaCompressionEnableWhenHorizontal_; + static uint32_t waterfallAreaCompressionSizeWhenHorizontal_; // The unit is vp. +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_DISPLAY_CUTOUT_CONTROLLER_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_dumper.h b/window_manager/dmserver/include/display_dumper.h new file mode 100644 index 0000000..3ee64b9 --- /dev/null +++ b/window_manager/dmserver/include/display_dumper.h @@ -0,0 +1,60 @@ +/* + * 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_ROSEN_DISPLAY_DUMPER_H +#define OHOS_ROSEN_DISPLAY_DUMPER_H + +#include "dm_common.h" +#include "abstract_display_controller.h" +#include "abstract_screen_controller.h" + +namespace OHOS { +namespace Rosen { +enum DumpType : uint32_t { + DUMP_ALL_SCREEN = 0, + DUMP_ALL_DISPLAY, + DUMP_SCREEN, + DUMP_DISPLAY, + DUMP_NONE = 100, +}; +class DisplayDumper : public RefBase { +public: + DisplayDumper(const sptr& abstractDisplayController, + const sptr& abstractScreenController, std::recursive_mutex& mutex); + DMError Dump(int fd, const std::vector& args) const; + +private: + void ShowHelpInfo(std::string& dumpInfo) const; + void ShowIllegalArgsInfo(std::string& dumpInfo, DMError errCode) const; + + DMError DumpInfo(const std::vector& args, std::string& dumpInfo) const; + DMError DumpAllScreenInfo(std::string& dumpInfo) const; + DMError DumpScreenInfo(const sptr& screenGroup, std::string& dumpInfo) const; + DMError DumpSpecifiedScreenInfo(ScreenId screenId, std::string& dumpInfo) const; + DMError DumpAllDisplayInfo(std::string& dumpInfo) const; + DMError DumpSpecifiedDisplayInfo(DisplayId displayId, std::string& dumpInfo) const; + + bool IsValidDigitString(const std::string& idStr) const; + std::string TransferTypeToString(ScreenType type) const; + void GetScreenInfo(const sptr& screen, std::ostringstream& oss) const; + void GetDisplayInfo(const sptr& display, std::ostringstream& oss) const; + + const sptr abstractDisplayController_; + const sptr abstractScreenController_; + std::recursive_mutex& mutex_; +}; +} +} +#endif // OHOS_ROSEN_DISPLAY_DUMPER_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_manager_agent_controller.h b/window_manager/dmserver/include/display_manager_agent_controller.h new file mode 100644 index 0000000..9f07fb5 --- /dev/null +++ b/window_manager/dmserver/include/display_manager_agent_controller.h @@ -0,0 +1,55 @@ +/* + * 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_ROSEN_DISPLAY_MANAGER_AGENT_CONTROLLER_H +#define OHOS_ROSEN_DISPLAY_MANAGER_AGENT_CONTROLLER_H + +#include +#include "wm_single_instance.h" +#include "client_agent_container.h" +#include "zidl/display_manager_agent_interface.h" + +namespace OHOS { +namespace Rosen { +class DisplayManagerAgentController { +WM_DECLARE_SINGLE_INSTANCE_BASE(DisplayManagerAgentController) +public: + bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type); + bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type); + + bool NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status); + bool NotifyDisplayStateChanged(DisplayId id, DisplayState state); + + void OnScreenConnect(sptr screenInfo); + void OnScreenDisconnect(ScreenId); + void OnScreenChange(sptr, ScreenChangeEvent); + void OnScreenGroupChange(const std::string&, const sptr&, ScreenGroupChangeEvent); + void OnScreenGroupChange(const std::string&, const std::vector>&, ScreenGroupChangeEvent); + void OnDisplayCreate(sptr); + void OnDisplayDestroy(DisplayId); + void OnDisplayChange(sptr, DisplayChangeEvent); + void OnScreenshot(sptr); + +private: + DisplayManagerAgentController() {} + virtual ~DisplayManagerAgentController() = default; + + ClientAgentContainer dmAgentContainer_; +}; +} +} +#endif // OHOS_ROSEN_DISPLAY_MANAGER_AGENT_CONTROLLER_H diff --git a/window_manager/dmserver/include/display_manager_config.h b/window_manager/dmserver/include/display_manager_config.h new file mode 100644 index 0000000..f8a5290 --- /dev/null +++ b/window_manager/dmserver/include/display_manager_config.h @@ -0,0 +1,50 @@ +/* + * 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_ROSEN_DISPLAY_MANAGER_CONFIG_H +#define OHOS_ROSEN_DISPLAY_MANAGER_CONFIG_H + +#include +#include "xml_config_base.h" +#include "libxml/parser.h" + +namespace OHOS::Rosen { +class DisplayManagerConfig : public RefBase, public XmlConfigBase { +public: + DisplayManagerConfig() = delete; + ~DisplayManagerConfig() = default; + + static bool LoadConfigXml(); + static const std::map& GetEnableConfig(); + static const std::map>& GetIntNumbersConfig(); + static const std::map& GetStringConfig(); + static void DumpConfig(); + +private: + static std::map enableConfig_; + static std::map> intNumbersConfig_; + static std::map stringConfig_; + + static bool IsValidNode(const xmlNode& currNode); + static void ReadEnableConfigInfo(const xmlNodePtr& currNode); + static void ReadIntNumbersConfigInfo(const xmlNodePtr& currNode); + static void ReadStringConfigInfo(const xmlNodePtr& currNode); + static std::string GetConfigPath(const std::string& configFileName); + + static std::vector Split(std::string str, std::string pattern); + static inline bool IsNumber(std::string str); +}; +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_DISPLAY_MANAGER_CONFIG_H diff --git a/window_manager/dmserver/include/display_manager_interface.h b/window_manager/dmserver/include/display_manager_interface.h new file mode 100644 index 0000000..c814292 --- /dev/null +++ b/window_manager/dmserver/include/display_manager_interface.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_DISPLAY_MANAGER_INTERFACE_H +#define FOUNDATION_DMSERVER_DISPLAY_MANAGER_INTERFACE_H + +#include +#include +#include + +#include "display_cutout_controller.h" +#include "display_info.h" +#include "dm_common.h" +#include "screen.h" +#include "screen_info.h" +#include "screen_group_info.h" +#include "zidl/display_manager_agent_interface.h" + +namespace OHOS::Rosen { +class IDisplayManager : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.IDisplayManager"); + + enum class DisplayManagerMessage : uint32_t { + TRANS_ID_GET_DEFAULT_DISPLAY_INFO = 0, + TRANS_ID_GET_DISPLAY_BY_ID, + TRANS_ID_GET_DISPLAY_BY_SCREEN, + TRANS_ID_GET_DISPLAY_SNAPSHOT, + TRANS_ID_REGISTER_DISPLAY_MANAGER_AGENT, + TRANS_ID_UNREGISTER_DISPLAY_MANAGER_AGENT, + TRANS_ID_WAKE_UP_BEGIN, + TRANS_ID_WAKE_UP_END, + TRANS_ID_SUSPEND_BEGIN, + TRANS_ID_SUSPEND_END, + TRANS_ID_SET_SCREEN_POWER_FOR_ALL, + TRANS_ID_GET_SCREEN_POWER, + TRANS_ID_SET_DISPLAY_STATE, + TRANS_ID_GET_DISPLAY_STATE, + TRANS_ID_GET_ALL_DISPLAYIDS, + TRANS_ID_NOTIFY_DISPLAY_EVENT, + TRANS_ID_SET_FREEZE_EVENT, + TRANS_ID_SCREEN_BASE = 1000, + TRANS_ID_CREATE_VIRTUAL_SCREEN = TRANS_ID_SCREEN_BASE, + TRANS_ID_DESTROY_VIRTUAL_SCREEN, + TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE, + TRANS_ID_GET_SCREEN_INFO_BY_ID, + TRANS_ID_GET_SCREEN_GROUP_INFO_BY_ID, + TRANS_ID_SET_SCREEN_ACTIVE_MODE, + TRANS_ID_GET_ALL_SCREEN_INFOS, + TRANS_ID_SET_ORIENTATION, + TRANS_ID_SET_VIRTUAL_PIXEL_RATIO, + TRANS_ID_SCREENGROUP_BASE = 1100, + TRANS_ID_SCREEN_MAKE_MIRROR = TRANS_ID_SCREENGROUP_BASE, + TRANS_ID_SCREEN_MAKE_EXPAND, + TRANS_ID_REMOVE_VIRTUAL_SCREEN_FROM_SCREEN_GROUP, + TRANS_ID_SCREEN_GAMUT_BASE = 1200, + TRANS_ID_SCREEN_GET_SUPPORTED_COLOR_GAMUTS = TRANS_ID_SCREEN_GAMUT_BASE, + TRANS_ID_SCREEN_GET_COLOR_GAMUT, + TRANS_ID_SCREEN_SET_COLOR_GAMUT, + TRANS_ID_SCREEN_GET_GAMUT_MAP, + TRANS_ID_SCREEN_SET_GAMUT_MAP, + TRANS_ID_SCREEN_SET_COLOR_TRANSFORM, + TRANS_ID_IS_SCREEN_ROTATION_LOCKED, + TRANS_ID_SET_SCREEN_ROTATION_LOCKED, + TRANS_ID_HAS_PRIVATE_WINDOW, + TRANS_ID_GET_CUTOUT_INFO, + }; + + virtual sptr GetDefaultDisplayInfo() = 0; + virtual sptr GetDisplayInfoById(DisplayId displayId) = 0; + virtual sptr GetDisplayInfoByScreen(ScreenId screenId) = 0; + virtual DMError HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) = 0; + + virtual ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) = 0; + virtual DMError DestroyVirtualScreen(ScreenId screenId) = 0; + virtual DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) = 0; + virtual bool SetOrientation(ScreenId screenId, Orientation orientation) = 0; + virtual std::shared_ptr GetDisplaySnapshot(DisplayId displayId) = 0; + virtual void SetScreenRotationLocked(bool isLocked) = 0; + virtual bool IsScreenRotationLocked() = 0; + + // colorspace, gamut + virtual DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) = 0; + virtual DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) = 0; + virtual DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) = 0; + virtual DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) = 0; + virtual DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) = 0; + virtual DMError SetScreenColorTransform(ScreenId screenId) = 0; + + virtual bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) = 0; + virtual bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) = 0; + virtual bool WakeUpBegin(PowerStateChangeReason reason) = 0; + virtual bool WakeUpEnd() = 0; + virtual bool SuspendBegin(PowerStateChangeReason reason) = 0; + virtual bool SuspendEnd() = 0; + virtual bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) = 0; + virtual ScreenPowerState GetScreenPower(ScreenId dmsScreenId) = 0; + virtual bool SetDisplayState(DisplayState state) = 0; + virtual DisplayState GetDisplayState(DisplayId displayId) = 0; + virtual std::vector GetAllDisplayIds() = 0; + virtual sptr GetCutoutInfo(DisplayId displayId) = 0; + virtual void NotifyDisplayEvent(DisplayEvent event) = 0; + virtual bool SetFreeze(std::vector displayIds, bool isFreeze) = 0; + virtual sptr GetScreenInfoById(ScreenId screenId) = 0; + virtual sptr GetScreenGroupInfoById(ScreenId screenId) = 0; + virtual std::vector> GetAllScreenInfos() = 0; + virtual ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) = 0; + virtual ScreenId MakeExpand(std::vector screenId, std::vector startPoint) = 0; + virtual void RemoveVirtualScreenFromGroup(std::vector screens) = 0; + virtual bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId) = 0; + virtual bool SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) = 0; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DMSERVER_DISPLAY_MANAGER_INTERFACE_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_manager_proxy.h b/window_manager/dmserver/include/display_manager_proxy.h new file mode 100644 index 0000000..48de3a7 --- /dev/null +++ b/window_manager/dmserver/include/display_manager_proxy.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_DISPLAY_MANAGER_PROXY_H +#define FOUNDATION_DMSERVER_DISPLAY_MANAGER_PROXY_H + +#include "display_manager_interface.h" + +#include "dm_common.h" + +#include "screen.h" + +#include + +namespace OHOS::Rosen { +class DisplayManagerProxy : public IRemoteProxy { +public: + explicit DisplayManagerProxy(const sptr &impl) + : IRemoteProxy(impl) {}; + ~DisplayManagerProxy() {}; + + sptr GetDefaultDisplayInfo() override; + sptr GetDisplayInfoById(DisplayId displayId) override; + sptr GetDisplayInfoByScreen(ScreenId screenId) override; + DMError HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) override; + + ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) override; + DMError DestroyVirtualScreen(ScreenId screenId) override; + DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; + bool SetOrientation(ScreenId screenId, Orientation orientation) override; + std::shared_ptr GetDisplaySnapshot(DisplayId displayId) override; + bool IsScreenRotationLocked() override; + void SetScreenRotationLocked(bool isLocked) override; + + // colorspace, gamut + DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) override; + DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) override; + DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) override; + DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) override; + DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) override; + DMError SetScreenColorTransform(ScreenId screenId) override; + + bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) override; + bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) override; + bool WakeUpBegin(PowerStateChangeReason reason) override; + bool WakeUpEnd() override; + bool SuspendBegin(PowerStateChangeReason reason) override; + bool SuspendEnd() override; + bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) override; + ScreenPowerState GetScreenPower(ScreenId dmsScreenId) override; + bool SetDisplayState(DisplayState state) override; + std::vector GetAllDisplayIds() override; + DisplayState GetDisplayState(DisplayId displayId) override; + sptr GetCutoutInfo(DisplayId displayId) override; + void NotifyDisplayEvent(DisplayEvent event) override; + bool SetFreeze(std::vector displayIds, bool isFreeze) override; + ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; + sptr GetScreenInfoById(ScreenId screenId) override; + sptr GetScreenGroupInfoById(ScreenId screenId) override; + std::vector> GetAllScreenInfos() override; + ScreenId MakeExpand(std::vector screenId, std::vector startPoint) override; + void RemoveVirtualScreenFromGroup(std::vector screens) override; + bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId) override; + bool SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DMSERVER_DISPLAY_MANAGER_PROXY_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_manager_service.h b/window_manager/dmserver/include/display_manager_service.h new file mode 100644 index 0000000..ccf579f --- /dev/null +++ b/window_manager/dmserver/include/display_manager_service.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_H +#define FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_H + +#include +#include + +#include +#include +#include + +#include "atomic_map.h" +#include "dm_common.h" +#include "display_dumper.h" +#include "screen.h" +#include "abstract_display.h" +#include "abstract_display_controller.h" +#include "abstract_screen_controller.h" +#include "display_change_listener.h" +#include "display_cutout_controller.h" +#include "display_manager_stub.h" +#include "display_power_controller.h" +#include "rsscreen_change_listener.h" +#include "singleton_delegator.h" +#include "window_info_queried_listener.h" + +namespace OHOS::Rosen { +class DisplayManagerService : public SystemAbility, public DisplayManagerStub { +DECLARE_SYSTEM_ABILITY(DisplayManagerService); +WM_DECLARE_SINGLE_INSTANCE_BASE(DisplayManagerService); + +public: + int Dump(int fd, const std::vector& args) override; + void OnStart() override; + void OnStop() override; + ScreenId CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) override; + DMError DestroyVirtualScreen(ScreenId screenId) override; + DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface) override; + bool IsScreenRotationLocked() override; + void SetScreenRotationLocked(bool isLocked) override; + + sptr GetDefaultDisplayInfo() override; + sptr GetDisplayInfoById(DisplayId displayId) override; + sptr GetDisplayInfoByScreen(ScreenId screenId) override; + sptr GetCutoutInfo(DisplayId displayId) override; + bool SetOrientation(ScreenId screenId, Orientation orientation) override; + bool SetOrientationFromWindow(ScreenId screenId, Orientation orientation); + bool SetRotationFromWindow(ScreenId screenId, Rotation targetRotation); + void SetGravitySensorSubscriptionEnabled(); + std::shared_ptr GetDisplaySnapshot(DisplayId displayId) override; + uint32_t GetRSScreenNum() const; + DMError HasPrivateWindow(DisplayId id, bool& hasPrivateWindow) override; + // colorspace, gamut + DMError GetScreenSupportedColorGamuts(ScreenId screenId, std::vector& colorGamuts) override; + DMError GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) override; + DMError SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) override; + DMError GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) override; + DMError SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) override; + DMError SetScreenColorTransform(ScreenId screenId) override; + + bool RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) override; + bool UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) override; + bool WakeUpBegin(PowerStateChangeReason reason) override; + bool WakeUpEnd() override; + bool SuspendBegin(PowerStateChangeReason reason) override; + bool SuspendEnd() override; + bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) override; + ScreenPowerState GetScreenPower(ScreenId dmsScreenId) override; + bool SetDisplayState(DisplayState state) override; + void UpdateRSTree(DisplayId displayId, DisplayId parentDisplayId, std::shared_ptr& surfaceNode, + bool isAdd, bool isMultiDisplay); + + DisplayState GetDisplayState(DisplayId displayId) override; + void NotifyDisplayEvent(DisplayEvent event) override; + bool SetFreeze(std::vector displayIds, bool isFreeze) override; + + ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) override; + ScreenId MakeExpand(std::vector screenId, std::vector startPoint) override; + void RemoveVirtualScreenFromGroup(std::vector screens) override; + sptr GetScreenInfoById(ScreenId screenId) override; + sptr GetScreenGroupInfoById(ScreenId screenId) override; + ScreenId GetScreenGroupIdByScreenId(ScreenId screenId); + std::vector> GetAllScreenInfos() override; + + std::vector GetAllDisplayIds() override; + bool SetScreenActiveMode(ScreenId screenId, uint32_t modeId) override; + bool SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) override; + void RegisterDisplayChangeListener(sptr listener); + void RegisterWindowInfoQueriedListener(const sptr& listener); + void RegisterRSScreenChangeListener(const sptr& listener); +private: + DisplayManagerService(); + ~DisplayManagerService() = default; + bool Init(); + void NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type); + void NotifyScreenshot(DisplayId displayId); + ScreenId GetScreenIdByDisplayId(DisplayId displayId) const; + void ConfigureDisplayManagerService(); + void ConfigureWaterfallDisplayCompressionParams(); + + std::recursive_mutex mutex_; + static inline SingletonDelegator delegator_; + sptr abstractDisplayController_; + sptr abstractScreenController_; + sptr displayPowerController_; + sptr displayCutoutController_; + sptr displayChangeListener_; + sptr windowInfoQueriedListener_; + sptr displayDumper_; + AtomicMap accessTokenIdMaps_; + bool isAutoRotationOpen_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_manager_service_inner.h b/window_manager/dmserver/include/display_manager_service_inner.h new file mode 100644 index 0000000..d3e4c28 --- /dev/null +++ b/window_manager/dmserver/include/display_manager_service_inner.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_INNER_H +#define FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_INNER_H + +#include + +#include +#include + +#include "abstract_display.h" +#include "cutout_info.h" +#include "display_change_listener.h" +#include "rsscreen_change_listener.h" +#include "singleton_delegator.h" +#include "wm_single_instance.h" +#include "window_info_queried_listener.h" + +namespace OHOS::Rosen { +class DisplayManagerServiceInner { +WM_DECLARE_SINGLE_INSTANCE(DisplayManagerServiceInner); + +public: + std::vector> GetAllDisplays() const; + DisplayId GetDefaultDisplayId() const; + sptr GetDefaultDisplay() const; + sptr GetDisplayById(DisplayId displayId) const; + std::vector GetAllDisplayIds() const; + uint32_t GetRSScreenNum() const; + sptr GetScreenInfoByDisplayId(DisplayId displayId) const; + ScreenId GetScreenGroupIdByDisplayId(DisplayId displayId) const; + sptr GetScreenModesByDisplayId(DisplayId displayId) const; + std::shared_ptr GetDisplaySnapshot(DisplayId) const; + void UpdateRSTree(DisplayId displayId, DisplayId parentDisplayId, std::shared_ptr& surfaceNode, + bool isAdd, bool isMultiDisplay); + void RegisterDisplayChangeListener(sptr listener); + bool SetOrientationFromWindow(DisplayId displayId, Orientation orientation); + bool SetRotationFromWindow(DisplayId displayId, Rotation targetRotation); + void SetGravitySensorSubscriptionEnabled(); + void RegisterWindowInfoQueriedListener(const sptr& listener); + void RegisterRSScreenChangeListener(const sptr& listener); + sptr GetCutoutInfo(DisplayId displayId) const; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DMSERVER_DISPLAY_MANAGER_SERVICE_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_manager_stub.h b/window_manager/dmserver/include/display_manager_stub.h new file mode 100644 index 0000000..d88c4a0 --- /dev/null +++ b/window_manager/dmserver/include/display_manager_stub.h @@ -0,0 +1,33 @@ +/* + * 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 FOUNDATION_DMSERVER_DISPLAY_MANAGER_STUB_H +#define FOUNDATION_DMSERVER_DISPLAY_MANAGER_STUB_H + +#include "display_manager_interface.h" + +#include + +namespace OHOS::Rosen { +class DisplayManagerStub : public IRemoteStub { +public: + DisplayManagerStub() = default; + ~DisplayManagerStub() = default; + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) override; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DMSERVER_DISPLAY_MANAGER_STUB_H \ No newline at end of file diff --git a/window_manager/dmserver/include/display_power_controller.h b/window_manager/dmserver/include/display_power_controller.h new file mode 100644 index 0000000..7bba6a2 --- /dev/null +++ b/window_manager/dmserver/include/display_power_controller.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021-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_ROSEN_DISPLAY_POWER_CONTROLLER_H +#define OHOS_ROSEN_DISPLAY_POWER_CONTROLLER_H + +#include +#include +#include +#include "display.h" +#include "display_change_listener.h" +#include "dm_common.h" + +namespace OHOS { +namespace Rosen { +class DisplayPowerController : public RefBase { +using DisplayStateChangeListener = std::function, + const std::map>&, DisplayStateChangeType)>; +public: + DisplayPowerController(std::recursive_mutex& mutex, DisplayStateChangeListener listener) + : mutex_(mutex), displayStateChangeListener_(listener) + { + } + virtual ~DisplayPowerController() = default; + + bool SuspendBegin(PowerStateChangeReason reason); + bool SetDisplayState(DisplayState state); + DisplayState GetDisplayState(DisplayId displayId); + void NotifyDisplayEvent(DisplayEvent event); + +private: + DisplayState displayState_ { DisplayState::UNKNOWN }; + bool isKeyguardDrawn_ { false }; + std::recursive_mutex& mutex_; + DisplayStateChangeListener displayStateChangeListener_; +}; +} +} +#endif // OHOS_ROSEN_DISPLAY_POWER_CONTROLLER_H \ No newline at end of file diff --git a/window_manager/dmserver/include/screen_rotation_controller.h b/window_manager/dmserver/include/screen_rotation_controller.h new file mode 100644 index 0000000..3b8abaa --- /dev/null +++ b/window_manager/dmserver/include/screen_rotation_controller.h @@ -0,0 +1,101 @@ +/* + * 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_ROSEN_SCREEN_ROTATION_CONTROLLER_H +#define OHOS_ROSEN_SCREEN_ROTATION_CONTROLLER_H + +#include +#include + +#include "sensor_agent.h" + +#include "dm_common.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +enum class SensorRotation: int32_t { + INVALID = -1, + ROTATION_0 = 0, + ROTATION_90, + ROTATION_180, + ROTATION_270, +}; + +enum class DeviceRotation: int32_t { + INVALID = -1, + ROTATION_PORTRAIT = 0, + ROTATION_LANDSCAPE, + ROTATION_PORTRAIT_INVERTED, + ROTATION_LANDSCAPE_INVERTED, +}; + +class ScreenRotationController : public RefBase { +public: + ScreenRotationController() = delete; + ~ScreenRotationController() = default; + static void Init(); + static void HandleSensorEventInput(DeviceRotation deviceRotation); + static bool IsScreenRotationLocked(); + static void SetScreenRotationLocked(bool isLocked); + static void SetDefaultDeviceRotationOffset(uint32_t defaultDeviceRotationOffset); + static void ProcessOrientationSwitch(Orientation orientation); + + static bool IsDefaultDisplayRotationPortrait(); + static bool IsDisplayRotationVertical(Rotation rotation); + static bool IsDisplayRotationHorizontal(Rotation rotation); + static DeviceRotation ConvertSensorToDeviceRotation(SensorRotation sensorRotation); +private: + static void HandleGravitySensorEventCallback(SensorEvent *event); + static Rotation GetCurrentDisplayRotation(); + static Orientation GetPreferredOrientation(); + static void SetScreenRotation(Rotation targetRotation); + static Rotation CalcTargetDisplayRotation(Orientation requestedOrientation, + DeviceRotation sensorRotationConverted); + static DeviceRotation CalcDeviceRotation(SensorRotation sensorRotation); + static Rotation ConvertDeviceToDisplayRotation(DeviceRotation sensorRotationConverted); + + static bool IsDeviceRotationVertical(DeviceRotation deviceRotation); + static bool IsDeviceRotationHorizontal(DeviceRotation deviceRotation); + static bool IsCurrentDisplayVertical(); + static bool IsCurrentDisplayHorizontal(); + static bool IsSensorRelatedOrientation(Orientation orientation); + + static void ProcessRotationMapping(); + static void ProcessSwitchToAutoRotationPortrait(DeviceRotation rotation); + static void ProcessSwitchToAutoRotationLandscape(DeviceRotation rotation); + static void ProcessSwitchToAutoRotation(DeviceRotation rotation); + static void ProcessSwitchToAutoRotationPortraitRestricted(); + static void ProcessSwitchToAutoRotationLandscapeRestricted(); + static void ProcessSwitchToSensorRelatedOrientation(Orientation orientation, DeviceRotation deviceRotation); + static void ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation); + static Rotation ProcessAutoRotationPortraitOrientation(DeviceRotation sensorRotationConveted); + static Rotation ProcessAutoRotationLandscapeOrientation(DeviceRotation sensorRotationConveted); + + static DisplayId defaultDisplayId_; + static uint32_t defaultDeviceRotationOffset_; + static uint32_t defaultDeviceRotation_; + static std::map sensorToDeviceRotationMap_; + static std::map deviceToDisplayRotationMap_; + static Orientation lastOrientationType_; + static Rotation currentDisplayRotation_; + static Rotation lastSensorDecidedRotation_; + static Rotation rotationLockedRotation_; + static bool isScreenRotationLocked_; + static DeviceRotation lastSensorRotationConverted_; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_SCREEN_ROTATION_CONTROLLER_H diff --git a/window_manager/dmserver/include/sensor_connector.h b/window_manager/dmserver/include/sensor_connector.h new file mode 100644 index 0000000..d489d76 --- /dev/null +++ b/window_manager/dmserver/include/sensor_connector.h @@ -0,0 +1,84 @@ +/* + * 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_ROSEN_SCREEN_CONNECTOR_H +#define OHOS_ROSEN_SCREEN_CONNECTOR_H + +#include +#include +#include "dm_common.h" +#ifdef WM_SUBSCRIBE_MOTION_ENABLE +#include "motion_agent.h" +#include "motion_callback_stub.h" +#endif +#include "screen_rotation_controller.h" +#include "sensor_agent.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +class SensorConnector : public RefBase { +public: + SensorConnector() = delete; + ~SensorConnector() = default; + + static void SubscribeRotationSensor(); + static void UnsubscribeRotationSensor(); +}; + +class GravitySensorSubscriber { +friend SensorConnector; +public: + GravitySensorSubscriber() = delete; + ~GravitySensorSubscriber() = default; +private: + static void SubscribeGravitySensor(); + static void UnsubscribeGravitySensor(); + + static void HandleGravitySensorEventCallback(SensorEvent *event); + static bool CheckCallbackTimeInterval(); + static int CalcRotationDegree(GravityData* gravityData); + static SensorRotation CalcSensorRotation(int sensorDegree); + + static SensorUser user_; + static bool isGravitySensorSubscribed_; + static long lastCallbackTime_; +}; + +#ifdef WM_SUBSCRIBE_MOTION_ENABLE +using OHOS::Msdp::MotionCallbackStub; +using OHOS::Msdp::MotionData; + +class RotationMotionEventCallback : public MotionCallbackStub { +public: + void OnMotionChanged(const MotionData& motionData) override; +}; + +class MotionSubscriber { +friend SensorConnector; +public: + MotionSubscriber() = delete; + ~MotionSubscriber() = default; +private: + static void SubscribeMotionSensor(); + static void UnsubscribeMotionSensor(); + + static sptr motionEventCallback_; + static bool isMotionSensorSubscribed_; +}; +#endif +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_SCREEN_CONNECTOR_H diff --git a/window_manager/dmserver/src/abstract_display.cpp b/window_manager/dmserver/src/abstract_display.cpp new file mode 100644 index 0000000..59722ce --- /dev/null +++ b/window_manager/dmserver/src/abstract_display.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2021-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 "abstract_display.h" + +#include "abstract_screen_controller.h" +#include "display_manager_config.h" +#include "display_manager_service.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractDisplay"}; + constexpr int32_t PAD_SCREEN_WIDTH = 2560; + constexpr int32_t PHONE_SCREEN_WIDTH = 2160; +} + +AbstractDisplay::AbstractDisplay(DisplayId id, std::string name, + sptr& info, sptr& absScreen) + : id_(id), + name_(name), + screenId_(absScreen->dmsId_), + screenGroupId_(absScreen->groupDmsId_), + width_(info->width_), + height_(info->height_), + refreshRate_(info->refreshRate_), + orientation_(absScreen->orientation_) +{ + RequestRotation(absScreen->rotation_); + auto numbersConfig = DisplayManagerConfig::GetIntNumbersConfig(); + if (numbersConfig.count("dpi") != 0) { + uint32_t densityDpi = static_cast(numbersConfig["dpi"][0]); + if (densityDpi >= DOT_PER_INCH_MINIMUM_VALUE && densityDpi <= DOT_PER_INCH_MAXIMUM_VALUE) { + virtualPixelRatio_ = static_cast(densityDpi) / BASELINE_DENSITY; + absScreen->SetVirtualPixelRatio(virtualPixelRatio_); + return; + } + } + if ((info->width_ >= PHONE_SCREEN_WIDTH) || (info->height_ >= PHONE_SCREEN_WIDTH)) { + if ((info->width_ == PAD_SCREEN_WIDTH) || (info->height_ == PAD_SCREEN_WIDTH)) { + virtualPixelRatio_ = 2.0f; // Pad is 2.0 + } else { + virtualPixelRatio_ = 3.0f; // Phone is 3.0 + } + } else { + virtualPixelRatio_ = 1.0f; // Other is 1.0 + } + absScreen->SetVirtualPixelRatio(virtualPixelRatio_); +} + +DisplayId AbstractDisplay::GetId() const +{ + return id_; +} + +int32_t AbstractDisplay::GetWidth() const +{ + return width_; +} + +int32_t AbstractDisplay::GetHeight() const +{ + return height_; +} + +uint32_t AbstractDisplay::GetRefreshRate() const +{ + return refreshRate_; +} + +float AbstractDisplay::GetVirtualPixelRatio() const +{ + return virtualPixelRatio_; +} + +int32_t AbstractDisplay::GetOffsetX() const +{ + return offsetX_; +} + +int32_t AbstractDisplay::GetOffsetY() const +{ + return offsetY_; +} + +void AbstractDisplay::SetOffsetX(int32_t offsetX) +{ + offsetX_ = offsetX; +} + +void AbstractDisplay::SetOffsetY(int32_t offsetY) +{ + offsetY_ = offsetY; +} + +void AbstractDisplay::SetWidth(int32_t width) +{ + width_ = width; +} + +void AbstractDisplay::SetHeight(int32_t height) +{ + height_ = height; +} + +void AbstractDisplay::SetOffset(int32_t offsetX, int32_t offsetY) +{ + offsetX_ = offsetX; + offsetY_ = offsetY; +} + +void AbstractDisplay::SetRefreshRate(uint32_t refreshRate) +{ + refreshRate_ = refreshRate; +} + +void AbstractDisplay::SetVirtualPixelRatio(float virtualPixelRatio) +{ + virtualPixelRatio_ = virtualPixelRatio; +} + +void AbstractDisplay::SetId(DisplayId id) +{ + id_ = id; +} + +void AbstractDisplay::SetOrientation(Orientation orientation) +{ + orientation_ = orientation; +} + +bool AbstractDisplay::RequestRotation(Rotation rotation) +{ + WLOGD("request rotation from %{public}u to %{public}u, display %{public}" PRIu64"", rotation_, rotation, id_); + if (rotation_ == rotation) { + WLOGFE("rotation not change %{public}u", rotation); + return false; + } + if (IsVertical(rotation) != IsVertical(rotation_)) { + std::swap(width_, height_); + } + rotation_ = rotation; + return true; +} + +Rotation AbstractDisplay::GetRotation() const +{ + return rotation_; +} + +Orientation AbstractDisplay::GetOrientation() const +{ + return orientation_; +} + +void AbstractDisplay::SetFreezeFlag(FreezeFlag freezeFlag) +{ + freezeFlag_ = freezeFlag; +} + +FreezeFlag AbstractDisplay::GetFreezeFlag() const +{ + return freezeFlag_; +} + +bool AbstractDisplay::BindAbstractScreen(sptr abstractScreen) +{ + if (abstractScreen == nullptr) { + WLOGE("display bind screen error, cannot get screen. display:%{public}" PRIu64"", id_); + return false; + } + ScreenId dmsScreenId = abstractScreen->dmsId_; + sptr info = abstractScreen->GetActiveScreenMode(); + if (info == nullptr) { + WLOGE("display bind screen error, cannot get info. display:%{public}" PRIu64", screen:%{public}" PRIu64"", + id_, dmsScreenId); + return false; + } + + Point point = abstractScreen->GetGroup()->GetChildPosition(dmsScreenId); + offsetX_ = point.posX_; + offsetY_ = point.posY_; + width_ = static_cast(info->width_); + height_ = static_cast(info->height_); + refreshRate_ = info->refreshRate_; + screenId_ = dmsScreenId; + WLOGD("display bind to screen. display:%{public}" PRIu64", screen:%{public}" PRIu64"", id_, dmsScreenId); + return true; +} + +ScreenId AbstractDisplay::GetAbstractScreenId() const +{ + return screenId_; +} + +ScreenId AbstractDisplay::GetAbstractScreenGroupId() const +{ + return screenGroupId_; +} + +sptr AbstractDisplay::ConvertToDisplayInfo() const +{ + sptr displayInfo = new(std::nothrow) DisplayInfo(); + if (displayInfo == nullptr) { + return displayInfo; + } + displayInfo->name_ = name_; + displayInfo->SetOffsetX(offsetX_); + displayInfo->SetOffsetY(offsetY_); + displayInfo->SetWidth(width_); + displayInfo->SetHeight(height_); + displayInfo->SetDisplayId(id_); + displayInfo->SetRefreshRate(refreshRate_); + displayInfo->SetScreenId(screenId_); + displayInfo->SetScreenGroupId(screenGroupId_); + displayInfo->SetVirtualPixelRatio(virtualPixelRatio_); + displayInfo->SetRotation(rotation_); + displayInfo->SetOrientation(orientation_); + displayInfo->displayState_ = displayState_; + displayInfo->SetWaterfallDisplayCompressionStatus(waterfallDisplayCompressionStatus_); + return displayInfo; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dmserver/src/abstract_display_controller.cpp b/window_manager/dmserver/src/abstract_display_controller.cpp new file mode 100644 index 0000000..61d29fb --- /dev/null +++ b/window_manager/dmserver/src/abstract_display_controller.cpp @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2021-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 "abstract_display_controller.h" + +#include +#include +#include +#include + +#include "display_cutout_controller.h" +#include "display_manager_agent_controller.h" +#include "display_manager_service.h" +#include "screen_group.h" +#include "screen_rotation_controller.h" +#include "surface_capture_future.h" +#include "window_manager_hilog.h" +#include "sys_cap_util.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractDisplayController"}; +} + +AbstractDisplayController::AbstractDisplayController(std::recursive_mutex& mutex, DisplayStateChangeListener listener) + : mutex_(mutex), rsInterface_(RSInterfaces::GetInstance()), displayStateChangeListener_(listener) +{ +} + +AbstractDisplayController::~AbstractDisplayController() +{ + abstractScreenController_ = nullptr; +} + +void AbstractDisplayController::Init(sptr abstractScreenController) +{ + WLOGFD("display controller init"); + displayCount_ = 0; + abstractScreenController_ = abstractScreenController; + abstractScreenCallback_ = new(std::nothrow) AbstractScreenController::AbstractScreenCallback(); + if (abstractScreenCallback_ == nullptr) { + WLOGFE("abstractScreenCallback init failed"); + return; + } + abstractScreenCallback_->onConnect_ + = std::bind(&AbstractDisplayController::OnAbstractScreenConnect, this, std::placeholders::_1); + abstractScreenCallback_->onDisconnect_ + = std::bind(&AbstractDisplayController::OnAbstractScreenDisconnect, this, std::placeholders::_1); + abstractScreenCallback_->onChange_ + = std::bind(&AbstractDisplayController::OnAbstractScreenChange, this, std::placeholders::_1, + std::placeholders::_2); + abstractScreenController->RegisterAbstractScreenCallback(abstractScreenCallback_); +} + +ScreenId AbstractDisplayController::GetDefaultScreenId() +{ + return rsInterface_.GetDefaultScreenId(); +} + +RSScreenModeInfo AbstractDisplayController::GetScreenActiveMode(ScreenId id) +{ + return rsInterface_.GetScreenActiveMode(id); +} + +sptr AbstractDisplayController::GetAbstractDisplay(DisplayId displayId) const +{ + if (displayId == DISPLAY_ID_INVALID) { + WLOGFE("display id is invalid."); + return nullptr; + } + std::lock_guard lock(mutex_); + auto iter = abstractDisplayMap_.find(displayId); + if (iter == abstractDisplayMap_.end()) { + WLOGFE("Failed to get AbstractDisplay %{public}" PRIu64", return nullptr!", displayId); + return nullptr; + } + return iter->second; +} + +sptr AbstractDisplayController::GetAbstractDisplayByScreen(ScreenId screenId) const +{ + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("screen id is invalid."); + return nullptr; + } + std::lock_guard lock(mutex_); + for (auto iter : abstractDisplayMap_) { + sptr display = iter.second; + if (display->GetAbstractScreenId() == screenId) { + return display; + } + } + WLOGFE("fail to get AbstractDisplay %{public}" PRIu64"", screenId); + return nullptr; +} + +std::vector AbstractDisplayController::GetAllDisplayIds() const +{ + std::lock_guard lock(mutex_); + std::vector res; + for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); ++iter) { + res.push_back(iter->first); + } + return res; +} + +std::shared_ptr AbstractDisplayController::GetScreenSnapshot(DisplayId displayId) +{ + sptr abstractDisplay = GetAbstractDisplay(displayId); + if (abstractDisplay == nullptr) { + WLOGFE("GetScreenSnapshot: GetAbstractDisplay failed"); + return nullptr; + } + ScreenId dmsScreenId = abstractDisplay->GetAbstractScreenId(); + std::shared_ptr displayNode = abstractScreenController_->GetRSDisplayNodeByScreenId(dmsScreenId); + + std::lock_guard lock(mutex_); + std::shared_ptr callback = std::make_shared(); + rsInterface_.TakeSurfaceCapture(displayNode, callback); + std::shared_ptr screenshot = callback->GetResult(2000); // wait for <= 2000ms + if (screenshot == nullptr) { + WLOGFE("Failed to get pixelmap from RS, return nullptr!"); + } + + // notify dm listener + sptr snapshotInfo = new ScreenshotInfo(); + snapshotInfo->SetTrigger(SysCapUtil::GetClientName()); + snapshotInfo->SetDisplayId(displayId); + DisplayManagerAgentController::GetInstance().OnScreenshot(snapshotInfo); + + return screenshot; +} + +void AbstractDisplayController::OnAbstractScreenConnect(sptr absScreen) +{ + if (absScreen == nullptr) { + WLOGFE("absScreen is null"); + return; + } + WLOGI("connect new screen. id:%{public}" PRIu64"", absScreen->dmsId_); + std::lock_guard lock(mutex_); + sptr group = absScreen->GetGroup(); + if (group == nullptr) { + WLOGE("the group information of the screen is wrong"); + return; + } + if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1) { + BindAloneScreenLocked(absScreen); + } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) { + WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked"); + AddScreenToMirrorLocked(absScreen); + } else if (group->combination_ == ScreenCombination::SCREEN_EXPAND) { + WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_EXPAND, AddScreenToExpandLocked"); + AddScreenToExpandLocked(absScreen); + } else { + WLOGE("support in future. combination:%{public}u", group->combination_); + } +} + +void AbstractDisplayController::OnAbstractScreenDisconnect(sptr absScreen) +{ + if (absScreen == nullptr) { + WLOGE("the information of the screen is wrong"); + return; + } + WLOGI("disconnect screen. id:%{public}" PRIu64"", absScreen->dmsId_); + sptr screenGroup; + DisplayId absDisplayId = DISPLAY_ID_INVALID; + sptr abstractDisplay = nullptr; + 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, abstractDisplay); + } else if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { + absDisplayId = ProcessExpandScreenDisconnected(absScreen, screenGroup, abstractDisplay); + } else { + WLOGE("support in future. combination:%{public}u", screenGroup->combination_); + } + if (absDisplayId == DISPLAY_ID_INVALID) { + WLOGE("the displayId of the disconnected expand screen was not found"); + return; + } + if (screenGroup->combination_ == ScreenCombination::SCREEN_ALONE + || screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR) { + if (screenGroup->GetChildCount() == 0) { + abstractDisplayMap_.erase(absDisplayId); + DisplayManagerAgentController::GetInstance().OnDisplayDestroy(absDisplayId); + } + } else if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { + SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::DESTROY); + DisplayManagerAgentController::GetInstance().OnDisplayDestroy(absDisplayId); + abstractDisplayMap_.erase(absDisplayId); + } else { + WLOGE("support in future. combination:%{public}u", screenGroup->combination_); + } +} + +DisplayId AbstractDisplayController::ProcessNormalScreenDisconnected( + sptr absScreen, sptr screenGroup, sptr& absDisplay) +{ + WLOGI("normal screen disconnect"); + if (absScreen == nullptr || screenGroup == nullptr) { + WLOGFE("Invalid params as nullptr."); + return DISPLAY_ID_INVALID; + } + 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_) { + WLOGI("normal screen disconnect, displayId: %{public}" PRIu64", screenId: %{public}" PRIu64"", + displayId, abstractDisplay->GetAbstractScreenId()); + abstractDisplay->BindAbstractScreen(defaultScreen); + absDisplay = abstractDisplay; + return displayId; + } + } + return DISPLAY_ID_INVALID; +} + +DisplayId AbstractDisplayController::ProcessExpandScreenDisconnected( + sptr absScreen, sptr screenGroup, sptr& absDisplay) +{ + WLOGI("expand screen disconnect"); + if (absScreen == nullptr || screenGroup == nullptr) { + WLOGFE("Invalid params as nullptr."); + return DISPLAY_ID_INVALID; + } + DisplayId displayId = DISPLAY_ID_INVALID; + for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) { + sptr abstractDisplay = iter->second; + if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) { + WLOGI("expand screen disconnect, displayId: %{public}" PRIu64", screenId: %{public}" PRIu64"", + displayId, abstractDisplay->GetAbstractScreenId()); + absDisplay = abstractDisplay; + displayId = iter->first; + } else { + abstractDisplay->SetOffset(0, 0); + auto screenId = abstractDisplay->GetAbstractScreenId(); + abstractScreenController_->GetRSDisplayNodeByScreenId(screenId)->SetDisplayOffset(0, 0); + } + } + return displayId; +} + +void AbstractDisplayController::OnAbstractScreenChange(sptr absScreen, DisplayChangeEvent event) +{ + if (absScreen == nullptr) { + WLOGE("OnAbstractScreenChanged::the information of the screen is wrong"); + return; + } + WLOGI("screen changes. id:%{public}" PRIu64"", absScreen->dmsId_); + if (event == DisplayChangeEvent::UPDATE_ORIENTATION) { + ProcessDisplayUpdateOrientation(absScreen); + } else if (event == DisplayChangeEvent::DISPLAY_SIZE_CHANGED) { + ProcessDisplaySizeChange(absScreen); + } else if (event == DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED) { + ProcessVirtualPixelRatioChange(absScreen); + } else if (event == DisplayChangeEvent::UPDATE_ROTATION) { + ProcessDisplayRotationChange(absScreen); + } else { + WLOGE("unknown screen change event. id:%{public}" PRIu64" event %{public}u", absScreen->dmsId_, event); + } +} + +void AbstractDisplayController::ProcessDisplayRotationChange(sptr absScreen) +{ + sptr abstractDisplay = GetAbstractDisplayByAbsScreen(absScreen); + if (abstractDisplay == nullptr) { + return; + } + if (abstractDisplay->RequestRotation(absScreen->rotation_)) { + // Notify rotation event to WMS + SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::UPDATE_ROTATION); + } + sptr displayInfo = abstractDisplay->ConvertToDisplayInfo(); + DisplayManagerAgentController::GetInstance().OnDisplayChange(displayInfo, + DisplayChangeEvent::UPDATE_ROTATION); + ProcessDisplayCompression(absScreen); +} + +void AbstractDisplayController::ProcessDisplayCompression(sptr absScreen) +{ + WLOGFI("Enter ProcessDisplayCompression"); + auto absDisplay = GetAbstractDisplayByAbsScreen(absScreen); + DisplayId defaultDisplayId = GetDefaultDisplayId(); + if (absDisplay->GetId() != defaultDisplayId) { + return; + } + uint32_t sizeInVp = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal(); + if (!DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal() || sizeInVp == 0) { + WLOGFI("Not enable waterfall display area compression."); + return; + } + auto mode = absScreen->GetActiveScreenMode(); + if (mode == nullptr) { + WLOGFW("SupportedScreenModes is null"); + return; + } + uint32_t screenHeight = mode->height_; + uint32_t screenWidth = mode->width_; + uint32_t sizeInPx = static_cast(sizeInVp * absDisplay->GetVirtualPixelRatio()); + // 4: Compression size shall less than 1/4 of the screen size. + if (sizeInPx >= screenHeight / 4 || sizeInPx >= screenWidth / 4) { + WLOGFW("Invalid value for waterfall display curved area avoid size of each sides"); + return; + } + WLOGFI("ProcessWaterfallCompression, sizeInPx: %{public}u", sizeInPx); + Rotation rotation = absDisplay->GetRotation(); + bool isDefaultRotationVertical = mode->height_ > mode->width_ ? true : false; + if (ScreenRotationController::IsDisplayRotationHorizontal(rotation)) { + uint32_t offsetY = sizeInPx; + uint32_t totalCompressedSize = offsetY * 2; // *2 for both sides. + uint32_t displayHeightAfter = isDefaultRotationVertical ? mode->width_ - totalCompressedSize : + mode->height_ - totalCompressedSize; + absDisplay->SetOffsetX(0); + absDisplay->SetOffsetY(offsetY); + absDisplay->SetHeight(displayHeightAfter); + absDisplay->SetWaterfallDisplayCompressionStatus(true); + } else { + if (!absDisplay->GetWaterfallDisplayCompressionStatus()) { + return; + } + absDisplay->SetOffsetX(0); + absDisplay->SetOffsetY(0); + absDisplay->SetHeight(isDefaultRotationVertical ? mode->height_ : mode->width_); + absDisplay->SetWidth(isDefaultRotationVertical ? mode->width_ : mode->height_); + absDisplay->SetWaterfallDisplayCompressionStatus(false); + } + SetDisplayStateChangeListener(absDisplay, DisplayStateChangeType::DISPLAY_COMPRESS); + DisplayManagerAgentController::GetInstance().OnDisplayChange( + absDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED); +} + +sptr AbstractDisplayController::GetAbstractDisplayByAbsScreen(sptr absScreen) +{ + sptr abstractDisplay = nullptr; + std::lock_guard lock(mutex_); + auto iter = abstractDisplayMap_.begin(); + for (; iter != abstractDisplayMap_.end(); iter++) { + if (iter->second->GetAbstractScreenId() == absScreen->dmsId_) { + abstractDisplay = iter->second; + 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 nullptr; + } + if (iter == abstractDisplayMap_.end()) { + if (group->combination_ == ScreenCombination::SCREEN_ALONE + || group->combination_ == ScreenCombination::SCREEN_EXPAND) { + WLOGFE("Screen combination is SCREEN_ALONE or SCREEN_EXPAND, cannot find abstract display of the screen"); + } 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."); + } else { + WLOGFE("Unknown combination"); + } + return nullptr; + } + return abstractDisplay; +} + +void AbstractDisplayController::ProcessDisplayUpdateOrientation(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; + } + } + + 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("Unknown combination"); + return; + } + } + } + abstractDisplay->SetOrientation(absScreen->orientation_); + if (abstractDisplay->RequestRotation(absScreen->rotation_)) { + // Notify rotation event to WMS + SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::UPDATE_ROTATION); + ProcessDisplayCompression(absScreen); + } +} + +void AbstractDisplayController::ProcessDisplaySizeChange(sptr absScreen) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:ProcessDisplaySizeChange(%" PRIu64")", absScreen->dmsId_); + sptr info = absScreen->GetActiveScreenMode(); + if (info == nullptr) { + WLOGE("cannot get active screen info."); + return; + } + + std::map> matchedDisplays; + { + std::lock_guard lock(mutex_); + for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); ++iter) { + sptr absDisplay = iter->second; + if (absDisplay == nullptr || absDisplay->GetAbstractScreenId() != absScreen->dmsId_) { + continue; + } + if (UpdateDisplaySize(absDisplay, info)) { + matchedDisplays.insert(std::make_pair(iter->first, iter->second)); + } + } + } + + WLOGFI("Size of matchedDisplays %{public}zu", matchedDisplays.size()); + for (auto iter = matchedDisplays.begin(); iter != matchedDisplays.end(); ++iter) { + WLOGFI("Notify display size change. Id %{public}" PRIu64"", iter->first); + sptr abstractDisplay = iter->second; + SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::SIZE_CHANGE); + DisplayManagerAgentController::GetInstance().OnDisplayChange( + abstractDisplay->ConvertToDisplayInfo(), DisplayChangeEvent::DISPLAY_SIZE_CHANGED); + } +} + +bool AbstractDisplayController::UpdateDisplaySize(sptr absDisplay, sptr info) +{ + if (absDisplay == nullptr || info == nullptr) { + WLOGFE("invalid params."); + return false; + } + if (info->height_ == static_cast(absDisplay->GetHeight()) && + info->width_ == static_cast(absDisplay->GetWidth())) { + WLOGFI("keep display size. display:%{public}" PRIu64"", absDisplay->GetId()); + return false; + } + absDisplay->SetHeight(info->height_); + absDisplay->SetWidth(info->width_); + WLOGFI("Reset H&W. id %{public}" PRIu64", size: %{public}d %{public}d", + absDisplay->GetId(), absDisplay->GetWidth(), absDisplay->GetHeight()); + return true; +} + +void AbstractDisplayController::ProcessVirtualPixelRatioChange(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; + } + } + } + if (abstractDisplay == nullptr) { + WLOGE("Failed to find abstract display of the screen."); + return; + } + abstractDisplay->SetVirtualPixelRatio(absScreen->virtualPixelRatio_); + // Notify virtual pixel ratio change event to WMS + SetDisplayStateChangeListener(abstractDisplay, DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE); + // Notify virtual pixel ratio change event to DisplayManager + DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(), + DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED); +} + +void AbstractDisplayController::BindAloneScreenLocked(sptr realAbsScreen) +{ + if (realAbsScreen == nullptr) { + WLOGE("BindAloneScreenLocked failed, realAbsScreen is nullptr"); + return; + } + ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); + if (defaultScreenId != SCREEN_ID_INVALID) { + if (defaultScreenId != realAbsScreen->dmsId_) { + WLOGE("The first real screen should be default for Phone. %{public}" PRIu64"", realAbsScreen->dmsId_); + return; + } + sptr info = realAbsScreen->GetActiveScreenMode(); + if (info == nullptr) { + WLOGE("bind alone screen error, cannot get info."); + return; + } + if (dummyDisplay_ == nullptr) { + DisplayId displayId = displayCount_.fetch_add(1); + std::ostringstream buffer; + buffer<<"display_"< display = new(std::nothrow) AbstractDisplay(displayId, name, info, realAbsScreen); + if (display == nullptr) { + WLOGFE("create display failed"); + return; + } + + abstractDisplayMap_.insert((std::make_pair(display->GetId(), display))); + WLOGI("create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"", + realAbsScreen->dmsId_, display->GetId()); + DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo()); + SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE); + } else { + WLOGI("bind display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"", + realAbsScreen->dmsId_, dummyDisplay_->GetId()); + bool updateFlag = static_cast(dummyDisplay_->GetHeight()) == info->height_ + && static_cast(dummyDisplay_->GetWidth()) == info->width_; + dummyDisplay_->BindAbstractScreen(abstractScreenController_->GetAbstractScreen(realAbsScreen->dmsId_)); + if (updateFlag) { + DisplayManagerAgentController::GetInstance().OnDisplayCreate(dummyDisplay_->ConvertToDisplayInfo()); + } + dummyDisplay_ = nullptr; + } + } else { + WLOGE("The first real screen should be default screen for Phone. %{public}" PRIu64"", realAbsScreen->dmsId_); + } +} + +void AbstractDisplayController::AddScreenToMirrorLocked(sptr absScreen) +{ + WLOGI("bind display to mirror. screen:%{public}" PRIu64"", absScreen->dmsId_); +} + +void AbstractDisplayController::AddScreenToExpandLocked(sptr absScreen) +{ + if (absScreen == nullptr) { + WLOGE("AddScreenToExpandLocked failed, absScreen is nullptr"); + return; + } + for (auto iter = abstractDisplayMap_.begin(); iter != abstractDisplayMap_.end(); iter++) { + sptr abstractDisplay = iter->second; + if (abstractDisplay->GetAbstractScreenId() == absScreen->dmsId_) { + WLOGE("error, screenId: %{public}" PRIu64" already has corresponding display", + absScreen->dmsId_); + return; + } + } + WLOGI("bind display to expand. screen:%{public}" PRIu64"", absScreen->dmsId_); + sptr info; + ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); + sptr defaultScreen = abstractScreenController_->GetAbstractScreen(defaultScreenId); + if (absScreen->type_ == ScreenType::VIRTUAL) { + WLOGI("screen type is virtual, use default screen info"); + if (defaultScreen == nullptr) { + WLOGE("bind display error, cannot get defaultScreen."); + return; + } + info = defaultScreen->GetActiveScreenMode(); + } else { + WLOGI("screen type is not virtual, get this screen info"); + info = absScreen->GetActiveScreenMode(); + } + if (info == nullptr) { + WLOGE("bind display error, cannot get info."); + return; + } + DisplayId displayId = displayCount_.fetch_add(1); + std::ostringstream buffer; + buffer<<"display_"< display = new AbstractDisplay(displayId, name, info, absScreen); + Point point = abstractScreenController_->GetAbstractScreenGroup(absScreen->groupDmsId_)-> + GetChildPosition(absScreen->dmsId_); + display->SetOffset(point.posX_, point.posY_); + abstractDisplayMap_.insert((std::make_pair(display->GetId(), display))); + WLOGI("create display for new screen. screen:%{public}" PRIu64", display:%{public}" PRIu64"", + absScreen->dmsId_, display->GetId()); + DisplayManagerAgentController::GetInstance().OnDisplayCreate(display->ConvertToDisplayInfo()); + SetDisplayStateChangeListener(display, DisplayStateChangeType::CREATE); +} + +void AbstractDisplayController::SetFreeze(std::vector displayIds, bool toFreeze) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetAllFreeze"); + DisplayStateChangeType type = toFreeze ? DisplayStateChangeType::FREEZE : DisplayStateChangeType::UNFREEZE; + DisplayChangeEvent event + = toFreeze ? DisplayChangeEvent::DISPLAY_FREEZED : DisplayChangeEvent::DISPLAY_UNFREEZED; + for (DisplayId displayId : displayIds) { + sptr abstractDisplay; + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetFreeze(%" PRIu64")", displayId); + { + WLOGI("setfreeze display %{public}" PRIu64"", displayId); + std::lock_guard lock(mutex_); + auto iter = abstractDisplayMap_.find(displayId); + if (iter == abstractDisplayMap_.end()) { + WLOGE("setfreeze fail, cannot get display %{public}" PRIu64"", displayId); + continue; + } + abstractDisplay = iter->second; + FreezeFlag curFlag = abstractDisplay->GetFreezeFlag(); + if ((toFreeze && (curFlag == FreezeFlag::FREEZING)) + || (!toFreeze && (curFlag == FreezeFlag::UNFREEZING))) { + WLOGE("setfreeze fail, display %{public}" PRIu64" freezeflag is %{public}u", + displayId, curFlag); + continue; + } + FreezeFlag flag = toFreeze ? FreezeFlag::FREEZING : FreezeFlag::UNFREEZING; + abstractDisplay->SetFreezeFlag(flag); + } + + // Notify freeze event to WMS + SetDisplayStateChangeListener(abstractDisplay, type); + // Notify freeze event to DisplayManager + DisplayManagerAgentController::GetInstance().OnDisplayChange(abstractDisplay->ConvertToDisplayInfo(), event); + } +} + +std::map> AbstractDisplayController::GetAllDisplayInfoOfGroup(sptr info) +{ + ScreenId screenGroupId = info->GetScreenGroupId(); + std::map> displayInfoMap; + std::lock_guard lock(mutex_); + for (const auto& iter : abstractDisplayMap_) { + sptr display = iter.second; + if (display->GetAbstractScreenGroupId() == screenGroupId) { + displayInfoMap.insert(std::make_pair(display->GetId(), display->ConvertToDisplayInfo())); + } + } + return displayInfoMap; +} + +void AbstractDisplayController::SetDisplayStateChangeListener( + sptr abstractDisplay, DisplayStateChangeType type) +{ + ScreenId defaultDisplayId = GetDefaultDisplayId(); + std::map> displayInfoMap = GetAllDisplayInfoOfGroup( + abstractDisplay->ConvertToDisplayInfo()); + displayStateChangeListener_(defaultDisplayId, abstractDisplay->ConvertToDisplayInfo(), displayInfoMap, type); +} + +DisplayId AbstractDisplayController::GetDefaultDisplayId() +{ + DisplayId defaultDisplayId = DISPLAY_ID_INVALID; + ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); + sptr defaultDisplay = GetAbstractDisplayByScreen(defaultScreenId); + if (defaultDisplay != nullptr) { + defaultDisplayId = defaultDisplay->GetId(); + } + return defaultDisplayId; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dmserver/src/abstract_screen.cpp b/window_manager/dmserver/src/abstract_screen.cpp new file mode 100644 index 0000000..6368a07 --- /dev/null +++ b/window_manager/dmserver/src/abstract_screen.cpp @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2021-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 "abstract_screen.h" + +#include +#include "abstract_screen_controller.h" +#include "display_manager_service.h" +#include "dm_common.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractScreenGroup"}; +} + +AbstractScreen::AbstractScreen(sptr screenController, const std::string& name, ScreenId dmsId, + ScreenId rsId) : name_(name), dmsId_(dmsId), rsId_(rsId), screenController_(screenController) +{ +} + +AbstractScreen::~AbstractScreen() +{ +} + +sptr AbstractScreen::GetActiveScreenMode() const +{ + if (activeIdx_ < 0 || activeIdx_ >= static_cast(modes_.size())) { + WLOGE("active mode index is wrong: %{public}d", activeIdx_); + return nullptr; + } + return modes_[activeIdx_]; +} + +std::vector> AbstractScreen::GetAbstractScreenModes() const +{ + return modes_; +} + +sptr AbstractScreen::GetGroup() const +{ + return screenController_->GetAbstractScreenGroup(groupDmsId_); +} + +sptr AbstractScreen::ConvertToScreenInfo() const +{ + sptr info = new(std::nothrow) ScreenInfo(); + if (info == nullptr) { + return nullptr; + } + FillScreenInfo(info); + return info; +} + +void AbstractScreen::UpdateRSTree(std::shared_ptr& surfaceNode, bool isAdd) +{ + if (rsDisplayNode_ == nullptr || surfaceNode == nullptr) { + WLOGFE("node is nullptr"); + return; + } + WLOGFI("%{public}s surface: %{public}s, %{public}" PRIu64"", (isAdd ? "add" : "remove"), + surfaceNode->GetName().c_str(), surfaceNode->GetId()); + + if (isAdd) { + surfaceNode->SetVisible(true); + rsDisplayNode_->AddChild(surfaceNode, -1); + } else { + rsDisplayNode_->RemoveChild(surfaceNode); + } +} + +void AbstractScreen::UpdateDisplayGroupRSTree(std::shared_ptr& surfaceNode, NodeId parentNodeId, + bool isAdd) +{ + if (rsDisplayNode_ == nullptr || surfaceNode == nullptr) { + WLOGFE("node is nullptr"); + return; + } + WLOGFI("%{public}s surface: %{public}s, %{public}" PRIu64"", (isAdd ? "add" : "remove"), + surfaceNode->GetName().c_str(), surfaceNode->GetId()); + + if (isAdd) { + surfaceNode->SetVisible(true); + rsDisplayNode_->AddCrossParentChild(surfaceNode, -1); + } else { + rsDisplayNode_->RemoveCrossParentChild(surfaceNode, parentNodeId); + } +} + +void AbstractScreen::InitRSDisplayNode(RSDisplayNodeConfig& config, Point& startPoint) +{ + if (rsDisplayNode_ != nullptr) { + rsDisplayNode_->SetDisplayNodeMirrorConfig(config); + } else { + std::shared_ptr rsDisplayNode = RSDisplayNode::Create(config); + if (rsDisplayNode == nullptr) { + WLOGE("fail to add child. create rsDisplayNode fail!"); + return; + } + rsDisplayNode_ = rsDisplayNode; + } + rSDisplayNodeConfig_ = config; + WLOGFI("SetDisplayOffset: posX:%{public}d, posY:%{public}d", startPoint.posX_, startPoint.posY_); + rsDisplayNode_->SetDisplayOffset(startPoint.posX_, startPoint.posY_); + uint32_t width = 0; + uint32_t height = 0; + sptr abstractScreenModes = GetActiveScreenMode(); + if (abstractScreenModes != nullptr) { + height = abstractScreenModes->height_; + width = abstractScreenModes->width_; + } + RSScreenType screenType; + auto ret = RSInterfaces::GetInstance().GetScreenType(rsId_, screenType); + if (ret == StatusCode::SUCCESS && screenType == RSScreenType::VIRTUAL_TYPE_SCREEN) { + rsDisplayNode_->SetSecurityDisplay(true); + WLOGFI("virtualScreen SetSecurityDisplay success"); + } + // If setDisplayOffset is not valid for SetFrame/SetBounds + rsDisplayNode_->SetFrame(0, 0, width, height); + rsDisplayNode_->SetBounds(0, 0, width, height); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } +} + +ScreenId AbstractScreen::GetScreenGroupId() const +{ + return groupDmsId_; +} + +DMError AbstractScreen::GetScreenSupportedColorGamuts(std::vector& colorGamuts) +{ + auto ret = RSInterfaces::GetInstance().GetScreenSupportedColorGamuts(rsId_, colorGamuts); + if (ret != StatusCode::SUCCESS) { + WLOGE("GetScreenSupportedColorGamuts fail! rsId %{public}" PRIu64"", rsId_); + return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + WLOGI("GetScreenSupportedColorGamuts ok! rsId %{public}" PRIu64", size %{public}u", + rsId_, static_cast(colorGamuts.size())); + + return DMError::DM_OK; +} + +DMError AbstractScreen::GetScreenColorGamut(ScreenColorGamut& colorGamut) +{ + auto ret = RSInterfaces::GetInstance().GetScreenColorGamut(rsId_, colorGamut); + if (ret != StatusCode::SUCCESS) { + WLOGE("GetScreenColorGamut fail! rsId %{public}" PRIu64"", rsId_); + return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + WLOGI("GetScreenColorGamut ok! rsId %{public}" PRIu64", colorGamut %{public}u", + rsId_, static_cast(colorGamut)); + + return DMError::DM_OK; +} + +DMError AbstractScreen::SetScreenColorGamut(int32_t colorGamutIdx) +{ + std::vector colorGamuts; + DMError res = GetScreenSupportedColorGamuts(colorGamuts); + if (res != DMError::DM_OK) { + WLOGE("SetScreenColorGamut fail! rsId %{public}" PRIu64"", rsId_); + return res; + } + if (colorGamutIdx < 0 || colorGamutIdx >= static_cast(colorGamuts.size())) { + WLOGE("SetScreenColorGamut fail! rsId %{public}" PRIu64" colorGamutIdx %{public}d invalid.", + rsId_, colorGamutIdx); + return DMError::DM_ERROR_INVALID_PARAM; + } + auto ret = RSInterfaces::GetInstance().SetScreenColorGamut(rsId_, colorGamutIdx); + if (ret != StatusCode::SUCCESS) { + WLOGE("SetScreenColorGamut fail! rsId %{public}" PRIu64"", rsId_); + return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + WLOGI("SetScreenColorGamut ok! rsId %{public}" PRIu64", colorGamutIdx %{public}u", + rsId_, colorGamutIdx); + + return DMError::DM_OK; +} + +DMError AbstractScreen::GetScreenGamutMap(ScreenGamutMap& gamutMap) +{ + auto ret = RSInterfaces::GetInstance().GetScreenGamutMap(rsId_, gamutMap); + if (ret != StatusCode::SUCCESS) { + WLOGE("GetScreenGamutMap fail! rsId %{public}" PRIu64"", rsId_); + return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + WLOGI("GetScreenGamutMap ok! rsId %{public}" PRIu64", gamutMap %{public}u", + rsId_, static_cast(gamutMap)); + + return DMError::DM_OK; +} + +DMError AbstractScreen::SetScreenGamutMap(ScreenGamutMap gamutMap) +{ + if (gamutMap > GAMUT_MAP_HDR_EXTENSION) { + return DMError::DM_ERROR_INVALID_PARAM; + } + auto ret = RSInterfaces::GetInstance().SetScreenGamutMap(rsId_, gamutMap); + if (ret != StatusCode::SUCCESS) { + WLOGE("SetScreenGamutMap fail! rsId %{public}" PRIu64"", rsId_); + return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + WLOGI("SetScreenGamutMap ok! rsId %{public}" PRIu64", gamutMap %{public}u", + rsId_, static_cast(gamutMap)); + + return DMError::DM_OK; +} + +DMError AbstractScreen::SetScreenColorTransform() +{ + WLOGI("SetScreenColorTransform ok! rsId %{public}" PRIu64"", rsId_); + + return DMError::DM_OK; +} + +void AbstractScreen::FillScreenInfo(sptr info) const +{ + if (info == nullptr) { + WLOGE("FillScreenInfo failed! info is nullptr"); + return; + } + info->id_ = dmsId_; + info->name_ = name_; + uint32_t width = 0; + uint32_t height = 0; + sptr abstractScreenModes = GetActiveScreenMode(); + if (abstractScreenModes != nullptr) { + height = abstractScreenModes->height_; + width = abstractScreenModes->width_; + } + float virtualPixelRatio = virtualPixelRatio_; + // "< 1e-6" means virtualPixelRatio is 0. + if (fabsf(virtualPixelRatio) < 1e-6) { + virtualPixelRatio = 1.0f; + } + info->virtualPixelRatio_ = virtualPixelRatio; + info->virtualHeight_ = height / virtualPixelRatio; + info->virtualWidth_ = width / virtualPixelRatio; + info->lastParent_ = lastGroupDmsId_; + info->parent_ = groupDmsId_; + info->isScreenGroup_ = isScreenGroup_; + info->rotation_ = rotation_; + info->orientation_ = orientation_; + info->type_ = type_; + info->modeId_ = activeIdx_; + info->modes_ = modes_; +} + +bool AbstractScreen::SetOrientation(Orientation orientation) +{ + orientation_ = orientation; + return true; +} + +bool AbstractScreen::SetVirtualPixelRatio(float virtualPixelRatio) +{ + virtualPixelRatio_ = virtualPixelRatio; + return true; +} + +float AbstractScreen::GetVirtualPixelRatio() const +{ + return virtualPixelRatio_; +} + +Rotation AbstractScreen::CalcRotation(Orientation orientation) const +{ + sptr info = GetActiveScreenMode(); + if (info == nullptr) { + return Rotation::ROTATION_0; + } + // vertical: phone(Plugin screen); horizontal: pad & external screen + bool isVerticalScreen = info->width_ < info->height_; + switch (orientation) { + case Orientation::UNSPECIFIED: { + return Rotation::ROTATION_0; + } + case Orientation::VERTICAL: { + return isVerticalScreen ? Rotation::ROTATION_0 : Rotation::ROTATION_90; + } + case Orientation::HORIZONTAL: { + return isVerticalScreen ? Rotation::ROTATION_90 : Rotation::ROTATION_0; + } + case Orientation::REVERSE_VERTICAL: { + return isVerticalScreen ? Rotation::ROTATION_180 : Rotation::ROTATION_270; + } + case Orientation::REVERSE_HORIZONTAL: { + return isVerticalScreen ? Rotation::ROTATION_270 : Rotation::ROTATION_180; + } + default: { + WLOGE("unknown orientation %{public}u", orientation); + return Rotation::ROTATION_0; + } + } +} + +AbstractScreenGroup::AbstractScreenGroup(sptr screenController, ScreenId dmsId, ScreenId rsId, + std::string name, ScreenCombination combination) : AbstractScreen(screenController, name, dmsId, rsId), + combination_(combination) +{ + type_ = ScreenType::UNDEFINED; + isScreenGroup_ = true; +} + +AbstractScreenGroup::~AbstractScreenGroup() +{ + rsDisplayNode_ = nullptr; + abstractScreenMap_.clear(); +} + +sptr AbstractScreenGroup::ConvertToScreenGroupInfo() const +{ + sptr screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + if (screenGroupInfo == nullptr) { + return nullptr; + } + FillScreenInfo(screenGroupInfo); + screenGroupInfo->combination_ = combination_; + for (auto iter = abstractScreenMap_.begin(); iter != abstractScreenMap_.end(); iter++) { + screenGroupInfo->children_.push_back(iter->first); + } + auto positions = GetChildrenPosition(); + screenGroupInfo->position_.insert(screenGroupInfo->position_.end(), positions.begin(), positions.end()); + return screenGroupInfo; +} + +bool AbstractScreenGroup::GetRSDisplayNodeConfig(sptr& dmsScreen, struct RSDisplayNodeConfig& config) +{ + if (dmsScreen == nullptr) { + WLOGE("dmsScreen is nullptr."); + return false; + } + config = { dmsScreen->rsId_ }; + switch (combination_) { + case ScreenCombination::SCREEN_ALONE: + [[fallthrough]]; + case ScreenCombination::SCREEN_EXPAND: + break; + case ScreenCombination::SCREEN_MIRROR: { + if (GetChildCount() == 0 || mirrorScreenId_ == dmsScreen->dmsId_) { + WLOGI("AddChild, SCREEN_MIRROR, config is not mirror"); + break; + } + if (mirrorScreenId_ == SCREEN_ID_INVALID || !HasChild(mirrorScreenId_)) { + WLOGI("AddChild, mirrorScreenId_ is invalid, use default screen"); + mirrorScreenId_ = screenController_->GetDefaultAbstractScreenId(); + } + // Todo displayNode is nullptr + std::shared_ptr displayNode = screenController_->GetRSDisplayNodeByScreenId(mirrorScreenId_); + if (displayNode == nullptr) { + WLOGFE("AddChild fail, displayNode is nullptr, cannot get DisplayNode"); + break; + } + NodeId nodeId = displayNode->GetId(); + WLOGI("AddChild, mirrorScreenId_:%{public}" PRIu64", rsId_:%{public}" PRIu64", nodeId:%{public}" PRIu64"", + mirrorScreenId_, dmsScreen->rsId_, nodeId); + config = {dmsScreen->rsId_, true, nodeId}; + break; + } + default: + WLOGE("fail to add child. invalid group combination:%{public}u", combination_); + return false; + } + return true; +} + +bool AbstractScreenGroup::AddChild(sptr& dmsScreen, Point& startPoint) +{ + if (dmsScreen == nullptr) { + WLOGE("AddChild, dmsScreen is nullptr."); + return false; + } + ScreenId screenId = dmsScreen->dmsId_; + auto iter = abstractScreenMap_.find(screenId); + if (iter != abstractScreenMap_.end()) { + WLOGE("AddChild, abstractScreenMap_ has dmsScreen:%{public}" PRIu64"", screenId); + return false; + } + struct RSDisplayNodeConfig config; + if (!GetRSDisplayNodeConfig(dmsScreen, config)) { + return false; + } + dmsScreen->InitRSDisplayNode(config, startPoint); + dmsScreen->lastGroupDmsId_ = dmsScreen->groupDmsId_; + dmsScreen->groupDmsId_ = dmsId_; + abstractScreenMap_.insert(std::make_pair(screenId, std::make_pair(dmsScreen, startPoint))); + return true; +} + +bool AbstractScreenGroup::AddChildren(std::vector>& dmsScreens, std::vector& startPoints) +{ + size_t size = dmsScreens.size(); + if (size != startPoints.size()) { + WLOGE("AddChildren, unequal size."); + return false; + } + bool res = true; + for (size_t i = 0; i < size; i++) { + res = AddChild(dmsScreens[i], startPoints[i]) && res; + } + return res; +} + +bool AbstractScreenGroup::RemoveChild(sptr& dmsScreen) +{ + if (dmsScreen == nullptr) { + WLOGE("RemoveChild, dmsScreen is nullptr."); + return false; + } + ScreenId screenId = dmsScreen->dmsId_; + dmsScreen->lastGroupDmsId_ = dmsScreen->groupDmsId_; + dmsScreen->groupDmsId_ = SCREEN_ID_INVALID; + if (dmsScreen->rsDisplayNode_ != nullptr) { + dmsScreen->rsDisplayNode_->SetDisplayOffset(0, 0); + dmsScreen->rsDisplayNode_->RemoveFromTree(); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } + dmsScreen->rsDisplayNode_ = nullptr; + } + return abstractScreenMap_.erase(screenId); +} + +bool AbstractScreenGroup::HasChild(ScreenId childScreen) const +{ + return abstractScreenMap_.find(childScreen) != abstractScreenMap_.end(); +} + +std::vector> AbstractScreenGroup::GetChildren() const +{ + std::vector> res; + for (auto iter = abstractScreenMap_.begin(); iter != abstractScreenMap_.end(); iter++) { + res.push_back(iter->second.first); + } + return res; +} + +std::vector AbstractScreenGroup::GetChildrenPosition() const +{ + std::vector res; + for (auto iter = abstractScreenMap_.begin(); iter != abstractScreenMap_.end(); iter++) { + res.push_back(iter->second.second); + } + return res; +} + +Point AbstractScreenGroup::GetChildPosition(ScreenId screenId) const +{ + Point point; + auto iter = abstractScreenMap_.find(screenId); + if (iter != abstractScreenMap_.end()) { + point = iter->second.second; + } + return point; +} + +size_t AbstractScreenGroup::GetChildCount() const +{ + return abstractScreenMap_.size(); +} +} // namespace OHOS::Rosen diff --git a/window_manager/dmserver/src/abstract_screen_controller.cpp b/window_manager/dmserver/src/abstract_screen_controller.cpp new file mode 100644 index 0000000..ec986a7 --- /dev/null +++ b/window_manager/dmserver/src/abstract_screen_controller.cpp @@ -0,0 +1,1277 @@ +/* + * Copyright (c) 2021-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 "abstract_screen_controller.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sys_cap_util.h" +#include "display_manager_agent_controller.h" +#include "display_manager_service.h" +#include "event_runner.h" +#include "screen_rotation_controller.h" +#include "window_manager_hilog.h" +#include "socperf_client.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "AbstractScreenController"}; + const std::string CONTROLLER_THREAD_ID = "AbstractScreenControllerThread"; +} + +AbstractScreenController::AbstractScreenController(std::recursive_mutex& mutex) + : mutex_(mutex), rsInterface_(RSInterfaces::GetInstance()) +{ + auto runner = AppExecFwk::EventRunner::Create(CONTROLLER_THREAD_ID); + controllerHandler_ = std::make_shared(runner); +} + +AbstractScreenController::~AbstractScreenController() = default; + +void AbstractScreenController::Init() +{ + WLOGFD("screen controller init"); + RegisterRsScreenConnectionChangeListener(); +} + +void AbstractScreenController::RegisterRsScreenConnectionChangeListener() +{ + WLOGFD("RegisterRsScreenConnectionChangeListener"); + auto res = rsInterface_.SetScreenChangeCallback( + [this](ScreenId rsScreenId, ScreenEvent screenEvent) { OnRsScreenConnectionChange(rsScreenId, screenEvent); }); + if (res != StatusCode::SUCCESS) { + auto task = [this] { + RegisterRsScreenConnectionChangeListener(); + }; + // post task after 50 ms. + controllerHandler_->PostTask(task, 50, AppExecFwk::EventQueue::Priority::HIGH); + } +} + +std::vector AbstractScreenController::GetAllScreenIds() const +{ + std::lock_guard lock(mutex_); + std::vector res; + for (const auto& iter : dmsScreenMap_) { + res.emplace_back(iter.first); + } + return res; +} + +uint32_t AbstractScreenController::GetRSScreenNum() const +{ + return screenIdManager_.GetRSScreenNum(); +} + +std::vector AbstractScreenController::GetAllValidScreenIds(const std::vector& screenIds) const +{ + std::lock_guard lock(mutex_); + std::vector validScreenIds; + for (ScreenId screenId : screenIds) { + auto screenIdIter = std::find(validScreenIds.begin(), validScreenIds.end(), screenId); + if (screenIdIter != validScreenIds.end()) { + continue; + } + auto iter = dmsScreenMap_.find(screenId); + if (iter != dmsScreenMap_.end() && iter->second->type_ != ScreenType::UNDEFINED) { + validScreenIds.emplace_back(screenId); + } + } + return validScreenIds; +} + +const std::shared_ptr& AbstractScreenController::GetRSDisplayNodeByScreenId(ScreenId dmsScreenId) const +{ + static std::shared_ptr notFound = nullptr; + sptr screen = GetAbstractScreen(dmsScreenId); + if (screen == nullptr) { + return notFound; + } + if (screen->rsDisplayNode_ == nullptr) { + return notFound; + } + WLOGI("GetRSDisplayNodeByScreenId: screen: %{public}" PRIu64", nodeId: %{public}" PRIu64" ", + screen->dmsId_, screen->rsDisplayNode_->GetId()); + return screen->rsDisplayNode_; +} + +void AbstractScreenController::UpdateRSTree(ScreenId dmsScreenId, ScreenId parentScreenId, + std::shared_ptr& surfaceNode, bool isAdd, bool isMultiDisplay) +{ + sptr abstractScreen = GetAbstractScreen(dmsScreenId); + if (abstractScreen == nullptr) { + WLOGE("[UpdateRSTree] can not find abstractScreen"); + return; + } + if (isMultiDisplay) { + sptr parentAbstractScreen = GetAbstractScreen(parentScreenId); + if (parentAbstractScreen == nullptr) { + WLOGE("[UpdateRSTree] can not find parentAbstractScreen"); + return; + } + if (parentAbstractScreen->rsDisplayNode_ == nullptr) { + WLOGE("rsDisplayNode of parentAbstractScreen is nullptr"); + return; + } + abstractScreen->UpdateDisplayGroupRSTree(surfaceNode, parentAbstractScreen->rsDisplayNode_->GetId(), isAdd); + } else { + abstractScreen->UpdateRSTree(surfaceNode, isAdd); + } +} + +sptr AbstractScreenController::GetAbstractScreen(ScreenId dmsScreenId) const +{ + WLOGD("GetAbstractScreen: screenId: %{public}" PRIu64"", dmsScreenId); + std::lock_guard lock(mutex_); + auto iter = dmsScreenMap_.find(dmsScreenId); + if (iter == dmsScreenMap_.end()) { + WLOGE("did not find screen:%{public}" PRIu64"", dmsScreenId); + return nullptr; + } + return iter->second; +} + +sptr AbstractScreenController::GetAbstractScreenGroup(ScreenId dmsScreenId) +{ + std::lock_guard lock(mutex_); + auto iter = dmsScreenGroupMap_.find(dmsScreenId); + if (iter == dmsScreenGroupMap_.end()) { + WLOGE("did not find screen:%{public}" PRIu64"", dmsScreenId); + return nullptr; + } + return iter->second; +} + +ScreenId AbstractScreenController::GetDefaultAbstractScreenId() +{ + if (defaultRsScreenId_ == SCREEN_ID_INVALID) { + defaultRsScreenId_ = rsInterface_.GetDefaultScreenId(); + } + if (defaultRsScreenId_ == SCREEN_ID_INVALID) { + WLOGFW("GetDefaultAbstractScreenId, rsDefaultId is invalid."); + return SCREEN_ID_INVALID; + } + std::lock_guard lock(mutex_); + ScreenId defaultDmsScreenId; + if (screenIdManager_.ConvertToDmsScreenId(defaultRsScreenId_, defaultDmsScreenId)) { + WLOGFD("GetDefaultAbstractScreenId, screen:%{public}" PRIu64"", defaultDmsScreenId); + return defaultDmsScreenId; + } + WLOGFI("GetDefaultAbstractScreenId, default screen is null, try to get."); + ProcessScreenConnected(defaultRsScreenId_); + return screenIdManager_.ConvertToDmsScreenId(defaultRsScreenId_); +} + +ScreenId AbstractScreenController::ConvertToRsScreenId(ScreenId dmsScreenId) const +{ + std::lock_guard lock(mutex_); + return screenIdManager_.ConvertToRsScreenId(dmsScreenId); +} + +ScreenId AbstractScreenController::ConvertToDmsScreenId(ScreenId rsScreenId) const +{ + std::lock_guard lock(mutex_); + return screenIdManager_.ConvertToDmsScreenId(rsScreenId); +} + +void AbstractScreenController::RegisterAbstractScreenCallback(sptr cb) +{ + std::lock_guard lock(mutex_); + abstractScreenCallback_ = cb; + for (auto& iter : dmsScreenMap_) { + if (iter.second != nullptr && abstractScreenCallback_ != nullptr) { + WLOGFI("dmsScreenId :%{public}" PRIu64"", iter.first); + abstractScreenCallback_->onConnect_(iter.second); + } + } +} + +void AbstractScreenController::RegisterRSScreenChangeListener(const sptr& listener) +{ + std::lock_guard lock(mutex_); + rSScreenChangeListener_ = listener; +} + +void AbstractScreenController::OnRsScreenConnectionChange(ScreenId rsScreenId, ScreenEvent screenEvent) +{ + WLOGFI("rs screen event. id:%{public}" PRIu64", event:%{public}u", rsScreenId, static_cast(screenEvent)); + if (screenEvent == ScreenEvent::CONNECTED) { + auto task = [this, rsScreenId] { + ProcessScreenConnected(rsScreenId); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); + } else if (screenEvent == ScreenEvent::DISCONNECTED) { + if (rsScreenId == defaultRsScreenId_) { + defaultRsScreenId_ = SCREEN_ID_INVALID; + } + auto task = [this, rsScreenId] { + ProcessScreenDisconnected(rsScreenId); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); + } else { + WLOGE("unknown message:%{public}ud", static_cast(screenEvent)); + } +} + +void AbstractScreenController::ProcessScreenConnected(ScreenId rsScreenId) +{ + std::lock_guard lock(mutex_); + if (screenIdManager_.HasRsScreenId(rsScreenId)) { + WLOGE("reconnect screen, screenId=%{public}" PRIu64"", rsScreenId); + return; + } + WLOGFD("connect new screen"); + auto absScreen = InitAndGetScreen(rsScreenId); + if (absScreen == nullptr) { + return; + } + sptr screenGroup = AddToGroupLocked(absScreen); + if (screenGroup == nullptr) { + return; + } + if (rsScreenId == rsInterface_.GetDefaultScreenId() && absScreen->rsDisplayNode_ != nullptr) { + absScreen->screenRequestedOrientation_ = buildInDefaultOrientation_; + Rotation rotationAfter = absScreen->CalcRotation(absScreen->screenRequestedOrientation_); + WLOGFD("set default rotation to %{public}d for buildin screen", rotationAfter); + sptr abstractScreenModes = absScreen->GetActiveScreenMode(); + if (abstractScreenModes != nullptr) { + float w = abstractScreenModes->width_; + float h = abstractScreenModes->height_; + float x = 0; + float y = 0; + if (!IsVertical(rotationAfter)) { + std::swap(w, h); + x = (h - w) / 2; // 2: used to calculate offset to center display node + y = (w - h) / 2; // 2: used to calculate offset to center display node + } + // 90.f is base degree + absScreen->rsDisplayNode_->SetRotation(-90.0f * static_cast(rotationAfter)); + absScreen->rsDisplayNode_->SetFrame(x, y, w, h); + absScreen->rsDisplayNode_->SetBounds(x, y, w, h); + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } + absScreen->rotation_ = rotationAfter; + absScreen->SetOrientation(absScreen->screenRequestedOrientation_); + } + } + NotifyScreenConnected(absScreen->ConvertToScreenInfo()); + NotifyScreenGroupChanged(absScreen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); + if (abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onConnect_(absScreen); + } + if (rSScreenChangeListener_ != nullptr) { + rSScreenChangeListener_->onConnected_(); + } +} + +sptr AbstractScreenController::InitAndGetScreen(ScreenId rsScreenId) +{ + ScreenId dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsScreenId); + std::ostringstream buffer; + buffer< absScreen = + new(std::nothrow) AbstractScreen(this, name, dmsScreenId, rsScreenId); + if (absScreen == nullptr) { + WLOGFE("new AbstractScreen failed."); + screenIdManager_.DeleteScreenId(dmsScreenId); + return nullptr; + } + if (!InitAbstractScreenModesInfo(absScreen)) { + screenIdManager_.DeleteScreenId(dmsScreenId); + WLOGFE("InitAndGetScreen failed."); + return nullptr; + } + dmsScreenMap_.insert(std::make_pair(dmsScreenId, absScreen)); + return absScreen; +} + +void AbstractScreenController::ProcessScreenDisconnected(ScreenId rsScreenId) +{ + WLOGFI("disconnect screen, screenId=%{public}" PRIu64"", rsScreenId); + ScreenId dmsScreenId; + std::lock_guard lock(mutex_); + if (!screenIdManager_.ConvertToDmsScreenId(rsScreenId, dmsScreenId)) { + WLOGFE("disconnect screen, screenId=%{public}" PRIu64" is not in rs2DmsScreenIdMap_", rsScreenId); + return; + } + auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); + sptr screenGroup; + if (dmsScreenMapIter != dmsScreenMap_.end()) { + auto screen = dmsScreenMapIter->second; + if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { + abstractScreenCallback_->onDisconnect_(screen); + } + screenGroup = RemoveFromGroupLocked(screen); + if (screenGroup != nullptr) { + NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::REMOVE_FROM_GROUP); + } + dmsScreenMap_.erase(dmsScreenMapIter); + NotifyScreenDisconnected(dmsScreenId); + if (rSScreenChangeListener_ != nullptr) { + rSScreenChangeListener_->onDisconnected_(); + } + if (screenGroup != nullptr && screenGroup->combination_ == ScreenCombination::SCREEN_MIRROR && + screen->dmsId_ == screenGroup->mirrorScreenId_ && screenGroup->GetChildCount() != 0) { + auto defaultScreenId = GetDefaultAbstractScreenId(); + std::vector screens; + for (auto screen : screenGroup->GetChildren()) { + if (screen->dmsId_ != defaultScreenId) { + screens.emplace_back(screen->dmsId_); + } + } + MakeMirror(defaultScreenId, screens); + } + } + screenIdManager_.DeleteScreenId(dmsScreenId); +} + +bool AbstractScreenController::InitAbstractScreenModesInfo(sptr& absScreen) +{ + std::vector allModes = rsInterface_.GetScreenSupportedModes(absScreen->rsId_); + if (allModes.size() == 0) { + WLOGE("supported screen mode is 0, screenId=%{public}" PRIu64"", absScreen->rsId_); + return false; + } + for (const RSScreenModeInfo& rsScreenModeInfo : allModes) { + sptr info = new(std::nothrow) SupportedScreenModes(); + if (info == nullptr) { + WLOGFE("create SupportedScreenModes failed"); + return false; + } + info->width_ = static_cast(rsScreenModeInfo.GetScreenWidth()); + info->height_ = static_cast(rsScreenModeInfo.GetScreenHeight()); + info->refreshRate_ = rsScreenModeInfo.GetScreenRefreshRate(); + absScreen->modes_.push_back(info); + WLOGD("fill screen idx:%{public}d w/h:%{public}d/%{public}d", + rsScreenModeInfo.GetScreenModeId(), info->width_, info->height_); + } + int32_t activeModeId = rsInterface_.GetScreenActiveMode(absScreen->rsId_).GetScreenModeId(); + WLOGD("fill screen activeModeId:%{public}d", activeModeId); + if (static_cast(activeModeId) >= allModes.size()) { + WLOGE("activeModeId exceed, screenId=%{public}" PRIu64", activeModeId:%{public}d/%{public}ud", + absScreen->rsId_, activeModeId, static_cast(allModes.size())); + return false; + } + absScreen->activeIdx_ = activeModeId; + return true; +} + +sptr AbstractScreenController::AddToGroupLocked(sptr newScreen) +{ + sptr res; + if (dmsScreenGroupMap_.empty()) { + WLOGI("connect the first screen"); + res = AddAsFirstScreenLocked(newScreen); + } else { + res = AddAsSuccedentScreenLocked(newScreen); + } + return res; +} + +sptr AbstractScreenController::RemoveFromGroupLocked(sptr screen) +{ + WLOGI("RemoveFromGroupLocked."); + auto groupDmsId = screen->groupDmsId_; + auto iter = dmsScreenGroupMap_.find(groupDmsId); + if (iter == dmsScreenGroupMap_.end()) { + WLOGE("RemoveFromGroupLocked. groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); + return nullptr; + } + sptr screenGroup = iter->second; + if (!RemoveChildFromGroup(screen, screenGroup)) { + return nullptr; + } + return screenGroup; +} + +bool AbstractScreenController::RemoveChildFromGroup(sptr screen, sptr screenGroup) +{ + bool res = screenGroup->RemoveChild(screen); + if (!res) { + WLOGE("RemoveFromGroupLocked. remove screen:%{public}" PRIu64" failed from screenGroup:%{public}" PRIu64".", + screen->dmsId_, screen->groupDmsId_); + return false; + } + if (screenGroup->GetChildCount() == 0) { + // Group removed, need to do something. + dmsScreenGroupMap_.erase(screenGroup->dmsId_); + dmsScreenMap_.erase(screenGroup->dmsId_); + } + return true; +} + +bool AbstractScreenController::CheckScreenInScreenGroup(sptr screen) const +{ + WLOGI("CheckScreenInScreenGroup."); + auto groupDmsId = screen->groupDmsId_; + auto iter = dmsScreenGroupMap_.find(groupDmsId); + if (iter == dmsScreenGroupMap_.end()) { + WLOGE("CheckScreenInScreenGroup. groupDmsId:%{public}" PRIu64"is not in dmsScreenGroupMap_.", groupDmsId); + return false; + } + sptr screenGroup = iter->second; + return screenGroup->HasChild(screen->dmsId_); +} + +sptr AbstractScreenController::AddAsFirstScreenLocked(sptr newScreen) +{ + ScreenId dmsGroupScreenId = screenIdManager_.CreateAndGetNewScreenId(SCREEN_ID_INVALID); + std::ostringstream buffer; + buffer<<"ScreenGroup_"< screenGroup; + if (isExpandCombination_) { + screenGroup = new(std::nothrow) AbstractScreenGroup(this, dmsGroupScreenId, + SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_EXPAND); + } else { + screenGroup = new(std::nothrow) AbstractScreenGroup(this, dmsGroupScreenId, + SCREEN_ID_INVALID, name, ScreenCombination::SCREEN_MIRROR); + } + + if (screenGroup == nullptr) { + WLOGE("new AbstractScreenGroup failed"); + screenIdManager_.DeleteScreenId(dmsGroupScreenId); + return nullptr; + } + Point point; + if (!screenGroup->AddChild(newScreen, point)) { + WLOGE("fail to add screen to group. screen=%{public}" PRIu64"", newScreen->dmsId_); + screenIdManager_.DeleteScreenId(dmsGroupScreenId); + return nullptr; + } + auto iter = dmsScreenGroupMap_.find(dmsGroupScreenId); + if (iter != dmsScreenGroupMap_.end()) { + WLOGE("group screen existed. id=%{public}" PRIu64"", dmsGroupScreenId); + dmsScreenGroupMap_.erase(iter); + } + dmsScreenGroupMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); + dmsScreenMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); + screenGroup->mirrorScreenId_ = newScreen->dmsId_; + WLOGI("connect new group screen, screenId: %{public}" PRIu64", screenGroupId: %{public}" PRIu64", " + "combination:%{public}u", newScreen->dmsId_, dmsGroupScreenId, newScreen->type_); + return screenGroup; +} + +sptr AbstractScreenController::AddAsSuccedentScreenLocked(sptr newScreen) +{ + ScreenId defaultScreenId = GetDefaultAbstractScreenId(); + auto iter = dmsScreenMap_.find(defaultScreenId); + if (iter == dmsScreenMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. defaultScreenId:%{public}" PRIu64" is not in dmsScreenMap_.", + defaultScreenId); + return nullptr; + } + auto screen = iter->second; + auto screenGroupIter = dmsScreenGroupMap_.find(screen->groupDmsId_); + if (screenGroupIter == dmsScreenGroupMap_.end()) { + WLOGE("AddAsSuccedentScreenLocked. groupDmsId:%{public}" PRIu64" is not in dmsScreenGroupMap_.", + screen->groupDmsId_); + return nullptr; + } + auto screenGroup = screenGroupIter->second; + Point point; + if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { + point = {screen->GetActiveScreenMode()->width_, 0}; + } + screenGroup->AddChild(newScreen, point); + return screenGroup; +} + +ScreenId AbstractScreenController::CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) +{ + ScreenId rsId = rsInterface_.CreateVirtualScreen(option.name_, option.width_, + option.height_, option.surface_, SCREEN_ID_INVALID, option.flags_); + WLOGFI("id: %{public}" PRIu64"", rsId); + if (rsId == SCREEN_ID_INVALID) { + return SCREEN_ID_INVALID; + } + std::lock_guard lock(mutex_); + ScreenId dmsScreenId = SCREEN_ID_INVALID; + if (!screenIdManager_.ConvertToDmsScreenId(rsId, dmsScreenId)) { + dmsScreenId = screenIdManager_.CreateAndGetNewScreenId(rsId); + auto absScreen = InitVirtualScreen(dmsScreenId, rsId, option); + if (absScreen == nullptr) { + screenIdManager_.DeleteScreenId(dmsScreenId); + return SCREEN_ID_INVALID; + } + dmsScreenMap_.insert(std::make_pair(dmsScreenId, absScreen)); + NotifyScreenConnected(absScreen->ConvertToScreenInfo()); + if (deathRecipient_ == nullptr) { + deathRecipient_ = + new AgentDeathRecipient([this](const sptr& agent) { OnRemoteDied(agent); }); + } + auto agIter = screenAgentMap_.find(displayManagerAgent); + if (agIter == screenAgentMap_.end()) { + displayManagerAgent->AddDeathRecipient(deathRecipient_); + } + screenAgentMap_[displayManagerAgent].emplace_back(dmsScreenId); + } else { + WLOGFI("id: %{public}" PRIu64" appears in screenIdManager_. ", rsId); + } + return dmsScreenId; +} + +sptr AbstractScreenController::InitVirtualScreen(ScreenId dmsScreenId, ScreenId rsId, + VirtualScreenOption option) +{ + sptr absScreen = new(std::nothrow) AbstractScreen(this, option.name_, dmsScreenId, rsId); + sptr info = new(std::nothrow) SupportedScreenModes(); + if (absScreen == nullptr || info == nullptr) { + WLOGFI("new AbstractScreen or SupportedScreenModes failed"); + screenIdManager_.DeleteScreenId(dmsScreenId); + rsInterface_.RemoveVirtualScreen(rsId); + return nullptr; + } + info->width_ = option.width_; + info->height_ = option.height_; + auto defaultScreen = GetAbstractScreen(GetDefaultAbstractScreenId()); + if (defaultScreen != nullptr && defaultScreen->GetActiveScreenMode() != nullptr) { + info->refreshRate_ = defaultScreen->GetActiveScreenMode()->refreshRate_; + } + absScreen->modes_.emplace_back(info); + absScreen->activeIdx_ = 0; + absScreen->type_ = ScreenType::VIRTUAL; + absScreen->virtualPixelRatio_ = option.density_; + return absScreen; +} + +DMError AbstractScreenController::DestroyVirtualScreen(ScreenId screenId) +{ + WLOGFI("AbstractScreenController::DestroyVirtualScreen"); + std::lock_guard lock(mutex_); + ScreenId rsScreenId = SCREEN_ID_INVALID; + screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId); + + sptr displayManagerAgent = nullptr; + bool agentFound = false; + for (auto &agentIter : screenAgentMap_) { + for (auto iter = agentIter.second.begin(); iter != agentIter.second.end(); iter++) { + if (*iter == screenId) { + iter = agentIter.second.erase(iter); + agentFound = true; + break; + } + } + if (agentFound) { + if (agentIter.first != nullptr && agentIter.second.empty()) { + agentIter.first->RemoveDeathRecipient(deathRecipient_); + screenAgentMap_.erase(agentIter.first); + } + break; + } + } + + if (rsScreenId != SCREEN_ID_INVALID && GetAbstractScreen(screenId) != nullptr) { + ProcessScreenDisconnected(rsScreenId); + } + screenIdManager_.DeleteScreenId(screenId); + + if (rsScreenId == SCREEN_ID_INVALID) { + WLOGFE("DestroyVirtualScreen: No corresponding rsScreenId"); + return DMError::DM_ERROR_INVALID_PARAM; + } + rsInterface_.RemoveVirtualScreen(rsScreenId); + return DMError::DM_OK; +} + +DMError AbstractScreenController::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + WLOGFI("AbstractScreenController::SetVirtualScreenSurface"); + int32_t res = -1; + ScreenId rsScreenId; + if (screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { + res = rsInterface_.SetVirtualScreenSurface(rsScreenId, surface); + } + if (res != 0) { + WLOGE("SetVirtualScreenSurface failed in RenderService"); + return DMError::DM_ERROR_RENDER_SERVICE_FAILED; + } + return DMError::DM_OK; +} + +void AbstractScreenController::SetBuildInDefaultOrientation(Orientation orientation) +{ + if (orientation >= Orientation::BEGIN && orientation <= Orientation::END) { + buildInDefaultOrientation_ = orientation; + } +} + +bool AbstractScreenController::SetOrientation(ScreenId screenId, Orientation newOrientation, bool isFromWindow) +{ + WLOGD("set orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation); + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("fail to set orientation, cannot find screen %{public}" PRIu64"", screenId); + return false; + } + if (screen->isScreenGroup_) { + WLOGE("cannot set orientation to the combination. screen: %{public}" PRIu64"", screenId); + return false; + } + if (isFromWindow) { + if (newOrientation == Orientation::UNSPECIFIED) { + newOrientation = screen->screenRequestedOrientation_; + } + } else { + screen->screenRequestedOrientation_ = newOrientation; + } + if (screen->orientation_ == newOrientation) { + WLOGI("skip setting orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation); + return true; + } + if (isFromWindow) { + ScreenRotationController::ProcessOrientationSwitch(newOrientation); + } else { + Rotation rotationAfter = screen->CalcRotation(newOrientation); + SetRotation(screenId, rotationAfter, false); + screen->rotation_ = rotationAfter; + } + if (!screen->SetOrientation(newOrientation)) { + WLOGE("fail to set rotation, screen %{public}" PRIu64"", screenId); + return false; + } + + // Notify rotation event to ScreenManager + NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ORIENTATION); + // Notify rotation event to AbstractDisplayController + if (abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ORIENTATION); + } + return true; +} + +void AbstractScreenController::SetScreenRotateAnimation( + sptr& screen, ScreenId screenId, Rotation rotationAfter) +{ + sptr abstractScreenModes = screen->GetActiveScreenMode(); + float w = 0; + float h = 0; + float x = 0; + float y = 0; + if (abstractScreenModes != nullptr) { + h = abstractScreenModes->height_; + w = abstractScreenModes->width_; + } + if (!IsVertical(rotationAfter)) { + std::swap(w, h); + x = (h - w) / 2; // 2: used to calculate offset to center display node + y = (w - h) / 2; // 2: used to calculate offset to center display node + } + auto displayNode = GetRSDisplayNodeByScreenId(screenId); + if (displayNode == nullptr) { + return; + } + if (rotationAfter == Rotation::ROTATION_0 && screen->rotation_ == Rotation::ROTATION_270) { + // avoid animation 270, 240, 210 ... 30, 0, should play from 90->0 + displayNode->SetRotation(90.f); + } else if (rotationAfter == Rotation::ROTATION_270 && screen->rotation_ == Rotation::ROTATION_0) { + // avoid animation 0, 30, 60 ... 270, should play from 360->270 + displayNode->SetRotation(-360.f); + } + std::weak_ptr weakNode = GetRSDisplayNodeByScreenId(screenId); + static const RSAnimationTimingProtocol timingProtocol(600); // animation time + static const RSAnimationTimingCurve curve_ = + RSAnimationTimingCurve::CreateCubicCurve(0.2, 0.0, 0.2, 1.0); // animation curve: cubic [0.2, 0.0, 0.2, 1.0] + // Increase frequency to improve windowRotation perf + // 10027 means "web_gesture" level that setting duration: 800, lit_cpu_min_freq: 1421000, mid_cpu_min_feq: 1882000 + OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequest(10027, ""); + RSNode::Animate(timingProtocol, curve_, [weakNode, x, y, w, h, rotationAfter]() { + auto displayNode = weakNode.lock(); + if (displayNode == nullptr) { + WLOGFE("SetScreenRotateAnimation error, cannot get DisplayNode"); + return; + } + displayNode->SetRotation(-90.f * static_cast(rotationAfter)); // 90.f is base degree + displayNode->SetFrame(x, y, w, h); + displayNode->SetBounds(x, y, w, h); + }, []() { + // ClosePerf in finishCallBack + OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequestEx(10027, false, ""); + }); +} + +bool AbstractScreenController::SetRotation(ScreenId screenId, Rotation rotationAfter, bool isFromWindow) +{ + WLOGFI("Enter SetRotation, screenId: %{public}" PRIu64 ", rotation: %{public}u, isFromWindow: %{public}u", + screenId, rotationAfter, isFromWindow); + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("SetRotation error, cannot get screen with screenId: %{public}" PRIu64, screenId); + return false; + } + if (rotationAfter != screen->rotation_) { + WLOGI("set orientation. rotation %{public}u", rotationAfter); + ScreenId rsScreenId; + if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { + WLOGE("Convert to RsScreenId fail. screenId: %{public}" PRIu64"", screenId); + return false; + } + SetScreenRotateAnimation(screen, screenId, rotationAfter); + screen->rotation_ = rotationAfter; + } else { + WLOGI("rotation not changed. screen %{public}" PRIu64" rotation %{public}u", screenId, rotationAfter); + } + + NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::UPDATE_ROTATION); + // Notify rotation event to AbstractDisplayController + if (abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::UPDATE_ROTATION); + } + return true; +} + +DMError AbstractScreenController::GetScreenSupportedColorGamuts(ScreenId screenId, + std::vector& colorGamuts) +{ + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + return DMError::DM_ERROR_INVALID_PARAM; + } + return screen->GetScreenSupportedColorGamuts(colorGamuts); +} + +DMError AbstractScreenController::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +{ + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + return DMError::DM_ERROR_INVALID_PARAM; + } + return screen->GetScreenColorGamut(colorGamut); +} + +DMError AbstractScreenController::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +{ + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + return DMError::DM_ERROR_INVALID_PARAM; + } + return screen->SetScreenColorGamut(colorGamutIdx); +} + +DMError AbstractScreenController::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +{ + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + return DMError::DM_ERROR_INVALID_PARAM; + } + return screen->GetScreenGamutMap(gamutMap); +} + +DMError AbstractScreenController::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +{ + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + return DMError::DM_ERROR_INVALID_PARAM; + } + return screen->SetScreenGamutMap(gamutMap); +} + +DMError AbstractScreenController::SetScreenColorTransform(ScreenId screenId) +{ + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + return DMError::DM_ERROR_INVALID_PARAM; + } + return screen->SetScreenColorTransform(); +} + +bool AbstractScreenController::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) +{ + WLOGI("SetScreenActiveMode: RsScreenId: %{public}" PRIu64", modeId: %{public}u", screenId, modeId); + if (screenId == SCREEN_ID_INVALID) { + WLOGFE("SetScreenActiveMode: invalid screenId"); + return false; + } + uint32_t usedModeId = 0; + { + std::lock_guard lock(mutex_); + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("SetScreenActiveMode: Get AbstractScreen failed"); + return false; + } + ScreenId rsScreenId = SCREEN_ID_INVALID; + if (!screenIdManager_.ConvertToRsScreenId(screenId, rsScreenId)) { + WLOGFE("SetScreenActiveMode: No corresponding rsId"); + return false; + } + rsInterface_.SetScreenActiveMode(rsScreenId, modeId); + usedModeId = static_cast(screen->activeIdx_); + screen->activeIdx_ = static_cast(modeId); + } + // add thread to process mode change sync event + if (usedModeId != modeId) { + WLOGI("SetScreenActiveMode: modeId: %{public}u -> %{public}u", usedModeId, modeId); + auto func = [=]() { + ProcessScreenModeChanged(screenId); + return; + }; + controllerHandler_->PostTask(func, AppExecFwk::EventQueue::Priority::HIGH); + } + return true; +} + +void AbstractScreenController::ProcessScreenModeChanged(ScreenId dmsScreenId) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:ProcessScreenModeChanged(%" PRIu64")", dmsScreenId); + sptr absScreen = nullptr; + sptr absScreenCallback = nullptr; + { + std::lock_guard lock(mutex_); + auto dmsScreenMapIter = dmsScreenMap_.find(dmsScreenId); + if (dmsScreenMapIter == dmsScreenMap_.end()) { + WLOGFE("dmsScreenId=%{public}" PRIu64" is not in dmsScreenMap", dmsScreenId); + return; + } + absScreen = GetAbstractScreen(dmsScreenId); + if (absScreen == nullptr) { + WLOGFE("screen is nullptr. dmsScreenId=%{public}" PRIu64"", dmsScreenId); + return; + } + absScreenCallback = abstractScreenCallback_; + } + + if (absScreenCallback != nullptr) { + absScreenCallback->onChange_(absScreen, DisplayChangeEvent::DISPLAY_SIZE_CHANGED); + } + NotifyScreenChanged(absScreen->ConvertToScreenInfo(), ScreenChangeEvent::CHANGE_MODE); +} + +bool AbstractScreenController::MakeMirror(ScreenId screenId, std::vector screens) +{ + WLOGI("MakeMirror, screenId:%{public}" PRIu64"", screenId); + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr || screen->type_ != ScreenType::REAL) { + WLOGFE("screen is nullptr, or screenType is not real."); + return false; + } + WLOGFI("GetAbstractScreenGroup start"); + auto group = GetAbstractScreenGroup(screen->groupDmsId_); + if (group == nullptr) { + std::lock_guard lock(mutex_); + sptr group = AddToGroupLocked(screen); + if (group == nullptr) { + WLOGFE("group is nullptr"); + return false; + } + NotifyScreenGroupChanged(screen->ConvertToScreenInfo(), ScreenGroupChangeEvent::ADD_TO_GROUP); + if (group != nullptr && abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onConnect_(screen); + } + } + WLOGFI("GetAbstractScreenGroup end"); + Point point; + std::vector startPoints; + startPoints.insert(startPoints.begin(), screens.size(), point); + bool filterMirroredScreen = + group->combination_ == ScreenCombination::SCREEN_MIRROR && group->mirrorScreenId_ == screen->dmsId_; + group->mirrorScreenId_ = screen->dmsId_; + ChangeScreenGroup(group, screens, startPoints, filterMirroredScreen, ScreenCombination::SCREEN_MIRROR); + WLOGFI("MakeMirror success"); + return true; +} + +void AbstractScreenController::ChangeScreenGroup(sptr group, const std::vector& screens, + const std::vector& startPoints, bool filterScreen, ScreenCombination combination) +{ + std::map removeChildResMap; + std::vector addScreens; + std::vector addChildPos; + std::lock_guard lock(mutex_); + for (uint64_t i = 0; i != screens.size(); i++) { + ScreenId screenId = screens[i]; + WLOGFI("ChangeScreenGroup: screenId: %{public}" PRIu64"", screenId); + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("screen:%{public}" PRIu64" is nullptr", screenId); + continue; + } + WLOGFI("ChangeScreenGroup: screen->groupDmsId_: %{public}" PRIu64"", screen->groupDmsId_); + if (filterScreen && screen->groupDmsId_ == group->dmsId_ && group->HasChild(screen->dmsId_)) { + continue; + } + if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { + abstractScreenCallback_->onDisconnect_(screen); + } + auto originGroup = RemoveFromGroupLocked(screen); + addChildPos.emplace_back(startPoints[i]); + removeChildResMap[screenId] = originGroup != nullptr; + addScreens.emplace_back(screenId); + } + group->combination_ = combination; + AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap); +} + +void AbstractScreenController::AddScreenToGroup(sptr group, + const std::vector& addScreens, const std::vector& addChildPos, + std::map& removeChildResMap) +{ + std::vector> addToGroup; + std::vector> removeFromGroup; + std::vector> changeGroup; + for (uint64_t i = 0; i != addScreens.size(); i++) { + ScreenId screenId = addScreens[i]; + sptr screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + continue; + } + Point expandPoint = addChildPos[i]; + WLOGFI("screenId: %{public}" PRIu64", Point: %{public}d, %{public}d", + screen->dmsId_, expandPoint.posX_, expandPoint.posY_); + bool addChildRes = group->AddChild(screen, expandPoint); + if (removeChildResMap[screenId] && addChildRes) { + changeGroup.emplace_back(screen->ConvertToScreenInfo()); + WLOGFI("changeGroup"); + } else if (removeChildResMap[screenId]) { + WLOGFI("removeChild"); + removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); + } else if (addChildRes) { + WLOGFI("AddChild"); + addToGroup.emplace_back(screen->ConvertToScreenInfo()); + } else { + WLOGFI("default, AddChild failed"); + } + if (abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onConnect_(screen); + } + if (rSScreenChangeListener_ != nullptr) { + rSScreenChangeListener_->onConnected_(); + } + } + + NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); + NotifyScreenGroupChanged(changeGroup, ScreenGroupChangeEvent::CHANGE_GROUP); + NotifyScreenGroupChanged(addToGroup, ScreenGroupChangeEvent::ADD_TO_GROUP); +} + +bool AbstractScreenController::MakeExpand(std::vector screenIds, std::vector startPoints) +{ + ScreenId defaultScreenId = GetDefaultAbstractScreenId(); + WLOGI("MakeExpand, defaultScreenId:%{public}" PRIu64"", defaultScreenId); + auto defaultScreen = GetAbstractScreen(defaultScreenId); + if (defaultScreen == nullptr) { + return false; + } + auto group = GetAbstractScreenGroup(defaultScreen->groupDmsId_); + if (group == nullptr) { + return false; + } + bool filterExpandScreen = group->combination_ == ScreenCombination::SCREEN_EXPAND; + ChangeScreenGroup(group, screenIds, startPoints, filterExpandScreen, ScreenCombination::SCREEN_EXPAND); + WLOGFI("MakeExpand success"); + return true; +} + +void AbstractScreenController::RemoveVirtualScreenFromGroup(std::vector screens) +{ + if (screens.empty()) { + return; + } + std::vector> removeFromGroup; + for (ScreenId screenId : screens) { + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr || screen->type_ != ScreenType::VIRTUAL) { + continue; + } + auto originGroup = GetAbstractScreenGroup(screen->groupDmsId_); + if (originGroup == nullptr) { + continue; + } + if (!originGroup->HasChild(screenId)) { + continue; + } + if (abstractScreenCallback_ != nullptr && CheckScreenInScreenGroup(screen)) { + abstractScreenCallback_->onDisconnect_(screen); + } + RemoveFromGroupLocked(screen); + removeFromGroup.emplace_back(screen->ConvertToScreenInfo()); + } + NotifyScreenGroupChanged(removeFromGroup, ScreenGroupChangeEvent::REMOVE_FROM_GROUP); +} + +bool AbstractScreenController::OnRemoteDied(const sptr& agent) +{ + if (agent == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto agentIter = screenAgentMap_.find(agent); + if (agentIter != screenAgentMap_.end()) { + while (screenAgentMap_[agent].size() > 0) { + auto diedId = screenAgentMap_[agent][0]; + WLOGI("destroy screenId in OnRemoteDied: %{public}" PRIu64"", diedId); + DMError res = DestroyVirtualScreen(diedId); + if (res != DMError::DM_OK) { + WLOGE("destroy failed in OnRemoteDied: %{public}" PRIu64"", diedId); + } + } + screenAgentMap_.erase(agent); + } + return true; +} + +ScreenId AbstractScreenController::ScreenIdManager::CreateAndGetNewScreenId(ScreenId rsScreenId) +{ + ScreenId dmsScreenId = dmsScreenCount_++; + if (dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end()) { + WLOGFW("dmsScreenId: %{public}" PRIu64" exit in dms2RsScreenIdMap_, warning.", dmsScreenId); + } + dms2RsScreenIdMap_[dmsScreenId] = rsScreenId; + if (rsScreenId == SCREEN_ID_INVALID) { + return dmsScreenId; + } + if (rs2DmsScreenIdMap_.find(rsScreenId) != rs2DmsScreenIdMap_.end()) { + WLOGFW("rsScreenId: %{public}" PRIu64" exit in rs2DmsScreenIdMap_, warning.", rsScreenId); + } + rs2DmsScreenIdMap_[rsScreenId] = dmsScreenId; + return dmsScreenId; +} + +bool AbstractScreenController::ScreenIdManager::DeleteScreenId(ScreenId dmsScreenId) +{ + auto iter = dms2RsScreenIdMap_.find(dmsScreenId); + if (iter == dms2RsScreenIdMap_.end()) { + return false; + } + ScreenId rsScreenId = iter->second; + dms2RsScreenIdMap_.erase(dmsScreenId); + rs2DmsScreenIdMap_.erase(rsScreenId); + return true; +} + +bool AbstractScreenController::ScreenIdManager::HasDmsScreenId(ScreenId dmsScreenId) const +{ + return dms2RsScreenIdMap_.find(dmsScreenId) != dms2RsScreenIdMap_.end(); +} + +bool AbstractScreenController::ScreenIdManager::HasRsScreenId(ScreenId dmsScreenId) const +{ + return rs2DmsScreenIdMap_.find(dmsScreenId) != rs2DmsScreenIdMap_.end(); +} + +uint32_t AbstractScreenController::ScreenIdManager::GetRSScreenNum() const +{ + return rs2DmsScreenIdMap_.size(); +} + +bool AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId, ScreenId& rsScreenId) const +{ + auto iter = dms2RsScreenIdMap_.find(dmsScreenId); + if (iter == dms2RsScreenIdMap_.end()) { + return false; + } + rsScreenId = iter->second; + return true; +} + +ScreenId AbstractScreenController::ScreenIdManager::ConvertToRsScreenId(ScreenId dmsScreenId) const +{ + ScreenId rsScreenId = SCREEN_ID_INVALID; + ConvertToRsScreenId(dmsScreenId, rsScreenId); + return rsScreenId; +} + +bool AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId, ScreenId& dmsScreenId) const +{ + auto iter = rs2DmsScreenIdMap_.find(rsScreenId); + if (iter == rs2DmsScreenIdMap_.end()) { + return false; + } + dmsScreenId = iter->second; + return true; +} + +ScreenId AbstractScreenController::ScreenIdManager::ConvertToDmsScreenId(ScreenId rsScreenId) const +{ + ScreenId dmsScreenId = SCREEN_ID_INVALID; + ConvertToDmsScreenId(rsScreenId, dmsScreenId); + return dmsScreenId; +} + +void AbstractScreenController::NotifyScreenConnected(sptr screenInfo) const +{ + if (screenInfo == nullptr) { + WLOGFE("NotifyScreenConnected error, screenInfo is nullptr."); + return; + } + auto task = [=] { + WLOGFI("NotifyScreenConnected, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); + DisplayManagerAgentController::GetInstance().OnScreenConnect(screenInfo); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void AbstractScreenController::NotifyScreenDisconnected(ScreenId screenId) const +{ + auto task = [=] { + WLOGFI("NotifyScreenDisconnected, screenId:%{public}" PRIu64"", screenId); + DisplayManagerAgentController::GetInstance().OnScreenDisconnect(screenId); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void AbstractScreenController::NotifyScreenChanged(sptr screenInfo, ScreenChangeEvent event) const +{ + if (screenInfo == nullptr) { + WLOGFE("NotifyScreenChanged error, screenInfo is nullptr."); + return; + } + auto task = [=] { + WLOGFI("NotifyScreenChanged, screenId:%{public}" PRIu64"", screenInfo->GetScreenId()); + DisplayManagerAgentController::GetInstance().OnScreenChange(screenInfo, event); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void AbstractScreenController::NotifyScreenGroupChanged( + const sptr& screenInfo, ScreenGroupChangeEvent event) const +{ + if (screenInfo == nullptr) { + WLOGFE("screenInfo is nullptr."); + return; + } + std::string trigger = SysCapUtil::GetClientName(); + auto task = [=] { + WLOGFI("screenId:%{public}" PRIu64", trigger:[%{public}s]", screenInfo->GetScreenId(), trigger.c_str()); + DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void AbstractScreenController::NotifyScreenGroupChanged( + const std::vector>& screenInfo, ScreenGroupChangeEvent event) const +{ + if (screenInfo.empty()) { + return; + } + std::string trigger = SysCapUtil::GetClientName(); + auto task = [=] { + WLOGFI("trigger:[%{public}s]", trigger.c_str()); + DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, screenInfo, event); + }; + controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +bool AbstractScreenController::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) const +{ + WLOGFI("state:%{public}u, reason:%{public}u", state, reason); + auto screenIds = GetAllScreenIds(); + if (screenIds.empty()) { + WLOGFI("no screen info"); + return false; + } + + ScreenPowerStatus status; + switch (state) { + case ScreenPowerState::POWER_ON: { + status = ScreenPowerStatus::POWER_STATUS_ON; + break; + } + case ScreenPowerState::POWER_OFF: { + status = ScreenPowerStatus::POWER_STATUS_OFF; + break; + } + default: { + WLOGFW("SetScreenPowerStatus state not support"); + return false; + } + } + + bool hasSetScreenPower = false; + for (auto screenId : screenIds) { + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + continue; + } + if (screen->type_ != ScreenType::REAL) { + WLOGD("skip virtual screen %{public}" PRIu64"", screen->dmsId_); + continue; + } + RSInterfaces::GetInstance().SetScreenPowerStatus(screen->rsId_, status); + WLOGI("set screen power status. rsscreen %{public}" PRIu64", status %{public}u", screen->rsId_, status); + hasSetScreenPower = true; + } + WLOGFI("SetScreenPowerStatus end"); + if (!hasSetScreenPower) { + WLOGFI("no real screen"); + return false; + } + return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent( + state == ScreenPowerState::POWER_ON ? DisplayPowerEvent::DISPLAY_ON : + DisplayPowerEvent::DISPLAY_OFF, EventStatus::END); +} + +ScreenPowerState AbstractScreenController::GetScreenPower(ScreenId dmsScreenId) const +{ + if (dmsScreenMap_.empty()) { + WLOGFE("no screen info"); + return ScreenPowerState::INVALID_STATE; + } + + ScreenId rsId = SCREEN_ID_INVALID; + auto iter = dmsScreenMap_.find(dmsScreenId); + if (iter != dmsScreenMap_.end()) { + rsId = ConvertToRsScreenId(dmsScreenId); + } + + if (rsId == SCREEN_ID_INVALID) { + WLOGFE("cannot find screen %{public}" PRIu64"", dmsScreenId); + return ScreenPowerState::INVALID_STATE; + } + auto state = static_cast(RSInterfaces::GetInstance().GetScreenPowerStatus(rsId)); + WLOGFI("GetScreenPower:%{public}u, rsscreen:%{public}" PRIu64".", state, rsId); + return state; +} + +bool AbstractScreenController::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) +{ + WLOGD("set virtual pixel ratio. screen %{public}" PRIu64" virtualPixelRatio %{public}f", + screenId, virtualPixelRatio); + auto screen = GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("fail to set virtual pixel ratio, cannot find screen %{public}" PRIu64"", screenId); + return false; + } + if (screen->isScreenGroup_) { + WLOGE("cannot set virtual pixel ratio to the combination. screen: %{public}" PRIu64"", screenId); + return false; + } + if (fabs(screen->virtualPixelRatio_ - virtualPixelRatio) < 1e-6) { + WLOGE("The density is equivalent to the original value, no update operation is required, aborted."); + return true; + } + screen->SetVirtualPixelRatio(virtualPixelRatio); + // Notify rotation event to AbstractDisplayController + if (abstractScreenCallback_ != nullptr) { + abstractScreenCallback_->onChange_(screen, DisplayChangeEvent::DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED); + } + NotifyScreenChanged(screen->ConvertToScreenInfo(), ScreenChangeEvent::VIRTUAL_PIXEL_RATIO_CHANGED); + return true; +} +} // namespace OHOS::Rosen diff --git a/window_manager/dmserver/src/display_cutout_controller.cpp b/window_manager/dmserver/src/display_cutout_controller.cpp new file mode 100644 index 0000000..5d1badb --- /dev/null +++ b/window_manager/dmserver/src/display_cutout_controller.cpp @@ -0,0 +1,324 @@ +/* + * 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 "display_cutout_controller.h" +#include +#include "display_manager_service_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayCutoutController"}; + const uint32_t NO_WATERFALL_DISPLAY_COMPRESSION_SIZE = 0; +} + +bool DisplayCutoutController::isWaterfallDisplay_ = false; +bool DisplayCutoutController::isWaterfallAreaCompressionEnableWhenHorizontal_ = false; +uint32_t DisplayCutoutController::waterfallAreaCompressionSizeWhenHorizontal_ = 0; + +void DisplayCutoutController::SetBuiltInDisplayCutoutSvgPath(const std::string& svgPath) +{ + SetCutoutSvgPath(0, svgPath); +} + +void DisplayCutoutController::SetIsWaterfallDisplay(bool isWaterfallDisplay) +{ + WLOGFI("Set isWaterfallDisplay: %{public}u", isWaterfallDisplay); + isWaterfallDisplay_ = isWaterfallDisplay; +} + +bool DisplayCutoutController::IsWaterfallDisplay() +{ + return isWaterfallDisplay_; +} + +void DisplayCutoutController::SetCurvedScreenBoundary(std::vector curvedScreenBoundary) +{ + while (curvedScreenBoundary.size() < 4) { // 4 directions. + curvedScreenBoundary.emplace_back(0); + } + WLOGFI("Set curvedScreenBoundary"); + curvedScreenBoundary_ = curvedScreenBoundary; +} + +void DisplayCutoutController::SetCutoutSvgPath(DisplayId displayId, const std::string& svgPath) +{ + WLOGFI("Set SvgPath: %{public}s", svgPath.c_str()); + if (svgPaths_.count(displayId) == 1) { + svgPaths_[displayId].emplace_back(svgPath); + } else { + std::vector pathVec; + pathVec.emplace_back(svgPath); + svgPaths_[displayId] = pathVec; + } + DMRect boundingRect = CalcCutoutBoundingRect(svgPath); + if (boundingRects_.count(displayId) == 1) { + boundingRects_[displayId].emplace_back(boundingRect); + } else { + std::vector rectVec; + rectVec.emplace_back(boundingRect); + boundingRects_[displayId] = rectVec; + } +} + +sptr DisplayCutoutController::GetCutoutInfo(DisplayId displayId) +{ + WLOGFD("Get Cutout Info"); + std::vector boundingRects; + WaterfallDisplayAreaRects waterfallDisplayAreaRects; + if (boundingRects_.count(displayId) == 1) { + TransferBoundingRectsByRotation(displayId, boundingRects); + } + if (displayId == DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId()) { + CalcBuiltInDisplayWaterfallRects(); + waterfallDisplayAreaRects = waterfallDisplayAreaRects_; + } + CutoutInfo *cutoutInfo = new CutoutInfo(boundingRects, waterfallDisplayAreaRects); + return cutoutInfo; +} + +void DisplayCutoutController::CheckBoundingRectsBoundary(DisplayId displayId, std::vector& boundingRects) +{ + sptr modes = + DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(displayId); + if (modes == nullptr) { + WLOGFE("DisplayId is invalid"); + return; + } + uint32_t displayHeight = modes->height_; + uint32_t displayWidth = modes->width_; + for (auto iter = boundingRects.begin(); iter != boundingRects.end();) { + DMRect boundingRect = *iter; + if (boundingRect.posX_ < 0 || boundingRect.posY_ < 0 || + static_cast(boundingRect.width_) + boundingRect.posX_ > static_cast(displayWidth) || + static_cast(boundingRect.height_) + boundingRect.posY_ > static_cast(displayHeight) || + boundingRect.width_ > displayWidth || boundingRect.height_ > displayHeight || + boundingRect.isUninitializedRect()) { + WLOGFE("boundingRect boundary is invalid"); + iter = boundingRects.erase(iter); + } else { + iter++; + } + } +} + +DMRect DisplayCutoutController::CalcCutoutBoundingRect(std::string svgPath) +{ + DMRect emptyRect = {0, 0, 0, 0}; + SkPath skCutoutSvgPath; + if (!SkParsePath::FromSVGString(svgPath.c_str(), &skCutoutSvgPath)) { + WLOGFE("Parse svg string path failed."); + return emptyRect; + } + SkRect skRect = skCutoutSvgPath.computeTightBounds(); + if (skRect.isEmpty()) { + WLOGFW("Get empty skRect"); + return emptyRect; + } + SkIRect skiRect = skRect.roundOut(); + if (skiRect.isEmpty()) { + WLOGFW("Get empty skiRect"); + return emptyRect; + } + int32_t left = static_cast(skiRect.left()); + int32_t top = static_cast(skiRect.top()); + uint32_t width = static_cast(skiRect.width()); + uint32_t height = static_cast(skiRect.height()); + WLOGFI("calc rect from path,[%{public}d, %{public}d, %{public}u, %{public}u]", left, top, width, height); + DMRect cutoutMinOuterRect = {.posX_ = left, .posY_ = top, .width_ = width, .height_ = height}; + return cutoutMinOuterRect; +} + +void DisplayCutoutController::CalcBuiltInDisplayWaterfallRects() +{ + WaterfallDisplayAreaRects emptyRects = {}; + if (!isWaterfallDisplay_) { + WLOGFI("not waterfall display"); + waterfallDisplayAreaRects_ = emptyRects; + return; + } + if (curvedScreenBoundary_.empty()) { + WLOGFI("curved screen boundary is empty"); + waterfallDisplayAreaRects_ = emptyRects; + return; + } + uint32_t left = static_cast(curvedScreenBoundary_[0]); + uint32_t top = static_cast(curvedScreenBoundary_[1]); + uint32_t right = static_cast(curvedScreenBoundary_[2]); + uint32_t bottom = static_cast(curvedScreenBoundary_[3]); + if (left == 0 && top == 0 && right == 0 && bottom == 0) { + waterfallDisplayAreaRects_ = emptyRects; + return; + } + sptr modes = + DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId( + DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId()); + if (!modes) { + WLOGE("support screen modes get failed"); + waterfallDisplayAreaRects_ = emptyRects; + return; + } + uint32_t displayHeight = modes->height_; + uint32_t displayWidth = modes->width_; + + if ((left > displayWidth / 2) || (right > displayWidth / 2) || // invalid if more than 1/2 width + (top > displayHeight / 2) || (bottom > displayHeight / 2)) { // invalid if more than 1/2 height + WLOGFE("Curved screen boundary data is not valid."); + waterfallDisplayAreaRects_ = emptyRects; + return; + } + CalcBuiltInDisplayWaterfallRectsByRotation( + DisplayManagerServiceInner::GetInstance().GetDefaultDisplay()->GetRotation(), + displayHeight, displayWidth); +} + +void DisplayCutoutController::CalcBuiltInDisplayWaterfallRectsByRotation( + Rotation rotation, uint32_t displayHeight, uint32_t displayWidth) +{ + uint32_t left = static_cast(curvedScreenBoundary_[0]); + uint32_t top = static_cast(curvedScreenBoundary_[1]); + uint32_t right = static_cast(curvedScreenBoundary_[2]); + uint32_t bottom = static_cast(curvedScreenBoundary_[3]); + switch (rotation) { + case Rotation::ROTATION_0: { + DMRect leftRect = CreateWaterfallRect(0, 0, left, displayHeight); + DMRect topRect = CreateWaterfallRect(0, 0, displayWidth, top); + DMRect rightRect = CreateWaterfallRect(displayWidth - right, 0, right, displayHeight); + DMRect bottomRect = CreateWaterfallRect(0, displayHeight - bottom, displayWidth, bottom); + waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect}; + return; + } + case Rotation::ROTATION_90: { + DMRect leftRect = CreateWaterfallRect(0, 0, bottom, displayWidth); + DMRect topRect = CreateWaterfallRect(0, 0, displayHeight, left); + DMRect rightRect = CreateWaterfallRect(displayHeight - top, 0, top, displayWidth); + DMRect bottomRect = CreateWaterfallRect(0, displayWidth - right, displayHeight, right); + waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect}; + return; + } + case Rotation::ROTATION_180: { + DMRect leftRect = CreateWaterfallRect(0, 0, right, displayHeight); + DMRect topRect = CreateWaterfallRect(0, 0, bottom, displayWidth); + DMRect rightRect = CreateWaterfallRect(displayWidth - left, 0, left, displayHeight); + DMRect bottomRect = CreateWaterfallRect(0, displayHeight - top, displayWidth, top); + waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect}; + return; + } + case Rotation::ROTATION_270: { + DMRect leftRect = CreateWaterfallRect(0, 0, top, displayWidth); + DMRect topRect = CreateWaterfallRect(0, 0, displayHeight, right); + DMRect rightRect = CreateWaterfallRect(displayHeight - bottom, 0, bottom, displayWidth); + DMRect bottomRect = CreateWaterfallRect(0, displayWidth - left, displayHeight, left); + waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect}; + return; + } + default: { + } + } +} + +void DisplayCutoutController::TransferBoundingRectsByRotation(DisplayId displayId, std::vector& boundingRects) +{ + std::vector resultVec; + if (boundingRects_.count(displayId) == 0) { + boundingRects = resultVec; + return; + } + std::vector displayBoundingRects = boundingRects_[displayId]; + if (displayBoundingRects.empty()) { + boundingRects = resultVec; + return; + } + sptr displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); + if (!displayInfo) { + WLOGFE("display invaild"); + return; + } + Rotation currentRotation = displayInfo->GetRotation(); + CheckBoundingRectsBoundary(displayId, displayBoundingRects); + if (currentRotation == Rotation::ROTATION_0) { + boundingRects = displayBoundingRects; + return; + } + sptr modes = + DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(displayId); + if (!modes) { + WLOGE("support screen modes get failed"); + return; + } + uint32_t displayHeight = modes->height_; + uint32_t displayWidth = modes->width_; + + switch (currentRotation) { + case Rotation::ROTATION_90: { + for (DMRect rect : displayBoundingRects) { + resultVec.emplace_back(DMRect {.posX_ = displayHeight - rect.posY_ - rect.height_, + .posY_ = rect.posX_, .width_ = rect.height_, .height_ = rect.width_}); + } + break; + } + case Rotation::ROTATION_180: { + for (DMRect rect : displayBoundingRects) { + resultVec.emplace_back(DMRect {displayWidth - rect.posX_ - rect.width_, + displayHeight - rect.posY_ - rect.height_, rect.width_, rect.height_}); + } + break; + } + case Rotation::ROTATION_270: { + for (DMRect rect : displayBoundingRects) { + resultVec.emplace_back(DMRect {rect.posY_, displayWidth - rect.posX_ - rect.width_, + rect.height_, rect.width_}); + } + break; + } + default: { + } + } + boundingRects = resultVec; +} + +DMRect DisplayCutoutController::CreateWaterfallRect(uint32_t left, uint32_t top, uint32_t width, uint32_t height) +{ + if (width == 0 || height == 0) { + return DMRect {0, 0, 0, 0}; + } + return DMRect {left, top, width, height}; +} + +void DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(bool isEnable) +{ + isWaterfallAreaCompressionEnableWhenHorizontal_ = isEnable; +} + +void DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(uint32_t size) +{ + waterfallAreaCompressionSizeWhenHorizontal_ = size; +} + +bool DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal() +{ + return isWaterfallDisplay_ && isWaterfallAreaCompressionEnableWhenHorizontal_; +} + +uint32_t DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal() +{ + if (!isWaterfallDisplay_ || !isWaterfallAreaCompressionEnableWhenHorizontal_) { + WLOGFW("Not waterfall display or not enable waterfall compression"); + return NO_WATERFALL_DISPLAY_COMPRESSION_SIZE; + } + return waterfallAreaCompressionSizeWhenHorizontal_; +} +} // Rosen +} // OHOS diff --git a/window_manager/dmserver/src/display_dumper.cpp b/window_manager/dmserver/src/display_dumper.cpp new file mode 100644 index 0000000..38cd0b6 --- /dev/null +++ b/window_manager/dmserver/src/display_dumper.cpp @@ -0,0 +1,351 @@ +/* + * 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 "display_dumper.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayDumper"}; + + constexpr int SCREEN_NAME_MAX_LENGTH = 20; + const std::string ARG_DUMP_HELP = "-h"; + const std::string ARG_DUMP_ALL = "-a"; + const std::string ARG_DUMP_SCREEN = "-s"; + const std::string ARG_DUMP_DISPLAY = "-d"; +} + +DisplayDumper::DisplayDumper(const sptr& abstractDisplayController, + const sptr& abstractScreenController, std::recursive_mutex& mutex) + : abstractDisplayController_(abstractDisplayController), abstractScreenController_(abstractScreenController), + mutex_(mutex) +{ +} + +DMError DisplayDumper::Dump(int fd, const std::vector& args) const +{ + WLOGFI("Dump begin fd: %{public}d", fd); + if (fd < 0) { + return DMError::DM_ERROR_INVALID_PARAM; + } + (void) signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE crash + UniqueFd ufd = UniqueFd(fd); // auto close + fd = ufd.Get(); + std::vector params; + for (auto& arg : args) { + params.emplace_back(Str16ToStr8(arg)); + } + + std::string dumpInfo; + if (params.empty()) { + ShowHelpInfo(dumpInfo); + } else if (params.size() == 1 && params[0] == ARG_DUMP_HELP) { // 1: params num + ShowHelpInfo(dumpInfo); + } else { + DMError errCode = DumpInfo(params, dumpInfo); + if (errCode != DMError::DM_OK) { + ShowIllegalArgsInfo(dumpInfo, errCode); + } + } + int ret = dprintf(fd, "%s\n", dumpInfo.c_str()); + if (ret < 0) { + WLOGFE("dprintf error"); + return DMError::DM_ERROR_UNKNOWN; + } + WLOGFI("Dump end"); + return DMError::DM_OK; +} + +void DisplayDumper::ShowHelpInfo(std::string& dumpInfo) const +{ + dumpInfo.append("Usage:\n") + .append(" -h ") + .append("|help text for the tool\n") + .append(" -s -a ") + .append("|dump all screen information in the system\n") + .append(" -d -a ") + .append("|dump all display information in the system\n") + .append(" -s {screen id} ") + .append("|dump specified screen information\n") + .append(" -d {display id} ") + .append("|dump specified display information\n"); +} + +void DisplayDumper::ShowIllegalArgsInfo(std::string& dumpInfo, DMError errCode) const +{ + switch (errCode) { + case DMError::DM_ERROR_INVALID_PARAM: + dumpInfo.append("The arguments are illegal and you can enter '-h' for help."); + break; + case DMError::DM_ERROR_NULLPTR: + dumpInfo.append("The screen or display is invalid, ") + .append("you can enter '-s -a' or '-d -a' to get valid screen or display id."); + break; + default: + break; + } +} + +DMError DisplayDumper::DumpInfo(const std::vector& args, std::string& dumpInfo) const +{ + if (args.size() != 2) { // 2: params num + return DMError::DM_ERROR_INVALID_PARAM; + } + + if (args[0] == ARG_DUMP_SCREEN && args[1] == ARG_DUMP_ALL) { + return DumpAllScreenInfo(dumpInfo); + } else if (args[0] == ARG_DUMP_DISPLAY && args[1] == ARG_DUMP_ALL) { + return DumpAllDisplayInfo(dumpInfo); + } else if (args[0] == ARG_DUMP_SCREEN && IsValidDigitString(args[1])) { + ScreenId screenId = std::stoull(args[1]); + return DumpSpecifiedScreenInfo(screenId, dumpInfo); + } else if (args[0] == ARG_DUMP_DISPLAY && IsValidDigitString(args[1])) { + DisplayId displayId = std::stoull(args[1]); + return DumpSpecifiedDisplayInfo(displayId, dumpInfo); + } else { + return DMError::DM_ERROR_INVALID_PARAM; + } +} + +DMError DisplayDumper::DumpAllScreenInfo(std::string& dumpInfo) const +{ + std::map> screenGroups; + std::vector screenIds = abstractScreenController_->GetAllScreenIds(); + std::ostringstream oss; + oss << "--------------------------------------Free Screen" + << "--------------------------------------" + << std::endl; + oss << "ScreenName Type IsGroup DmsId RsId ActiveIdx VPR Rotation Orientation " + << "RequestOrientation NodeId IsMirrored MirrorNodeId" + << std::endl; + std::lock_guard lock(mutex_); + for (ScreenId screenId : screenIds) { + auto screen = abstractScreenController_->GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("screen is null"); + return DMError::DM_ERROR_NULLPTR; + } + if (SCREEN_ID_INVALID == screen->groupDmsId_ || screen->isScreenGroup_) { + GetScreenInfo(screen, oss); + } + if (screen->isScreenGroup_) { + auto screenGroup = abstractScreenController_->GetAbstractScreenGroup(screenId); + screenGroups.insert(std::make_pair(screenId, screenGroup)); + } + } + oss << "total screen num: " << screenIds.size() << std::endl; + dumpInfo.append(oss.str()); + for (auto it = screenGroups.begin(); it != screenGroups.end(); it++) { + DMError ret = DumpScreenInfo(it->second, dumpInfo); + if (ret != DMError::DM_OK) { + return ret; + } + } + return DMError::DM_OK; +} + +DMError DisplayDumper::DumpScreenInfo(const sptr& screenGroup, std::string& dumpInfo) const +{ + if (screenGroup == nullptr) { + WLOGFE("screenGroup is null"); + return DMError::DM_ERROR_NULLPTR; + } + std::ostringstream oss; + oss << "-------------------------------------ScreenGroup " << screenGroup->dmsId_ + << "-------------------------------------" + << std::endl; + oss << "ScreenName Type IsGroup DmsId RsId " + << "ActiveIdx VPR Rotation Orientation " + << "RequestOrientation NodeId IsMirrored MirrorNodeId" + << std::endl; + auto childrenScreen = screenGroup->GetChildren(); + for (auto screen : childrenScreen) { + GetScreenInfo(screen, oss); + } + dumpInfo.append(oss.str()); + return DMError::DM_OK; +} + +DMError DisplayDumper::DumpSpecifiedScreenInfo(ScreenId screenId, std::string& dumpInfo) const +{ + auto screen = abstractScreenController_->GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGFE("screen is null"); + return DMError::DM_ERROR_NULLPTR; + } + const std::string& screenName = screen->name_.size() <= SCREEN_NAME_MAX_LENGTH ? + screen->name_ : screen->name_.substr(0, SCREEN_NAME_MAX_LENGTH); + std::string isGroup = screen->isScreenGroup_ ? "true" : "false"; + std::string screenType = TransferTypeToString(screen->type_); + std::string isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false"; + NodeId nodeId = (screen->rsDisplayNode_ == nullptr) ? SCREEN_ID_INVALID : screen->rsDisplayNode_->GetId(); + std::ostringstream oss; + oss << "ScreenName: " << screenName << std::endl; + oss << "Type: " << screenType << std::endl; + oss << "IsGroup: " << isGroup << std::endl; + oss << "DmsId: " << screen->dmsId_ << std::endl; + oss << "RsId: " << screen->rsId_ << std::endl; + oss << "GroupDmsId: " << screen->groupDmsId_ << std::endl; + oss << "ActiveIdx: " << screen->activeIdx_ << std::endl; + oss << "VPR: " << screen->virtualPixelRatio_ << std::endl; + oss << "Rotation: " << static_cast(screen->rotation_) << std::endl; + oss << "Orientation: " << static_cast(screen->orientation_) << std::endl; + oss << "RequestOrientation: " << static_cast(screen->screenRequestedOrientation_) << std::endl; + oss << "NodeId: " << nodeId << std::endl; + oss << "IsMirrored: " << isMirrored << std::endl; + oss << "MirrorNodeId: " << screen->rSDisplayNodeConfig_.mirrorNodeId << std::endl; + dumpInfo.append(oss.str()); + return DMError::DM_OK; +} + +DMError DisplayDumper::DumpAllDisplayInfo(std::string& dumpInfo) const +{ + std::vector displayIds = abstractDisplayController_->GetAllDisplayIds(); + std::ostringstream oss; + oss << "--------------------------------------Display Info" + << "--------------------------------------" + << std::endl; + oss << "DisplayId ScreenId RefreshRate VPR Rotation Orientation FreezeFlag [ x y w h ]" + << std::endl; + std::lock_guard lock(mutex_); + for (DisplayId displayId : displayIds) { + auto display = abstractDisplayController_->GetAbstractDisplay(displayId); + if (display == nullptr) { + WLOGFE("display is null"); + return DMError::DM_ERROR_NULLPTR; + } + GetDisplayInfo(display, oss); + } + dumpInfo.append(oss.str()); + return DMError::DM_OK; +} + +DMError DisplayDumper::DumpSpecifiedDisplayInfo(DisplayId displayId, std::string& dumpInfo) const +{ + auto display = abstractDisplayController_->GetAbstractDisplay(displayId); + if (display == nullptr) { + WLOGFE("display is null"); + return DMError::DM_ERROR_NULLPTR; + } + std::ostringstream oss; + oss << "DisplayId: " << display->GetId() << std::endl; + oss << "ScreenId: " << display->GetAbstractScreenId() << std::endl; + oss << "RefreshRate: " << display->GetRefreshRate() << std::endl; + oss << "VPR: " << display->GetVirtualPixelRatio() << std::endl; + oss << "Rotation: " << static_cast(display->GetRotation()) << std::endl; + oss << "Orientation: " << static_cast(display->GetOrientation()) << std::endl; + oss << "FreezeFlag: " << static_cast(display->GetFreezeFlag()) << std::endl; + oss << "DisplayRect: " << "[ " + << display->GetOffsetX() << ", " << display->GetOffsetY() << ", " + << display->GetWidth() << ", " << display->GetHeight() << " ]" << std::endl; + dumpInfo.append(oss.str()); + return DMError::DM_OK; +} + +bool DisplayDumper::IsValidDigitString(const std::string& idStr) const +{ + if (idStr.empty()) { + return false; + } + for (char ch : idStr) { + if ((ch >= '0' && ch <= '9')) { + continue; + } + WLOGFE("invalid id"); + return false; + } + return true; +} + +std::string DisplayDumper::TransferTypeToString(ScreenType type) const +{ + std::string screenType; + switch (type) { + case ScreenType::REAL: + screenType = "REAL"; + break; + case ScreenType::VIRTUAL: + screenType = "VIRTUAL"; + break; + default: + screenType = "UNDEFINED"; + break; + } + return screenType; +} + +void DisplayDumper::GetScreenInfo(const sptr& screen, std::ostringstream& oss) const +{ + if (screen == nullptr) { + WLOGFE("screen is null"); + return; + } + const std::string& screenName = screen->name_.size() <= SCREEN_NAME_MAX_LENGTH ? + screen->name_ : screen->name_.substr(0, SCREEN_NAME_MAX_LENGTH); + std::string isGroup = screen->isScreenGroup_ ? "true" : "false"; + std::string screenType = TransferTypeToString(screen->type_); + std::string isMirrored = screen->rSDisplayNodeConfig_.isMirrored ? "true" : "false"; + NodeId nodeId = (screen->rsDisplayNode_ == nullptr) ? SCREEN_ID_INVALID : screen->rsDisplayNode_->GetId(); + // std::setw is used to set the output width and different width values are set to keep the format aligned. + oss << std::left << std::setw(21) << screenName + << std::left << std::setw(9) << screenType + << std::left << std::setw(8) << isGroup + << std::left << std::setw(6) << screen->dmsId_ + << std::left << std::setw(21) << screen->rsId_ + << std::left << std::setw(10) << screen->activeIdx_ + << std::left << std::setw(4) << screen->virtualPixelRatio_ + << std::left << std::setw(9) << static_cast(screen->rotation_) + << std::left << std::setw(12) << static_cast(screen->orientation_) + << std::left << std::setw(19) << static_cast(screen->screenRequestedOrientation_) + << std::left << std::setw(21) << nodeId + << std::left << std::setw(11) << isMirrored + << std::left << std::setw(13) << screen->rSDisplayNodeConfig_.mirrorNodeId + << std::endl; +} + +void DisplayDumper::GetDisplayInfo(const sptr& display, std::ostringstream& oss) const +{ + if (display == nullptr) { + WLOGFE("display is null"); + return; + } + // std::setw is used to set the output width and different width values are set to keep the format aligned. + oss << std::left << std::setw(10) << display->GetId() + << std::left << std::setw(9) << display->GetAbstractScreenId() + << std::left << std::setw(12) << display->GetRefreshRate() + << std::left << std::setw(4) << display->GetVirtualPixelRatio() + << std::left << std::setw(9) << static_cast(display->GetRotation()) + << std::left << std::setw(12) << static_cast(display->GetOrientation()) + << std::left << std::setw(11) << static_cast(display->GetFreezeFlag()) + << "[ " + << std::left << std::setw(5) << display->GetOffsetX() + << std::left << std::setw(5) << display->GetOffsetY() + << std::left << std::setw(5) << display->GetWidth() + << std::left << std::setw(5) << display->GetHeight() + << "]" + << std::endl; +} +} +} \ No newline at end of file diff --git a/window_manager/dmserver/src/display_manager_agent_controller.cpp b/window_manager/dmserver/src/display_manager_agent_controller.cpp new file mode 100644 index 0000000..52ac271 --- /dev/null +++ b/window_manager/dmserver/src/display_manager_agent_controller.cpp @@ -0,0 +1,193 @@ +/* + * 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 "display_manager_agent_controller.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerAgentController"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerAgentController) + +bool DisplayManagerAgentController::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + return dmAgentContainer_.RegisterAgent(displayManagerAgent, type); +} + +bool DisplayManagerAgentController::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + return dmAgentContainer_.UnregisterAgent(displayManagerAgent, type); +} + +bool DisplayManagerAgentController::NotifyDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) +{ + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_POWER_EVENT_LISTENER); + if (agents.empty()) { + return false; + } + WLOGFI("NotifyDisplayPowerEvent"); + for (auto& agent : agents) { + agent->NotifyDisplayPowerEvent(event, status); + } + return true; +} + +bool DisplayManagerAgentController::NotifyDisplayStateChanged(DisplayId id, DisplayState state) +{ + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_STATE_LISTENER); + if (agents.empty()) { + return false; + } + WLOGFI("NotifyDisplayStateChanged"); + for (auto& agent : agents) { + agent->NotifyDisplayStateChanged(id, state); + } + return true; +} + +void DisplayManagerAgentController::OnScreenConnect(sptr screenInfo) +{ + if (screenInfo == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("OnScreenConnect"); + for (auto& agent : agents) { + agent->OnScreenConnect(screenInfo); + } +} + +void DisplayManagerAgentController::OnScreenDisconnect(ScreenId screenId) +{ + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("OnScreenDisconnect"); + for (auto& agent : agents) { + agent->OnScreenDisconnect(screenId); + } +} + +void DisplayManagerAgentController::OnScreenChange(sptr screenInfo, ScreenChangeEvent screenChangeEvent) +{ + if (screenInfo == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("OnScreenChange"); + for (auto& agent : agents) { + agent->OnScreenChange(screenInfo, screenChangeEvent); + } +} + +void DisplayManagerAgentController::OnScreenGroupChange(const std::string& trigger, + const sptr& screenInfo, ScreenGroupChangeEvent groupEvent) +{ + if (screenInfo == nullptr) { + return; + } + std::vector> screenInfos; + screenInfos.push_back(screenInfo); + OnScreenGroupChange(trigger, screenInfos, groupEvent); +} + +void DisplayManagerAgentController::OnScreenGroupChange(const std::string& trigger, + const std::vector>& screenInfos, ScreenGroupChangeEvent groupEvent) +{ + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER); + std::vector> infos; + for (auto& screenInfo : screenInfos) { + if (screenInfo != nullptr) { + infos.emplace_back(screenInfo); + } + } + if (agents.empty() || infos.empty()) { + return; + } + for (auto& agent : agents) { + agent->OnScreenGroupChange(trigger, infos, groupEvent); + } +} + +void DisplayManagerAgentController::OnDisplayCreate(sptr displayInfo) +{ + if (displayInfo == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("OnDisplayCreate"); + for (auto& agent : agents) { + agent->OnDisplayCreate(displayInfo); + } +} + +void DisplayManagerAgentController::OnDisplayDestroy(DisplayId displayId) +{ + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("OnDisplayDestroy"); + for (auto& agent : agents) { + agent->OnDisplayDestroy(displayId); + } +} + +void DisplayManagerAgentController::OnDisplayChange( + sptr displayInfo, DisplayChangeEvent displayChangeEvent) +{ + if (displayInfo == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::DISPLAY_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("OnDisplayChange"); + for (auto& agent : agents) { + agent->OnDisplayChange(displayInfo, displayChangeEvent); + } +} + +void DisplayManagerAgentController::OnScreenshot(sptr info) +{ + if (info == nullptr) { + return; + } + auto agents = dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREENSHOT_EVENT_LISTENER); + if (agents.empty()) { + return; + } + WLOGFI("onScreenshot"); + for (auto& agent : agents) { + agent->OnScreenshot(info); + } +} +} +} \ No newline at end of file diff --git a/window_manager/dmserver/src/display_manager_config.cpp b/window_manager/dmserver/src/display_manager_config.cpp new file mode 100644 index 0000000..30afb6c --- /dev/null +++ b/window_manager/dmserver/src/display_manager_config.cpp @@ -0,0 +1,228 @@ +/* + * 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 "display_manager_config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config_policy_utils.h" +#include "window_manager_hilog.h" + + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerConfig"}; +} + +std::map DisplayManagerConfig::enableConfig_; +std::map> DisplayManagerConfig::intNumbersConfig_; +std::map DisplayManagerConfig::stringConfig_; + +std::vector DisplayManagerConfig::Split(std::string str, std::string pattern) +{ + std::vector result; + str += pattern; + int32_t length = static_cast(str.size()); + for (int32_t i = 0; i < length; i++) { + int32_t position = static_cast(str.find(pattern, i)); + if (position < length) { + std::string tmp = str.substr(i, position - i); + result.push_back(tmp); + i = position + static_cast(pattern.size()) - 1; + } + } + return result; +} + +bool inline DisplayManagerConfig::IsNumber(std::string str) +{ + for (int32_t i = 0; i < static_cast(str.size()); i++) { + if (str.at(i) < '0' || str.at(i) > '9') { + return false; + } + } + return true; +} + +std::string DisplayManagerConfig::GetConfigPath(const std::string& configFileName) +{ + char buf[PATH_MAX + 1]; + char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1); + char tmpPath[PATH_MAX + 1] = { 0 }; + if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) { + WLOGFI("[DmConfig] can not get customization config file"); + return "/system/" + configFileName; + } + return std::string(tmpPath); +} + +bool DisplayManagerConfig::LoadConfigXml() +{ + auto configFilePath = GetConfigPath("etc/window/resources/display_manager_config.xml"); + xmlDocPtr docPtr = nullptr; + { + std::lock_guard lock(mutex_); + docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS); + } + WLOGFI("[DmConfig] filePath: %{public}s", configFilePath.c_str()); + if (docPtr == nullptr) { + WLOGFE("[DmConfig] load xml error!"); + return false; + } + + xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); + if (rootPtr == nullptr || rootPtr->name == nullptr || + xmlStrcmp(rootPtr->name, reinterpret_cast("Configs"))) { + WLOGFE("[DmConfig] get root element failed!"); + xmlFreeDoc(docPtr); + return false; + } + + for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { + if (!IsValidNode(*curNodePtr)) { + WLOGFE("DmConfig]: invalid node!"); + continue; + } + + auto nodeName = curNodePtr->name; + if (!xmlStrcmp(nodeName, reinterpret_cast("isWaterfallDisplay")) || + !xmlStrcmp(nodeName, reinterpret_cast("isWaterfallAreaCompressionEnableWhenHorizontal"))) { + ReadEnableConfigInfo(curNodePtr); + continue; + } + if (!xmlStrcmp(nodeName, reinterpret_cast("dpi")) || + !xmlStrcmp(nodeName, reinterpret_cast("defaultDeviceRotationOffset")) || + !xmlStrcmp(nodeName, reinterpret_cast("cutoutArea")) || + !xmlStrcmp(nodeName, reinterpret_cast("curvedScreenBoundary")) || + !xmlStrcmp(nodeName, reinterpret_cast("waterfallAreaCompressionSizeWhenHorzontal")) || + !xmlStrcmp(nodeName, reinterpret_cast("buildInDefaultOrientation"))) { + ReadIntNumbersConfigInfo(curNodePtr); + continue; + } + if (!xmlStrcmp(nodeName, reinterpret_cast("defaultDisplayCutoutPath"))) { + ReadStringConfigInfo(curNodePtr); + continue; + } + } + xmlFreeDoc(docPtr); + return true; +} + +bool DisplayManagerConfig::IsValidNode(const xmlNode& currNode) +{ + if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) { + return false; + } + return true; +} + +void DisplayManagerConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode) +{ + xmlChar* context = xmlNodeGetContent(currNode); + if (context == nullptr) { + WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); + return; + } + + std::vector numbersVec; + std::string numbersStr = reinterpret_cast(context); + if (numbersStr.empty()) { + xmlFree(context); + return; + } + auto numbers = Split(numbersStr, " "); + for (auto& num : numbers) { + if (!IsNumber(num)) { + WLOGFE("[DmConfig] read number error: nodeName:(%{public}s)", currNode->name); + xmlFree(context); + return; + } + numbersVec.emplace_back(std::stoi(num)); + } + + std::string nodeName = reinterpret_cast(currNode->name); + intNumbersConfig_[nodeName] = numbersVec; + xmlFree(context); +} + +void DisplayManagerConfig::ReadEnableConfigInfo(const xmlNodePtr& currNode) +{ + xmlChar* enable = xmlGetProp(currNode, reinterpret_cast("enable")); + if (enable == nullptr) { + WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); + return; + } + + std::string nodeName = reinterpret_cast(currNode->name); + if (!xmlStrcmp(enable, reinterpret_cast("true"))) { + enableConfig_[nodeName] = true; + } else { + enableConfig_[nodeName] = false; + } + xmlFree(enable); +} + +void DisplayManagerConfig::ReadStringConfigInfo(const xmlNodePtr& currNode) +{ + xmlChar* context = xmlNodeGetContent(currNode); + if (context == nullptr) { + WLOGFE("[DmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); + return; + } + + std::string inputString = reinterpret_cast(context); + std::string nodeName = reinterpret_cast(currNode->name); + stringConfig_[nodeName] = inputString; + xmlFree(context); +} + +const std::map& DisplayManagerConfig::GetEnableConfig() +{ + return enableConfig_; +} + +const std::map>& DisplayManagerConfig::GetIntNumbersConfig() +{ + return intNumbersConfig_; +} + +const std::map& DisplayManagerConfig::GetStringConfig() +{ + return stringConfig_; +} + +void DisplayManagerConfig::DumpConfig() +{ + for (auto& enable : enableConfig_) { + WLOGFI("[DmConfig] Enable: %{public}s %{public}u", enable.first.c_str(), enable.second); + } + for (auto& numbers : intNumbersConfig_) { + WLOGFI("[DmConfig] Numbers: %{public}s %{public}zu", numbers.first.c_str(), numbers.second.size()); + for (auto& num : numbers.second) { + WLOGFI("[DmConfig] Num: %{public}d", num); + } + } + for (auto& string : stringConfig_) { + WLOGFI("[DmConfig] String: %{public}s", string.first.c_str()); + } +} +} // namespace OHOS::Rosen diff --git a/window_manager/dmserver/src/display_manager_proxy.cpp b/window_manager/dmserver/src/display_manager_proxy.cpp new file mode 100644 index 0000000..561fdbd --- /dev/null +++ b/window_manager/dmserver/src/display_manager_proxy.cpp @@ -0,0 +1,1106 @@ +/* + * Copyright (c) 2021-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 "display_manager_proxy.h" + +#include +#include +#include + +#include "marshalling_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerProxy"}; +} + +sptr DisplayManagerProxy::GetDefaultDisplayInfo() +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetDefaultDisplayInfo: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetDefaultDisplayInfo: WriteInterfaceToken failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_DEFAULT_DISPLAY_INFO), + data, reply, option) != ERR_NONE) { + WLOGFW("GetDefaultDisplayInfo: SendRequest failed"); + return nullptr; + } + sptr info = reply.ReadParcelable(); + if (info == nullptr) { + WLOGFW("DisplayManagerProxy::GetDefaultDisplayInfo SendRequest nullptr."); + } + return info; +} + +sptr DisplayManagerProxy::GetDisplayInfoById(DisplayId displayId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetDisplayInfoById: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetDisplayInfoById: WriteInterfaceToken failed"); + return nullptr; + } + if (!data.WriteUint64(displayId)) { + WLOGFW("GetDisplayInfoById: WriteUint64 displayId failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_DISPLAY_BY_ID), + data, reply, option) != ERR_NONE) { + WLOGFW("GetDisplayInfoById: SendRequest failed"); + return nullptr; + } + + sptr info = reply.ReadParcelable(); + if (info == nullptr) { + WLOGFW("DisplayManagerProxy::GetDisplayInfoById SendRequest nullptr."); + return nullptr; + } + return info; +} + +sptr DisplayManagerProxy::GetDisplayInfoByScreen(ScreenId screenId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFE("fail to get displayInfo by screenId: remote is null"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("fail to get displayInfo by screenId: WriteInterfaceToken failed"); + return nullptr; + } + if (!data.WriteUint64(screenId)) { + WLOGFW("fail to get displayInfo by screenId: WriteUint64 displayId failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_DISPLAY_BY_SCREEN), + data, reply, option) != ERR_NONE) { + WLOGFW("fail to get displayInfo by screenId: SendRequest failed"); + return nullptr; + } + + sptr info = reply.ReadParcelable(); + if (info == nullptr) { + WLOGFW("fail to get displayInfo by screenId: SendRequest null"); + return nullptr; + } + return info; +} + +ScreenId DisplayManagerProxy::CreateVirtualScreen(VirtualScreenOption virtualOption, + const sptr& displayManagerAgent) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("CreateVirtualScreen: remote is nullptr"); + return SCREEN_ID_INVALID; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("CreateVirtualScreen: WriteInterfaceToken failed"); + return SCREEN_ID_INVALID; + } + bool res = data.WriteString(virtualOption.name_) && data.WriteUint32(virtualOption.width_) && + data.WriteUint32(virtualOption.height_) && data.WriteFloat(virtualOption.density_) && + data.WriteInt32(virtualOption.flags_) && data.WriteBool(virtualOption.isForShot_); + if (virtualOption.surface_ != nullptr && virtualOption.surface_->GetProducer() != nullptr) { + res = res && + data.WriteBool(true) && + data.WriteRemoteObject(virtualOption.surface_->GetProducer()->AsObject()); + } else { + WLOGFW("CreateVirtualScreen: surface is nullptr"); + res = res && data.WriteBool(false); + } + if (displayManagerAgent != nullptr) { + res = res && + data.WriteRemoteObject(displayManagerAgent); + } + if (!res) { + WLOGFE("Write data failed"); + return SCREEN_ID_INVALID; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_CREATE_VIRTUAL_SCREEN), + data, reply, option) != ERR_NONE) { + WLOGFW("CreateVirtualScreen: SendRequest failed"); + return SCREEN_ID_INVALID; + } + + ScreenId screenId = static_cast(reply.ReadUint64()); + WLOGFI("CreateVirtualScreen %" PRIu64"", screenId); + return screenId; +} + +DMError DisplayManagerProxy::DestroyVirtualScreen(ScreenId screenId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DestroyVirtualScreen: remote is nullptr"); + return DMError::DM_ERROR_REMOTE_CREATE_FAILED; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("DestroyVirtualScreen: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("DestroyVirtualScreen: WriteUint64 screenId failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_DESTROY_VIRTUAL_SCREEN), + data, reply, option) != ERR_NONE) { + WLOGFW("DestroyVirtualScreen: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +DMError DisplayManagerProxy::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SetVirtualScreenSurface: remote is nullptr"); + return DMError::DM_ERROR_REMOTE_CREATE_FAILED; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SetVirtualScreenSurface: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + bool res = data.WriteUint64(static_cast(screenId)); + if (surface != nullptr && surface->GetProducer() != nullptr) { + res = res && + data.WriteBool(true) && + data.WriteRemoteObject(surface->GetProducer()->AsObject()); + } else { + WLOGFW("SetVirtualScreenSurface: surface is nullptr"); + res = res && data.WriteBool(false); + } + if (!res) { + WLOGFW("SetVirtualScreenSurface: Write screenId/surface failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE), + data, reply, option) != ERR_NONE) { + WLOGFW("SetVirtualScreenSurface: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +bool DisplayManagerProxy::SetOrientation(ScreenId screenId, Orientation orientation) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("fail to set orientation: remote is null"); + return false; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("fail to set orientation: WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("fail to set orientation: Write screenId failed"); + return false; + } + if (!data.WriteUint32(static_cast(orientation))) { + WLOGFW("fail to set orientation: Write orientation failed"); + return false; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_ORIENTATION), + data, reply, option) != ERR_NONE) { + WLOGFW("fail to set orientation: SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +std::shared_ptr DisplayManagerProxy::GetDisplaySnapshot(DisplayId displayId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetDisplaySnapshot: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetDisplaySnapshot: WriteInterfaceToken failed"); + return nullptr; + } + + if (!data.WriteUint64(displayId)) { + WLOGFE("Write displayId failed"); + return nullptr; + } + + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_DISPLAY_SNAPSHOT), + data, reply, option) != ERR_NONE) { + WLOGFW("GetDisplaySnapshot: SendRequest failed"); + return nullptr; + } + + std::shared_ptr pixelMap(reply.ReadParcelable()); + if (pixelMap == nullptr) { + WLOGFW("DisplayManagerProxy::GetDisplaySnapshot SendRequest nullptr."); + return nullptr; + } + return pixelMap; +} + +DMError DisplayManagerProxy::GetScreenSupportedColorGamuts(ScreenId screenId, + std::vector& colorGamuts) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DisplayManagerProxy::GetScreenSupportedColorGamuts: remote is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFW("DisplayManagerProxy::GetScreenSupportedColorGamuts: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("DisplayManagerProxy::GetScreenSupportedColorGamuts: WriteUint64 screenId failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_GET_SUPPORTED_COLOR_GAMUTS), + data, reply, option) != ERR_NONE) { + WLOGFW("DisplayManagerProxy::GetScreenSupportedColorGamuts: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + DMError ret = static_cast(reply.ReadInt32()); + if (ret != DMError::DM_OK) { + return ret; + } + MarshallingHelper::UnmarshallingVectorObj(reply, colorGamuts, + [](Parcel& parcel, ScreenColorGamut& color) { + uint32_t value; + bool res = parcel.ReadUint32(value); + color = static_cast(value); + return res; + } + ); + return ret; +} + +DMError DisplayManagerProxy::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DisplayManagerProxy::GetScreenColorGamut: remote is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFW("DisplayManagerProxy::GetScreenColorGamut: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("DisplayManagerProxy::GetScreenColorGamut: WriteUint64 uint64_t failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_GET_COLOR_GAMUT), + data, reply, option) != ERR_NONE) { + WLOGFW("DisplayManagerProxy::GetScreenColorGamut: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + DMError ret = static_cast(reply.ReadInt32()); + if (ret != DMError::DM_OK) { + return ret; + } + colorGamut = static_cast(reply.ReadUint32()); + return ret; +} + +DMError DisplayManagerProxy::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DisplayManagerProxy::SetScreenColorGamut: remote is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFW("DisplayManagerProxy::SetScreenColorGamut: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId)) || !data.WriteInt32(colorGamutIdx)) { + WLOGFW("DisplayManagerProxy::SetScreenColorGamut: Write failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_SET_COLOR_GAMUT), + data, reply, option) != ERR_NONE) { + WLOGFW("DisplayManagerProxy::SetScreenColorGamut: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +DMError DisplayManagerProxy::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DisplayManagerProxy::GetScreenGamutMap: remote is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFW("DisplayManagerProxy::GetScreenGamutMap: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("DisplayManagerProxy::GetScreenGamutMap: WriteUint64 screenId failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_GET_GAMUT_MAP), + data, reply, option) != ERR_NONE) { + WLOGFW("DisplayManagerProxy::GetScreenGamutMap: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + DMError ret = static_cast(reply.ReadInt32()); + if (ret != DMError::DM_OK) { + return ret; + } + gamutMap = static_cast(reply.ReadUint32()); + return ret; +} + +DMError DisplayManagerProxy::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DisplayManagerProxy::SetScreenGamutMap: remote is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFW("DisplayManagerProxy::SetScreenGamutMap: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId)) || !data.WriteUint32(static_cast(gamutMap))) { + WLOGFW("DisplayManagerProxy::SetScreenGamutMap: Writ failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_SET_GAMUT_MAP), + data, reply, option) != ERR_NONE) { + WLOGFW("DisplayManagerProxy::SetScreenGamutMap: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +DMError DisplayManagerProxy::SetScreenColorTransform(ScreenId screenId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("DisplayManagerProxy::SetScreenColorTransform: remote is nullptr"); + return DMError::DM_ERROR_NULLPTR; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFW("DisplayManagerProxy::SetScreenColorTransform: WriteInterfaceToken failed"); + return DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED; + } + if (!data.WriteUint64(static_cast(screenId))) { + WLOGFW("DisplayManagerProxy::SetScreenColorTransform: WriteUint64 screenId failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_SET_COLOR_TRANSFORM), + data, reply, option) != ERR_NONE) { + WLOGFW("DisplayManagerProxy::SetScreenColorTransform: SendRequest failed"); + return DMError::DM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +bool DisplayManagerProxy::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + + if (!data.WriteRemoteObject(displayManagerAgent->AsObject())) { + WLOGFE("Write IDisplayManagerAgent failed"); + return false; + } + + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write DisplayManagerAgent type failed"); + return false; + } + + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_REGISTER_DISPLAY_MANAGER_AGENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + + if (!data.WriteRemoteObject(displayManagerAgent->AsObject())) { + WLOGFE("Write IWindowManagerAgent failed"); + return false; + } + + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write DisplayManagerAgent type failed"); + return false; + } + + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_UNREGISTER_DISPLAY_MANAGER_AGENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::WakeUpBegin(PowerStateChangeReason reason) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint32(static_cast(reason))) { + WLOGFE("Write PowerStateChangeReason failed"); + return false; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_WAKE_UP_BEGIN), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::WakeUpEnd() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_WAKE_UP_END), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::SuspendBegin(PowerStateChangeReason reason) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint32(static_cast(reason))) { + WLOGFE("Write PowerStateChangeReason failed"); + return false; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SUSPEND_BEGIN), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::SuspendEnd() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SUSPEND_END), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint32(static_cast(state))) { + WLOGFE("Write ScreenPowerState failed"); + return false; + } + if (!data.WriteUint32(static_cast(reason))) { + WLOGFE("Write PowerStateChangeReason failed"); + return false; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_SCREEN_POWER_FOR_ALL), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +ScreenPowerState DisplayManagerProxy::GetScreenPower(ScreenId dmsScreenId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return ScreenPowerState::INVALID_STATE; + } + if (!data.WriteUint64(static_cast(dmsScreenId))) { + WLOGFE("Write dmsScreenId failed"); + return ScreenPowerState::INVALID_STATE; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_SCREEN_POWER), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return ScreenPowerState::INVALID_STATE; + } + return static_cast(reply.ReadUint32()); +} + +bool DisplayManagerProxy::SetDisplayState(DisplayState state) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint32(static_cast(state))) { + WLOGFE("Write DisplayState failed"); + return false; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_DISPLAY_STATE), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +DisplayState DisplayManagerProxy::GetDisplayState(DisplayId displayId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return DisplayState::UNKNOWN; + } + if (!data.WriteUint64(displayId)) { + WLOGFE("Write displayId failed"); + return DisplayState::UNKNOWN; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_DISPLAY_STATE), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return DisplayState::UNKNOWN; + } + return static_cast(reply.ReadUint32()); +} + +std::vector DisplayManagerProxy::GetAllDisplayIds() +{ + std::vector allDisplayIds; + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return allDisplayIds; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_ALL_DISPLAYIDS), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return allDisplayIds; + } + reply.ReadUInt64Vector(&allDisplayIds); + return allDisplayIds; +} + +sptr DisplayManagerProxy::GetCutoutInfo(DisplayId displayId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetCutoutInfo: remote is null"); + return nullptr; + } + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetCutoutInfo: GetCutoutInfo failed"); + return nullptr; + } + if (!data.WriteUint64(displayId)) { + WLOGFE("GetCutoutInfo: write displayId failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_CUTOUT_INFO), + data, reply, option) != ERR_NONE) { + WLOGFW("GetCutoutInfo: GetCutoutInfo failed"); + return nullptr; + } + sptr info = reply.ReadParcelable(); + return info; +} + +DMError DisplayManagerProxy::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return DMError::DM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint64(displayId)) { + return DMError::DM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_HAS_PRIVATE_WINDOW), + data, reply, option) != ERR_NONE) { + return DMError::DM_ERROR_IPC_FAILED; + } + DMError ret = static_cast(reply.ReadInt32()); + hasPrivateWindow = reply.ReadBool(); + return ret; +} + +void DisplayManagerProxy::NotifyDisplayEvent(DisplayEvent event) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint32(static_cast(event))) { + WLOGFE("Write DisplayEvent failed"); + return; + } + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_NOTIFY_DISPLAY_EVENT), + data, reply, option) != ERR_NONE) { + WLOGFW("SendRequest failed"); + return; + } +} + +bool DisplayManagerProxy::SetFreeze(std::vector displayIds, bool isFreeze) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUInt64Vector(displayIds)) { + WLOGFE("set freeze fail: write displayId failed."); + return false; + } + if (!data.WriteBool(isFreeze)) { + WLOGFE("set freeze fail: write freeze flag failed."); + return false; + } + + if (Remote()->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_FREEZE_EVENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return false; + } + return true; +} + +ScreenId DisplayManagerProxy::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("create mirror fail: remote is null"); + return SCREEN_ID_INVALID; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("create mirror fail: WriteInterfaceToken failed"); + return SCREEN_ID_INVALID; + } + bool res = data.WriteUint64(static_cast(mainScreenId)) && + data.WriteUInt64Vector(mirrorScreenId); + if (!res) { + WLOGFE("create mirror fail: data write failed"); + return SCREEN_ID_INVALID; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_MIRROR), + data, reply, option) != ERR_NONE) { + WLOGFW("create mirror fail: SendRequest failed"); + return SCREEN_ID_INVALID; + } + return static_cast(reply.ReadUint64()); +} + +sptr DisplayManagerProxy::GetScreenInfoById(ScreenId screenId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetScreenInfoById: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetScreenInfoById: WriteInterfaceToken failed"); + return nullptr; + } + if (!data.WriteUint64(screenId)) { + WLOGFE("GetScreenInfoById: Write screenId failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_SCREEN_INFO_BY_ID), + data, reply, option) != ERR_NONE) { + WLOGFW("GetScreenInfoById: SendRequest failed"); + return nullptr; + } + + sptr info = reply.ReadStrongParcelable(); + if (info == nullptr) { + WLOGFW("GetScreenInfoById SendRequest nullptr."); + return nullptr; + } + for (auto& mode : info->GetModes()) { + WLOGFI("info modes is width: %{public}u, height: %{public}u, refreshRate: %{public}u", + mode->width_, mode->height_, mode->refreshRate_); + } + return info; +} + +sptr DisplayManagerProxy::GetScreenGroupInfoById(ScreenId screenId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetScreenGroupInfoById: remote is nullptr"); + return nullptr; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetScreenGroupInfoById: WriteInterfaceToken failed"); + return nullptr; + } + if (!data.WriteUint64(screenId)) { + WLOGFE("GetScreenGroupInfoById: Write screenId failed"); + return nullptr; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_SCREEN_GROUP_INFO_BY_ID), + data, reply, option) != ERR_NONE) { + WLOGFW("GetScreenGroupInfoById: SendRequest failed"); + return nullptr; + } + + sptr info = reply.ReadStrongParcelable(); + if (info == nullptr) { + WLOGFW("GetScreenGroupInfoById SendRequest nullptr."); + return nullptr; + } + return info; +} + +std::vector> DisplayManagerProxy::GetAllScreenInfos() +{ + std::vector> screenInfos; + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("GetAllScreenInfos: remote is nullptr"); + return screenInfos; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("GetAllScreenInfos: WriteInterfaceToken failed"); + return screenInfos; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_GET_ALL_SCREEN_INFOS), + data, reply, option) != ERR_NONE) { + WLOGFW("GetAllScreenInfos: SendRequest failed"); + return screenInfos; + } + + MarshallingHelper::UnmarshallingVectorParcelableObj(reply, screenInfos); + return screenInfos; +} + +ScreenId DisplayManagerProxy::MakeExpand(std::vector screenId, std::vector startPoint) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("MakeExpand: remote is null"); + return SCREEN_ID_INVALID; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("MakeExpand: WriteInterfaceToken failed"); + return SCREEN_ID_INVALID; + } + if (!data.WriteUInt64Vector(screenId)) { + WLOGFE("MakeExpand: write screenId failed"); + return SCREEN_ID_INVALID; + } + if (!MarshallingHelper::MarshallingVectorObj(data, startPoint, [](Parcel& parcel, const Point& point) { + return parcel.WriteInt32(point.posX_) && parcel.WriteInt32(point.posY_); + })) { + WLOGFE("MakeExpand: write startPoint failed"); + return SCREEN_ID_INVALID; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_EXPAND), + data, reply, option) != ERR_NONE) { + WLOGFE("MakeExpand: SendRequest failed"); + return SCREEN_ID_INVALID; + } + return static_cast(reply.ReadUint64()); +} + +void DisplayManagerProxy::RemoveVirtualScreenFromGroup(std::vector screens) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("cancel make mirror or expand fail: remote is null"); + return; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("cancel make mirror or expand fail: WriteInterfaceToken failed"); + return; + } + bool res = data.WriteUInt64Vector(screens); + if (!res) { + WLOGFE("cancel make mirror or expand fail: write screens failed."); + return; + } + if (remote->SendRequest(static_cast( + DisplayManagerMessage::TRANS_ID_REMOVE_VIRTUAL_SCREEN_FROM_SCREEN_GROUP), + data, reply, option) != ERR_NONE) { + WLOGFW("cancel make mirror or expand fail: SendRequest failed"); + } +} + +bool DisplayManagerProxy::SetScreenActiveMode(ScreenId screenId, uint32_t modeId) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SetScreenActiveMode: remote is null"); + return false; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SetScreenActiveMode: WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint64(screenId) || !data.WriteUint32(modeId)) { + WLOGFE("SetScreenActiveMode: write screenId/modeId failed"); + return false; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_SCREEN_ACTIVE_MODE), + data, reply, option) != ERR_NONE) { + WLOGFE("SetScreenActiveMode: SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SetVirtualPixelRatio: remote is null"); + return false; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SetVirtualPixelRatio: WriteInterfaceToken failed"); + return false; + } + if (!data.WriteUint64(screenId) || !data.WriteFloat(virtualPixelRatio)) { + WLOGFE("SetVirtualPixelRatio: write screenId/modeId failed"); + return false; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_PIXEL_RATIO), + data, reply, option) != ERR_NONE) { + WLOGFE("SetVirtualPixelRatio: SendRequest failed"); + return false; + } + return reply.ReadBool(); +} + +bool DisplayManagerProxy::IsScreenRotationLocked() +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("IsScreenRotationLocked: remote is nullptr"); + return false; + } + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("IsScreenRotationLocked: WriteInterfaceToken failed"); + return false; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_IS_SCREEN_ROTATION_LOCKED), + data, reply, option) != ERR_NONE) { + WLOGFW("IsScreenRotationLocked: SendRequest failed"); + return false; + } + bool isLocked = reply.ReadBool(); + return isLocked; +} + +void DisplayManagerProxy::SetScreenRotationLocked(bool isLocked) +{ + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFW("SetScreenRotationLocked: remote is null"); + return; + } + + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("SetScreenRotationLocked: WriteInterfaceToken failed"); + return; + } + if (!data.WriteBool(isLocked)) { + WLOGFE("SetScreenRotationLocked: write isLocked failed"); + return; + } + if (remote->SendRequest(static_cast(DisplayManagerMessage::TRANS_ID_SET_SCREEN_ROTATION_LOCKED), + data, reply, option) != ERR_NONE) { + WLOGFE("SetScreenRotationLocked: SendRequest failed"); + return; + } +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dmserver/src/display_manager_service.cpp b/window_manager/dmserver/src/display_manager_service.cpp new file mode 100644 index 0000000..b038d1f --- /dev/null +++ b/window_manager/dmserver/src/display_manager_service.cpp @@ -0,0 +1,709 @@ +/* + * Copyright (c) 2021-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 "display_manager_service.h" + +#include +#include +#include +#include +#include + +#include "display_manager_agent_controller.h" +#include "display_manager_config.h" +#include "dm_common.h" +#include "parameters.h" +#include "permission.h" +#include "sensor_connector.h" +#include "transaction/rs_interfaces.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerService"}; + const std::string SCREEN_CAPTURE_PERMISSION = "ohos.permission.CAPTURE_SCREEN"; +} +WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerService) +const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&SingletonContainer::Get()); + +#define CHECK_SCREEN_AND_RETURN(ret) \ + do { \ + if (screenId == SCREEN_ID_INVALID) { \ + WLOGFE("screenId invalid"); \ + return ret; \ + } \ + } while (false) + +DisplayManagerService::DisplayManagerService() : SystemAbility(DISPLAY_MANAGER_SERVICE_SA_ID, true), + abstractDisplayController_(new AbstractDisplayController(mutex_, + std::bind(&DisplayManagerService::NotifyDisplayStateChange, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4))), + abstractScreenController_(new AbstractScreenController(mutex_)), + displayPowerController_(new DisplayPowerController(mutex_, + std::bind(&DisplayManagerService::NotifyDisplayStateChange, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4))), + displayCutoutController_(new DisplayCutoutController()), + isAutoRotationOpen_(OHOS::system::GetParameter( + "persist.display.ar.enabled", "1") == "1") // autoRotation default enabled +{ +} + +int DisplayManagerService::Dump(int fd, const std::vector& args) +{ + if (displayDumper_ == nullptr) { + displayDumper_ = new DisplayDumper(abstractDisplayController_, abstractScreenController_, mutex_); + } + return static_cast(displayDumper_->Dump(fd, args)); +} + +void DisplayManagerService::OnStart() +{ + WLOGFI("start"); + if (!Init()) { + WLOGFE("Init failed"); + return; + } + + if (!Publish(this)) { + WLOGFE("Publish failed"); + } + WLOGFI("end"); +} + +bool DisplayManagerService::Init() +{ + WLOGFI("DisplayManagerService::Init start"); + if (DisplayManagerConfig::LoadConfigXml()) { + DisplayManagerConfig::DumpConfig(); + ConfigureDisplayManagerService(); + } + abstractScreenController_->Init(); + abstractDisplayController_->Init(abstractScreenController_); + WLOGFI("DisplayManagerService::Init success"); + return true; +} + +void DisplayManagerService::ConfigureDisplayManagerService() +{ + auto numbersConfig = DisplayManagerConfig::GetIntNumbersConfig(); + auto enableConfig = DisplayManagerConfig::GetEnableConfig(); + auto stringConfig = DisplayManagerConfig::GetStringConfig(); + if (numbersConfig.count("defaultDeviceRotationOffset") != 0) { + uint32_t defaultDeviceRotationOffset = static_cast(numbersConfig["defaultDeviceRotationOffset"][0]); + ScreenRotationController::SetDefaultDeviceRotationOffset(defaultDeviceRotationOffset); + } + if (enableConfig.count("isWaterfallDisplay") != 0) { + displayCutoutController_->SetIsWaterfallDisplay( + static_cast(enableConfig["isWaterfallDisplay"])); + } + if (numbersConfig.count("curvedScreenBoundary") != 0) { + displayCutoutController_->SetCurvedScreenBoundary( + static_cast>(numbersConfig["curvedScreenBoundary"])); + } + if (stringConfig.count("defaultDisplayCutoutPath") != 0) { + displayCutoutController_->SetBuiltInDisplayCutoutSvgPath( + static_cast(stringConfig["defaultDisplayCutoutPath"])); + } + ConfigureWaterfallDisplayCompressionParams(); + if (numbersConfig.count("buildInDefaultOrientation") != 0) { + Orientation orientation = static_cast(numbersConfig["buildInDefaultOrientation"][0]); + abstractScreenController_->SetBuildInDefaultOrientation(orientation); + } +} + +void DisplayManagerService::ConfigureWaterfallDisplayCompressionParams() +{ + auto numbersConfig = DisplayManagerConfig::GetIntNumbersConfig(); + auto enableConfig = DisplayManagerConfig::GetEnableConfig(); + if (enableConfig.count("isWaterfallAreaCompressionEnableWhenHorizontal") != 0) { + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal( + static_cast(enableConfig["isWaterfallAreaCompressionEnableWhenHorizontal"])); + } + if (numbersConfig.count("waterfallAreaCompressionSizeWhenHorzontal") != 0) { + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal( + static_cast(numbersConfig["waterfallAreaCompressionSizeWhenHorzontal"][0])); + } +} + +void DisplayManagerService::RegisterDisplayChangeListener(sptr listener) +{ + displayChangeListener_ = listener; + WLOGFI("IDisplayChangeListener registered"); +} + +void DisplayManagerService::RegisterWindowInfoQueriedListener(const sptr& listener) +{ + windowInfoQueriedListener_ = listener; +} + +DMError DisplayManagerService::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("check has private window permission denied!"); + return DMError::DM_ERROR_INVALID_PERMISSION; + } + std::vector displayIds = GetAllDisplayIds(); + auto iter = std::find(displayIds.begin(), displayIds.end(), displayId); + if (iter == displayIds.end()) { + WLOGFE("invalid displayId"); + return DMError::DM_ERROR_INVALID_PARAM; + } + if (windowInfoQueriedListener_ != nullptr) { + windowInfoQueriedListener_->HasPrivateWindow(displayId, hasPrivateWindow); + return DMError::DM_OK; + } + return DMError::DM_ERROR_NULLPTR; +} + +void DisplayManagerService::NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) +{ + DisplayId id = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId(); + WLOGFI("DisplayId %{public}" PRIu64"", id); + if (displayChangeListener_ != nullptr) { + displayChangeListener_->OnDisplayStateChange(defaultDisplayId, displayInfo, displayInfoMap, type); + } +} + +void DisplayManagerService::NotifyScreenshot(DisplayId displayId) +{ + if (displayChangeListener_ != nullptr) { + displayChangeListener_->OnScreenshot(displayId); + } +} + +sptr DisplayManagerService::GetDefaultDisplayInfo() +{ + ScreenId dmsScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); + WLOGFD("GetDefaultDisplayInfo %{public}" PRIu64"", dmsScreenId); + sptr display = abstractDisplayController_->GetAbstractDisplayByScreen(dmsScreenId); + if (display == nullptr) { + WLOGFE("fail to get displayInfo by id: invalid display"); + return nullptr; + } + return display->ConvertToDisplayInfo(); +} + +sptr DisplayManagerService::GetDisplayInfoById(DisplayId displayId) +{ + sptr display = abstractDisplayController_->GetAbstractDisplay(displayId); + if (display == nullptr) { + WLOGFE("fail to get displayInfo by id: invalid display"); + return nullptr; + } + return display->ConvertToDisplayInfo(); +} + +sptr DisplayManagerService::GetDisplayInfoByScreen(ScreenId screenId) +{ + sptr display = abstractDisplayController_->GetAbstractDisplayByScreen(screenId); + if (display == nullptr) { + WLOGFE("fail to get displayInfo by screenId: invalid display"); + return nullptr; + } + return display->ConvertToDisplayInfo(); +} + +ScreenId DisplayManagerService::CreateVirtualScreen(VirtualScreenOption option, + const sptr& displayManagerAgent) +{ + if (displayManagerAgent == nullptr) { + WLOGFE("displayManagerAgent invalid"); + return SCREEN_ID_INVALID; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:CreateVirtualScreen(%s)", option.name_.c_str()); + if (option.surface_ != nullptr && !Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION) && + !Permission::IsStartByHdcd()) { + WLOGFE("permission denied"); + return SCREEN_ID_INVALID; + } + ScreenId screenId = abstractScreenController_->CreateVirtualScreen(option, displayManagerAgent); + CHECK_SCREEN_AND_RETURN(SCREEN_ID_INVALID); + accessTokenIdMaps_.insert(std::pair(screenId, IPCSkeleton::GetCallingTokenID())); + return screenId; +} + +DMError DisplayManagerService::DestroyVirtualScreen(ScreenId screenId) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("destory virtual screen permission denied!"); + return DMError::DM_ERROR_INVALID_PERMISSION; + } + if (!accessTokenIdMaps_.isExistAndRemove(screenId, IPCSkeleton::GetCallingTokenID())) { + return DMError::DM_ERROR_INVALID_CALLING; + } + + WLOGFI("DestroyVirtualScreen::ScreenId: %{public}" PRIu64 "", screenId); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:DestroyVirtualScreen(%" PRIu64")", screenId); + return abstractScreenController_->DestroyVirtualScreen(screenId); +} + +DMError DisplayManagerService::SetVirtualScreenSurface(ScreenId screenId, sptr surface) +{ + WLOGFI("SetVirtualScreenSurface::ScreenId: %{public}" PRIu64 "", screenId); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + if (Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION) || + Permission::IsStartByHdcd()) { + return abstractScreenController_->SetVirtualScreenSurface(screenId, surface); + } + WLOGFE("permission denied"); + return DMError::DM_ERROR_INVALID_CALLING; +} + +bool DisplayManagerService::SetOrientation(ScreenId screenId, Orientation orientation) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set orientation permission denied!"); + return false; + } + if (orientation < Orientation::UNSPECIFIED || orientation > Orientation::REVERSE_HORIZONTAL) { + WLOGFE("SetOrientation::orientation: %{public}u", static_cast(orientation)); + return false; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetOrientation(%" PRIu64")", screenId); + return abstractScreenController_->SetOrientation(screenId, orientation, false); +} + +bool DisplayManagerService::SetOrientationFromWindow(ScreenId screenId, Orientation orientation) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetOrientationFromWindow(%" PRIu64")", screenId); + return abstractScreenController_->SetOrientation(screenId, orientation, true); +} + +bool DisplayManagerService::SetRotationFromWindow(ScreenId screenId, Rotation targetRotation) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetRotationFromWindow(%" PRIu64")", screenId); + return abstractScreenController_->SetRotation(screenId, targetRotation, true); +} + +std::shared_ptr DisplayManagerService::GetDisplaySnapshot(DisplayId displayId) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:GetDisplaySnapshot(%" PRIu64")", displayId); + if (Permission::CheckCallingPermission(SCREEN_CAPTURE_PERMISSION) || + Permission::IsStartByHdcd()) { + auto res = abstractDisplayController_->GetScreenSnapshot(displayId); + if (res != nullptr) { + NotifyScreenshot(displayId); + } + return res; + } + return nullptr; +} + +uint32_t DisplayManagerService::GetRSScreenNum() const +{ + return abstractScreenController_->GetRSScreenNum(); +} + +DMError DisplayManagerService::GetScreenSupportedColorGamuts(ScreenId screenId, + std::vector& colorGamuts) +{ + WLOGFI("GetScreenSupportedColorGamuts::ScreenId: %{public}" PRIu64 "", screenId); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + return abstractScreenController_->GetScreenSupportedColorGamuts(screenId, colorGamuts); +} + +DMError DisplayManagerService::GetScreenColorGamut(ScreenId screenId, ScreenColorGamut& colorGamut) +{ + WLOGFI("GetScreenColorGamut::ScreenId: %{public}" PRIu64 "", screenId); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + return abstractScreenController_->GetScreenColorGamut(screenId, colorGamut); +} + +DMError DisplayManagerService::SetScreenColorGamut(ScreenId screenId, int32_t colorGamutIdx) +{ + WLOGFI("SetScreenColorGamut::ScreenId: %{public}" PRIu64 ", colorGamutIdx %{public}d", screenId, colorGamutIdx); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + return abstractScreenController_->SetScreenColorGamut(screenId, colorGamutIdx); +} + +DMError DisplayManagerService::GetScreenGamutMap(ScreenId screenId, ScreenGamutMap& gamutMap) +{ + WLOGFI("GetScreenGamutMap::ScreenId: %{public}" PRIu64 "", screenId); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + return abstractScreenController_->GetScreenGamutMap(screenId, gamutMap); +} + +DMError DisplayManagerService::SetScreenGamutMap(ScreenId screenId, ScreenGamutMap gamutMap) +{ + WLOGFI("SetScreenGamutMap::ScreenId: %{public}" PRIu64 ", ScreenGamutMap %{public}u", + screenId, static_cast(gamutMap)); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + return abstractScreenController_->SetScreenGamutMap(screenId, gamutMap); +} + +DMError DisplayManagerService::SetScreenColorTransform(ScreenId screenId) +{ + WLOGFI("SetScreenColorTransform::ScreenId: %{public}" PRIu64 "", screenId); + CHECK_SCREEN_AND_RETURN(DMError::DM_ERROR_INVALID_PARAM); + return abstractScreenController_->SetScreenColorTransform(screenId); +} + +void DisplayManagerService::OnStop() +{ + WLOGFI("ready to stop display service."); +} + +bool DisplayManagerService::RegisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + if (type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER && !Permission::IsSystemCalling()) { + WLOGFE("register display manager agent permission denied!"); + return false; + } + if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { + WLOGFE("displayManagerAgent invalid"); + return false; + } + return DisplayManagerAgentController::GetInstance().RegisterDisplayManagerAgent(displayManagerAgent, type); +} + +bool DisplayManagerService::UnregisterDisplayManagerAgent(const sptr& displayManagerAgent, + DisplayManagerAgentType type) +{ + if (type == DisplayManagerAgentType::SCREEN_EVENT_LISTENER && !Permission::IsSystemCalling()) { + WLOGFE("unregister display manager agent permission denied!"); + return false; + } + if ((displayManagerAgent == nullptr) || (displayManagerAgent->AsObject() == nullptr)) { + WLOGFE("displayManagerAgent invalid"); + return false; + } + return DisplayManagerAgentController::GetInstance().UnregisterDisplayManagerAgent(displayManagerAgent, type); +} + +bool DisplayManagerService::WakeUpBegin(PowerStateChangeReason reason) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:WakeUpBegin(%u)", reason); + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("wake up begin permission denied!"); + return false; + } + return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::WAKE_UP, + EventStatus::BEGIN); +} + +bool DisplayManagerService::WakeUpEnd() +{ + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("wake up end permission denied!"); + return false; + } + return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::WAKE_UP, + EventStatus::END); +} + +bool DisplayManagerService::SuspendBegin(PowerStateChangeReason reason) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SuspendBegin(%u)", reason); + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("suspend begin permission denied!"); + return false; + } + displayPowerController_->SuspendBegin(reason); + return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::SLEEP, + EventStatus::BEGIN); +} + +bool DisplayManagerService::SuspendEnd() +{ + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("suspend end permission denied!"); + return false; + } + return DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::SLEEP, + EventStatus::END); +} + +bool DisplayManagerService::SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason) +{ + WLOGFI("SetScreenPowerForAll"); + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("set screen power for all permission denied!"); + return false; + } + return abstractScreenController_->SetScreenPowerForAll(state, reason); +} + +ScreenPowerState DisplayManagerService::GetScreenPower(ScreenId dmsScreenId) +{ + return abstractScreenController_->GetScreenPower(dmsScreenId); +} + +bool DisplayManagerService::SetDisplayState(DisplayState state) +{ + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("set display state permission denied!"); + return false; + } + ScreenId dmsScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); + sptr display = abstractDisplayController_->GetAbstractDisplayByScreen(dmsScreenId); + if (display != nullptr) { + display->SetDisplayState(state); + } + return displayPowerController_->SetDisplayState(state); +} + +ScreenId DisplayManagerService::GetScreenIdByDisplayId(DisplayId displayId) const +{ + sptr abstractDisplay = abstractDisplayController_->GetAbstractDisplay(displayId); + if (abstractDisplay == nullptr) { + WLOGFE("GetScreenIdByDisplayId: GetAbstractDisplay failed"); + return SCREEN_ID_INVALID; + } + return abstractDisplay->GetAbstractScreenId(); +} + +DisplayState DisplayManagerService::GetDisplayState(DisplayId displayId) +{ + std::lock_guard lock(mutex_); + return displayPowerController_->GetDisplayState(displayId); +} + +void DisplayManagerService::NotifyDisplayEvent(DisplayEvent event) +{ + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("notify display event permission denied!"); + return; + } + displayPowerController_->NotifyDisplayEvent(event); +} + +bool DisplayManagerService::SetFreeze(std::vector displayIds, bool isFreeze) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set freeze permission denied!"); + return false; + } + abstractDisplayController_->SetFreeze(displayIds, isFreeze); + return true; +} + +ScreenId DisplayManagerService::MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenIds) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("make mirror permission denied!"); + return SCREEN_ID_INVALID; + } + WLOGFI("MakeMirror. mainScreenId :%{public}" PRIu64"", mainScreenId); + auto allMirrorScreenIds = abstractScreenController_->GetAllValidScreenIds(mirrorScreenIds); + auto iter = std::find(allMirrorScreenIds.begin(), allMirrorScreenIds.end(), mainScreenId); + if (iter != allMirrorScreenIds.end()) { + allMirrorScreenIds.erase(iter); + } + auto mainScreen = abstractScreenController_->GetAbstractScreen(mainScreenId); + if (mainScreen == nullptr || allMirrorScreenIds.empty()) { + WLOGFI("create mirror fail. main screen :%{public}" PRIu64", screens' size:%{public}u", + mainScreenId, static_cast(allMirrorScreenIds.size())); + return SCREEN_ID_INVALID; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:MakeMirror"); + if (!abstractScreenController_->MakeMirror(mainScreenId, allMirrorScreenIds)) { + WLOGFE("make mirror failed."); + return SCREEN_ID_INVALID; + } + if (abstractScreenController_->GetAbstractScreenGroup(mainScreen->groupDmsId_) == nullptr) { + WLOGFE("get screen group failed."); + return SCREEN_ID_INVALID; + } + return mainScreen->groupDmsId_; +} + +void DisplayManagerService::RemoveVirtualScreenFromGroup(std::vector screens) +{ + abstractScreenController_->RemoveVirtualScreenFromGroup(screens); +} + +void DisplayManagerService::UpdateRSTree(DisplayId displayId, DisplayId parentDisplayId, + std::shared_ptr& surfaceNode, bool isAdd, bool isMultiDisplay) +{ + WLOGFI("UpdateRSTree, currentDisplayId: %{public}" PRIu64", isAdd: %{public}d, isMultiDisplay: %{public}d, " + "parentDisplayId: %{public}" PRIu64"", displayId, isAdd, isMultiDisplay, parentDisplayId); + ScreenId screenId = GetScreenIdByDisplayId(displayId); + ScreenId parentScreenId = GetScreenIdByDisplayId(parentDisplayId); + CHECK_SCREEN_AND_RETURN(); + + abstractScreenController_->UpdateRSTree(screenId, parentScreenId, surfaceNode, isAdd, isMultiDisplay); +} + +sptr DisplayManagerService::GetScreenInfoById(ScreenId screenId) +{ + auto screen = abstractScreenController_->GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGE("cannot find screenInfo: %{public}" PRIu64"", screenId); + return nullptr; + } + return screen->ConvertToScreenInfo(); +} + +sptr DisplayManagerService::GetScreenGroupInfoById(ScreenId screenId) +{ + auto screenGroup = abstractScreenController_->GetAbstractScreenGroup(screenId); + if (screenGroup == nullptr) { + WLOGE("cannot find screenGroupInfo: %{public}" PRIu64"", screenId); + return nullptr; + } + return screenGroup->ConvertToScreenGroupInfo(); +} + +ScreenId DisplayManagerService::GetScreenGroupIdByScreenId(ScreenId screenId) +{ + auto screen = abstractScreenController_->GetAbstractScreen(screenId); + if (screen == nullptr) { + WLOGE("cannot find screenInfo: %{public}" PRIu64"", screenId); + return SCREEN_ID_INVALID; + } + return screen->GetScreenGroupId(); +} + +std::vector DisplayManagerService::GetAllDisplayIds() +{ + return abstractDisplayController_->GetAllDisplayIds(); +} + +std::vector> DisplayManagerService::GetAllScreenInfos() +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("get all screen infos permission denied!"); + return std::vector>(); + } + std::vector screenIds = abstractScreenController_->GetAllScreenIds(); + std::vector> screenInfos; + for (auto screenId: screenIds) { + auto screenInfo = GetScreenInfoById(screenId); + if (screenInfo == nullptr) { + WLOGE("cannot find screenInfo: %{public}" PRIu64"", screenId); + continue; + } + screenInfos.emplace_back(screenInfo); + } + return screenInfos; +} + +ScreenId DisplayManagerService::MakeExpand(std::vector expandScreenIds, std::vector startPoints) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("make expand permission denied!"); + return SCREEN_ID_INVALID; + } + 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 SCREEN_ID_INVALID; + } + std::map pointsMap; + uint32_t size = expandScreenIds.size(); + for (uint32_t i = 0; i < size; i++) { + if (pointsMap.find(expandScreenIds[i]) != pointsMap.end()) { + continue; + } + pointsMap[expandScreenIds[i]] = startPoints[i]; + } + ScreenId defaultScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); + WLOGFI("MakeExpand, defaultScreenId:%{public}" PRIu64"", defaultScreenId); + auto allExpandScreenIds = abstractScreenController_->GetAllValidScreenIds(expandScreenIds); + auto iter = std::find(allExpandScreenIds.begin(), allExpandScreenIds.end(), defaultScreenId); + if (iter != allExpandScreenIds.end()) { + allExpandScreenIds.erase(iter); + } + if (allExpandScreenIds.empty()) { + WLOGFE("allExpandScreenIds is empty. make expand failed."); + return SCREEN_ID_INVALID; + } + std::shared_ptr rsDisplayNode; + std::vector points; + for (uint32_t i = 0; i < allExpandScreenIds.size(); i++) { + rsDisplayNode = abstractScreenController_->GetRSDisplayNodeByScreenId(allExpandScreenIds[i]); + points.emplace_back(pointsMap[allExpandScreenIds[i]]); + if (rsDisplayNode != nullptr) { + rsDisplayNode->SetDisplayOffset(pointsMap[allExpandScreenIds[i]].posX_, + pointsMap[allExpandScreenIds[i]].posY_); + } + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:MakeExpand"); + if (!abstractScreenController_->MakeExpand(allExpandScreenIds, points)) { + WLOGFE("make expand failed."); + return SCREEN_ID_INVALID; + } + 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) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set screen active permission denied!"); + return false; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetScreenActiveMode(%" PRIu64", %u)", screenId, modeId); + return abstractScreenController_->SetScreenActiveMode(screenId, modeId); +} + +bool DisplayManagerService::SetVirtualPixelRatio(ScreenId screenId, float virtualPixelRatio) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set virtual pixel permission denied!"); + return false; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "dms:SetVirtualPixelRatio(%" PRIu64", %f)", screenId, + virtualPixelRatio); + return abstractScreenController_->SetVirtualPixelRatio(screenId, virtualPixelRatio); +} + +bool DisplayManagerService::IsScreenRotationLocked() +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("is screen rotation locked permission denied!"); + return false; + } + return ScreenRotationController::IsScreenRotationLocked(); +} + +void DisplayManagerService::SetScreenRotationLocked(bool isLocked) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set screen rotation locked permission denied!"); + return; + } + ScreenRotationController::SetScreenRotationLocked(isLocked); +} + +void DisplayManagerService::SetGravitySensorSubscriptionEnabled() +{ + if (!isAutoRotationOpen_) { + WLOGFE("autoRotation is not open"); + ScreenRotationController::Init(); + return; + } + SensorConnector::SubscribeRotationSensor(); +} + +sptr DisplayManagerService::GetCutoutInfo(DisplayId displayId) +{ + return displayCutoutController_->GetCutoutInfo(displayId); +} + +void DisplayManagerService::RegisterRSScreenChangeListener(const sptr& listener) +{ + abstractScreenController_->RegisterRSScreenChangeListener(listener); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dmserver/src/display_manager_service_inner.cpp b/window_manager/dmserver/src/display_manager_service_inner.cpp new file mode 100644 index 0000000..96d0571 --- /dev/null +++ b/window_manager/dmserver/src/display_manager_service_inner.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021-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 "display_manager_service_inner.h" + +#include +#include + +#include "display_manager_service.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerServiceInner"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(DisplayManagerServiceInner) + +DisplayId DisplayManagerServiceInner::GetDefaultDisplayId() const +{ + auto defaultDisplayInfo = DisplayManagerService::GetInstance().GetDefaultDisplayInfo(); + if (defaultDisplayInfo == nullptr) { + WLOGFE("GetDefaultDisplayId, defaultDisplayInfo is nullptr."); + return DISPLAY_ID_INVALID; + } + return defaultDisplayInfo->GetDisplayId(); +} + +sptr DisplayManagerServiceInner::GetDisplayById(DisplayId displayId) const +{ + sptr display = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + if (display == nullptr) { + WLOGFE("GetDisplayById can not find corresponding display!\n"); + } + return display; +} + +sptr DisplayManagerServiceInner::GetDefaultDisplay() const +{ + return DisplayManagerService::GetInstance().GetDefaultDisplayInfo(); +} + +std::vector DisplayManagerServiceInner::GetAllDisplayIds() const +{ + return DisplayManagerService::GetInstance().GetAllDisplayIds(); +} + +void DisplayManagerServiceInner::RegisterWindowInfoQueriedListener(const sptr& listener) +{ + DisplayManagerService::GetInstance().RegisterWindowInfoQueriedListener(listener); +} + +std::vector> DisplayManagerServiceInner::GetAllDisplays() const +{ + std::vector> res; + auto displayIds = GetAllDisplayIds(); + for (auto displayId: displayIds) { + sptr display = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + if (display != nullptr) { + res.emplace_back(display); + } else { + WLOGFE("GetAllDisplays display %" PRIu64" nullptr!", displayId); + } + } + return res; +} + +void DisplayManagerServiceInner::UpdateRSTree(DisplayId displayId, DisplayId parentDisplayId, + std::shared_ptr& surfaceNode, bool isAdd, bool isMultiDisplay) +{ + DisplayManagerService::GetInstance().UpdateRSTree(displayId, parentDisplayId, surfaceNode, isAdd, isMultiDisplay); +} + +uint32_t DisplayManagerServiceInner::GetRSScreenNum() const +{ + return DisplayManagerService::GetInstance().GetRSScreenNum(); +} + +sptr DisplayManagerServiceInner::GetScreenInfoByDisplayId(DisplayId displayId) const +{ + auto displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + if (displayInfo == nullptr) { + WLOGFE("can not get display."); + return nullptr; + } + return DisplayManagerService::GetInstance().GetScreenInfoById(displayInfo->GetScreenId()); +} + +ScreenId DisplayManagerServiceInner::GetScreenGroupIdByDisplayId(DisplayId displayId) const +{ + auto displayInfo = DisplayManagerService::GetInstance().GetDisplayInfoById(displayId); + if (displayInfo == nullptr) { + WLOGFE("can not get display."); + return INVALID_SCREEN_ID; + } + return DisplayManagerService::GetInstance().GetScreenGroupIdByScreenId(displayInfo->GetScreenId()); +} + +sptr DisplayManagerServiceInner::GetScreenModesByDisplayId(DisplayId displayId) const +{ + const sptr screenInfo = GetScreenInfoByDisplayId(displayId); + if (screenInfo == nullptr) { + WLOGFE("can not get display."); + return nullptr; + } + auto modes = screenInfo->GetModes(); + auto id = screenInfo->GetModeId(); + if (id >= modes.size()) { + WLOGFE("can not get screenMode."); + return nullptr; + } + return modes[id]; +} + +std::shared_ptr DisplayManagerServiceInner::GetDisplaySnapshot(DisplayId displayId) const +{ + return DisplayManagerService::GetInstance().GetDisplaySnapshot(displayId); +} + +void DisplayManagerServiceInner::RegisterDisplayChangeListener(sptr listener) +{ + DisplayManagerService::GetInstance().RegisterDisplayChangeListener(listener); +} + +bool DisplayManagerServiceInner::SetOrientationFromWindow(DisplayId displayId, Orientation orientation) +{ + auto displayInfo = GetDisplayById(displayId); + if (displayInfo == nullptr) { + return false; + } + return DisplayManagerService::GetInstance(). + SetOrientationFromWindow(displayInfo->GetScreenId(), orientation); +} + +bool DisplayManagerServiceInner::SetRotationFromWindow(DisplayId displayId, Rotation targetRotation) +{ + auto displayInfo = GetDisplayById(displayId); + if (displayInfo == nullptr) { + return false; + } + return DisplayManagerService::GetInstance(). + SetRotationFromWindow(displayInfo->GetScreenId(), targetRotation); +} + +void DisplayManagerServiceInner::SetGravitySensorSubscriptionEnabled() +{ + DisplayManagerService::GetInstance().SetGravitySensorSubscriptionEnabled(); +} + +void DisplayManagerServiceInner::RegisterRSScreenChangeListener(const sptr& listener) +{ + DisplayManagerService::GetInstance().RegisterRSScreenChangeListener(listener); +} + +sptr DisplayManagerServiceInner::GetCutoutInfo(DisplayId displayId) const +{ + return DisplayManagerService::GetInstance().GetCutoutInfo(displayId); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dmserver/src/display_manager_stub.cpp b/window_manager/dmserver/src/display_manager_stub.cpp new file mode 100644 index 0000000..d110598 --- /dev/null +++ b/window_manager/dmserver/src/display_manager_stub.cpp @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2021-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 "display_manager_stub.h" + +#include "dm_common.h" + +#include + +#include "marshalling_helper.h" +#include "window_manager_hilog.h" + +#include "transaction/rs_interfaces.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerStub"}; +} + +int32_t DisplayManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + WLOGFD("OnRemoteRequest code is %{public}u", code); + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + DisplayManagerMessage msgId = static_cast(code); + switch (msgId) { + case DisplayManagerMessage::TRANS_ID_GET_DEFAULT_DISPLAY_INFO: { + auto info = GetDefaultDisplayInfo(); + reply.WriteParcelable(info); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_DISPLAY_BY_ID: { + DisplayId displayId = data.ReadUint64(); + auto info = GetDisplayInfoById(displayId); + reply.WriteParcelable(info); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_DISPLAY_BY_SCREEN: { + ScreenId screenId = data.ReadUint64(); + auto info = GetDisplayInfoByScreen(screenId); + reply.WriteParcelable(info); + break; + } + case DisplayManagerMessage::TRANS_ID_CREATE_VIRTUAL_SCREEN: { + std::string name = data.ReadString(); + uint32_t width = data.ReadUint32(); + uint32_t height = data.ReadUint32(); + float density = data.ReadFloat(); + int32_t flags = data.ReadInt32(); + bool isForShot = data.ReadBool(); + bool isSurfaceValid = data.ReadBool(); + sptr surface = nullptr; + if (isSurfaceValid) { + sptr surfaceObject = data.ReadRemoteObject(); + sptr bp = iface_cast(surfaceObject); + surface = Surface::CreateSurfaceAsProducer(bp); + } + sptr virtualScreenAgent = data.ReadRemoteObject(); + VirtualScreenOption option = { + .name_ = name, + .width_ = width, + .height_ = height, + .density_ = density, + .surface_ = surface, + .flags_ = flags, + .isForShot_ = isForShot + }; + ScreenId screenId = CreateVirtualScreen(option, virtualScreenAgent); + reply.WriteUint64(static_cast(screenId)); + break; + } + case DisplayManagerMessage::TRANS_ID_DESTROY_VIRTUAL_SCREEN: { + ScreenId screenId = static_cast(data.ReadUint64()); + DMError result = DestroyVirtualScreen(screenId); + reply.WriteInt32(static_cast(result)); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE: { + ScreenId screenId = static_cast(data.ReadUint64()); + bool isSurfaceValid = data.ReadBool(); + sptr surface = nullptr; + if (isSurfaceValid) { + sptr surfaceObject = data.ReadRemoteObject(); + sptr bp = iface_cast(surfaceObject); + surface = Surface::CreateSurfaceAsProducer(bp); + } + DMError result = SetVirtualScreenSurface(screenId, surface); + reply.WriteInt32(static_cast(result)); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_ORIENTATION: { + ScreenId screenId = static_cast(data.ReadUint64()); + Orientation orientation = static_cast(data.ReadUint32()); + reply.WriteBool(SetOrientation(screenId, orientation)); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_DISPLAY_SNAPSHOT: { + DisplayId displayId = data.ReadUint64(); + std::shared_ptr displaySnapshot = GetDisplaySnapshot(displayId); + reply.WriteParcelable(displaySnapshot == nullptr ? nullptr : displaySnapshot.get()); + break; + } + case DisplayManagerMessage::TRANS_ID_REGISTER_DISPLAY_MANAGER_AGENT: { + auto agent = iface_cast(data.ReadRemoteObject()); + auto type = static_cast(data.ReadUint32()); + reply.WriteBool(RegisterDisplayManagerAgent(agent, type)); + break; + } + case DisplayManagerMessage::TRANS_ID_UNREGISTER_DISPLAY_MANAGER_AGENT: { + auto agent = iface_cast(data.ReadRemoteObject()); + auto type = static_cast(data.ReadUint32()); + reply.WriteBool(UnregisterDisplayManagerAgent(agent, type)); + break; + } + case DisplayManagerMessage::TRANS_ID_WAKE_UP_BEGIN: { + PowerStateChangeReason reason = static_cast(data.ReadUint32()); + reply.WriteBool(WakeUpBegin(reason)); + break; + } + case DisplayManagerMessage::TRANS_ID_WAKE_UP_END: { + reply.WriteBool(WakeUpEnd()); + break; + } + case DisplayManagerMessage::TRANS_ID_SUSPEND_BEGIN: { + PowerStateChangeReason reason = static_cast(data.ReadUint32()); + reply.WriteBool(SuspendBegin(reason)); + break; + } + case DisplayManagerMessage::TRANS_ID_SUSPEND_END: { + reply.WriteBool(SuspendEnd()); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_SCREEN_POWER_FOR_ALL: { + ScreenPowerState state = static_cast(data.ReadUint32()); + PowerStateChangeReason reason = static_cast(data.ReadUint32()); + reply.WriteBool(SetScreenPowerForAll(state, reason)); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_SCREEN_POWER: { + ScreenId dmsScreenId; + if (!data.ReadUint64(dmsScreenId)) { + WLOGFE("fail to read dmsScreenId."); + break; + } + reply.WriteUint32(static_cast(GetScreenPower(dmsScreenId))); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_DISPLAY_STATE: { + DisplayState state = static_cast(data.ReadUint32()); + reply.WriteBool(SetDisplayState(state)); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_DISPLAY_STATE: { + DisplayState state = GetDisplayState(data.ReadUint64()); + reply.WriteUint32(static_cast(state)); + break; + } + case DisplayManagerMessage::TRANS_ID_NOTIFY_DISPLAY_EVENT: { + DisplayEvent event = static_cast(data.ReadUint32()); + NotifyDisplayEvent(event); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_FREEZE_EVENT: { + std::vector ids; + data.ReadUInt64Vector(&ids); + SetFreeze(ids, data.ReadBool()); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_MIRROR: { + ScreenId mainScreenId = static_cast(data.ReadUint64()); + std::vector mirrorScreenId; + if (!data.ReadUInt64Vector(&mirrorScreenId)) { + WLOGE("fail to receive mirror screen in stub. screen:%{public}" PRIu64"", mainScreenId); + break; + } + ScreenId result = MakeMirror(mainScreenId, mirrorScreenId); + reply.WriteUint64(static_cast(result)); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_SCREEN_INFO_BY_ID: { + ScreenId screenId = static_cast(data.ReadUint64()); + auto screenInfo = GetScreenInfoById(screenId); + reply.WriteStrongParcelable(screenInfo); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_SCREEN_GROUP_INFO_BY_ID: { + ScreenId screenId = static_cast(data.ReadUint64()); + auto screenGroupInfo = GetScreenGroupInfoById(screenId); + reply.WriteStrongParcelable(screenGroupInfo); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_ALL_SCREEN_INFOS: { + std::vector> screenInfos = GetAllScreenInfos(); + if (!MarshallingHelper::MarshallingVectorParcelableObj(reply, screenInfos)) { + WLOGE("fail to marshalling screenInfos in stub."); + } + break; + } + case DisplayManagerMessage::TRANS_ID_GET_ALL_DISPLAYIDS: { + std::vector allDisplayIds = GetAllDisplayIds(); + reply.WriteUInt64Vector(allDisplayIds); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_EXPAND: { + std::vector screenId; + if (!data.ReadUInt64Vector(&screenId)) { + WLOGE("fail to receive expand screen in stub."); + break; + } + std::vector startPoint; + if (!MarshallingHelper::UnmarshallingVectorObj(data, startPoint, [](Parcel& parcel, Point& point) { + return parcel.ReadInt32(point.posX_) && parcel.ReadInt32(point.posY_); + })) { + WLOGE("fail to receive startPoint in stub."); + break; + } + ScreenId result = MakeExpand(screenId, startPoint); + reply.WriteUint64(static_cast(result)); + break; + } + case DisplayManagerMessage::TRANS_ID_REMOVE_VIRTUAL_SCREEN_FROM_SCREEN_GROUP: { + std::vector screenId; + if (!data.ReadUInt64Vector(&screenId)) { + WLOGE("fail to receive screens in stub."); + break; + } + RemoveVirtualScreenFromGroup(screenId); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_SCREEN_ACTIVE_MODE: { + ScreenId screenId = static_cast(data.ReadUint64()); + uint32_t modeId = data.ReadUint32(); + bool res = SetScreenActiveMode(screenId, modeId); + reply.WriteBool(res); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_PIXEL_RATIO: { + ScreenId screenId = static_cast(data.ReadUint64()); + float virtualPixelRatio = data.ReadFloat(); + bool res = SetVirtualPixelRatio(screenId, virtualPixelRatio); + reply.WriteBool(res); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_GET_SUPPORTED_COLOR_GAMUTS: { + ScreenId screenId = static_cast(data.ReadUint64()); + std::vector colorGamuts; + DMError ret = GetScreenSupportedColorGamuts(screenId, colorGamuts); + reply.WriteInt32(static_cast(ret)); + if (ret != DMError::DM_OK) { + break; + } + MarshallingHelper::MarshallingVectorObj(reply, colorGamuts, + [](Parcel& parcel, const ScreenColorGamut& color) { + return parcel.WriteUint32(static_cast(color)); + } + ); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_GET_COLOR_GAMUT: { + ScreenId screenId = static_cast(data.ReadUint64()); + ScreenColorGamut colorGamut; + DMError ret = GetScreenColorGamut(screenId, colorGamut); + reply.WriteInt32(static_cast(ret)); + if (ret != DMError::DM_OK) { + break; + } + reply.WriteUint32(static_cast(colorGamut)); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_SET_COLOR_GAMUT: { + ScreenId screenId = static_cast(data.ReadUint64()); + int32_t colorGamutIdx = data.ReadInt32(); + DMError ret = SetScreenColorGamut(screenId, colorGamutIdx); + reply.WriteInt32(static_cast(ret)); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_GET_GAMUT_MAP: { + ScreenId screenId = static_cast(data.ReadUint64()); + ScreenGamutMap gamutMap; + DMError ret = GetScreenGamutMap(screenId, gamutMap); + reply.WriteInt32(static_cast(ret)); + if (ret != DMError::DM_OK) { + break; + } + reply.WriteInt32(static_cast(gamutMap)); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_SET_GAMUT_MAP: { + ScreenId screenId = static_cast(data.ReadUint64()); + ScreenGamutMap gamutMap = static_cast(data.ReadUint32()); + DMError ret = SetScreenGamutMap(screenId, gamutMap); + reply.WriteInt32(static_cast(ret)); + break; + } + case DisplayManagerMessage::TRANS_ID_SCREEN_SET_COLOR_TRANSFORM: { + ScreenId screenId = static_cast(data.ReadUint64()); + DMError ret = SetScreenColorTransform(screenId); + reply.WriteInt32(static_cast(ret)); + break; + } + case DisplayManagerMessage::TRANS_ID_IS_SCREEN_ROTATION_LOCKED: { + bool isLocked = IsScreenRotationLocked(); + reply.WriteBool(isLocked); + break; + } + case DisplayManagerMessage::TRANS_ID_SET_SCREEN_ROTATION_LOCKED: { + bool isLocked = static_cast(data.ReadBool()); + SetScreenRotationLocked(isLocked); + break; + } + case DisplayManagerMessage::TRANS_ID_HAS_PRIVATE_WINDOW: { + DisplayId id = static_cast(data.ReadUint64()); + bool hasPrivateWindow = false; + DMError ret = HasPrivateWindow(id, hasPrivateWindow); + reply.WriteInt32(static_cast(ret)); + reply.WriteBool(hasPrivateWindow); + break; + } + case DisplayManagerMessage::TRANS_ID_GET_CUTOUT_INFO: { + DisplayId displayId = static_cast(data.ReadUint64()); + sptr cutoutInfo = GetCutoutInfo(displayId); + reply.WriteParcelable(cutoutInfo); + break; + } + default: + WLOGFW("unknown transaction code"); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return 0; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/dmserver/src/display_power_controller.cpp b/window_manager/dmserver/src/display_power_controller.cpp new file mode 100644 index 0000000..b2cca50 --- /dev/null +++ b/window_manager/dmserver/src/display_power_controller.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021-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 "display_power_controller.h" +#include "display_manager_service.h" +#include "display_manager_agent_controller.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayPowerController"}; +} + +bool DisplayPowerController::SuspendBegin(PowerStateChangeReason reason) +{ + WLOGFI("reason:%{public}u", reason); + std::map> emptyMap; + displayStateChangeListener_(DISPLAY_ID_INVALID, nullptr, emptyMap, DisplayStateChangeType::BEFORE_SUSPEND); + return true; +} + +bool DisplayPowerController::SetDisplayState(DisplayState state) +{ + WLOGFI("state:%{public}u", state); + { + std::lock_guard lock(mutex_); + if (displayState_ == state) { + WLOGFE("state is already set"); + return false; + } + } + switch (state) { + case DisplayState::ON: { + bool isKeyguardDrawn; + { + std::lock_guard lock(mutex_); + displayState_ = state; + isKeyguardDrawn = isKeyguardDrawn_; + } + if (!isKeyguardDrawn) { + std::map> emptyMap; + displayStateChangeListener_(DISPLAY_ID_INVALID, nullptr, + emptyMap, DisplayStateChangeType::BEFORE_UNLOCK); + } + DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::DISPLAY_ON, + EventStatus::BEGIN); + break; + } + case DisplayState::OFF: { + { + std::lock_guard lock(mutex_); + displayState_ = state; + } + DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::DISPLAY_OFF, + EventStatus::BEGIN); + break; + } + default: { + WLOGFW("unknown DisplayState!"); + return false; + } + } + DisplayManagerAgentController::GetInstance().NotifyDisplayStateChanged(DISPLAY_ID_INVALID, state); + return true; +} + +DisplayState DisplayPowerController::GetDisplayState(DisplayId displayId) +{ + return displayState_; +} + +void DisplayPowerController::NotifyDisplayEvent(DisplayEvent event) +{ + WLOGFI("DisplayEvent:%{public}u", event); + if (event == DisplayEvent::UNLOCK) { + std::map> emptyMap; + displayStateChangeListener_(DISPLAY_ID_INVALID, nullptr, emptyMap, DisplayStateChangeType::BEFORE_UNLOCK); + DisplayManagerAgentController::GetInstance().NotifyDisplayPowerEvent(DisplayPowerEvent::DESKTOP_READY, + EventStatus::BEGIN); + std::lock_guard lock(mutex_); + isKeyguardDrawn_ = false; + return; + } + if (event == DisplayEvent::KEYGUARD_DRAWN) { + std::lock_guard lock(mutex_); + isKeyguardDrawn_ = true; + } +} +} +} \ No newline at end of file diff --git a/window_manager/dmserver/src/screen_rotation_controller.cpp b/window_manager/dmserver/src/screen_rotation_controller.cpp new file mode 100644 index 0000000..f9d24f4 --- /dev/null +++ b/window_manager/dmserver/src/screen_rotation_controller.cpp @@ -0,0 +1,437 @@ +/* + * 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 "screen_rotation_controller.h" + +#include +#include + +#include "display_manager_service_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenRotationController"}; +} + +DisplayId ScreenRotationController::defaultDisplayId_ = 0; +Rotation ScreenRotationController::currentDisplayRotation_; +bool ScreenRotationController::isScreenRotationLocked_ = true; +uint32_t ScreenRotationController::defaultDeviceRotationOffset_ = 0; +Orientation ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; +Rotation ScreenRotationController::lastSensorDecidedRotation_; +Rotation ScreenRotationController::rotationLockedRotation_; +uint32_t ScreenRotationController::defaultDeviceRotation_ = 0; +std::map ScreenRotationController::sensorToDeviceRotationMap_; +std::map ScreenRotationController::deviceToDisplayRotationMap_; +DeviceRotation ScreenRotationController::lastSensorRotationConverted_ = DeviceRotation::INVALID; + +void ScreenRotationController::Init() +{ + ProcessRotationMapping(); + currentDisplayRotation_ = GetCurrentDisplayRotation(); + lastSensorDecidedRotation_ = currentDisplayRotation_; + rotationLockedRotation_ = currentDisplayRotation_; +} + +bool ScreenRotationController::IsScreenRotationLocked() +{ + return isScreenRotationLocked_; +} + +void ScreenRotationController::SetScreenRotationLocked(bool isLocked) +{ + if (isLocked) { + rotationLockedRotation_ = GetCurrentDisplayRotation(); + } + isScreenRotationLocked_ = isLocked; +} + +void ScreenRotationController::SetDefaultDeviceRotationOffset(uint32_t defaultDeviceRotationOffset) +{ + // Available options for defaultDeviceRotationOffset: {0, 90, 180, 270} + if (defaultDeviceRotationOffset < 0 || defaultDeviceRotationOffset > 270 || defaultDeviceRotationOffset % 90 != 0) { + return; + } + defaultDeviceRotationOffset_ = defaultDeviceRotationOffset; +} + +void ScreenRotationController::HandleSensorEventInput(DeviceRotation deviceRotation) +{ + Orientation orientation = GetPreferredOrientation(); + + currentDisplayRotation_ = GetCurrentDisplayRotation(); + lastSensorRotationConverted_ = deviceRotation; + if (!IsSensorRelatedOrientation(orientation)) { + return; + } + if (deviceRotation == DeviceRotation::INVALID) { + return; + } + if (currentDisplayRotation_ == ConvertDeviceToDisplayRotation(deviceRotation)) { + return; + } + Rotation targetDisplayRotation = CalcTargetDisplayRotation(orientation, deviceRotation); + SetScreenRotation(targetDisplayRotation); +} + +Rotation ScreenRotationController::GetCurrentDisplayRotation() +{ + sptr defaultDisplayInfo = DisplayManagerServiceInner::GetInstance().GetDefaultDisplay(); + if (defaultDisplayInfo == nullptr) { + WLOGFE("Cannot get default display info"); + return defaultDeviceRotation_ == 0 ? ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT) : + ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE); + } + return defaultDisplayInfo->GetRotation(); +} + +Orientation ScreenRotationController::GetPreferredOrientation() +{ + sptr screenInfo = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(defaultDisplayId_); + if (screenInfo == nullptr) { + WLOGFE("Cannot get default screen info"); + return Orientation::UNSPECIFIED; + } + return screenInfo->GetOrientation(); +} + +Rotation ScreenRotationController::CalcTargetDisplayRotation( + Orientation requestedOrientation, DeviceRotation sensorRotationConverted) +{ + switch (requestedOrientation) { + case Orientation::SENSOR: { + lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted); + return ConvertDeviceToDisplayRotation(sensorRotationConverted); + } + case Orientation::SENSOR_VERTICAL: { + return ProcessAutoRotationPortraitOrientation(sensorRotationConverted); + } + case Orientation::SENSOR_HORIZONTAL: { + return ProcessAutoRotationLandscapeOrientation(sensorRotationConverted); + } + case Orientation::UNSPECIFIED: + case Orientation::AUTO_ROTATION_RESTRICTED: { + if (isScreenRotationLocked_) { + return currentDisplayRotation_; + } + lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted); + return ConvertDeviceToDisplayRotation(sensorRotationConverted); + } + case Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED: { + if (isScreenRotationLocked_) { + return currentDisplayRotation_; + } + return ProcessAutoRotationPortraitOrientation(sensorRotationConverted); + } + case Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED: { + if (isScreenRotationLocked_) { + return currentDisplayRotation_; + } + return ProcessAutoRotationLandscapeOrientation(sensorRotationConverted); + } + default: { + return currentDisplayRotation_; + } + } +} + +Rotation ScreenRotationController::ProcessAutoRotationPortraitOrientation(DeviceRotation sensorRotationConverted) +{ + if (IsDeviceRotationHorizontal(sensorRotationConverted)) { + return currentDisplayRotation_; + } + lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted); + return ConvertDeviceToDisplayRotation(sensorRotationConverted); +} + +Rotation ScreenRotationController::ProcessAutoRotationLandscapeOrientation(DeviceRotation sensorRotationConverted) +{ + if (IsDeviceRotationVertical(sensorRotationConverted)) { + return currentDisplayRotation_; + } + lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted); + return ConvertDeviceToDisplayRotation(sensorRotationConverted); +} + +void ScreenRotationController::SetScreenRotation(Rotation targetRotation) +{ + if (targetRotation == GetCurrentDisplayRotation()) { + return; + } + DisplayManagerServiceInner::GetInstance().GetDefaultDisplay()->SetRotation(targetRotation); + DisplayManagerServiceInner::GetInstance().SetRotationFromWindow(defaultDisplayId_, targetRotation); + WLOGFI("dms: Set screen rotation: %{public}u", targetRotation); +} + +DeviceRotation ScreenRotationController::CalcDeviceRotation(SensorRotation sensorRotation) +{ + if (sensorRotation == SensorRotation::INVALID) { + return DeviceRotation::INVALID; + } + // offset(in degree) divided by 90 to get rotation bias + int32_t bias = static_cast(defaultDeviceRotationOffset_ / 90); + int32_t deviceRotationValue = static_cast(sensorRotation) - bias; + while (deviceRotationValue < 0) { + // +4 is used to normalize the values into the range 0~3, corresponding to the four rotations. + deviceRotationValue += 4; + } + if (defaultDeviceRotation_ == 1) { + deviceRotationValue += static_cast(defaultDeviceRotation_); + // %2 to determine whether the rotation is horizontal or vertical. + if (deviceRotationValue % 2 == 0) { + // if device's default rotation is landscape, use -2 to swap 0 and 90, 180 and 270. + deviceRotationValue -= 2; + } + } + return static_cast(deviceRotationValue); +} + +bool ScreenRotationController::IsSensorRelatedOrientation(Orientation orientation) +{ + if ((orientation >= Orientation::UNSPECIFIED && orientation <= Orientation::REVERSE_HORIZONTAL) || + orientation == Orientation::LOCKED) { + return false; + } + return true; +} + +void ScreenRotationController::ProcessSwitchToSensorRelatedOrientation( + Orientation orientation, DeviceRotation sensorRotationConverted) +{ + lastOrientationType_ = orientation; + switch (orientation) { + case Orientation::AUTO_ROTATION_RESTRICTED: { + if (isScreenRotationLocked_) { + SetScreenRotation(rotationLockedRotation_); + return; + } + [[fallthrough]]; + } + case Orientation::SENSOR: { + ProcessSwitchToAutoRotation(sensorRotationConverted); + return; + } + case Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED: { + if (isScreenRotationLocked_) { + ProcessSwitchToAutoRotationPortraitRestricted(); + return; + } + [[fallthrough]]; + } + case Orientation::SENSOR_VERTICAL: { + ProcessSwitchToAutoRotationPortrait(sensorRotationConverted); + return; + } + case Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED: { + if (isScreenRotationLocked_) { + ProcessSwitchToAutoRotationLandscapeRestricted(); + return; + } + [[fallthrough]]; + } + case Orientation::SENSOR_HORIZONTAL: { + ProcessSwitchToAutoRotationLandscape(sensorRotationConverted); + return; + } + default: { + return; + } + } +} + +void ScreenRotationController::ProcessSwitchToAutoRotation(DeviceRotation rotation) +{ + if (rotation != DeviceRotation::INVALID) { + return; + } +} + +void ScreenRotationController::ProcessSwitchToAutoRotationPortrait(DeviceRotation rotation) +{ + if (IsCurrentDisplayVertical()) { + return; + } + if (IsDeviceRotationVertical(rotation)) { + return; + } + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)); +} + +void ScreenRotationController::ProcessSwitchToAutoRotationLandscape(DeviceRotation rotation) +{ + if (IsCurrentDisplayHorizontal()) { + return; + } + if (IsDeviceRotationHorizontal(rotation)) { + return; + } + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)); +} + +void ScreenRotationController::ProcessSwitchToAutoRotationPortraitRestricted() +{ + if (IsCurrentDisplayVertical()) { + return; + } + if (IsDisplayRotationVertical(rotationLockedRotation_)) { + SetScreenRotation(rotationLockedRotation_); + return; + } + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)); +} + +void ScreenRotationController::ProcessSwitchToAutoRotationLandscapeRestricted() +{ + if (IsCurrentDisplayHorizontal()) { + return; + } + if (IsDisplayRotationHorizontal(rotationLockedRotation_)) { + SetScreenRotation(rotationLockedRotation_); + return; + } + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)); +} + +DeviceRotation ScreenRotationController::ConvertSensorToDeviceRotation(SensorRotation sensorRotation) +{ + if (sensorToDeviceRotationMap_.empty()) { + ProcessRotationMapping(); + } + return sensorToDeviceRotationMap_.at(sensorRotation); +} + +Rotation ScreenRotationController::ConvertDeviceToDisplayRotation(DeviceRotation deviceRotation) +{ + if (deviceRotation == DeviceRotation::INVALID) { + return GetCurrentDisplayRotation(); + } + if (deviceToDisplayRotationMap_.empty()) { + ProcessRotationMapping(); + } + return deviceToDisplayRotationMap_.at(deviceRotation); +} + +void ScreenRotationController::ProcessRotationMapping() +{ + sptr modes = + DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(defaultDisplayId_); + // 0 means PORTRAIT, 1 means LANDSCAPE. + defaultDeviceRotation_ = modes->width_ < modes->height_ ? 0 : 1; + if (deviceToDisplayRotationMap_.empty()) { + deviceToDisplayRotationMap_ = { + {DeviceRotation::ROTATION_PORTRAIT, + defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90}, + {DeviceRotation::ROTATION_LANDSCAPE, + defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90}, + {DeviceRotation::ROTATION_PORTRAIT_INVERTED, + defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270}, + {DeviceRotation::ROTATION_LANDSCAPE_INVERTED, + defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270}, + }; + } + if (sensorToDeviceRotationMap_.empty()) { + sensorToDeviceRotationMap_ = { + {SensorRotation::ROTATION_0, CalcDeviceRotation(SensorRotation::ROTATION_0)}, + {SensorRotation::ROTATION_90, CalcDeviceRotation(SensorRotation::ROTATION_90)}, + {SensorRotation::ROTATION_180, CalcDeviceRotation(SensorRotation::ROTATION_180)}, + {SensorRotation::ROTATION_270, CalcDeviceRotation(SensorRotation::ROTATION_270)}, + {SensorRotation::INVALID, DeviceRotation::INVALID}, + }; + } +} + +bool ScreenRotationController::IsDeviceRotationVertical(DeviceRotation deviceRotation) +{ + return (deviceRotation == DeviceRotation::ROTATION_PORTRAIT) || + (deviceRotation == DeviceRotation::ROTATION_PORTRAIT_INVERTED); +} + +bool ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation deviceRotation) +{ + return (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE) || + (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE_INVERTED); +} + +bool ScreenRotationController::IsCurrentDisplayVertical() +{ + return IsDisplayRotationVertical(GetCurrentDisplayRotation()); +} + +bool ScreenRotationController::IsCurrentDisplayHorizontal() +{ + return IsDisplayRotationHorizontal(GetCurrentDisplayRotation()); +} + +bool ScreenRotationController::IsDefaultDisplayRotationPortrait() +{ + return Rotation::ROTATION_0 == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT); +} + +bool ScreenRotationController::IsDisplayRotationVertical(Rotation rotation) +{ + return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)) || + (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED)); +} + +bool ScreenRotationController::IsDisplayRotationHorizontal(Rotation rotation) +{ + return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)) || + (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED)); +} + +void ScreenRotationController::ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation) +{ + if (lastOrientationType_ == orientation) { + return; + } + lastOrientationType_ = orientation; + switch (orientation) { + case Orientation::UNSPECIFIED: { + SetScreenRotation(Rotation::ROTATION_0); + break; + } + case Orientation::VERTICAL: { + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)); + break; + } + case Orientation::REVERSE_VERTICAL: { + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED)); + break; + } + case Orientation::HORIZONTAL: { + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)); + break; + } + case Orientation::REVERSE_HORIZONTAL: { + SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED)); + break; + } + default: { + return; + } + } +} + +void ScreenRotationController::ProcessOrientationSwitch(Orientation orientation) +{ + if (!IsSensorRelatedOrientation(orientation)) { + ProcessSwitchToSensorUnrelatedOrientation(orientation); + } else { + ProcessSwitchToSensorRelatedOrientation(orientation, lastSensorRotationConverted_); + } +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/dmserver/src/sensor_connector.cpp b/window_manager/dmserver/src/sensor_connector.cpp new file mode 100644 index 0000000..aa551fb --- /dev/null +++ b/window_manager/dmserver/src/sensor_connector.cpp @@ -0,0 +1,237 @@ +/* + * 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 "sensor_connector.h" + +#include +#include + +#include "display_manager_service_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SensorConnector"}; + constexpr int64_t ORIENTATION_SENSOR_SAMPLING_RATE = 200000000; // 200ms + constexpr int64_t ORIENTATION_SENSOR_REPORTING_RATE = 0; + constexpr long ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL = 200; // 200ms + constexpr int VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT = 3; +#ifdef WM_SUBSCRIBE_MOTION_ENABLE + constexpr int32_t MOTION_ACTION_PORTRAIT = 0; + constexpr int32_t MOTION_ACTION_LEFT_LANDSCAPE = 1; + constexpr int32_t MOTION_ACTION_PORTRAIT_INVERTED = 2; + constexpr int32_t MOTION_ACTION_RIGHT_LANDSCAPE = 3; +#endif +} + +bool GravitySensorSubscriber::isGravitySensorSubscribed_ = false; +SensorUser GravitySensorSubscriber::user_; +long GravitySensorSubscriber::lastCallbackTime_ = 0; + +#ifdef WM_SUBSCRIBE_MOTION_ENABLE +bool MotionSubscriber::isMotionSensorSubscribed_ = false; +sptr MotionSubscriber::motionEventCallback_ = nullptr; +#endif + +void SensorConnector::SubscribeRotationSensor() +{ + WLOGFI("dms: subscribe rotation-related sensor"); + ScreenRotationController::Init(); +#ifdef WM_SUBSCRIBE_MOTION_ENABLE + MotionSubscriber::SubscribeMotionSensor(); + if (MotionSubscriber::isMotionSensorSubscribed_) { + return; + } +#endif + GravitySensorSubscriber::SubscribeGravitySensor(); +} + +void SensorConnector::UnsubscribeRotationSensor() +{ +#ifdef WM_SUBSCRIBE_MOTION_ENABLE + MotionSubscriber::UnsubscribeMotionSensor(); +#endif + GravitySensorSubscriber::UnsubscribeGravitySensor(); +} + +// Gravity Sensor +void GravitySensorSubscriber::SubscribeGravitySensor() +{ + WLOGFI("dms: Subscribe gravity Sensor"); + if (isGravitySensorSubscribed_) { + WLOGFE("dms: gravity sensor's already subscribed"); + return; + } + if (strcpy_s(user_.name, sizeof(user_.name), "ScreenRotationController") != EOK) { + WLOGFE("dms strcpy_s error"); + return; + } + user_.userData = nullptr; + user_.callback = &HandleGravitySensorEventCallback; + if (SubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) { + WLOGFE("dms: Subscribe gravity sensor failed"); + return; + } + SetBatch(SENSOR_TYPE_ID_GRAVITY, &user_, ORIENTATION_SENSOR_SAMPLING_RATE, ORIENTATION_SENSOR_REPORTING_RATE); + SetMode(SENSOR_TYPE_ID_GRAVITY, &user_, SENSOR_ON_CHANGE); + if (ActivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) { + WLOGFE("dms: Activate gravity sensor failed"); + return; + } + isGravitySensorSubscribed_ = true; +} + +void GravitySensorSubscriber::UnsubscribeGravitySensor() +{ + WLOGFI("dms: Unsubscribe gravity Sensor"); + if (!isGravitySensorSubscribed_) { + WLOGFE("dms: Orientation Sensor is not subscribed"); + return; + } + if (DeactivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) { + WLOGFE("dms: Deactivate gravity sensor failed"); + return; + } + if (UnsubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) { + WLOGFE("dms: Unsubscribe gravity sensor failed"); + return; + } + isGravitySensorSubscribed_ = false; +} + +void GravitySensorSubscriber::HandleGravitySensorEventCallback(SensorEvent *event) +{ + if (!CheckCallbackTimeInterval()) { + return; + } + if (event->sensorTypeId != SENSOR_TYPE_ID_GRAVITY) { + WLOGE("dms: Orientation Sensor Callback is not SENSOR_TYPE_ID_GRAVITY"); + return; + } + GravityData* gravityData = reinterpret_cast(event->data); + int sensorDegree = CalcRotationDegree(gravityData); + DeviceRotation sensorRotationConverted = ScreenRotationController::ConvertSensorToDeviceRotation( + CalcSensorRotation(sensorDegree)); + ScreenRotationController::HandleSensorEventInput(sensorRotationConverted); +} + +SensorRotation GravitySensorSubscriber::CalcSensorRotation(int sensorDegree) +{ + // Use ROTATION_0 when degree range is [0, 30]∪[330, 359] + if (sensorDegree >= 0 && (sensorDegree <= 30 || sensorDegree >= 330)) { + return SensorRotation::ROTATION_0; + } else if (sensorDegree >= 60 && sensorDegree <= 120) { // Use ROTATION_90 when degree range is [60, 120] + return SensorRotation::ROTATION_90; + } else if (sensorDegree >= 150 && sensorDegree <= 210) { // Use ROTATION_180 when degree range is [150, 210] + return SensorRotation::ROTATION_180; + } else if (sensorDegree >= 240 && sensorDegree <= 300) { // Use ROTATION_270 when degree range is [240, 300] + return SensorRotation::ROTATION_270; + } else { + return SensorRotation::INVALID; + } +} + +int GravitySensorSubscriber::CalcRotationDegree(GravityData* gravityData) +{ + float x = gravityData->x; + float y = gravityData->y; + float z = gravityData->z; + int degree = -1; + if ((x * x + y * y) * VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT < z * z) { + return degree; + } + // arccotx = pi / 2 - arctanx, 90 is used to calculate acot(in degree); degree = rad / pi * 180 + degree = 90 - static_cast(round(atan2(y, -x) / M_PI * 180)); + // Normalize the degree to the range of 0~360 + return degree >= 0 ? degree % 360 : degree % 360 + 360; +} + +bool GravitySensorSubscriber::CheckCallbackTimeInterval() +{ + std::chrono::milliseconds ms = std::chrono::time_point_cast( + std::chrono::steady_clock::now()).time_since_epoch(); + long currentTimeInMillitm = ms.count(); + if (currentTimeInMillitm - lastCallbackTime_ < ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL) { + return false; + } + lastCallbackTime_ = currentTimeInMillitm; + return true; +} + +// Motion +#ifdef WM_SUBSCRIBE_MOTION_ENABLE +void MotionSubscriber::SubscribeMotionSensor() +{ + WLOGFI("dms: Subscribe motion Sensor"); + if (isMotionSensorSubscribed_) { + WLOGFE("dms: motion sensor's already subscribed"); + return; + } + sptr callback = new (std::nothrow) RotationMotionEventCallback(); + int32_t ret = OHOS::Msdp::SubscribeCallback(OHOS::Msdp::TYPE_ROTATION, callback); + if (ret != 0) { + return; + } + motionEventCallback_ = callback; + isMotionSensorSubscribed_ = true; +} + +void MotionSubscriber::UnsubscribeMotionSensor() +{ + if (!isMotionSensorSubscribed_) { + WLOGFI("dms: Unsubscribe motion sensor"); + return; + } + int32_t ret = OHOS::Msdp::UnsubscribeCallback(OHOS::Msdp::TYPE_ROTATION, motionEventCallback_); + if (ret != 0) { + return; + } + isMotionSensorSubscribed_ = false; +} + +void RotationMotionEventCallback::OnMotionChanged(const MotionData& motionData) +{ + if (motionData.result != 1) { + return; + } + DeviceRotation motionRotation = DeviceRotation::INVALID; + switch (motionData.rotateAction) { + case MOTION_ACTION_PORTRAIT: { + motionRotation = DeviceRotation::ROTATION_PORTRAIT; + break; + } + case MOTION_ACTION_LEFT_LANDSCAPE: { + motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ? + DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE; + break; + } + case MOTION_ACTION_PORTRAIT_INVERTED: { + motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED; + break; + } + case MOTION_ACTION_RIGHT_LANDSCAPE: { + motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ? + DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED; + break; + } + default: { + break; + } + } + ScreenRotationController::HandleSensorEventInput(motionRotation); +} +#endif +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/dmserver/test/BUILD.gn b/window_manager/dmserver/test/BUILD.gn new file mode 100644 index 0000000..a29ddb1 --- /dev/null +++ b/window_manager/dmserver/test/BUILD.gn @@ -0,0 +1,17 @@ +# 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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/dmserver/test/unittest/BUILD.gn b/window_manager/dmserver/test/unittest/BUILD.gn new file mode 100644 index 0000000..f0ae3a0 --- /dev/null +++ b/window_manager/dmserver/test/unittest/BUILD.gn @@ -0,0 +1,192 @@ +# 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. + +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +module_out_path = "window_manager/dmserver" + +group("unittest") { + testonly = true + + deps = [ + ":dmserver_abstract_display_controller_test", + ":dmserver_abstract_display_test", + ":dmserver_abstract_screen_controller_test", + ":dmserver_abstract_screen_test", + ":dmserver_display_cutout_controller_test", + ":dmserver_display_dumper_test", + ":dmserver_display_manager_agent_controller_test", + ":dmserver_display_manager_config_test", + ":dmserver_display_manager_proxy_test", + ":dmserver_display_manager_service_test", + ":dmserver_screen_rotation_controller_test", + ] +} + +ohos_unittest("dmserver_abstract_screen_controller_test") { + module_out_path = module_out_path + + sources = [ "abstract_screen_controller_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_display_manager_agent_controller_test") { + module_out_path = module_out_path + + sources = [ "display_manager_agent_controller_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_abstract_display_test") { + module_out_path = module_out_path + + sources = [ "abstract_display_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_display_manager_service_test") { + module_out_path = module_out_path + + sources = [ "display_manager_service_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_display_manager_proxy_test") { + module_out_path = module_out_path + + sources = [ "display_manager_proxy_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] + + external_deps = [ "graphic_standard:surface" ] +} + +ohos_unittest("dmserver_screen_rotation_controller_test") { + module_out_path = module_out_path + + sources = [ "screen_rotation_controller_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] + + if (window_manager_feature_subscribe_motion) { + if (defined(global_parts_info) && defined(global_parts_info.msdp_motion)) { + external_deps = [ "motion:motion_interface_native" ] + defines = [ "WM_SUBSCRIBE_MOTION_ENABLE" ] + } + } +} + +ohos_unittest("dmserver_display_dumper_test") { + module_out_path = module_out_path + + sources = [ "display_dumper_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_abstract_screen_test") { + module_out_path = module_out_path + + sources = [ "abstract_screen_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_display_cutout_controller_test") { + module_out_path = module_out_path + + sources = [ "display_cutout_controller_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_abstract_display_controller_test") { + module_out_path = module_out_path + + sources = [ "abstract_display_controller_test.cpp" ] + + deps = [ ":dmserver_unittest_common" ] +} + +ohos_unittest("dmserver_display_manager_config_test") { + module_out_path = module_out_path + include_dirs = [ "//foundation/window/window_manager/dmserver/src" ] + + sources = [ "display_manager_config_test.cpp" ] + + deps = [ + ":dmserver_unittest_common", + "//third_party/libxml2:libxml2", + ] + + external_deps = [ "config_policy:configpolicy_util" ] +} + +## Build dmserver_unittest_common.a {{{ +config("dmserver_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/snapshot", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/test/common/mock", + "//foundation/window/window_manager/test/common/utils/include", + "//foundation/window/window_manager/utils/include", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client", # RSSurface + "//base/sensors/sensor/interfaces/native/include", + ] +} + +ohos_static_library("dmserver_unittest_common") { + visibility = [ ":*" ] + testonly = true + + public_configs = [ + ":dmserver_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//commonlibrary/c_utils/base:utils", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/multimedia/image_framework/interfaces/innerkits:image_native", # PixelMap + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/snapshot:snapshot_display", + "//foundation/window/window_manager/test/common/utils:libtestutil", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + "//third_party/libjpeg-turbo:turbojpeg_static", # jpeg + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "hilog_native:libhilog", + "ipc:ipc_core", + "sensor:sensor_interface_native", + ] + subsystem_name = "window" + part_name = "window_manager" +} +## Build dmserver_unittest_common.a }}} diff --git a/window_manager/dmserver/test/unittest/abstract_display_controller_test.cpp b/window_manager/dmserver/test/unittest/abstract_display_controller_test.cpp new file mode 100644 index 0000000..d45b723 --- /dev/null +++ b/window_manager/dmserver/test/unittest/abstract_display_controller_test.cpp @@ -0,0 +1,508 @@ +/* + * 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 "abstract_display.h" +#include "abstract_display_controller.h" +#include "display_cutout_controller.h" +#include "screen.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class AbstractDisplayControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + +private: + void InitScreen(); + std::string name_ = "abstract_display_controller_test"; + sptr modesInfo_; + std::recursive_mutex mutex_; + sptr absScreenController_ = nullptr; + sptr absDisplayController_ = nullptr; + sptr absScreen_ = nullptr;; + ScreenId defaultScreenId_ = 0; + DisplayId defaultDisplayId_ = 0; + sptr absDisplay_ = nullptr; + sptr displayCutoutController_ = nullptr; +}; + +void AbstractDisplayControllerTest::SetUpTestCase() +{ +} + +void AbstractDisplayControllerTest::TearDownTestCase() +{ +} + +void AbstractDisplayControllerTest::SetUp() +{ + absDisplayController_ = new AbstractDisplayController(mutex_, [](DisplayId, sptr, + const std::map>&, DisplayStateChangeType) {}); + ASSERT_NE(nullptr, absDisplayController_); + absScreenController_ = new AbstractScreenController(mutex_); + ASSERT_NE(nullptr, absScreenController_); + absDisplayController_->Init(absScreenController_); + + ScreenId id = absScreenController_->GetDefaultAbstractScreenId(); + defaultScreenId_ = id; + + absScreen_ = absScreenController_->GetAbstractScreen(defaultScreenId_); + ASSERT_NE(nullptr, absScreen_); + + InitScreen(); + absDisplay_ = absDisplayController_->GetAbstractDisplayByScreen(defaultScreenId_); + ASSERT_NE(nullptr, absDisplay_); + defaultDisplayId_ = absDisplay_->GetId(); + displayCutoutController_ = new DisplayCutoutController(); +} + +void AbstractDisplayControllerTest::TearDown() +{ + absScreenController_->ProcessScreenDisconnected(defaultScreenId_); + absScreenController_ = nullptr; + absDisplayController_ = nullptr; + displayCutoutController_ = nullptr; +} + +void AbstractDisplayControllerTest::InitScreen() +{ + modesInfo_ = new SupportedScreenModes(); + modesInfo_->width_ = 200; // 200 is test width + modesInfo_->height_ = 200; // 200 is test height + modesInfo_->refreshRate_ = 60; // 60 is test data + absScreen_->modes_[0] = modesInfo_; +} + +namespace { +/** + * @tc.name: OnAbstractScreenConnectAndDisConnect01 + * @tc.desc: OnAbstractScreenConnectAndDisConnect with nullptr + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, OnAbstractScreenConnectAndDisConnect01, Function | SmallTest | Level3) +{ + sptr absScreen = nullptr; + absDisplayController_->OnAbstractScreenConnect(absScreen); + absDisplayController_->OnAbstractScreenDisconnect(absScreen); + absScreen_->groupDmsId_ = SCREEN_ID_INVALID; + EXPECT_EQ(nullptr, absScreen_->GetGroup()); + absDisplayController_->OnAbstractScreenConnect(absScreen_); + absDisplayController_->OnAbstractScreenDisconnect(absScreen_); +} + +/** + * @tc.name: OnAbstractScreenConnectAndDisConnect02 + * @tc.desc: OnAbstractScreenConnectAndDisConnect02 with different ScreenCombination + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, OnAbstractScreenConnectAndDisConnect02, Function | SmallTest | Level3) +{ + auto group = absScreen_->GetGroup(); + EXPECT_NE(nullptr, group); + group->abstractScreenMap_.insert(std::make_pair(100, std::make_pair(absScreen_, Point(0, 0)))); // 100 is test data + group->combination_ = ScreenCombination::SCREEN_MIRROR; + absDisplayController_->OnAbstractScreenConnect(absScreen_); + absDisplayController_->OnAbstractScreenDisconnect(absScreen_); +} + +/** + * @tc.name: OnAbstractScreenConnectAndDisConnect03 + * @tc.desc: OnAbstractScreenConnectAndDisConnect03 with different ScreenCombination + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, OnAbstractScreenConnectAndDisConnect03, Function | SmallTest | Level3) +{ + auto group = absScreen_->GetGroup(); + EXPECT_NE(nullptr, group); + group->abstractScreenMap_.insert(std::make_pair(100, std::make_pair(absScreen_, Point(0, 0)))); // 100 is test data + group->combination_ = ScreenCombination::SCREEN_EXPAND; + absDisplayController_->OnAbstractScreenConnect(absScreen_); + absDisplayController_->OnAbstractScreenDisconnect(absScreen_); + + group->combination_ = static_cast(100); // 100 is test data + absDisplayController_->OnAbstractScreenConnect(absScreen_); + absDisplayController_->OnAbstractScreenDisconnect(absScreen_); +} + +/** + * @tc.name: ProcessNormalScreenDisconnected01 + * @tc.desc: ProcessNormalScreenDisconnected01 failed + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessNormalScreenDisconnected01, Function | SmallTest | Level3) +{ + sptr absScreen = nullptr; + sptr screenGroup = nullptr; + auto displayId = absDisplayController_->ProcessNormalScreenDisconnected(absScreen, absScreen_->GetGroup(), + absDisplay_); + EXPECT_EQ(DISPLAY_ID_INVALID, displayId); + + displayId = absDisplayController_->ProcessNormalScreenDisconnected(absScreen_, screenGroup, absDisplay_); + EXPECT_EQ(DISPLAY_ID_INVALID, displayId); + + absDisplayController_->abstractDisplayMap_.clear(); + displayId = absDisplayController_->ProcessNormalScreenDisconnected(absScreen_, screenGroup, absDisplay_); + EXPECT_EQ(DISPLAY_ID_INVALID, displayId); +} + +/** + * @tc.name: ProcessExpandScreenDisconnected01 + * @tc.desc: ProcessExpandScreenDisconnected01 failed + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessExpandScreenDisconnected01, Function | SmallTest | Level3) +{ + sptr absScreen = nullptr; + sptr screenGroup = nullptr; + auto displayId = absDisplayController_->ProcessExpandScreenDisconnected(absScreen, absScreen_->GetGroup(), + absDisplay_); + EXPECT_EQ(DISPLAY_ID_INVALID, displayId); + + displayId = absDisplayController_->ProcessExpandScreenDisconnected(absScreen_, screenGroup, absDisplay_); + EXPECT_EQ(DISPLAY_ID_INVALID, displayId); + + absDisplayController_->abstractDisplayMap_.clear(); + displayId = absDisplayController_->ProcessExpandScreenDisconnected(absScreen_, screenGroup, absDisplay_); + EXPECT_EQ(DISPLAY_ID_INVALID, displayId); +} + +/** + * @tc.name: OnAbstractScreenChange01 + * @tc.desc: OnAbstractScreenChange01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, OnAbstractScreenChange01, Function | SmallTest | Level3) +{ + sptr absScreen = nullptr; + absDisplayController_->OnAbstractScreenChange(absScreen, DisplayChangeEvent::UNKNOWN); + EXPECT_NE(nullptr, absScreen_); + absDisplayController_->OnAbstractScreenChange(absScreen_, DisplayChangeEvent::UNKNOWN); + absDisplayController_->OnAbstractScreenChange(absScreen_, DisplayChangeEvent::DISPLAY_SIZE_CHANGED); +} + +/** + * @tc.name: ProcessDisplayRotationChange01 + * @tc.desc: ProcessDisplayRotationChange01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessDisplayRotationChange01, Function | SmallTest | Level3) +{ + sptr absScreen = new AbstractScreen(absScreenController_, name_, 1, 1); + EXPECT_EQ(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen)); + absDisplayController_->ProcessDisplayRotationChange(absScreen); + + auto display = absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_); + EXPECT_NE(nullptr, display); + display->rotation_ = absScreen_->rotation_; + EXPECT_EQ(false, display->RequestRotation(absScreen->rotation_)); + absDisplayController_->ProcessDisplayRotationChange(absScreen_); +} + +/** + * @tc.name: ProcessDisplayCompression01 + * @tc.desc: ProcessDisplayCompression01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessDisplayCompression01, Function | SmallTest | Level3) +{ + bool isWaterfallDisplayOrigin = DisplayCutoutController::IsWaterfallDisplay(); + bool isCompressionEnableOrigin = + DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal(); + uint32_t testSizeOrigin = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal(); + DisplayCutoutController::SetIsWaterfallDisplay(true); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(true); + EXPECT_EQ(true, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(20); // 20 is test size + uint32_t sizeInVp = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal(); + EXPECT_NE(0, sizeInVp); + auto mode = absScreen_->GetActiveScreenMode(); + EXPECT_NE(nullptr, mode); + mode->height_ = 60; // 60 is test data + absDisplayController_->ProcessDisplayCompression(absScreen_); + + mode->width_ = 60; // 60 is test data + absDisplayController_->ProcessDisplayCompression(absScreen_); + + mode->height_ = 100; // 100 is test data + absDisplayController_->ProcessDisplayCompression(absScreen_); + + auto oriIdx = absScreen_->activeIdx_; + absScreen_->activeIdx_ = -1; + absDisplayController_->ProcessDisplayCompression(absScreen_); + absScreen_->activeIdx_ = oriIdx; + + DisplayCutoutController::SetIsWaterfallDisplay(isWaterfallDisplayOrigin); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(isCompressionEnableOrigin); + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSizeOrigin); +} + +/** + * @tc.name: GetAbstractDisplayByAbsScreen01 + * @tc.desc: GetAbstractDisplayByAbsScreen01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, GetAbstractDisplayByAbsScreen01, Function | SmallTest | Level3) +{ + EXPECT_NE(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_)); + + auto oriId = absScreen_->groupDmsId_; + absScreen_->groupDmsId_ = SCREEN_ID_INVALID; + sptr group = absScreen_->GetGroup(); + EXPECT_EQ(nullptr, group); + EXPECT_EQ(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_)); + absScreen_->groupDmsId_ = oriId; + + group = absScreen_->GetGroup(); + EXPECT_NE(nullptr, group); + absDisplayController_->abstractDisplayMap_.clear(); + group->combination_ = ScreenCombination::SCREEN_ALONE; + EXPECT_EQ(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_)); + + group->combination_ = ScreenCombination::SCREEN_EXPAND; + EXPECT_EQ(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_)); + + group->combination_ = ScreenCombination::SCREEN_MIRROR; + EXPECT_EQ(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_)); + + group->combination_ = static_cast(100); // 100 is test data + EXPECT_EQ(nullptr, absDisplayController_->GetAbstractDisplayByAbsScreen(absScreen_)); +} + +/** + * @tc.name: ProcessDisplayUpdateOrientation01 + * @tc.desc: ProcessDisplayUpdateOrientation01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessDisplayUpdateOrientation01, Function | SmallTest | Level3) +{ + absDisplayController_->ProcessDisplayUpdateOrientation(absScreen_); + + auto oriId = absScreen_->groupDmsId_; + absScreen_->groupDmsId_ = SCREEN_ID_INVALID; + sptr group = absScreen_->GetGroup(); + EXPECT_EQ(nullptr, group); + absDisplayController_->ProcessDisplayUpdateOrientation(absScreen_); + absScreen_->groupDmsId_ = oriId; + + group = absScreen_->GetGroup(); + EXPECT_NE(nullptr, group); + absDisplayController_->abstractDisplayMap_.clear(); + group->combination_ = ScreenCombination::SCREEN_ALONE; + absDisplayController_->ProcessDisplayUpdateOrientation(absScreen_); + + group->combination_ = ScreenCombination::SCREEN_EXPAND; + absDisplayController_->ProcessDisplayUpdateOrientation(absScreen_); + + group->combination_ = ScreenCombination::SCREEN_MIRROR; + absDisplayController_->ProcessDisplayUpdateOrientation(absScreen_); + + group->combination_ = static_cast(100); // 100 is test data + absDisplayController_->ProcessDisplayUpdateOrientation(absScreen_); +} + +/** + * @tc.name: ProcessDisplaySizeChange01 + * @tc.desc: ProcessDisplaySizeChange01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessDisplaySizeChange01, Function | SmallTest | Level3) +{ + absDisplayController_->ProcessDisplaySizeChange(absScreen_); + auto display = absDisplayController_->abstractDisplayMap_.at(defaultDisplayId_); + EXPECT_NE(nullptr, display); + display->screenId_ = SCREEN_ID_INVALID; + absDisplayController_->ProcessDisplaySizeChange(absScreen_); + + absDisplayController_->abstractDisplayMap_[defaultDisplayId_] = nullptr; + absDisplayController_->ProcessDisplaySizeChange(absScreen_); + + absDisplayController_->abstractDisplayMap_.clear(); + absDisplayController_->ProcessDisplaySizeChange(absScreen_); + + auto oriIdx = absScreen_->activeIdx_; + absScreen_->activeIdx_ = -1; + auto mode = absScreen_->GetActiveScreenMode(); + EXPECT_EQ(nullptr, mode); + absDisplayController_->ProcessDisplaySizeChange(absScreen_); + absScreen_->activeIdx_ = oriIdx; +} + +/** + * @tc.name: UpdateDisplaySize01 + * @tc.desc: UpdateDisplaySize01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, UpdateDisplaySize01, Function | SmallTest | Level3) +{ + EXPECT_EQ(false, absDisplayController_->UpdateDisplaySize(nullptr, modesInfo_)); + + EXPECT_EQ(false, absDisplayController_->UpdateDisplaySize(absDisplay_, nullptr)); + + EXPECT_EQ(false, absDisplayController_->UpdateDisplaySize(nullptr, nullptr)); + + sptr info = new SupportedScreenModes(); + + info->height_ = absDisplay_->GetHeight(); + info->width_ = absDisplay_->GetWidth(); + EXPECT_EQ(false, absDisplayController_->UpdateDisplaySize(absDisplay_, info)); + + info->width_ = absDisplay_->GetWidth(); + info->height_ = 200; // 200 is test height + EXPECT_EQ(true, absDisplayController_->UpdateDisplaySize(absDisplay_, info)); + + info->width_ = 200; // 200 is test height + info->height_ = absDisplay_->GetHeight(); + EXPECT_EQ(true, absDisplayController_->UpdateDisplaySize(absDisplay_, info)); + + info->width_ = 100; // 100 is test width + info->height_ = 100; // 100 is test height + EXPECT_EQ(true, absDisplayController_->UpdateDisplaySize(absDisplay_, info)); +} + +/** + * @tc.name: ProcessVirtualPixelRatioChange01 + * @tc.desc: ProcessVirtualPixelRatioChange01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, ProcessVirtualPixelRatioChange01, Function | SmallTest | Level3) +{ + auto display = absDisplayController_->abstractDisplayMap_.at(defaultDisplayId_); + EXPECT_NE(nullptr, display); + display->screenId_ = SCREEN_ID_INVALID; + absDisplayController_->ProcessVirtualPixelRatioChange(absScreen_); + + absDisplayController_->abstractDisplayMap_.clear(); + absDisplayController_->ProcessVirtualPixelRatioChange(absScreen_); +} + +/** + * @tc.name: BindAloneScreenLocked01 + * @tc.desc: BindAloneScreenLocked01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, BindAloneScreenLocked01, Function | SmallTest | Level3) +{ + absDisplayController_->BindAloneScreenLocked(nullptr); + + sptr absScreen = new AbstractScreen(absScreenController_, name_, 1, 1); + EXPECT_NE(nullptr, absScreen); + absDisplayController_->BindAloneScreenLocked(absScreen); + + absDisplayController_->dummyDisplay_ = absDisplay_; + sptr info = absScreen_->GetActiveScreenMode(); + info->height_ = absDisplay_->GetHeight(); + info->width_ = absDisplay_->GetWidth(); + bool updateFlag = static_cast(absDisplayController_->dummyDisplay_->GetHeight()) == info->height_ + && static_cast(absDisplayController_->dummyDisplay_->GetWidth()) == info->width_; + EXPECT_NE(nullptr, info); + EXPECT_EQ(true, updateFlag); + absDisplayController_->BindAloneScreenLocked(absScreen_); + + absDisplay_->SetWidth(100); // 100 is test size + absDisplay_->SetHeight(100); // 100 is test size + absDisplayController_->dummyDisplay_ = absDisplay_; + EXPECT_NE(nullptr, info); + updateFlag = static_cast(absDisplayController_->dummyDisplay_->GetHeight()) == info->height_ + && static_cast(absDisplayController_->dummyDisplay_->GetWidth()) == info->width_; + EXPECT_EQ(false, updateFlag); + absDisplayController_->BindAloneScreenLocked(absScreen_); + + auto oriIdx = absScreen_->activeIdx_; + absScreen_->activeIdx_ = -1; + info = absScreen_->GetActiveScreenMode(); + EXPECT_EQ(nullptr, info); + absDisplayController_->BindAloneScreenLocked(absScreen_); + absScreen_->activeIdx_ = oriIdx; +} + +/** + * @tc.name: AddScreenToExpandLocked01 + * @tc.desc: AddScreenToExpandLocked01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, AddScreenToExpandLocked01, Function | SmallTest | Level3) +{ + absDisplayController_->AddScreenToExpandLocked(nullptr); + + sptr absScreen = new AbstractScreen(absScreenController_, name_, 1, 1); + EXPECT_NE(nullptr, absScreen); + absDisplayController_->AddScreenToExpandLocked(absScreen); + + absDisplayController_->AddScreenToExpandLocked(absScreen_); + + absDisplayController_->abstractDisplayMap_.clear(); + absDisplayController_->AddScreenToExpandLocked(absScreen_); + + absDisplayController_->abstractDisplayMap_.clear(); + absScreen_->type_ = ScreenType::VIRTUAL; + absDisplayController_->AddScreenToExpandLocked(absScreen_); +} + +/** + * @tc.name: SetFreeze01 + * @tc.desc: SetFreeze01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, SetFreeze01, Function | SmallTest | Level3) +{ + absDisplayController_->abstractDisplayMap_.clear(); + std::vector displayIds(1, 0); + auto iter = absDisplayController_->abstractDisplayMap_.find(0); + EXPECT_EQ(true, iter == absDisplayController_->abstractDisplayMap_.end()); + absDisplayController_->SetFreeze(displayIds, false); +} + +/** + * @tc.name: GetAllDisplayInfoOfGroup01 + * @tc.desc: GetAllDisplayInfoOfGroup01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, GetAllDisplayInfoOfGroup01, Function | SmallTest | Level3) +{ + sptr displayInfo = new DisplayInfo(); + EXPECT_NE(nullptr, displayInfo); + displayInfo->SetScreenGroupId(100); // 100 is test size + auto displayInfoMap = absDisplayController_->GetAllDisplayInfoOfGroup(displayInfo); + EXPECT_EQ(0, displayInfoMap.size()); +} + +/** + * @tc.name: GetDefaultDisplayId01 + * @tc.desc: GetDefaultDisplayId01 + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayControllerTest, GetDefaultDisplayId01, Function | SmallTest | Level3) +{ + auto absDisplayController = new AbstractDisplayController(mutex_, [](DisplayId, sptr, + const std::map>&, DisplayStateChangeType) {}); + EXPECT_NE(nullptr, absDisplayController); + absDisplayController->abstractScreenController_ = new AbstractScreenController(mutex_); + EXPECT_NE(nullptr, absDisplayController->abstractScreenController_); + ScreenId defaultScreenId = absDisplayController->abstractScreenController_->GetDefaultAbstractScreenId(); + sptr defaultDisplay = absDisplayController->GetAbstractDisplayByScreen(defaultScreenId); + EXPECT_EQ(nullptr, defaultDisplay); + EXPECT_EQ(DISPLAY_ID_INVALID, absDisplayController->GetDefaultDisplayId()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/test/unittest/abstract_display_test.cpp b/window_manager/dmserver/test/unittest/abstract_display_test.cpp new file mode 100644 index 0000000..efe000c --- /dev/null +++ b/window_manager/dmserver/test/unittest/abstract_display_test.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 "abstract_display.h" +#include "abstract_screen_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class AbstractDisplayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + DisplayId id = 1; + std::string name = "abstract_display_test"; + SupportedScreenModes modesInfo; + std::recursive_mutex mutex; + sptr absController; + sptr absScreen; + sptr absDisplay; + sptr absDisplay2; + sptr absDisplay3; +}; + +void AbstractDisplayTest::SetUpTestCase() +{ +} + +void AbstractDisplayTest::TearDownTestCase() +{ +} + +void AbstractDisplayTest::SetUp() +{ + modesInfo.width_ = 2160; + modesInfo.height_ = 1600; + modesInfo.refreshRate_ = 60; + sptr info = new SupportedScreenModes(modesInfo); + absController = nullptr; + absScreen = new AbstractScreen(absController, name, 1, 1); + absDisplay = new AbstractDisplay(id, name, info, absScreen); + modesInfo.width_ = 800; + modesInfo.height_ = 2560; + absDisplay2 = new AbstractDisplay(id, name, info, absScreen); + modesInfo.width_ = 2560; + modesInfo.height_ = 2560; + absDisplay3 = new AbstractDisplay(id, name, info, absScreen); +} + +void AbstractDisplayTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: BindAbstractScreen + * @tc.desc: BindAbstractScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayTest, BindAbstractScreen01, Function | SmallTest | Level3) +{ + sptr abstractScreen = nullptr; + ASSERT_EQ(false, absDisplay->BindAbstractScreen(abstractScreen)); +} +/** + * @tc.name: BindAbstractScreen + * @tc.desc: BindAbstractScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractDisplayTest, BindAbstractScreen02, Function | SmallTest | Level3) +{ + sptr abstractScreen = absScreen; + abstractScreen->activeIdx_ = -1; + ASSERT_EQ(false, absDisplay->BindAbstractScreen(abstractScreen)); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/test/unittest/abstract_screen_controller_test.cpp b/window_manager/dmserver/test/unittest/abstract_screen_controller_test.cpp new file mode 100644 index 0000000..8e3b0dd --- /dev/null +++ b/window_manager/dmserver/test/unittest/abstract_screen_controller_test.cpp @@ -0,0 +1,601 @@ +/* + * 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 "abstract_screen_controller.h" +#include "iremote_object_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class AbstractScreenControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + std::recursive_mutex mutex; + sptr absController_ = new AbstractScreenController(mutex); + std::string name = "AbstractScreenController"; + std::vector> screenVec; + std::vector> screenGroupVec; +}; + +void AbstractScreenControllerTest::SetUpTestCase() +{ +} + +void AbstractScreenControllerTest::TearDownTestCase() +{ +} + +void AbstractScreenControllerTest::SetUp() +{ + uint64_t index = 5; + for (uint64_t i = 0; i < index; ++i) { + ScreenId dmsId = i; + ScreenId rsId = i; + sptr absScreen = new AbstractScreen(absController_, name, dmsId, rsId); + sptr absScreenGroup = new AbstractScreenGroup(absController_, + dmsId, rsId, name, ScreenCombination::SCREEN_ALONE); + screenVec.emplace_back(absScreen); + screenGroupVec.emplace_back(absScreenGroup); + // init dmsScreenMap_ + absController_->dmsScreenMap_.insert(std::make_pair(dmsId, absScreen)); + // init screenIdManager_ + absController_->screenIdManager_.rs2DmsScreenIdMap_.insert(std::make_pair(rsId, dmsId)); + absController_->screenIdManager_.dms2RsScreenIdMap_.insert(std::make_pair(dmsId, rsId)); + // init dmsScreenGroupMap_ + absController_->dmsScreenGroupMap_.insert(std::make_pair(rsId, absScreenGroup)); + } + screenVec[4]->type_ = ScreenType::UNDEFINED; + screenVec[3]->type_ = ScreenType::VIRTUAL; + absController_->dmsScreenMap_.insert(std::make_pair(index, nullptr)); + absController_->screenIdManager_.dms2RsScreenIdMap_.insert(std::make_pair(index, SCREEN_ID_INVALID)); + absController_->dmsScreenGroupMap_.insert(std::make_pair(index, nullptr)); +} + +void AbstractScreenControllerTest::TearDown() +{ + screenVec.clear(); +} + +namespace { +/** + * @tc.name: GetAllValidScreenIds + * @tc.desc: GetAllValidScreenIds test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, GetAllValidScreenIds, Function | SmallTest | Level3) +{ + std::vector screenIds {0, 1, 1, 2, 2, 3, 4}; + std::vector valid {0, 1, 2, 3}; + ASSERT_EQ(valid, absController_->GetAllValidScreenIds(screenIds)); +} +/** + * @tc.name: GetRSDisplayNodeByScreenId + * @tc.desc: GetRSDisplayNodeByScreenId test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, GetRSDisplayNodeByScreenId, Function | SmallTest | Level3) +{ + ScreenId id = 6; + std::shared_ptr node = nullptr; + ASSERT_EQ(node, absController_->GetRSDisplayNodeByScreenId(id)); +} +/** + * @tc.name: UpdateRSTree + * @tc.desc: UpdateRSTree test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, UpdateRSTree01, Function | SmallTest | Level3) +{ + ScreenId id = 8; + std::shared_ptr node = nullptr; + absController_->UpdateRSTree(id, id, node, true, true); + ASSERT_EQ(nullptr, absController_->GetAbstractScreen(id)); +} +/** + * @tc.name: UpdateRSTree + * @tc.desc: UpdateRSTree test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, UpdateRSTree02, Function | SmallTest | Level3) +{ + ScreenId id = 1; + ScreenId parentId = 8; + std::shared_ptr node = nullptr; + absController_->UpdateRSTree(id, parentId, node, true, true); + ASSERT_NE(nullptr, absController_->GetAbstractScreen(id)); + ASSERT_EQ(nullptr, absController_->GetAbstractScreen(parentId)); +} +/** + * @tc.name: UpdateRSTree + * @tc.desc: UpdateRSTree test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, UpdateRSTree03, Function | SmallTest | Level3) +{ + ScreenId id = 1; + ScreenId parentId = 2; + std::shared_ptr node = nullptr; + ASSERT_NE(nullptr, absController_->GetAbstractScreen(id)); + sptr parentScreen = absController_->GetAbstractScreen(parentId); + ASSERT_NE(nullptr, absController_->GetAbstractScreen(parentId)); + parentScreen->rsDisplayNode_ = nullptr; + absController_->UpdateRSTree(id, parentId, node, true, true); +} +/** + * @tc.name: RegisterAbstractScreenCallback + * @tc.desc: RegisterAbstractScreenCallback test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, RegisterAbstractScreenCallback, Function | SmallTest | Level3) +{ + sptr cb = nullptr; + absController_->RegisterAbstractScreenCallback(cb); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: AddToGroupLocked + * @tc.desc: AddToGroupLocked test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, AddToGroupLocked, Function | SmallTest | Level3) +{ + ASSERT_EQ(false, absController_->dmsScreenGroupMap_.empty()); + ASSERT_EQ(nullptr, absController_->AddToGroupLocked(screenVec[0])); +} +/** + * @tc.name: RemoveFromGroupLocked + * @tc.desc: RemoveFromGroupLocked test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, RemoveFromGroupLocked01, Function | SmallTest | Level3) +{ + sptr screen = screenVec[0]; + screen->groupDmsId_ = 0; + ASSERT_EQ(nullptr, absController_->RemoveFromGroupLocked(screen)); +} +/** + * @tc.name: RemoveChildFromGroup + * @tc.desc: RemoveChildFromGroup test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, RemoveChildFromGroup01, Function | SmallTest | Level3) +{ + sptr screen = screenVec[0]; + ScreenId dmsId = screen->dmsId_; + Point point; + auto p = std::make_pair(screen, point); + sptr screenGroup = absController_->dmsScreenGroupMap_[0]; + screenGroup->abstractScreenMap_.insert(std::make_pair(dmsId, p)); + ASSERT_EQ(true, absController_->RemoveChildFromGroup(screen, screenGroup)); +} +/** + * @tc.name: AddAsSuccedentScreenLocked + * @tc.desc: AddAsSuccedentScreenLocked test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, AddAsSuccedentScreenLocked01, Function | SmallTest | Level3) +{ + sptr screen = screenVec[0]; + absController_->dmsScreenMap_.erase(absController_->GetDefaultAbstractScreenId()); + ASSERT_EQ(nullptr, absController_->AddAsSuccedentScreenLocked(screen)); +} +/** + * @tc.name: AddAsSuccedentScreenLocked + * @tc.desc: AddAsSuccedentScreenLocked test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, AddAsSuccedentScreenLocked02, Function | SmallTest | Level3) +{ + sptr screen = screenVec[0]; + ASSERT_EQ(nullptr, absController_->AddAsSuccedentScreenLocked(screen)); +} +/** + * @tc.name: CreateVirtualScreen + * @tc.desc: CreateVirtualScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, CreateVirtualScreen01, Function | SmallTest | Level3) +{ + VirtualScreenOption option; + sptr displayManagerAgent = new IRemoteObjectMocker(); + ASSERT_EQ(0, absController_->CreateVirtualScreen(option, displayManagerAgent)); +} +/** + * @tc.name: InitVirtualScreen + * @tc.desc: InitVirtualScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, InitVirtualScreen01, Function | SmallTest | Level3) +{ + VirtualScreenOption option; + absController_->dmsScreenMap_.erase(absController_->GetDefaultAbstractScreenId()); + sptr screen = absController_->InitVirtualScreen(0, 0, option); + ASSERT_EQ(0, screen->activeIdx_); +} +/** + * @tc.name: InitVirtualScreen + * @tc.desc: InitVirtualScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, InitVirtualScreen02, Function | SmallTest | Level3) +{ + VirtualScreenOption option; + sptr defaultScreen = absController_->dmsScreenMap_[absController_->GetDefaultAbstractScreenId()]; + sptr modes; + defaultScreen->modes_.emplace_back(modes); + defaultScreen->activeIdx_ = 0; + ASSERT_EQ(nullptr, defaultScreen->GetActiveScreenMode()); + sptr screen = absController_->InitVirtualScreen(0, 0, option); + ASSERT_EQ(ScreenType::VIRTUAL, screen->type_); +} +/** + * @tc.name: DestroyVirtualScreen + * @tc.desc: DestroyVirtualScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, DestroyVirtualScreen01, Function | SmallTest | Level3) +{ + ScreenId id = 5; + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, absController_->DestroyVirtualScreen(id)); +} +/** + * @tc.name: DestroyVirtualScreen + * @tc.desc: DestroyVirtualScreen test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, DestroyVirtualScreen02, Function | SmallTest | Level3) +{ + ScreenId id = 1; + ASSERT_EQ(DMError::DM_OK, absController_->DestroyVirtualScreen(id)); +} +/** + * @tc.name: SetVirtualScreenSurface + * @tc.desc: SetVirtualScreenSurface test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetVirtualScreenSurface01, Function | SmallTest | Level3) +{ + ScreenId id = 6; + sptr surface = nullptr; + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, absController_->SetVirtualScreenSurface(id, surface)); +} +/** + * @tc.name: SetBuildInDefaultOrientation + * @tc.desc: SetBuildInDefaultOrientation test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetBuildInDefaultOrientation, Function | SmallTest | Level3) +{ + Orientation orientation = Orientation::BEGIN; + absController_->SetBuildInDefaultOrientation(orientation); + ASSERT_EQ(orientation, absController_->buildInDefaultOrientation_); +} +/** + * @tc.name: SetOrientation + * @tc.desc: SetOrientation test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetOrientation01, Function | SmallTest | Level3) +{ + absController_->dmsScreenMap_[1]->isScreenGroup_ = true; + Orientation orientation = Orientation::BEGIN; + ASSERT_EQ(false, absController_->SetOrientation(1, orientation, true)); +} +/** + * @tc.name: SetRotation + * @tc.desc: SetRotation test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetRotation01, Function | SmallTest | Level3) +{ + absController_->dmsScreenMap_[1]->rotation_ = Rotation::ROTATION_180; + absController_->screenIdManager_.dms2RsScreenIdMap_.erase(1); + ASSERT_EQ(false, absController_->SetRotation(1, Rotation::ROTATION_0, true)); +} +/** + * @tc.name: SetScreenActiveMode + * @tc.desc: SetScreenActiveMode test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetScreenActiveMode01, Function | SmallTest | Level3) +{ + ASSERT_EQ(false, absController_->SetScreenActiveMode(5, 0)); +} +/** + * @tc.name: SetScreenActiveMode + * @tc.desc: SetScreenActiveMode test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetScreenActiveMode02, Function | SmallTest | Level3) +{ + absController_->screenIdManager_.dms2RsScreenIdMap_.erase(1); + ASSERT_EQ(false, absController_->SetScreenActiveMode(1, 0)); +} +/** + * @tc.name: ProcessScreenModeChanged + * @tc.desc: ProcessScreenModeChanged test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, ProcessScreenModeChanged01, Function | SmallTest | Level3) +{ + absController_->ProcessScreenModeChanged(7); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: ProcessScreenModeChanged + * @tc.desc: ProcessScreenModeChanged test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, ProcessScreenModeChanged02, Function | SmallTest | Level3) +{ + absController_->ProcessScreenModeChanged(5); + ASSERT_EQ(nullptr, absController_->dmsScreenMap_[5]); +} +/** + * @tc.name: ProcessScreenModeChanged + * @tc.desc: ProcessScreenModeChanged test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, ProcessScreenModeChanged03, Function | SmallTest | Level3) +{ + absController_->ProcessScreenModeChanged(2); + ASSERT_NE(nullptr, absController_->dmsScreenMap_[2]); +} +/** + * @tc.name: ChangeScreenGroup + * @tc.desc: ChangeScreenGroup test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, ChangeScreenGroup01, Function | SmallTest | Level3) +{ + sptr group = screenGroupVec[0]; + Point point; + auto abs2pointPair = std::make_pair(screenVec[0], point); + group->abstractScreenMap_.insert(std::make_pair(0, abs2pointPair)); + group->abstractScreenMap_.insert(std::make_pair(1, abs2pointPair)); + std::vector startPoints; + std::vector screens; + for (ScreenId i = 0; i < 7; ++i) { + screens.emplace_back(i); + startPoints.emplace_back(point); + if (i < absController_->dmsScreenMap_.size() && absController_->dmsScreenMap_[i] != nullptr) { + absController_->dmsScreenMap_[i]->groupDmsId_ = 1; + } + } + absController_->ChangeScreenGroup(group, screens, startPoints, true, ScreenCombination::SCREEN_ALONE); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: ChangeScreenGroup + * @tc.desc: ChangeScreenGroup test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, ChangeScreenGroup02, Function | SmallTest | Level3) +{ + sptr group = screenGroupVec[0]; + Point point; + auto abs2pointPair = std::make_pair(screenVec[0], point); + group->abstractScreenMap_.insert(std::make_pair(0, abs2pointPair)); + group->abstractScreenMap_.insert(std::make_pair(1, abs2pointPair)); + std::vector startPoints; + std::vector screens; + for(ScreenId i = 0; i < 7; ++i) { + screens.emplace_back(i); + startPoints.emplace_back(point); + if (i < absController_->dmsScreenMap_.size() && absController_->dmsScreenMap_[i] != nullptr) { + absController_->dmsScreenMap_[i]->groupDmsId_ = 1; + } + } + absController_->abstractScreenCallback_ = nullptr; + absController_->ChangeScreenGroup(group, screens, startPoints, true, ScreenCombination::SCREEN_ALONE); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: ChangeScreenGroup + * @tc.desc: ChangeScreenGroup test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, AddScreenToGroup01, Function | SmallTest | Level3) +{ + sptr group = screenGroupVec[0]; + std::vector addScreens {0, 1, 2, 3, 4, 5}; + Point point; + std::vector addChildPos(10, point); + std::map removeChildResMap; + absController_->AddScreenToGroup(group, addScreens, addChildPos, removeChildResMap); + absController_->abstractScreenCallback_ = nullptr; + absController_->rSScreenChangeListener_ = nullptr; + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: MakeExpand + * @tc.desc: MakeExpand test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, MakeExpand01, Function | SmallTest | Level3) +{ + std::vector screenIds; + std::vector startPoints; + ScreenId defaultId = absController_->GetDefaultAbstractScreenId(); + absController_->dmsScreenMap_[defaultId] = nullptr; + ASSERT_EQ(false, absController_->MakeExpand(screenIds, startPoints)); +} +/** + * @tc.name: MakeExpand + * @tc.desc: MakeExpand test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, MakeExpand02, Function | SmallTest | Level3) +{ + std::vector screenIds; + std::vector startPoints; + ScreenId defaultId = absController_->GetDefaultAbstractScreenId(); + auto defaultScreen = absController_->GetAbstractScreen(defaultId); + ScreenId groupDmsId = defaultScreen->groupDmsId_; + absController_->dmsScreenGroupMap_[groupDmsId] = nullptr; + ASSERT_EQ(false, absController_->MakeExpand(screenIds, startPoints)); +} +/** + * @tc.name: RemoveVirtualScreenFromGroup + * @tc.desc: RemoveVirtualScreenFromGroup test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, RemoveVirtualScreenFromGroup01, Function | SmallTest | Level3) +{ + std::vector screens {0, 1, 2, 3, 4, 5, 6, 7}; + absController_->abstractScreenCallback_ = nullptr; + absController_->RemoveVirtualScreenFromGroup(screens); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: OnRemoteDied + * @tc.desc: OnRemoteDied test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, OnRemoteDied01, Function | SmallTest | Level3) +{ + sptr agent = nullptr; + ASSERT_EQ(false, absController_->OnRemoteDied(agent)); +} +/** + * @tc.name: OnRemoteDied + * @tc.desc: OnRemoteDied test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, OnRemoteDied02, Function | SmallTest | Level3) +{ + sptr agent = new IRemoteObjectMocker(); + ASSERT_EQ(true, absController_->OnRemoteDied(agent)); +} +/** + * @tc.name: OnRemoteDied + * @tc.desc: OnRemoteDied test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, OnRemoteDied03, Function | SmallTest | Level3) +{ + sptr agent = new IRemoteObjectMocker(); + std::vector screens {5}; + absController_->screenAgentMap_.insert(std::make_pair(agent, screens)); + ASSERT_EQ(true, absController_->OnRemoteDied(agent)); + ASSERT_EQ(0, absController_->screenAgentMap_.size()); +} +/** + * @tc.name: CreateAndGetNewScreenId + * @tc.desc: CreateAndGetNewScreenId test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, CreateAndGetNewScreenId01, Function | SmallTest | Level3) +{ + ScreenId rsScreenId = 1; + ScreenId dmsScreenId = absController_->screenIdManager_.dmsScreenCount_; + ASSERT_EQ(dmsScreenId, absController_->screenIdManager_.CreateAndGetNewScreenId(rsScreenId)); + ASSERT_EQ(++dmsScreenId, absController_->screenIdManager_.dmsScreenCount_); +} +/** + * @tc.name: ConvertToRsScreenId + * @tc.desc: ConvertToRsScreenId test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, ConvertToRsScreenId01, Function | SmallTest | Level3) +{ + ScreenId rsScreenId; + ScreenId dmsScreenId = 8; + ASSERT_EQ(false, absController_->screenIdManager_.ConvertToRsScreenId(dmsScreenId, rsScreenId)); +} +/** + * @tc.name: NotifyScreenConnected + * @tc.desc: NotifyScreenConnected test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, NotifyScreenConnected, Function | SmallTest | Level3) +{ + sptr screenInfo = nullptr; + absController_->NotifyScreenConnected(screenInfo); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: NotifyScreenConnected + * @tc.desc: NotifyScreenConnected test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, NotifyScreenChanged, Function | SmallTest | Level3) +{ + sptr screenInfo = nullptr; + absController_->NotifyScreenChanged(screenInfo, ScreenChangeEvent::UPDATE_ORIENTATION); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: NotifyScreenConnected + * @tc.desc: NotifyScreenConnected test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, NotifyScreenGroupChanged, Function | SmallTest | Level3) +{ + sptr screenInfo = nullptr; + absController_->NotifyScreenGroupChanged(screenInfo, ScreenGroupChangeEvent::ADD_TO_GROUP); + ASSERT_EQ(6, absController_->dmsScreenMap_.size()); +} +/** + * @tc.name: NotifyScreenConnected + * @tc.desc: NotifyScreenConnected test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetScreenPowerForAll, Function | SmallTest | Level3) +{ + for (uint32_t i = 0; i < screenVec.size(); ++i) { + if (screenVec[i] != nullptr && screenVec[i]->type_ == ScreenType::REAL) { + screenVec[i]->type_ = ScreenType::UNDEFINED; + } + } + ASSERT_EQ(false, absController_->SetScreenPowerForAll(ScreenPowerState::INVALID_STATE, + PowerStateChangeReason::POWER_BUTTON)); +} +/** + * @tc.name: SetVirtualPixelRatio + * @tc.desc: SetVirtualPixelRatio test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetVirtualPixelRatio01, Function | SmallTest | Level3) +{ + auto screen = screenVec[0]; + ScreenId id = 0; + float ratio = 1.0; + screen->isScreenGroup_ = true; + ASSERT_EQ(false, absController_->SetVirtualPixelRatio(id, ratio)); +} +/** + * @tc.name: SetVirtualPixelRatio + * @tc.desc: SetVirtualPixelRatio test + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenControllerTest, SetVirtualPixelRatio02, Function | SmallTest | Level3) +{ + ScreenId id = 0; + float ratio = 1.0; + absController_->abstractScreenCallback_ = nullptr; + ASSERT_EQ(true, absController_->SetVirtualPixelRatio(id, ratio)); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/test/unittest/abstract_screen_test.cpp b/window_manager/dmserver/test/unittest/abstract_screen_test.cpp new file mode 100644 index 0000000..4bea689 --- /dev/null +++ b/window_manager/dmserver/test/unittest/abstract_screen_test.cpp @@ -0,0 +1,187 @@ +/* + * 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 "abstract_screen.h" +#include "abstract_screen_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class AbstractScreenTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static sptr absScreen_; + static std::recursive_mutex mutex_; + static std::string name_; +}; + +sptr AbstractScreenTest::absScreen_ = nullptr; +std::recursive_mutex AbstractScreenTest::mutex_; +std::string AbstractScreenTest::name_ = "AbstractScreenTest"; + +void AbstractScreenTest::SetUpTestCase() +{ + sptr absScreenController = new AbstractScreenController(mutex_); + absScreen_ = new AbstractScreen(absScreenController, name_, 0, 0); + absScreen_->modes_.clear(); + absScreen_->activeIdx_ = 0; +} + +void AbstractScreenTest::TearDownTestCase() +{ +} + +void AbstractScreenTest::SetUp() +{ +} + +void AbstractScreenTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetScreenMode + * @tc.desc: Get screen mode + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenTest, GetScreenMode, Function | SmallTest | Level3) +{ + sptr mode0 = new SupportedScreenModes(); + sptr mode1 = new SupportedScreenModes(); + absScreen_->modes_ = {mode0, mode1}; + + absScreen_->activeIdx_ = -1; + ASSERT_EQ(nullptr, absScreen_->GetActiveScreenMode()); + absScreen_->activeIdx_ = static_cast(absScreen_->modes_.size()); + ASSERT_EQ(nullptr, absScreen_->GetActiveScreenMode()); + absScreen_->activeIdx_ = 0; + ASSERT_EQ(mode0, absScreen_->GetActiveScreenMode()); + absScreen_->activeIdx_ = 1; + ASSERT_EQ(mode1, absScreen_->GetActiveScreenMode()); + + ASSERT_EQ(mode0, (absScreen_->GetAbstractScreenModes())[0]); + ASSERT_EQ(mode1, (absScreen_->GetAbstractScreenModes())[1]); +} +/** + * @tc.name: ConvertToScreenInfo + * @tc.desc: Convert to screen info + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenTest, ConvertToScreenInfo, Function | SmallTest | Level3) +{ + ASSERT_NE(nullptr, absScreen_->ConvertToScreenInfo()); +} +/** + * @tc.name: RSTree + * @tc.desc: RS tree + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenTest, RSTree, Function | SmallTest | Level3) +{ + std::shared_ptr surfaceNode; + absScreen_->rsDisplayNode_ = nullptr; + absScreen_->UpdateRSTree(surfaceNode, true); + absScreen_->UpdateDisplayGroupRSTree(surfaceNode, 0, true); + + struct RSDisplayNodeConfig config; + absScreen_->rsDisplayNode_ = std::make_shared(config); + ASSERT_NE(nullptr, absScreen_->rsDisplayNode_); + absScreen_->UpdateRSTree(surfaceNode, true); + absScreen_->UpdateDisplayGroupRSTree(surfaceNode, 0, true); + + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::DEFAULT); + absScreen_->UpdateDisplayGroupRSTree(surfaceNode, 0, true); + absScreen_->UpdateDisplayGroupRSTree(surfaceNode, 0, false); + ASSERT_NE(nullptr, absScreen_->rsDisplayNode_); + absScreen_->rsDisplayNode_ = nullptr; +} +/** + * @tc.name: ColorGamut + * @tc.desc: Screen color gamut + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenTest, ColorGamut, Function | SmallTest | Level3) +{ + sptr absScreenController0 = new AbstractScreenController(mutex_); + sptr absScreen0 = new AbstractScreen(absScreenController0, name_, 0, -1ULL); + std::vector colorGamuts; + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, absScreen0->GetScreenSupportedColorGamuts(colorGamuts)); + ScreenColorGamut colorGamut; + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, absScreen0->GetScreenColorGamut(colorGamut)); + + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, absScreen0->SetScreenColorGamut(0)); + + ScreenGamutMap gamutMap; + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, absScreen0->GetScreenGamutMap(gamutMap)); + + gamutMap = ScreenGamutMap::GAMUT_MAP_HDR_EXTENSION; + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, absScreen0->GetScreenGamutMap(gamutMap)); +} +/** + * @tc.name: FillScreenInfo + * @tc.desc: Fill screen info + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenTest, FillScreenInfo, Function | SmallTest | Level3) +{ + absScreen_->FillScreenInfo(nullptr); + sptr info = new ScreenInfo(); + ASSERT_NE(nullptr, info); + + absScreen_->virtualPixelRatio_ = 0.f; + absScreen_->FillScreenInfo(info); + ASSERT_EQ(1.f, info->virtualPixelRatio_); + + absScreen_->virtualPixelRatio_ = 2.f; + absScreen_->FillScreenInfo(info); + ASSERT_EQ(2.f, info->virtualPixelRatio_); +} +/** + * @tc.name: CalcRotation + * @tc.desc: Calc rotation + * @tc.type: FUNC + */ +HWTEST_F(AbstractScreenTest, CalcRotation, Function | SmallTest | Level3) +{ + absScreen_->modes_.clear(); + absScreen_->activeIdx_ = 0; + + ASSERT_EQ(Rotation::ROTATION_0, absScreen_->CalcRotation(Orientation::UNSPECIFIED)); + + sptr mode = new SupportedScreenModes(); + mode->width_ = 1; + mode->height_ = 1; + absScreen_->modes_ = {mode}; + + ASSERT_EQ(Rotation::ROTATION_0, absScreen_->CalcRotation(Orientation::UNSPECIFIED)); + ASSERT_EQ(Rotation::ROTATION_90, absScreen_->CalcRotation(Orientation::VERTICAL)); + ASSERT_EQ(Rotation::ROTATION_0, absScreen_->CalcRotation(Orientation::HORIZONTAL)); + ASSERT_EQ(Rotation::ROTATION_270, absScreen_->CalcRotation(Orientation::REVERSE_VERTICAL)); + ASSERT_EQ(Rotation::ROTATION_180, absScreen_->CalcRotation(Orientation::REVERSE_HORIZONTAL)); + ASSERT_EQ(Rotation::ROTATION_0, absScreen_->CalcRotation(Orientation::LOCKED)); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/test/unittest/display_cutout_controller_test.cpp b/window_manager/dmserver/test/unittest/display_cutout_controller_test.cpp new file mode 100644 index 0000000..f13d309 --- /dev/null +++ b/window_manager/dmserver/test/unittest/display_cutout_controller_test.cpp @@ -0,0 +1,257 @@ +/* + * 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 "display_cutout_controller.h" +#include "display_manager_service_inner.h" +#include "display_manager_service.h" +#include "dm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayCutoutControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void DisplayCutoutControllerTest::SetUpTestCase() +{ +} + +void DisplayCutoutControllerTest::TearDownTestCase() +{ +} + +void DisplayCutoutControllerTest::SetUp() +{ +} + +void DisplayCutoutControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: SetCurvedScreenBoundary + * @tc.desc: SetCurvedScreenBoundary size < 4 + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, SetCurvedScreenBoundary, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + std::vector curvedScreenBoundary; + curvedScreenBoundary.emplace_back(2); + controller->SetCurvedScreenBoundary(curvedScreenBoundary); + ASSERT_EQ(controller->curvedScreenBoundary_.size(), 4); +} + +/** + * @tc.name: SetCutoutSvgPath + * @tc.desc: SetCutoutSvgPath + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, SetCutoutSvgPath, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + DisplayId displayId = 1; + std::string svgPath = "m10"; + controller->SetCutoutSvgPath(displayId, svgPath); + controller->SetCutoutSvgPath(displayId, svgPath); + ASSERT_EQ(controller->svgPaths_.size(), 1); + ASSERT_EQ(controller->svgPaths_[displayId].size(), 2); +} + +/** + * @tc.name: GetCutoutInfo + * @tc.desc: GetCutoutInfo + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, GetCutoutInfo, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + std::string svgPath = "m10"; + controller->SetCutoutSvgPath(displayId, svgPath); + controller->SetIsWaterfallDisplay(true); + sptr cutoutInfo = controller->GetCutoutInfo(displayId); + ASSERT_NE(cutoutInfo, nullptr); +} + + +/** + * @tc.name: CalcBuiltInDisplayWaterfallRects + * @tc.desc: CalcBuiltInDisplayWaterfallRects + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, CalcBuiltInDisplayWaterfallRects, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + controller->SetIsWaterfallDisplay(true); + std::vector curvedScreenBoundary; + controller->SetCurvedScreenBoundary(curvedScreenBoundary); + controller->CalcBuiltInDisplayWaterfallRects(); + ASSERT_TRUE(controller->waterfallDisplayAreaRects_.isUninitialized()); + curvedScreenBoundary.emplace_back(1); + curvedScreenBoundary.emplace_back(2); + curvedScreenBoundary.emplace_back(3); + curvedScreenBoundary.emplace_back(4); + controller->SetCurvedScreenBoundary(curvedScreenBoundary); + controller->CalcBuiltInDisplayWaterfallRects(); + ASSERT_TRUE(controller->waterfallDisplayAreaRects_.isUninitialized()); +} + + +/** + * @tc.name: CalcBuiltInDisplayWaterfallRectsByRotation + * @tc.desc: CalcBuiltInDisplayWaterfallRectsByRotation + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, CalcBuiltInDisplayWaterfallRectsByRotation, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + uint32_t displayHeight = 300; + uint32_t displayWidth = 300; + std::vector curvedScreenBoundary; + curvedScreenBoundary.emplace_back(0); + curvedScreenBoundary.emplace_back(0); + curvedScreenBoundary.emplace_back(500); + curvedScreenBoundary.emplace_back(500); + controller->SetCurvedScreenBoundary(curvedScreenBoundary); + controller->CalcBuiltInDisplayWaterfallRectsByRotation(Rotation::ROTATION_270, displayHeight, displayWidth); + controller->CalcBuiltInDisplayWaterfallRectsByRotation(Rotation::ROTATION_180, displayHeight, displayWidth); + controller->CalcBuiltInDisplayWaterfallRectsByRotation(Rotation::ROTATION_90, displayHeight, displayWidth); + controller->CalcBuiltInDisplayWaterfallRectsByRotation(Rotation::ROTATION_0, displayHeight, displayWidth); + controller->CalcBuiltInDisplayWaterfallRectsByRotation(static_cast(10), displayHeight, displayWidth); + ASSERT_FALSE(controller->waterfallDisplayAreaRects_.isUninitialized()); +} + +/** + * @tc.name: CheckBoundingRectsBoundary + * @tc.desc: CheckBoundingRectsBoundary + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, CheckBoundingRectsBoundary, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + std::vector boundingRects; + controller->CheckBoundingRectsBoundary(displayId, boundingRects); + ASSERT_TRUE(boundingRects.empty()); +} + +/** + * @tc.name: CalcCutoutBoundingRect + * @tc.desc: CalcCutoutBoundingRect success + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, CalcCutoutBoundingRect, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + std::string svgPath = "M 100,100 m -75,0 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0 z"; + DMRect rect = controller->CalcCutoutBoundingRect(svgPath); + DMRect emptyRect = {0, 0, 0, 0}; + ASSERT_NE(rect, emptyRect); +} + +/** + * @tc.name: TransferBoundingRectsByRotation01 + * @tc.desc: TransferBoundingRectsByRotation empty + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, TransferBoundingRectsByRotation01, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + DisplayId id = 10; + std::vector boundingRects; + controller->TransferBoundingRectsByRotation(id, boundingRects); + ASSERT_TRUE(boundingRects.empty()); +} + +/** + * @tc.name: TransferBoundingRectsByRotation02 + * @tc.desc: TransferBoundingRectsByRotation empty + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, TransferBoundingRectsByRotation02, Function | SmallTest | Level1) +{ + sptr controller = new DisplayCutoutController(); + DisplayId id = 10; + std::vector emptyRects; + controller->boundingRects_[id] = emptyRects; + std::vector boundingRects; + controller->TransferBoundingRectsByRotation(id, boundingRects); + ASSERT_TRUE(boundingRects.empty()); +} + +/** + * @tc.name: TransferBoundingRectsByRotation03 + * @tc.desc: TransferBoundingRectsByRotation success + * @tc.type: FUNC + */ +HWTEST_F(DisplayCutoutControllerTest, TransferBoundingRectsByRotation03, Function | SmallTest | Level1) +{ + DisplayId id = 11; + ScreenId sid = 12; + std::string name = "abstract_display_test"; + SupportedScreenModes modesInfo; + modesInfo.width_ = 2160; + modesInfo.height_ = 1600; + modesInfo.refreshRate_ = 60; + sptr info = new SupportedScreenModes(modesInfo); + sptr absScreenController; + sptr absScreen; + absScreenController = nullptr; + absScreen = new AbstractScreen(absScreenController, name, sid, 1); + auto displayController = DisplayManagerService::GetInstance().abstractDisplayController_; + + sptr absDisplay = new AbstractDisplay(id, name, info, absScreen); + absDisplay->RequestRotation(Rotation::ROTATION_0); + displayController->abstractDisplayMap_.insert((std::make_pair(id, absDisplay))); + + sptr controller = new DisplayCutoutController(); + std::vector dmRects; + DMRect rect = {1, 1, 100, 100}; + dmRects.emplace_back(rect); + controller->boundingRects_[id] = dmRects; + ASSERT_FALSE(controller->boundingRects_.count(id) == 0); + ASSERT_FALSE(controller->boundingRects_[id].empty()); + ASSERT_NE(DisplayManagerServiceInner::GetInstance().GetDisplayById(id), nullptr); + std::vector boundingRects; + controller->TransferBoundingRectsByRotation(id, boundingRects); + + absScreenController = DisplayManagerService::GetInstance().abstractScreenController_; + absScreenController->dmsScreenMap_.insert(std::make_pair(sid, absScreen)); + absScreen->modes_.emplace_back(info); + absDisplay->RequestRotation(Rotation::ROTATION_180); + controller->TransferBoundingRectsByRotation(id, boundingRects); + + absDisplay->RequestRotation(Rotation::ROTATION_90); + controller->TransferBoundingRectsByRotation(id, boundingRects); + + absDisplay->RequestRotation(Rotation::ROTATION_270); + controller->TransferBoundingRectsByRotation(id, boundingRects); + ASSERT_FALSE(boundingRects.empty()); + displayController->abstractDisplayMap_.clear(); + absScreenController->dmsScreenMap_.clear(); +} +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/dmserver/test/unittest/display_dumper_test.cpp b/window_manager/dmserver/test/unittest/display_dumper_test.cpp new file mode 100644 index 0000000..cee6944 --- /dev/null +++ b/window_manager/dmserver/test/unittest/display_dumper_test.cpp @@ -0,0 +1,350 @@ +/* + * 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 "display_dumper.h" +#include "display_manager_service.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayDumperTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void DisplayDumperTest::SetUpTestCase() +{ +} + +void DisplayDumperTest::TearDownTestCase() +{ +} + +void DisplayDumperTest::SetUp() +{ +} + +void DisplayDumperTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Dump01 + * @tc.desc: Dump + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump01, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 1; + std::vector args; + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_OK); +} + +/** + * @tc.name: Dump02 + * @tc.desc: Dump fd less 0 + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump02, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = -1; + std::vector args; + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_ERROR_INVALID_PARAM); +} + +/** + * @tc.name: Dump03 + * @tc.desc: Dump one param with '-h' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump03, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 3; + std::vector args; + const std::u16string DUMP_HELP = u"-h"; + args.emplace_back(DUMP_HELP); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_TRUE(ret == DMError::DM_OK || ret == DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump04 + * @tc.desc: Dump one param with '-x' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump04, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 4; + std::vector args; + const std::u16string DUMP_HELP = u"-x"; + args.emplace_back(DUMP_HELP); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_TRUE(ret == DMError::DM_OK || ret == DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump05 + * @tc.desc: Dump two param with '-s -a' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump05, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 5; + std::vector args; + const std::u16string DUMP_SCREEN = u"-s"; + const std::u16string DUMP_ALL = u"-a"; + args.emplace_back(DUMP_SCREEN); + args.emplace_back(DUMP_ALL); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump06 + * @tc.desc: Dump two param with '-d -a' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump06, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 6; + std::vector args; + const std::u16string DUMP_DISPLAY = u"-d"; + const std::u16string DUMP_ALL = u"-a"; + args.emplace_back(DUMP_DISPLAY); + args.emplace_back(DUMP_ALL); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_TRUE(ret == DMError::DM_OK || ret == DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump07 + * @tc.desc: Dump two param with '-s 1' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump071, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 71; + std::vector args; + const std::u16string DUMP_SCREEN = u"-s"; + const std::u16string DUMP_NUMBER = u"0"; + args.emplace_back(DUMP_SCREEN); + args.emplace_back(DUMP_NUMBER); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump07 + * @tc.desc: Dump two param with '-s -1' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump07, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 7; + std::vector args; + const std::u16string DUMP_SCREEN = u"-s"; + const std::u16string DUMP_NUMBER = u"-1"; + args.emplace_back(DUMP_SCREEN); + args.emplace_back(DUMP_NUMBER); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump08 + * @tc.desc: Dump two param with '-d 1' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump08, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 8; + std::vector args; + const std::u16string DUMP_DISPLAY = u"-d"; + const std::u16string DUMP_NUMBER = u"1"; + args.emplace_back(DUMP_DISPLAY); + args.emplace_back(DUMP_NUMBER); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump09 + * @tc.desc: Dump two param with '-d -1' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump09, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 9; + std::vector args; + const std::u16string DUMP_DISPLAY = u"-d"; + const std::u16string DUMP_NUMBER = u"-1"; + args.emplace_back(DUMP_DISPLAY); + args.emplace_back(DUMP_NUMBER); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_EQ(ret, DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: Dump10 + * @tc.desc: Dump three param with '-d -a 1' + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, Dump10, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + int fd = 10; + std::vector args; + const std::u16string DUMP_DISPLAY = u"-d"; + const std::u16string DUMP_ALL = u"-a"; + const std::u16string DUMP_NUMBER = u"1"; + args.emplace_back(DUMP_DISPLAY); + args.emplace_back(DUMP_ALL); + args.emplace_back(DUMP_NUMBER); + DMError ret = displayDumper->Dump(fd, args); + ASSERT_TRUE(ret == DMError::DM_OK || ret == DMError::DM_ERROR_UNKNOWN); +} + +/** + * @tc.name: IsValidDigitString01 + * @tc.desc: IsValidDigitString "06w" + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, IsValidDigitString01, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + std::string idStr = "06w"; + bool ret = displayDumper->IsValidDigitString(idStr); + ASSERT_EQ(ret, false); +} + +/** + * @tc.name: IsValidDigitString02 + * @tc.desc: IsValidDigitString "96+" + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, IsValidDigitString02, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + std::string idStr = "96+"; + bool ret = displayDumper->IsValidDigitString(idStr); + ASSERT_EQ(ret, false); +} + +/** + * @tc.name: IsValidDigitString03 + * @tc.desc: IsValidDigitString empty + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, IsValidDigitString03, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + std::string idStr; + bool ret = displayDumper->IsValidDigitString(idStr); + ASSERT_EQ(ret, false); +} + +/** + * @tc.name: DumpAllScreenInfo01 + * @tc.desc: DumpAllScreenInfo + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, DumpAllScreenInfo01, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + std::string dumpInfo; + displayDumper->DumpAllScreenInfo(dumpInfo); +} + +/** + * @tc.name: GetDisplayInfo01 + * @tc.desc: GetDisplayInfo + * @tc.type: FUNC + */ +HWTEST_F(DisplayDumperTest, GetDisplayInfo01, Function | SmallTest | Level1) +{ + sptr displayDumper; + displayDumper = new DisplayDumper(DisplayManagerService::GetInstance().abstractDisplayController_, + DisplayManagerService::GetInstance().abstractScreenController_, + DisplayManagerService::GetInstance().mutex_); + std::ostringstream oss; + displayDumper->GetDisplayInfo(nullptr, oss); +} +} +} +} \ No newline at end of file diff --git a/window_manager/dmserver/test/unittest/display_manager_agent_controller_test.cpp b/window_manager/dmserver/test/unittest/display_manager_agent_controller_test.cpp new file mode 100644 index 0000000..0c8831b --- /dev/null +++ b/window_manager/dmserver/test/unittest/display_manager_agent_controller_test.cpp @@ -0,0 +1,146 @@ +/* + * 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 "display_manager_agent_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayManagerAgentControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void DisplayManagerAgentControllerTest::SetUpTestCase() +{ +} + +void DisplayManagerAgentControllerTest::TearDownTestCase() +{ +} + +void DisplayManagerAgentControllerTest::SetUp() +{ +} + +void DisplayManagerAgentControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnScreenConnect + * @tc.desc: OnScreenConnect test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnScreenConnect, Function | SmallTest | Level3) +{ + sptr screenInfo = nullptr; + DisplayManagerAgentController::GetInstance().OnScreenConnect(screenInfo); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); +} +/** + * @tc.name: OnScreenChange + * @tc.desc: OnScreenChange test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnScreenChange, Function | SmallTest | Level3) +{ + sptr screenInfo = nullptr; + DisplayManagerAgentController::GetInstance().OnScreenChange(screenInfo, ScreenChangeEvent::UPDATE_ROTATION); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); +} +/** + * @tc.name: OnScreenGroupChange + * @tc.desc: OnScreenChange test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnScreenGroupChange, Function | SmallTest | Level3) +{ + sptr screenInfo = nullptr; + std::string trigger; + DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, + screenInfo, ScreenGroupChangeEvent::ADD_TO_GROUP); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); + std::vector> screenInfos; + screenInfos.push_back(screenInfo); + DisplayManagerAgentController::GetInstance().OnScreenGroupChange(trigger, + screenInfos, ScreenGroupChangeEvent::ADD_TO_GROUP); +} +/** + * @tc.name: OnDisplayCreate + * @tc.desc: OnDisplayCreate test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnDisplayCreate, Function | SmallTest | Level3) +{ + sptr displayInfo; + DisplayManagerAgentController::GetInstance().OnDisplayCreate(displayInfo); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); +} +/** + * @tc.name: OnDisplayDestroy + * @tc.desc: OnDisplayDestroy test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnDisplayDestroy, Function | SmallTest | Level3) +{ + DisplayId displayId = 0; + DisplayManagerAgentController::GetInstance().OnDisplayDestroy(displayId); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); +} +/** + * @tc.name: OnDisplayChange + * @tc.desc: OnDisplayChange test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnDisplayChange, Function | SmallTest | Level3) +{ + sptr displayInfo = nullptr; + DisplayManagerAgentController::GetInstance().OnDisplayChange(displayInfo, DisplayChangeEvent::UNKNOWN); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); + displayInfo = new DisplayInfo(); + DisplayManagerAgentController::GetInstance().OnDisplayChange(displayInfo, DisplayChangeEvent::UNKNOWN); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); +} +/** + * @tc.name: OnScreenshot + * @tc.desc: OnScreenshot test + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerAgentControllerTest, OnScreenshot, Function | SmallTest | Level3) +{ + sptr info = nullptr; + DisplayManagerAgentController::GetInstance().OnScreenshot(info); + ASSERT_EQ(0, DisplayManagerAgentController::GetInstance(). + dmAgentContainer_.GetAgentsByType(DisplayManagerAgentType::SCREEN_EVENT_LISTENER).size()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/test/unittest/display_manager_config_test.cpp b/window_manager/dmserver/test/unittest/display_manager_config_test.cpp new file mode 100644 index 0000000..b089c38 --- /dev/null +++ b/window_manager/dmserver/test/unittest/display_manager_config_test.cpp @@ -0,0 +1,167 @@ +/* + * 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 "display_manager_config.h" +#include "display_manager_config.cpp" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayManagerConfigTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void DisplayManagerConfigTest::SetUpTestCase() +{ +} + +void DisplayManagerConfigTest::TearDownTestCase() +{ +} + +void DisplayManagerConfigTest::SetUp() +{ +} + +void DisplayManagerConfigTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: IsNumber + * @tc.desc: test function : IsNumber + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerConfigTest, IsNumber, Function | SmallTest | Level1) +{ + bool result = DisplayManagerConfig::IsNumber("123"); + ASSERT_EQ(true, result); + result = DisplayManagerConfig::IsNumber("a123"); + ASSERT_EQ(false, result); +} + +/** + * @tc.name: GetConfigPath + * @tc.desc: test function : GetConfigPath + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerConfigTest, GetConfigPath, Function | SmallTest | Level1) +{ + auto result = DisplayManagerConfig::GetConfigPath(""); + ASSERT_STRNE("/system/", result.c_str()); + + result = DisplayManagerConfig::GetConfigPath("a.xml"); + ASSERT_STREQ("/system/a.xml", result.c_str()); +} + +/** + * @tc.name: ReadEnableConfigInfo + * @tc.desc: test function : ReadEnableConfigInfo + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerConfigTest, ReadEnableConfigInfo, Function | SmallTest | Level1) +{ + DisplayManagerConfig::enableConfig_.clear(); + + auto configFilePath = DisplayManagerConfig::GetConfigPath("etc/window/resources/display_manager_config.xml"); + xmlDocPtr docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS); + if (docPtr == nullptr) { + return; + } + + xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); + if (rootPtr == nullptr || rootPtr->name == nullptr || + xmlStrcmp(rootPtr->name, reinterpret_cast("Configs"))) { + xmlFreeDoc(docPtr); + return; + } + for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { + if (!DisplayManagerConfig::IsValidNode(*curNodePtr)) { + continue; + } + + auto nodeName = curNodePtr->name; + if (!xmlStrcmp(nodeName, reinterpret_cast("isWaterfallDisplay"))) { + DisplayManagerConfig::ReadEnableConfigInfo(curNodePtr); + continue; + } + + if (!xmlStrcmp(nodeName, reinterpret_cast("dpi"))) { + DisplayManagerConfig::ReadEnableConfigInfo(curNodePtr); + continue; + } + } + + DisplayManagerConfig::DumpConfig(); + xmlFreeDoc(docPtr); +} + +/** + * @tc.name: ReadStringConfigInfo + * @tc.desc: test function : ReadStringConfigInfo + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerConfigTest, ReadStringConfigInfo, Function | SmallTest | Level1) +{ + DisplayManagerConfig::enableConfig_.clear(); + + auto configFilePath = DisplayManagerConfig::GetConfigPath("etc/window/resources/display_manager_config.xml"); + xmlDocPtr docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS); + if (docPtr == nullptr) { + return; + } + + xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); + if (rootPtr == nullptr || rootPtr->name == nullptr || + xmlStrcmp(rootPtr->name, reinterpret_cast("Configs"))) { + xmlFreeDoc(docPtr); + return; + } + for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { + if (!DisplayManagerConfig::IsValidNode(*curNodePtr)) { + continue; + } + + auto nodeName = curNodePtr->name; + if (!xmlStrcmp(nodeName, reinterpret_cast("defaultDisplayCutoutPath"))) { + DisplayManagerConfig::ReadStringConfigInfo(curNodePtr); + continue; + } + + if (!xmlStrcmp(nodeName, reinterpret_cast("dpi"))) { + DisplayManagerConfig::ReadStringConfigInfo(curNodePtr); + continue; + } + } + + DisplayManagerConfig::DumpConfig(); + xmlFreeDoc(docPtr); +} + +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dmserver/test/unittest/display_manager_proxy_test.cpp b/window_manager/dmserver/test/unittest/display_manager_proxy_test.cpp new file mode 100644 index 0000000..fd01c32 --- /dev/null +++ b/window_manager/dmserver/test/unittest/display_manager_proxy_test.cpp @@ -0,0 +1,299 @@ +/* + * 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 "display_manager_proxy.h" +#include "iremote_object_mocker.h" + +#include + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using RemoteMocker = MockIRemoteObject; +class DisplayManagerProxyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void DisplayManagerProxyTest::SetUpTestCase() +{ +} + +void DisplayManagerProxyTest::TearDownTestCase() +{ +} + +void DisplayManagerProxyTest::SetUp() +{ +} + +void DisplayManagerProxyTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetDefaultDisplayInfo + * @tc.desc: test DisplayManagerProxy::GetDefaultDisplayInfo + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, GetDefaultDisplayInfo01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto displayInfo1 = proxy1.GetDefaultDisplayInfo(); + ASSERT_EQ(nullptr, displayInfo1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + auto displayInfo2 = proxy2.GetDefaultDisplayInfo(); + ASSERT_EQ(nullptr, displayInfo2); + + remoteMocker->sendRequestResult_ = 1; + auto displayInfo3 = proxy2.GetDefaultDisplayInfo(); + ASSERT_EQ(nullptr, displayInfo3); +} +/** + * @tc.name: GetDisplayInfoById01 + * @tc.desc: test DisplayManagerProxy::GetDisplayInfoById + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, GetDisplayInfoById01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto displayInfo1 = proxy1.GetDisplayInfoById(0); + ASSERT_EQ(nullptr, displayInfo1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + auto displayInfo2 = proxy2.GetDisplayInfoById(0); + ASSERT_EQ(nullptr, displayInfo2); + + remoteMocker->sendRequestResult_ = 1; + auto displayInfo3 = proxy2.GetDisplayInfoById(0); + ASSERT_EQ(nullptr, displayInfo3); +} +/** + * @tc.name: GetDisplayInfoByScreen01 + * @tc.desc: test DisplayManagerProxy::GetDisplayInfoByScreen + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, GetDisplayInfoByScreen01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto displayInfo1 = proxy1.GetDisplayInfoByScreen(0); + ASSERT_EQ(nullptr, displayInfo1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + auto displayInfo2 = proxy2.GetDisplayInfoByScreen(0); + ASSERT_EQ(nullptr, displayInfo2); + + remoteMocker->sendRequestResult_ = 1; + auto displayInfo3 = proxy2.GetDisplayInfoByScreen(0); + ASSERT_EQ(nullptr, displayInfo3); +} +/** + * @tc.name: CreateVirtualScreen01 + * @tc.desc: test DisplayManagerProxy::CreateVirtualScreen + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, CreateVirtualScreen01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + VirtualScreenOption virtualOption1; + virtualOption1.name_ = "testVirtualOption"; + sptr displayManagerAgent1 = new RemoteMocker(); + auto screenId1 = proxy1.CreateVirtualScreen(virtualOption1, displayManagerAgent1); + ASSERT_EQ(SCREEN_ID_INVALID, screenId1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + VirtualScreenOption virtualOption2; + virtualOption2.name_ = "testVirtualOption"; + sptr displayManagerAgent2 = new RemoteMocker(); + auto screenId2 = proxy2.CreateVirtualScreen(virtualOption2, displayManagerAgent2); + ASSERT_EQ(0, screenId2); + + remoteMocker->sendRequestResult_ = 1; + auto screenId3 = proxy2.CreateVirtualScreen(virtualOption2, displayManagerAgent2); + ASSERT_EQ(SCREEN_ID_INVALID, screenId3); +} +/** + * @tc.name: DestroyVirtualScreen01 + * @tc.desc: test DisplayManagerProxy::DestroyVirtualScreen + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, DestroyVirtualScreen01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto result1 = proxy1.DestroyVirtualScreen(0); + ASSERT_EQ(DMError::DM_ERROR_REMOTE_CREATE_FAILED, result1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + auto result2 = proxy2.DestroyVirtualScreen(0); + ASSERT_EQ(DMError::DM_OK, result2); + + remoteMocker->sendRequestResult_ = 1; + auto result3 = proxy2.DestroyVirtualScreen(0); + ASSERT_EQ(DMError::DM_ERROR_IPC_FAILED, result3); +} +/** + * @tc.name: SetVirtualScreenSurface01 + * @tc.desc: test DisplayManagerProxy::SetVirtualScreenSurface + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, SetVirtualScreenSurface01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto result1 = proxy1.SetVirtualScreenSurface(0, nullptr); + ASSERT_EQ(DMError::DM_ERROR_REMOTE_CREATE_FAILED, result1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + auto result2 = proxy2.SetVirtualScreenSurface(0, nullptr); + ASSERT_EQ(DMError::DM_OK, result2); + sptr surface = OHOS::Surface::CreateSurfaceAsConsumer(); + auto result3 = proxy2.SetVirtualScreenSurface(0, surface); + ASSERT_EQ(DMError::DM_OK, result3); + + remoteMocker->sendRequestResult_ = 1; + auto result4 = proxy2.SetVirtualScreenSurface(0, surface); + ASSERT_EQ(DMError::DM_ERROR_IPC_FAILED, result4); +} +/** + * @tc.name: SetOrientation01 + * @tc.desc: test DisplayManagerProxy::SetOrientation + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, SetOrientation01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto result1 = proxy1.SetOrientation(0, Orientation::VERTICAL); + ASSERT_EQ(false, result1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + auto result2 = proxy2.SetOrientation(0, Orientation::VERTICAL); + ASSERT_EQ(false, result2); + + remoteMocker->sendRequestResult_ = 1; + auto result3 = proxy2.SetOrientation(0, Orientation::VERTICAL); + ASSERT_EQ(false, result3); +} +/** + * @tc.name: GetDisplaySnapshot01 + * @tc.desc: test DisplayManagerProxy::GetDisplaySnapshot + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, GetDisplaySnapshot01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto result1 = proxy1.GetDisplaySnapshot(0); + ASSERT_EQ(nullptr, result1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + + auto result2 = proxy2.GetDisplaySnapshot(0); + ASSERT_EQ(nullptr, result2); + remoteMocker->sendRequestResult_ = 1; + auto result3 = proxy2.GetDisplaySnapshot(0); + ASSERT_EQ(nullptr, result3); +} +/** + * @tc.name: GetScreenSupportedColorGamuts01 + * @tc.desc: test DisplayManagerProxy::GetScreenSupportedColorGamuts + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, GetScreenSupportedColorGamuts01, Function | SmallTest | Level1) +{ + std::vector gamutVector; + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + auto result1 = proxy1.GetScreenSupportedColorGamuts(0, gamutVector); + ASSERT_EQ(DMError::DM_ERROR_NULLPTR, result1); + gamutVector.clear(); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + auto result2 = proxy2.GetScreenSupportedColorGamuts(0, gamutVector); + ASSERT_EQ(DMError::DM_OK, result2); + remoteMocker->sendRequestResult_ = 1; + auto result3 = proxy2.GetScreenSupportedColorGamuts(0, gamutVector); + ASSERT_EQ(DMError::DM_ERROR_IPC_FAILED, result3); +} +/** + * @tc.name: GetScreenColorGamut01 + * @tc.desc: test DisplayManagerProxy::GetScreenColorGamut + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerProxyTest, GetScreenColorGamut01, Function | SmallTest | Level1) +{ + DisplayManagerProxy proxy1(nullptr); + ASSERT_EQ(nullptr, proxy1.remoteObject_); + ScreenColorGamut screenColorGamut; + auto result1 = proxy1.GetScreenColorGamut(0, screenColorGamut); + ASSERT_EQ(DMError::DM_ERROR_NULLPTR, result1); + + sptr remoteMocker = new RemoteMocker(); + DisplayManagerProxy proxy2(remoteMocker); + ASSERT_EQ(static_cast>(remoteMocker), proxy2.remoteObject_); + screenColorGamut = ScreenColorGamut::COLOR_GAMUT_ADOBE_RGB; + auto result2 = proxy2.GetScreenColorGamut(0, screenColorGamut); + ASSERT_EQ(DMError::DM_OK, result2); + ASSERT_EQ(ScreenColorGamut::COLOR_GAMUT_NATIVE, screenColorGamut); + + screenColorGamut = ScreenColorGamut::COLOR_GAMUT_ADOBE_RGB; + remoteMocker->sendRequestResult_ = 1; + auto result3 = proxy2.GetScreenColorGamut(0, screenColorGamut); + ASSERT_EQ(DMError::DM_ERROR_IPC_FAILED, result3); + ASSERT_EQ(ScreenColorGamut::COLOR_GAMUT_ADOBE_RGB, screenColorGamut); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/dmserver/test/unittest/display_manager_service_test.cpp b/window_manager/dmserver/test/unittest/display_manager_service_test.cpp new file mode 100644 index 0000000..196b66b --- /dev/null +++ b/window_manager/dmserver/test/unittest/display_manager_service_test.cpp @@ -0,0 +1,395 @@ +/* + * 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 "display_manager_config.h" +#include "display_manager_service.h" +#include "display_manager_agent_default.h" +#include "common_test_utils.h" + + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayManagerServiceTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void SetAceessTokenPermission(const std::string processName); + static sptr dms_; +}; + +sptr DisplayManagerServiceTest::dms_ = nullptr; + +void DisplayManagerServiceTest::SetUpTestCase() +{ + dms_ = new DisplayManagerService(); + + dms_->abstractScreenController_->defaultRsScreenId_ = 0; + dms_->abstractScreenController_->screenIdManager_.rs2DmsScreenIdMap_.clear(); + dms_->abstractScreenController_->screenIdManager_.rs2DmsScreenIdMap_ = { + {0, 0} + }; + dms_->abstractScreenController_->screenIdManager_.dms2RsScreenIdMap_.clear(); + dms_->abstractScreenController_->screenIdManager_.dms2RsScreenIdMap_ = { + {0, 0} + }; + const char** perms = new const char *[1]; + perms[0] = "ohos.permission.CAPTURE_SCREEN"; + CommonTestUtils::SetAceessTokenPermission("DisplayManagerServiceTest", perms, 1); +} + +void DisplayManagerServiceTest::TearDownTestCase() +{ + dms_ = nullptr; +} + +void DisplayManagerServiceTest::SetUp() +{ +} + +void DisplayManagerServiceTest::TearDown() +{ +} + +class DisplayChangeListenerTest : public IDisplayChangeListener { +public: + void OnDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) override {}; + void OnScreenshot(DisplayId displayId) override {}; +}; + +class WindowInfoQueriedListenerTest : public IWindowInfoQueriedListener { +public: + void HasPrivateWindow(DisplayId id, bool& hasPrivateWindow) override {}; +}; + +namespace { +/** + * @tc.name: Dump + * @tc.desc: DMS dump + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, Dump, Function | SmallTest | Level3) +{ + std::vector args; + ASSERT_EQ(static_cast(DMError::DM_ERROR_INVALID_PARAM), dms_->Dump(-1, args)); +} + +/** + * @tc.name: Config + * @tc.desc: DMS config + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, Config, Function | SmallTest | Level3) +{ + DisplayManagerConfig::intNumbersConfig_.clear(); + DisplayManagerConfig::enableConfig_.clear(); + DisplayManagerConfig::stringConfig_.clear(); + dms_->ConfigureDisplayManagerService(); + + DisplayManagerConfig::intNumbersConfig_ = { + {"dpi", {320}}, + {"defaultDeviceRotationOffset", {90}}, + {"curvedScreenBoundary", {20, 30, 40, 50}}, + {"buildInDefaultOrientation", {90}}, + {"waterfallAreaCompressionSizeWhenHorzontal", {90}} + }; + DisplayManagerConfig::enableConfig_ = { + {"isWaterfallDisplay", false}, + {"isWaterfallAreaCompressionEnableWhenHorizontal", false} + }; + DisplayManagerConfig::stringConfig_ = { + {"defaultDisplayCutoutPath", "/path"} + }; + + dms_->ConfigureDisplayManagerService(); +} + +/** + * @tc.name: DisplayChange + * @tc.desc: DMS display change + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, DisplayChange, Function | SmallTest | Level3) +{ + std::map> displayInfoMap; + sptr displayInfo = new DisplayInfo(); + + dms_->RegisterDisplayChangeListener(nullptr); + dms_->NotifyDisplayStateChange(0, nullptr, displayInfoMap, DisplayStateChangeType::SIZE_CHANGE); + dms_->NotifyScreenshot(0); + + sptr displayChangeListener = new DisplayChangeListenerTest(); + ASSERT_NE(nullptr, displayChangeListener); + dms_->RegisterDisplayChangeListener(displayChangeListener); + dms_->NotifyDisplayStateChange(0, displayInfo, displayInfoMap, DisplayStateChangeType::SIZE_CHANGE); + dms_->NotifyScreenshot(0); + + dms_->NotifyDisplayEvent(DisplayEvent::UNLOCK); + + std::vector displayIds; + dms_->SetFreeze(displayIds, false); + + sptr screenChangeListener = new IRSScreenChangeListener(); + dms_->RegisterRSScreenChangeListener(screenChangeListener); + dms_->abstractScreenController_->rSScreenChangeListener_ = nullptr; +} + +/** + * @tc.name: HasPrivateWindow + * @tc.desc: DMS has private window + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, HasPrivateWindow, Function | SmallTest | Level3) +{ + bool hasPrivateWindow = false; + dms_->abstractDisplayController_->abstractDisplayMap_.clear(); + dms_->abstractDisplayController_->abstractDisplayMap_ = { + {1, nullptr} + }; + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->HasPrivateWindow(0, hasPrivateWindow)); + + dms_->RegisterWindowInfoQueriedListener(nullptr); + ASSERT_EQ(DMError::DM_ERROR_NULLPTR, dms_->HasPrivateWindow(1, hasPrivateWindow)); + + sptr windowInfoQueriedListener = new WindowInfoQueriedListenerTest(); + ASSERT_NE(nullptr, windowInfoQueriedListener); + dms_->RegisterWindowInfoQueriedListener(windowInfoQueriedListener); + ASSERT_EQ(DMError::DM_OK, dms_->HasPrivateWindow(1, hasPrivateWindow)); +} + +/** + * @tc.name: GetDisplayInfo + * @tc.desc: DMS get display info + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, GetDisplayInfo, Function | SmallTest | Level2) +{ + // build abstractDisplayController_ env + std::string name = "testDisplay"; + sptr info = new SupportedScreenModes(); + sptr absScreen = new AbstractScreen(dms_->abstractScreenController_, name, 0, 0); + sptr absDisplay = new AbstractDisplay(0, name, info, absScreen); + + dms_->abstractDisplayController_->abstractDisplayMap_.clear(); + ASSERT_EQ(nullptr, dms_->GetDefaultDisplayInfo()); + + dms_->abstractDisplayController_->abstractDisplayMap_ = { + {0, absDisplay} + }; + ASSERT_EQ(absDisplay->name_, dms_->GetDefaultDisplayInfo()->name_); + + ASSERT_EQ(nullptr, dms_->GetDisplayInfoById(1)); + ASSERT_EQ(absDisplay->name_, dms_->GetDisplayInfoById(0)->name_); + + ASSERT_EQ(nullptr, dms_->GetDisplayInfoByScreen(1)); + ASSERT_EQ(absDisplay->name_, dms_->GetDisplayInfoByScreen(0)->name_); + + absDisplay->screenId_ = 0; + ASSERT_EQ(1, dms_->GetRSScreenNum()); + + ASSERT_EQ(SCREEN_ID_INVALID, dms_->GetScreenIdByDisplayId(1)); + ASSERT_EQ(0, dms_->GetScreenIdByDisplayId(0)); + + ASSERT_EQ(nullptr, dms_->GetScreenInfoById(1)); + ASSERT_EQ(nullptr, dms_->GetScreenInfoById(0)); + + ASSERT_EQ(nullptr, dms_->GetScreenGroupInfoById(1)); + ASSERT_EQ(nullptr, dms_->GetScreenGroupInfoById(0)); + + ASSERT_EQ(SCREEN_ID_INVALID, dms_->GetScreenGroupIdByScreenId(1)); + ASSERT_EQ(SCREEN_ID_INVALID, dms_->GetScreenGroupIdByScreenId(0)); + + dms_->GetAllDisplayIds(); + dms_->GetAllScreenInfos(); + + dms_->abstractDisplayController_->abstractDisplayMap_.clear(); +} + +/** + * @tc.name: VirtualScreen + * @tc.desc: DMS virtual screen + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, VirtualScreen, Function | SmallTest | Level3) +{ + VirtualScreenOption option; + ASSERT_EQ(-1, dms_->CreateVirtualScreen(option, nullptr)); + + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetVirtualScreenSurface(-1, nullptr)); + ASSERT_EQ(DMError::DM_ERROR_RENDER_SERVICE_FAILED, dms_->SetVirtualScreenSurface(0, nullptr)); + + std::vector screens; + dms_->RemoveVirtualScreenFromGroup(screens); +} + +/** + * @tc.name: OrientationAndRotation + * @tc.desc: DMS set oritation and rotation + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, OrientationAndRotation, Function | SmallTest | Level3) +{ + Orientation orientation = Orientation::UNSPECIFIED; + ASSERT_EQ(false, dms_->SetOrientation(0, orientation)); + ASSERT_EQ(false, dms_->SetOrientationFromWindow(0, orientation)); + Rotation rotation = Rotation::ROTATION_0; + ASSERT_EQ(false, dms_->SetRotationFromWindow(0, rotation)); +} + +/** + * @tc.name: ScreenColor + * @tc.desc: DMS screen color + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, ScreenColor, Function | SmallTest | Level3) +{ + std::vector colorGamuts; + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->GetScreenSupportedColorGamuts(SCREEN_ID_INVALID, colorGamuts)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->GetScreenSupportedColorGamuts(0, colorGamuts)); + + ScreenColorGamut colorGamut = ScreenColorGamut::COLOR_GAMUT_SRGB; + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->GetScreenColorGamut(SCREEN_ID_INVALID, colorGamut)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->GetScreenColorGamut(0, colorGamut)); + + colorGamut = ScreenColorGamut::COLOR_GAMUT_SRGB; + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenColorGamut(SCREEN_ID_INVALID, colorGamut)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenColorGamut(0, colorGamut)); + + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenColorGamut(SCREEN_ID_INVALID, 0)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenColorGamut(0, 0)); + + ScreenGamutMap gamutMap; + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->GetScreenGamutMap(SCREEN_ID_INVALID, gamutMap)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->GetScreenGamutMap(0, gamutMap)); + + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenGamutMap(SCREEN_ID_INVALID, gamutMap)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenGamutMap(0, gamutMap)); + + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenColorTransform(SCREEN_ID_INVALID)); + ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, dms_->SetScreenColorTransform(0)); +} + +/** + * @tc.name: RegisterDisplayManagerAgent + * @tc.desc: DMS rigister display manager agent + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, RegisterDisplayManagerAgent, Function | SmallTest | Level3) +{ + sptr displayManagerAgent = new DisplayManagerAgentDefault(); + DisplayManagerAgentType type = DisplayManagerAgentType::DISPLAY_STATE_LISTENER; + + ASSERT_EQ(false, dms_->RegisterDisplayManagerAgent(nullptr, type)); + ASSERT_EQ(false, dms_->UnregisterDisplayManagerAgent(nullptr, type)); + + ASSERT_EQ(false, dms_->UnregisterDisplayManagerAgent(displayManagerAgent, type)); + + ASSERT_EQ(true, dms_->RegisterDisplayManagerAgent(displayManagerAgent, type)); + ASSERT_EQ(true, dms_->UnregisterDisplayManagerAgent(displayManagerAgent, type)); +} + +/** + * @tc.name: ScreenPower + * @tc.desc: DMS screen power + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, ScreenPower, Function | SmallTest | Level3) +{ + PowerStateChangeReason reason = PowerStateChangeReason::POWER_BUTTON; + ScreenPowerState state = ScreenPowerState::POWER_ON; + DisplayState displayState = DisplayState::ON; + + ASSERT_EQ(false, dms_->WakeUpBegin(reason)); + ASSERT_EQ(false, dms_->WakeUpEnd()); + + ASSERT_EQ(false, dms_->SuspendBegin(reason)); + ASSERT_EQ(false, dms_->SuspendEnd()); + + ASSERT_EQ(false, dms_->SetScreenPowerForAll(state, reason)); + + ASSERT_EQ(true, dms_->SetDisplayState(displayState)); + ASSERT_EQ(DisplayState::ON, dms_->GetDisplayState(0)); +} + +/** + * @tc.name: RsDisplayNode + * @tc.desc: DMS rs display node + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, RsDisplayNode, Function | SmallTest | Level3) +{ + struct RSSurfaceNodeConfig config; + std::shared_ptr surfaceNode = RSSurfaceNode::Create(config); + dms_->UpdateRSTree(DISPLAY_ID_INVALID, DISPLAY_ID_INVALID, surfaceNode, true, false); + dms_->UpdateRSTree(0, 0, surfaceNode, true, false); +} + +/** + * @tc.name: MirrorAndExpand + * @tc.desc: DMS mirror + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, MirrorAndExpand, Function | SmallTest | Level3) +{ + std::vector mirrorScreenIds; + ASSERT_EQ(SCREEN_ID_INVALID, dms_->MakeMirror(DISPLAY_ID_INVALID, mirrorScreenIds)); + + std::vector expandScreenIds; + std::vector startPoints; + ASSERT_EQ(SCREEN_ID_INVALID, dms_->MakeExpand(expandScreenIds, startPoints)); +} + +/** + * @tc.name: ScreenActiveMode + * @tc.desc: DMS mirror + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, ScreenActiveMode, Function | SmallTest | Level3) +{ + ASSERT_EQ(false, dms_->SetScreenActiveMode(SCREEN_ID_INVALID, 0)); +} + +/** + * @tc.name: VirtualPixelRatio + * @tc.desc: DMS mirror + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, VirtualPixelRatio, Function | SmallTest | Level3) +{ + ASSERT_EQ(false, dms_->SetVirtualPixelRatio(SCREEN_ID_INVALID, 0.f)); +} + +/** + * @tc.name: ScreenRotationLock + * @tc.desc: DMS mirror + * @tc.type: FUNC + */ +HWTEST_F(DisplayManagerServiceTest, ScreenRotationLock, Function | SmallTest | Level3) +{ + dms_->SetScreenRotationLocked(false); + ASSERT_EQ(false, dms_->IsScreenRotationLocked()); + ASSERT_NE(nullptr, dms_->GetCutoutInfo(10)); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/dmserver/test/unittest/screen_rotation_controller_test.cpp b/window_manager/dmserver/test/unittest/screen_rotation_controller_test.cpp new file mode 100644 index 0000000..253f5d5 --- /dev/null +++ b/window_manager/dmserver/test/unittest/screen_rotation_controller_test.cpp @@ -0,0 +1,557 @@ +/* + * 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 "display_manager_service.h" +#include "sensor_connector.h" +#include "screen_rotation_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class ScreenRotationControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void ScreenRotationControllerTest::SetUpTestCase() +{ + DisplayManagerService::GetInstance().abstractScreenController_->defaultRsScreenId_ = 0; + DisplayManagerService::GetInstance().abstractScreenController_->screenIdManager_.rs2DmsScreenIdMap_.clear(); + DisplayManagerService::GetInstance().abstractScreenController_->screenIdManager_.rs2DmsScreenIdMap_ = { + {0, 0} + }; + DisplayManagerService::GetInstance().abstractScreenController_->screenIdManager_.dms2RsScreenIdMap_.clear(); + DisplayManagerService::GetInstance().abstractScreenController_->screenIdManager_.dms2RsScreenIdMap_ = { + {0, 0} + }; + + std::string name = "testDisplay"; + sptr info = new SupportedScreenModes(); + info->width_ = 100; // 100 width + info->height_ = 200; // 200 height + sptr absScreen = new AbstractScreen(DisplayManagerService::GetInstance().abstractScreenController_, + name, 0, 0); + absScreen->activeIdx_ = 0; + absScreen->modes_.clear(); + absScreen->modes_ = { { info } }; + sptr absDisplay = new AbstractDisplay(0, name, info, absScreen); + DisplayManagerService::GetInstance().abstractDisplayController_->abstractDisplayMap_ = { + {0, absDisplay} + }; + DisplayManagerService::GetInstance().abstractScreenController_->dmsScreenMap_ = { + {0, absScreen} + }; +} + +void ScreenRotationControllerTest::TearDownTestCase() +{ +} + +void ScreenRotationControllerTest::SetUp() +{ +} + +void ScreenRotationControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GravitySensor + * @tc.desc: Subscribe and unsubscribe gravity sensor + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, GravitySensor, Function | SmallTest | Level3) +{ + GravitySensorSubscriber::isGravitySensorSubscribed_ = true; + GravitySensorSubscriber::SubscribeGravitySensor(); + ASSERT_EQ(true, GravitySensorSubscriber::isGravitySensorSubscribed_); + + GravitySensorSubscriber::isGravitySensorSubscribed_ = false; + GravitySensorSubscriber::SubscribeGravitySensor(); + + GravitySensorSubscriber::isGravitySensorSubscribed_ = false; + GravitySensorSubscriber::UnsubscribeGravitySensor(); + + GravitySensorSubscriber::isGravitySensorSubscribed_ = true; + GravitySensorSubscriber::UnsubscribeGravitySensor(); +} + +/** + * @tc.name: ScreenRotationLocked + * @tc.desc: Set and get screen rotation locked + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, ScreenRotationLocked, Function | SmallTest | Level3) +{ + ScreenRotationController::SetScreenRotationLocked(false); + ASSERT_EQ(false, ScreenRotationController::IsScreenRotationLocked()); + + ScreenRotationController::SetScreenRotationLocked(true); + ASSERT_EQ(true, ScreenRotationController::IsScreenRotationLocked()); +} + +/** + * @tc.name: DefaultDeviceRotationOffset + * @tc.desc: Set default device rotation offset + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, DefaultDeviceRotationOffset, Function | SmallTest | Level3) +{ + ScreenRotationController::defaultDeviceRotationOffset_ = 90; + + ScreenRotationController::SetDefaultDeviceRotationOffset(360); + ASSERT_EQ(90, ScreenRotationController::defaultDeviceRotationOffset_); + + ScreenRotationController::SetDefaultDeviceRotationOffset(10); + ASSERT_EQ(90, ScreenRotationController::defaultDeviceRotationOffset_); + + ScreenRotationController::SetDefaultDeviceRotationOffset(180); + ASSERT_EQ(180, ScreenRotationController::defaultDeviceRotationOffset_); +} + +/** + * @tc.name: CheckCallbackTimeInterval + * @tc.desc: Check callbcak time interval + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, CheckCallbackTimeInterval, Function | SmallTest | Level3) +{ + std::chrono::milliseconds ms = std::chrono::time_point_cast( + std::chrono::steady_clock::now()).time_since_epoch(); + long currentTimeInMillitm = ms.count(); + + GravitySensorSubscriber::lastCallbackTime_ = currentTimeInMillitm; + ASSERT_EQ(false, GravitySensorSubscriber::CheckCallbackTimeInterval()); + + GravitySensorSubscriber::lastCallbackTime_ = currentTimeInMillitm - 200; + ASSERT_EQ(true, GravitySensorSubscriber::CheckCallbackTimeInterval()); +} + +/** + * @tc.name: HandleGravitySensorEventCallback + * @tc.desc: Handel gravity sensor event callback + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, HandleGravitySensorEventCallback, Function | SmallTest | Level3) +{ + SensorEvent event; + GravityData data = {0.f, 0.f, 0.f}; + event.sensorTypeId = SENSOR_TYPE_ID_NONE; + event.data = reinterpret_cast(&data); + + std::chrono::milliseconds ms = std::chrono::time_point_cast( + std::chrono::system_clock::now()).time_since_epoch(); + long currentTimeInMillitm = ms.count(); + + GravitySensorSubscriber::lastCallbackTime_ = currentTimeInMillitm; + GravitySensorSubscriber::HandleGravitySensorEventCallback(&event); + + GravitySensorSubscriber::lastCallbackTime_ = currentTimeInMillitm - 200; + GravitySensorSubscriber::HandleGravitySensorEventCallback(&event); + + event.sensorTypeId = SENSOR_TYPE_ID_GRAVITY; + GravitySensorSubscriber::lastCallbackTime_ = currentTimeInMillitm - 200; + GravitySensorSubscriber::HandleGravitySensorEventCallback(&event); + + data.z = 1.f; + GravitySensorSubscriber::lastCallbackTime_ = currentTimeInMillitm - 200; + GravitySensorSubscriber::HandleGravitySensorEventCallback(&event); + ASSERT_EQ(DeviceRotation::INVALID, ScreenRotationController::lastSensorRotationConverted_); +} + +/** + * @tc.name: CalcRotationDegree + * @tc.desc: Calc rotation degree + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, CalcRotationDegree, Function | SmallTest | Level3) +{ + GravityData data0 = {0.f, 0.f, 0.f}; + ASSERT_EQ(270, GravitySensorSubscriber::CalcRotationDegree(&data0)); + + GravityData data1 = {0.f, 0.f, 1.f}; + ASSERT_EQ(-1, GravitySensorSubscriber::CalcRotationDegree(&data1)); + + GravityData data2 = {1.f, 1.f, 1.f}; + ASSERT_EQ(315, GravitySensorSubscriber::CalcRotationDegree(&data2)); +} + +/** + * @tc.name: CalcTargetDisplayRotation + * @tc.desc: Calc target display rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, CalcTargetDisplayRotation, Function | SmallTest | Level3) +{ + ScreenRotationController::ProcessRotationMapping(); + ScreenRotationController::currentDisplayRotation_ = Rotation::ROTATION_0; + + DeviceRotation deviceRitation = DeviceRotation::ROTATION_PORTRAIT; + + Orientation orientation = Orientation::SENSOR; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::SENSOR_VERTICAL; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::SENSOR_HORIZONTAL; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = true; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + ScreenRotationController::isScreenRotationLocked_ = false; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::AUTO_ROTATION_RESTRICTED; + ScreenRotationController::isScreenRotationLocked_ = true; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + ScreenRotationController::isScreenRotationLocked_ = false; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED; + ScreenRotationController::isScreenRotationLocked_ = true; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + ScreenRotationController::isScreenRotationLocked_ = false; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED; + ScreenRotationController::isScreenRotationLocked_ = true; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + ScreenRotationController::isScreenRotationLocked_ = false; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); + + orientation = Orientation::VERTICAL; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::CalcTargetDisplayRotation(orientation, deviceRitation)); +} + +/** + * @tc.name: ProcessAutoRotation + * @tc.desc: Process auto rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, ProcessAutoRotation, Function | SmallTest | Level3) +{ + ScreenRotationController::currentDisplayRotation_ = Rotation::ROTATION_90; + ScreenRotationController::ProcessRotationMapping(); + + DeviceRotation deviceRitation = DeviceRotation::ROTATION_LANDSCAPE; + ASSERT_EQ(Rotation::ROTATION_90, ScreenRotationController::ProcessAutoRotationPortraitOrientation(deviceRitation)); + deviceRitation = DeviceRotation::ROTATION_LANDSCAPE_INVERTED; + ASSERT_EQ(Rotation::ROTATION_90, ScreenRotationController::ProcessAutoRotationPortraitOrientation(deviceRitation)); + deviceRitation = DeviceRotation::ROTATION_PORTRAIT_INVERTED; + ASSERT_EQ(Rotation::ROTATION_180, ScreenRotationController::ProcessAutoRotationPortraitOrientation(deviceRitation)); + + deviceRitation = DeviceRotation::ROTATION_PORTRAIT; + ASSERT_EQ(Rotation::ROTATION_90, ScreenRotationController::ProcessAutoRotationLandscapeOrientation(deviceRitation)); + deviceRitation = DeviceRotation::ROTATION_PORTRAIT_INVERTED; + ASSERT_EQ(Rotation::ROTATION_90, ScreenRotationController::ProcessAutoRotationLandscapeOrientation(deviceRitation)); + deviceRitation = DeviceRotation::ROTATION_LANDSCAPE; + ASSERT_EQ(Rotation::ROTATION_90, ScreenRotationController::ProcessAutoRotationLandscapeOrientation(deviceRitation)); +} + +/** + * @tc.name: CalcDeviceRotation + * @tc.desc: Calc device rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, CalcDeviceRotation, Function | SmallTest | Level3) +{ + SensorRotation rotation = SensorRotation::INVALID; + ASSERT_EQ(DeviceRotation::INVALID, ScreenRotationController::CalcDeviceRotation(rotation)); + + rotation = SensorRotation::ROTATION_0; + ScreenRotationController::defaultDeviceRotationOffset_ = 0; + ScreenRotationController::defaultDeviceRotation_ = 0; + ASSERT_EQ(DeviceRotation::ROTATION_PORTRAIT, ScreenRotationController::CalcDeviceRotation(rotation)); + + rotation = SensorRotation::ROTATION_0; + ScreenRotationController::defaultDeviceRotationOffset_ = 90; + ScreenRotationController::defaultDeviceRotation_ = 0; + ASSERT_EQ(DeviceRotation::ROTATION_LANDSCAPE_INVERTED, ScreenRotationController::CalcDeviceRotation(rotation)); + + rotation = SensorRotation::ROTATION_0; + ScreenRotationController::defaultDeviceRotationOffset_ = 90; + ScreenRotationController::defaultDeviceRotation_ = 1; + ASSERT_EQ(DeviceRotation::ROTATION_PORTRAIT_INVERTED, ScreenRotationController::CalcDeviceRotation(rotation)); + + rotation = SensorRotation::ROTATION_0; + ScreenRotationController::defaultDeviceRotationOffset_ = 0; + ScreenRotationController::defaultDeviceRotation_ = 1; + ASSERT_EQ(DeviceRotation::ROTATION_LANDSCAPE, ScreenRotationController::CalcDeviceRotation(rotation)); +} + +/** + * @tc.name: IsSensorRelatedOrientation + * @tc.desc: Is sensor related orientation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, IsSensorRelatedOrientation, Function | SmallTest | Level3) +{ + ASSERT_EQ(false, ScreenRotationController::IsSensorRelatedOrientation(Orientation::LOCKED)); + ASSERT_EQ(false, ScreenRotationController::IsSensorRelatedOrientation(Orientation::UNSPECIFIED)); + ASSERT_EQ(false, ScreenRotationController::IsSensorRelatedOrientation(Orientation::VERTICAL)); + ASSERT_EQ(false, ScreenRotationController::IsSensorRelatedOrientation(Orientation::HORIZONTAL)); + ASSERT_EQ(false, ScreenRotationController::IsSensorRelatedOrientation(Orientation::REVERSE_VERTICAL)); + ASSERT_EQ(false, ScreenRotationController::IsSensorRelatedOrientation(Orientation::REVERSE_HORIZONTAL)); + ASSERT_EQ(true, ScreenRotationController::IsSensorRelatedOrientation(Orientation::SENSOR)); + ASSERT_EQ(true, ScreenRotationController::IsSensorRelatedOrientation(Orientation::SENSOR_VERTICAL)); + ASSERT_EQ(true, ScreenRotationController::IsSensorRelatedOrientation(Orientation::SENSOR_HORIZONTAL)); + ASSERT_EQ(true, ScreenRotationController::IsSensorRelatedOrientation(Orientation::AUTO_ROTATION_RESTRICTED)); + ASSERT_EQ(true, ScreenRotationController::IsSensorRelatedOrientation( + Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED)); + ASSERT_EQ(true, ScreenRotationController::IsSensorRelatedOrientation( + Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED)); +} + +/** + * @tc.name: ProcessSwitchToSensorRelatedOrientation + * @tc.desc: Process switch to sensor related orientation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, ProcessSwitchToSensorRelatedOrientation, Function | SmallTest | Level3) +{ + Orientation orientation = Orientation::SENSOR; + DeviceRotation deviceRitation = DeviceRotation::ROTATION_LANDSCAPE; + + ScreenRotationController::lastOrientationType_ = Orientation::SENSOR; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = true; + orientation = Orientation::AUTO_ROTATION_RESTRICTED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = false; + orientation = Orientation::AUTO_ROTATION_RESTRICTED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + orientation = Orientation::SENSOR; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = true; + orientation = Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = false; + orientation = Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + orientation = Orientation::SENSOR_VERTICAL; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = true; + orientation = Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + ScreenRotationController::isScreenRotationLocked_ = false; + orientation = Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + orientation = Orientation::SENSOR_HORIZONTAL; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + ASSERT_EQ(Orientation::SENSOR_HORIZONTAL, ScreenRotationController::lastOrientationType_); + + ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED; + orientation = Orientation::LOCKED; + ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(orientation, deviceRitation); + ASSERT_EQ(Orientation::LOCKED, ScreenRotationController::lastOrientationType_); +} + +/** + * @tc.name: ProcessSwitchToAutoRotation + * @tc.desc: Process switch to auto rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, ProcessSwitchToAutoRotation, Function | SmallTest | Level3) +{ + DeviceRotation deviceRotation = DeviceRotation::INVALID; + ScreenRotationController::ProcessSwitchToAutoRotation(deviceRotation); + deviceRotation = DeviceRotation::ROTATION_PORTRAIT; + ScreenRotationController::ProcessSwitchToAutoRotation(deviceRotation); + + deviceRotation = DeviceRotation::INVALID; + ScreenRotationController::ProcessSwitchToAutoRotationPortrait(deviceRotation); + deviceRotation = DeviceRotation::ROTATION_PORTRAIT; + ScreenRotationController::ProcessSwitchToAutoRotationPortrait(deviceRotation); + + deviceRotation = DeviceRotation::INVALID; + ScreenRotationController::ProcessSwitchToAutoRotationLandscape(deviceRotation); + deviceRotation = DeviceRotation::ROTATION_LANDSCAPE; + ScreenRotationController::ProcessSwitchToAutoRotationLandscape(deviceRotation); + + ScreenRotationController::ProcessSwitchToAutoRotationPortraitRestricted(); + ScreenRotationController::ProcessSwitchToAutoRotationLandscapeRestricted(); +} + +/** + * @tc.name: CalcSensorRotation + * @tc.desc: Calc sensor rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, CalcSensorRotation, Function | SmallTest | Level3) +{ + ASSERT_EQ(SensorRotation::INVALID, GravitySensorSubscriber::CalcSensorRotation(-30)); + ASSERT_EQ(SensorRotation::ROTATION_0, GravitySensorSubscriber::CalcSensorRotation(15)); + ASSERT_EQ(SensorRotation::ROTATION_0, GravitySensorSubscriber::CalcSensorRotation(345)); + ASSERT_EQ(SensorRotation::ROTATION_90, GravitySensorSubscriber::CalcSensorRotation(75)); + ASSERT_EQ(SensorRotation::ROTATION_180, GravitySensorSubscriber::CalcSensorRotation(180)); + ASSERT_EQ(SensorRotation::ROTATION_270, GravitySensorSubscriber::CalcSensorRotation(270)); + ASSERT_EQ(SensorRotation::ROTATION_0, GravitySensorSubscriber::CalcSensorRotation(600)); +} + +/** + * @tc.name: ConvertRotation + * @tc.desc: Convert rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, ConvertRotation, Function | SmallTest | Level3) +{ + ScreenRotationController::sensorToDeviceRotationMap_.clear(); + SensorRotation rotation = SensorRotation::INVALID; + ASSERT_EQ(DeviceRotation::INVALID, ScreenRotationController::ConvertSensorToDeviceRotation(rotation)); + ASSERT_EQ(DeviceRotation::INVALID, ScreenRotationController::ConvertSensorToDeviceRotation(rotation)); + + DeviceRotation deviceRotation = DeviceRotation::INVALID; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::ConvertDeviceToDisplayRotation(deviceRotation)); + + ScreenRotationController::deviceToDisplayRotationMap_.clear(); + deviceRotation = DeviceRotation::ROTATION_PORTRAIT; + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::ConvertDeviceToDisplayRotation(deviceRotation)); + ASSERT_EQ(Rotation::ROTATION_0, ScreenRotationController::ConvertDeviceToDisplayRotation(deviceRotation)); +} + +/** + * @tc.name: IsDeviceRotationVerticalOrHorizontal + * @tc.desc: Check device rotation + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, IsDeviceRotationVerticalOrHorizontal, Function | SmallTest | Level3) +{ + ASSERT_EQ(true, ScreenRotationController::IsDeviceRotationVertical(DeviceRotation::ROTATION_PORTRAIT)); + ASSERT_EQ(true, ScreenRotationController::IsDeviceRotationVertical(DeviceRotation::ROTATION_PORTRAIT_INVERTED)); + ASSERT_EQ(false, ScreenRotationController::IsDeviceRotationVertical(DeviceRotation::ROTATION_LANDSCAPE)); + + ASSERT_EQ(true, ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation::ROTATION_LANDSCAPE)); + ASSERT_EQ(true, ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation::ROTATION_LANDSCAPE_INVERTED)); + ASSERT_EQ(false, ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation::ROTATION_PORTRAIT)); +} + +/** + * @tc.name: ProcessOrientationSwitch + * @tc.desc: Process orientation switch + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, ProcessOrientationSwitch, Function | SmallTest | Level3) +{ + ScreenRotationController::ProcessOrientationSwitch(Orientation::UNSPECIFIED); + ScreenRotationController::ProcessOrientationSwitch(Orientation::VERTICAL); + ScreenRotationController::ProcessOrientationSwitch(Orientation::HORIZONTAL); + ScreenRotationController::ProcessOrientationSwitch(Orientation::REVERSE_VERTICAL); + ScreenRotationController::ProcessOrientationSwitch(Orientation::SENSOR); + ScreenRotationController::ProcessOrientationSwitch(Orientation::SENSOR_VERTICAL); + ScreenRotationController::ProcessOrientationSwitch(Orientation::SENSOR_HORIZONTAL); + ScreenRotationController::ProcessOrientationSwitch(Orientation::AUTO_ROTATION_RESTRICTED); + ScreenRotationController::ProcessOrientationSwitch(Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED); + ScreenRotationController::ProcessOrientationSwitch(Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED); + ScreenRotationController::ProcessOrientationSwitch(Orientation::LOCKED); + ASSERT_EQ(Orientation::LOCKED, ScreenRotationController::lastOrientationType_); +} +#ifdef WM_SUBSCRIBE_MOTION_ENABLE +/** + * @tc.name: SubscribeMotionSensor + * @tc.desc: check function MotionSubscriber::SubscribeMotionSensor + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, SubscribeMotionSensor, Function | SmallTest | Level3) +{ + MotionSubscriber::isMotionSensorSubscribed_ = true; + MotionSubscriber::SubscribeMotionSensor(); + ASSERT_EQ(true, MotionSubscriber::isMotionSensorSubscribed_); + + MotionSubscriber::isMotionSensorSubscribed_ = false; + MotionSubscriber::SubscribeMotionSensor(); + ASSERT_EQ(true, MotionSubscriber::isMotionSensorSubscribed_); + + MotionSubscriber::isMotionSensorSubscribed_ = false; + MotionSubscriber::UnsubscribeMotionSensor(); + ASSERT_EQ(false, MotionSubscriber::isMotionSensorSubscribed_); + + MotionSubscriber::isMotionSensorSubscribed_ = true; + MotionSubscriber::UnsubscribeMotionSensor(); + ASSERT_EQ(false, MotionSubscriber::isMotionSensorSubscribed_); +} + +/** + * @tc.name: OnMotionChanged + * @tc.desc: check function RotationMotionEventCallback->SubscribeMotionSensor + * @tc.type: FUNC + */ +HWTEST_F(ScreenRotationControllerTest, OnMotionChanged, Function | SmallTest | Level3) +{ + DeviceRotation currentRotation = ScreenRotationController::lastSensorRotationConverted_; + DeviceRotation motionRotation = DeviceRotation::INVALID; + + MotionData motionData; + motionData.result = OHOS::Msdp::MotionStatusResult::VALUE_INVALID; + motionData.rotateAction = 1; + MotionSubscriber::motionEventCallback_->OnMotionChanged(motionData); + ASSERT_EQ(currentRotation, ScreenRotationController::lastSensorRotationConverted_); + + motionData.result = OHOS::Msdp::MotionStatusResult::VALUE_ENTER; + motionData.rotateAction = 0; + motionRotation = DeviceRotation::ROTATION_PORTRAIT; + MotionSubscriber::motionEventCallback_->OnMotionChanged(motionData); + ASSERT_EQ(motionRotation, ScreenRotationController::lastSensorRotationConverted_); + + motionData.rotateAction = 1; + MotionSubscriber::motionEventCallback_->OnMotionChanged(motionData); + motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ? + DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE; + ASSERT_EQ(motionRotation, ScreenRotationController::lastSensorRotationConverted_); + + motionData.rotateAction = 2; + MotionSubscriber::motionEventCallback_->OnMotionChanged(motionData); + motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED; + ASSERT_EQ(motionRotation, ScreenRotationController::lastSensorRotationConverted_); + + motionData.rotateAction = 3; + MotionSubscriber::motionEventCallback_->OnMotionChanged(motionData); + motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ? + DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED; + ASSERT_EQ(motionRotation, ScreenRotationController::lastSensorRotationConverted_); + + ScreenRotationController::HandleSensorEventInput(currentRotation); +} +#endif +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/etc/BUILD.gn b/window_manager/etc/BUILD.gn new file mode 100644 index 0000000..71de65c --- /dev/null +++ b/window_manager/etc/BUILD.gn @@ -0,0 +1,36 @@ +# 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. + +import("//build/ohos.gni") + +################################################################################# +group("wms_etc") { + deps = [ + ":wms.para", + ":wms.para.dac", + ] +} + +ohos_prebuilt_etc("wms.para") { + source = "wms.para" + relative_install_dir = "param" + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_prebuilt_etc("wms.para.dac") { + source = "wms.para.dac" + relative_install_dir = "param" + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/etc/wms.para b/window_manager/etc/wms.para new file mode 100644 index 0000000..10cefe4 --- /dev/null +++ b/window_manager/etc/wms.para @@ -0,0 +1,14 @@ +# 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. + +bootevent.wms.fullscreen.ready=false \ No newline at end of file diff --git a/window_manager/etc/wms.para.dac b/window_manager/etc/wms.para.dac new file mode 100644 index 0000000..cdccccf --- /dev/null +++ b/window_manager/etc/wms.para.dac @@ -0,0 +1,14 @@ +# 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. + +bootevent.wms.fullscreen.ready = foundation:foundation:0775 \ No newline at end of file diff --git a/window_manager/extension/extension_connection/BUILD.gn b/window_manager/extension/extension_connection/BUILD.gn new file mode 100644 index 0000000..c744f05 --- /dev/null +++ b/window_manager/extension/extension_connection/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright (C) 2022-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. + +import("//build/ohos.gni") + +config("libwindow_extension_client_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "include/zidl", + "../window_extension/include/zidl", + ] +} + +config("libextension_connection_public_config") { + include_dirs = [ "../../interfaces/innerkits/extension" ] +} + +ohos_shared_library("libwindow_extension_client") { + install_enable = true + sources = [ + "../window_extension/src/zidl/window_extension_proxy.cpp", + "src/window_extension_client_stub_impl.cpp", + "src/window_extension_connection.cpp", + "src/zidl/window_extension_client_stub.cpp", + ] + + configs = [ + ":libwindow_extension_client_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + public_configs = [ ":libextension_connection_public_config" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_manager", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + ] + + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/extension/extension_connection/include/window_extension_client_stub_impl.h b/window_manager/extension/extension_connection/include/window_extension_client_stub_impl.h new file mode 100644 index 0000000..242de11 --- /dev/null +++ b/window_manager/extension/extension_connection/include/window_extension_client_stub_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 WINDOW_EXTENSION_CLIENT_STUB_IMPL_H +#define WINDOW_EXTENSION_CLIENT_STUB_IMPL_H + +#include "window_extension_client_stub.h" +#include "window_extension_connection.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionClientStubImpl : public WindowExtensionClientStub { +public: + explicit WindowExtensionClientStubImpl(sptr& componentCallback) + : componentCallback_(componentCallback) {}; + ~WindowExtensionClientStubImpl() = default; + + void OnWindowReady(const std::shared_ptr& surfaceNode) override; + void OnBackPress() override; + void OnKeyEvent(const std::shared_ptr& keyEvent) override; + void OnPointerEvent(const std::shared_ptr& pointerEvent) override; +private: + sptr componentCallback_; +}; +} // namespcce Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_CLIENT_STUB_IMPL_H \ No newline at end of file diff --git a/window_manager/extension/extension_connection/include/zidl/window_extension_client_interface.h b/window_manager/extension/extension_connection/include/zidl/window_extension_client_interface.h new file mode 100644 index 0000000..764e8ed --- /dev/null +++ b/window_manager/extension/extension_connection/include/zidl/window_extension_client_interface.h @@ -0,0 +1,43 @@ +/* + * 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 WINDOW_EXTENSION_CLIENT_INTERFACE_H +#define WINDOW_EXTENSION_CLIENT_INTERFACE_H + +#include +#include +#include +#include + +namespace OHOS { +namespace Rosen { +class IWindowExtensionClient : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.rosen.window.extension"); + enum { + TRANS_ID_ON_WINDOW_READY = 1, + TRANS_ID_ON_BACK_PRESS, + TRANS_ID_ON_KEY_EVENT, + TRANS_ID_ON_POINTER_EVENT, + }; + + virtual void OnWindowReady(const std::shared_ptr& surfaceNode) = 0; + virtual void OnBackPress() = 0; + virtual void OnKeyEvent(const std::shared_ptr& keyEvent) = 0; + virtual void OnPointerEvent(const std::shared_ptr& pointerEvent) = 0; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_CLIENT_INTERFACE_H \ No newline at end of file diff --git a/window_manager/extension/extension_connection/include/zidl/window_extension_client_proxy.h b/window_manager/extension/extension_connection/include/zidl/window_extension_client_proxy.h new file mode 100644 index 0000000..984f281 --- /dev/null +++ b/window_manager/extension/extension_connection/include/zidl/window_extension_client_proxy.h @@ -0,0 +1,38 @@ +/* + * 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 WINODW_EXTENSION_CLIENT_PROXY_H +#define WINODW_EXTENSION_CLIENT_PROXY_H + +#include +#include "window_extension_client_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionClientProxy : public IRemoteProxy { +public: + WindowExtensionClientProxy(const sptr& impl) + : IRemoteProxy(impl) {}; + ~WindowExtensionClientProxy() {}; + void OnWindowReady(const std::shared_ptr& surfaceNode) override; + void OnBackPress() override; + void OnKeyEvent(const std::shared_ptr& keyEvent) override; + void OnPointerEvent(const std::shared_ptr& pointerEvent) override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINODW_EXTENSION_CLIENT_PROXY_H \ No newline at end of file diff --git a/window_manager/extension/extension_connection/include/zidl/window_extension_client_stub.h b/window_manager/extension/extension_connection/include/zidl/window_extension_client_stub.h new file mode 100644 index 0000000..c152460 --- /dev/null +++ b/window_manager/extension/extension_connection/include/zidl/window_extension_client_stub.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 WINDOW_EXTENSION_CLIENT_STUB_H +#define WINDOW_EXTENSION_CLIENT_STUB_H + +#include +#include "window_extension_client_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionClientStub : public IRemoteStub { +public: + WindowExtensionClientStub() = default; + ~WindowExtensionClientStub() = default; + + virtual int OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption& option) override; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_CLIENT_STUB_H \ No newline at end of file diff --git a/window_manager/extension/extension_connection/src/window_extension_client_stub_impl.cpp b/window_manager/extension/extension_connection/src/window_extension_client_stub_impl.cpp new file mode 100644 index 0000000..0e437c2 --- /dev/null +++ b/window_manager/extension/extension_connection/src/window_extension_client_stub_impl.cpp @@ -0,0 +1,58 @@ +/* + * 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 "window_extension_client_stub_impl.h" + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionClientStubImpl"}; +} + +void WindowExtensionClientStubImpl::OnWindowReady(const std::shared_ptr& surfaceNode) +{ + if (componentCallback_ != nullptr) { + componentCallback_->OnWindowReady(surfaceNode); + WLOGFI("called"); + } +} + +void WindowExtensionClientStubImpl::OnBackPress() +{ + if (componentCallback_ != nullptr) { + componentCallback_->OnBackPress(); + WLOGFI("called"); + } +} + +void WindowExtensionClientStubImpl::OnKeyEvent(const std::shared_ptr& keyEvent) +{ + if (componentCallback_ != nullptr) { + componentCallback_->OnKeyEvent(keyEvent); + WLOGFI("called"); + } +} + +void WindowExtensionClientStubImpl::OnPointerEvent(const std::shared_ptr& pointerEvent) +{ + if (componentCallback_ != nullptr) { + componentCallback_->OnPointerEvent(pointerEvent); + WLOGFI("called"); + } +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/extension_connection/src/window_extension_connection.cpp b/window_manager/extension/extension_connection/src/window_extension_connection.cpp new file mode 100644 index 0000000..9e97179 --- /dev/null +++ b/window_manager/extension/extension_connection/src/window_extension_connection.cpp @@ -0,0 +1,236 @@ +/* + * 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 "window_extension_connection.h" + +#include +#include +#include +#include +#include + +#include "window_extension_proxy.h" +#include "window_extension_client_stub_impl.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionConnection"}; +} + +class WindowExtensionConnection::Impl : public AAFwk::AbilityConnectionStub { +public: + Impl() = default; + ~Impl() = default; + void OnAbilityConnectDone(const AppExecFwk::ElementName& element, + const sptr& remoteObject, int resultCode) override; + void OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode) override; + + int ConnectExtension(const AppExecFwk::ElementName& element, const Rect& rect, + uint32_t uid, uint32_t windowId, const sptr& callback); + void DisconnectExtension(); + void Show() const; + void Hide() const; + void SetBounds(const Rect& rect) const; + void RequestFocus() const; +private: + class WindowExtensionClientRecipient + final : public IRemoteObject::DeathRecipient { + public: + explicit WindowExtensionClientRecipient(sptr callback); + ~WindowExtensionClientRecipient() = default; + void OnRemoteDied(const wptr& remote); + private: + sptr callback_; + }; + + sptr componentCallback_; + sptr proxy_; + sptr deathRecipient_; +}; + +WindowExtensionConnection::WindowExtensionConnection() + : pImpl_(new Impl()) +{ +} + +WindowExtensionConnection::~WindowExtensionConnection() +{ + DisconnectExtension(); + WLOGI("disconnect"); +} + +WindowExtensionConnection::Impl::WindowExtensionClientRecipient::WindowExtensionClientRecipient( + sptr callback) + : callback_(callback) +{ +} + +void WindowExtensionConnection::Impl::WindowExtensionClientRecipient::OnRemoteDied(const wptr& wptrDeath) +{ + if (wptrDeath == nullptr) { + WLOGFE("wptrDeath is null"); + return; + } + + sptr object = wptrDeath.promote(); + if (!object) { + WLOGFE("object is null"); + return; + } + + if (callback_ != nullptr) { + WLOGFI("on extension disconnected"); + callback_->OnExtensionDisconnected(); + } + WLOGFI("Remote died"); +} + +int WindowExtensionConnection::Impl::ConnectExtension(const AppExecFwk::ElementName& element, + const Rect& rect, uint32_t uid, uint32_t windowId, const sptr& callback) +{ + AAFwk::Want want; + want.SetElement(element); + StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::CONNECT_EXTENSION), + "WindowExtension %s-%s", element.GetBundleName().c_str(), element.GetAbilityName().c_str()); + want.SetParam(RECT_FORM_KEY_POS_X, rect.posX_); + want.SetParam(RECT_FORM_KEY_POS_Y, rect.posY_); + want.SetParam(RECT_FORM_KEY_WIDTH, static_cast(rect.width_)); + want.SetParam(RECT_FORM_KEY_HEIGHT, static_cast(rect.height_)); + want.SetParam(WINDOW_ID, static_cast(windowId)); + // 100 default userId + auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want, this, nullptr, uid); + if (ret == ERR_OK) { + componentCallback_ = callback; + } + WLOGFI("Connection extension end ret = %{public}d windowId = %{public}u", ret, windowId); + return ret; +} + +void WindowExtensionConnection::Impl::Show() const +{ + if (proxy_ != nullptr) { + proxy_->Show(); + WLOGFI("show window"); + } +} + +void WindowExtensionConnection::Impl::Hide() const +{ + if (proxy_ != nullptr) { + proxy_->Hide(); + WLOGFI("hide window"); + } +} + +void WindowExtensionConnection::Impl::RequestFocus() const +{ + if (proxy_ != nullptr) { + proxy_->RequestFocus(); + } +} + +void WindowExtensionConnection::Impl::SetBounds(const Rect& rect) const +{ + if (proxy_ != nullptr) { + proxy_->SetBounds(rect); + } +} + +void WindowExtensionConnection::Impl::DisconnectExtension() +{ + if (AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(this) != ERR_OK) { + WLOGFE("ConnectAbility failed!"); + return; + } +} + +void WindowExtensionConnection::Impl::OnAbilityConnectDone(const AppExecFwk::ElementName& element, + const sptr& remoteObject, int resultCode) +{ + if (!remoteObject) { + WLOGFE("remote object is null"); + return; + } + if (!proxy_) { + proxy_ = new(std::nothrow) WindowExtensionProxy(remoteObject); + if (!proxy_) { + WLOGFE("get proxy failed"); + return; + } + } + if (!deathRecipient_) { + deathRecipient_ = new(std::nothrow) WindowExtensionClientRecipient(componentCallback_); + if (!deathRecipient_) { + WLOGFE("get death recipient failed"); + return; + } + } + if (!proxy_->AsObject() || !proxy_->AsObject()->AddDeathRecipient(deathRecipient_)) { + WLOGFE("Failed to add death recipient"); + } + sptr clientToken(new WindowExtensionClientStubImpl(componentCallback_)); + if (clientToken != nullptr) { + proxy_->GetExtensionWindow(clientToken); + WLOGFI("GetExtensionWindow"); + } + WLOGFI("call end"); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::CONNECT_EXTENSION), + "WindowExtension %s-%s", element.GetBundleName().c_str(), element.GetAbilityName().c_str()); +} + +void WindowExtensionConnection::Impl::OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode) +{ + if (componentCallback_ != nullptr) { + componentCallback_->OnExtensionDisconnected(); + } + WLOGFI("end"); +} + +int WindowExtensionConnection::ConnectExtension(const AppExecFwk::ElementName& element, + const Rect& rect, uint32_t uid, uint32_t windowId, const sptr& callback) const +{ + return pImpl_->ConnectExtension(element, rect, uid, windowId, callback); +} + +void WindowExtensionConnection::Show() const +{ + pImpl_->Show(); +} + +void WindowExtensionConnection::Hide() const +{ + pImpl_->Hide(); +} + +void WindowExtensionConnection::RequestFocus() const +{ + pImpl_->RequestFocus(); +} + +void WindowExtensionConnection::SetBounds(const Rect& rect) const +{ + pImpl_->SetBounds(rect); +} + +void WindowExtensionConnection::DisconnectExtension() const +{ + pImpl_->DisconnectExtension(); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/extension/extension_connection/src/zidl/window_extension_client_proxy.cpp b/window_manager/extension/extension_connection/src/zidl/window_extension_client_proxy.cpp new file mode 100644 index 0000000..0ad7330 --- /dev/null +++ b/window_manager/extension/extension_connection/src/zidl/window_extension_client_proxy.cpp @@ -0,0 +1,107 @@ +/* + * 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 "window_extension_client_proxy.h" + +#include +#include +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionProxy"}; +} + +void WindowExtensionClientProxy::OnWindowReady(const std::shared_ptr& surfaceNode) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write token failed"); + return; + } + + if (surfaceNode == nullptr || (!surfaceNode->Marshalling(data))) { + WLOGFE("write surfaceNode failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_ON_WINDOW_READY, data, replay, option) != ERR_NONE) { + WLOGFE("send request failed"); + } + WLOGFI("end"); +} + +void WindowExtensionClientProxy::OnBackPress() +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_SYNC); + WLOGFI("call"); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write token failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_ON_BACK_PRESS, data, replay, option) != ERR_NONE) { + WLOGFE("send request failed"); + } + WLOGFI("end"); +} + +void WindowExtensionClientProxy::OnKeyEvent(const std::shared_ptr& keyEvent) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write token failed"); + return; + } + + if (!keyEvent->WriteToParcel(data)) { + WLOGFE("write key event failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_ON_KEY_EVENT, data, replay, option) != ERR_NONE) { + WLOGFE("send request failed"); + } + WLOGFI("end"); +} + +void WindowExtensionClientProxy::OnPointerEvent(const std::shared_ptr& pointerEvent) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_SYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write token failed"); + return; + } + + if (!pointerEvent->WriteToParcel(data)) { + WLOGFE("write key event failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_ON_POINTER_EVENT, data, replay, option) != ERR_NONE) { + WLOGFE("send request failed"); + } + WLOGFI("end"); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/extension_connection/src/zidl/window_extension_client_stub.cpp b/window_manager/extension/extension_connection/src/zidl/window_extension_client_stub.cpp new file mode 100644 index 0000000..5ad7768 --- /dev/null +++ b/window_manager/extension/extension_connection/src/zidl/window_extension_client_stub.cpp @@ -0,0 +1,70 @@ +/* + * 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 "window_extension_client_stub.h" + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionClientStub"}; +} +int WindowExtensionClientStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + WLOGFI(" code is %{public}d", code); + switch (code) { + case TRANS_ID_ON_WINDOW_READY: { + std::shared_ptr surfaceNode = RSSurfaceNode::Unmarshalling(data); + OnWindowReady(surfaceNode); + break; + } + case TRANS_ID_ON_BACK_PRESS: { + OnBackPress(); + break; + } + case TRANS_ID_ON_KEY_EVENT: { + std::shared_ptr keyEvent = MMI::KeyEvent::Create(); + if (keyEvent == nullptr) { + WLOGFE("create keyevent failed"); + break; + } + keyEvent->ReadFromParcel(data); + OnKeyEvent(keyEvent); + break; + } + case TRANS_ID_ON_POINTER_EVENT: { + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + if (pointerEvent == nullptr) { + WLOGFE("create pointer event failed"); + break; + } + pointerEvent->ReadFromParcel(data); + OnPointerEvent(pointerEvent); + break; + } + default: { + break; + } + } + return 0; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/window_extension/BUILD.gn b/window_manager/extension/window_extension/BUILD.gn new file mode 100644 index 0000000..5948175 --- /dev/null +++ b/window_manager/extension/window_extension/BUILD.gn @@ -0,0 +1,104 @@ +# 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. + +import("//build/ohos.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +config("libwindow_extension_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "include/zidl", + "../extension_connection/include", + "../extension_connection/include/zidl", + "../../interfaces/kits/napi/window_runtime/window_napi", + "../../interfaces/innerkits/extension", + "../../interfaces/innerkits/wm", + ] +} + +## Build libwindow_extension.so +ohos_shared_library("libwindow_extension") { + sources = [ + "../extension_connection/src/zidl/window_extension_client_proxy.cpp", + "src/js_window_extension.cpp", + "src/js_window_extension_context.cpp", + "src/window_extension.cpp", + "src/window_extension_context.cpp", + "src/window_extension_stub_impl.cpp", + "src/zidl/window_extension_stub.cpp", + ] + + configs = [ + ":libwindow_extension_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_path}/frameworks/native/appkit:app_context", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/interfaces/kits/napi/window_runtime:window_native_kit", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:runtime", + "c_utils:utils", + "hilog_native:libhilog", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +config("window_extension_module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", + ] +} + +ohos_shared_library("window_extension_module") { + sources = [ "src/window_extension_module_loader.cpp" ] + + configs = [ + ":window_extension_module_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ "//foundation/window/window_manager/extension/window_extension:libwindow_extension" ] + + external_deps = [ + "ability_runtime:abilitykit_native", + "hiviewdfx_hilog_native:libhilog", + ] + relative_install_dir = "extensionability/" + subsystem_name = "window" + part_name = "window_manager" +} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/extension/window_extension/include/js_window_extension.h b/window_manager/extension/window_extension/include/js_window_extension.h new file mode 100644 index 0000000..6ea85b0 --- /dev/null +++ b/window_manager/extension/window_extension/include/js_window_extension.h @@ -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. + */ + +#ifndef JS_WINDOW_EXTENSION_H +#define JS_WINDOW_EXTENSION_H + +#include +#include + +#include "js_window_extension_context.h" +#include "window.h" +#include "window_extension.h" +#include "window_extension_stub.h" +#include "window_extension_stub_impl.h" + +namespace OHOS { +namespace Rosen { +class JsWindowExtension : public WindowExtension { +public: + JsWindowExtension(AbilityRuntime::JsRuntime& jsRuntime); + virtual ~JsWindowExtension() override; + + /** + * @brief Create JsAccessibilityExtension. + * + * @param runtime The runtime. + * @return The JsAccessibilityExtension instance. + */ + static JsWindowExtension* Create(const std::unique_ptr& runtime); + + /** + * @brief Init the extension. + * + * @param record the extension record. + * @param application the application info. + * @param handler the extension handler. + * @param token the remote token. + */ + void Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + /** + * @brief Called when this Accessibility extension is connected for the first time. + * + * You can override this function to implement your own processing logic. + * + * @param want Indicates the {@link Want} structure containing connection information + * about the Accessibility extension. + * @return Returns a pointer to the sid of the connected Accessibility extension. + */ + sptr OnConnect(const AAFwk::Want& want) override; + + /** + * @brief Called when all abilities connected to this Service extension are disconnected. + * + * You can override this function to implement your own processing logic. + * + */ + void OnDisconnect(const AAFwk::Want& want) override; + + /** + * @brief Called when this extension is started. You must override this function if you want to perform some + * initialization operations during extension startup. + * + * This function can be called only once in the entire lifecycle of an extension. + * @param Want Indicates the {@link Want} structure containing startup information about the extension. + */ + virtual void OnStart(const AAFwk::Want& want) override; +private: + void GetSrcPath(std::string& srcPath) const; + NativeValue* CallJsMethod(const char* name, NativeValue* const* argv = nullptr, size_t argc = 0) const; + void OnWindowCreated() const; + void BindContext(NativeEngine& engine, NativeObject* obj); + + AbilityRuntime::JsRuntime& jsRuntime_; + std::unique_ptr jsObj_; + std::shared_ptr shellContextRef_; + sptr stub_; + static int extensionCnt_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // JS_WINDOW_EXTENSION_H \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/js_window_extension_context.h b/window_manager/extension/window_extension/include/js_window_extension_context.h new file mode 100644 index 0000000..5fc11db --- /dev/null +++ b/window_manager/extension/window_extension/include/js_window_extension_context.h @@ -0,0 +1,42 @@ +/* + * 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 JS_WINDOW_EXTENSION_CONTEXT_H +#define JS_WINDOW_EXTENSION_CONTEXT_H + +#include +#include +#include +#include + +#include "window.h" +#include "window_extension_context.h" + +namespace OHOS { +namespace Rosen { +class JsWindowConnectCallback : public AbilityRuntime::AbilityConnectCallback { +public: + JsWindowConnectCallback() = default; + ~JsWindowConnectCallback() = default; + virtual void OnAbilityConnectDone(const AppExecFwk::ElementName& element, + const sptr& remoteObject, int resultCode) override; + virtual void OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode) override; +}; + +NativeValue* CreateJsWindowExtensionContext(NativeEngine& engine, + const std::shared_ptr& context); +} // namespace Rosen +} // namespace OHOS +#endif // JS_WINDOW_EXTENSION_CONTEXT_H diff --git a/window_manager/extension/window_extension/include/window_extension.h b/window_manager/extension/window_extension/include/window_extension.h new file mode 100644 index 0000000..16825ee --- /dev/null +++ b/window_manager/extension/window_extension/include/window_extension.h @@ -0,0 +1,69 @@ +/* + * 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 WINDOW_EXTENSION_H +#define WINDOW_EXTENSION_H + +#include +#include + +namespace OHOS { +namespace Rosen { +class WindowExtensionContext; + +class WindowExtension : public AbilityRuntime::ExtensionBase { +public: + WindowExtension() = default; + virtual ~WindowExtension() = default; + + /** + * @brief Create and init context. + * + * @param record the extension record. + * @param application the application info. + * @param handler the extension handler. + * @param token the remote token. + * @return The created context. + */ + virtual std::shared_ptr CreateAndInitContext( + const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + /** + * @brief Init the extension. + * + * @param record the extension record. + * @param application the application info. + * @param handler the extension handler. + * @param token the remote token. + */ + virtual void Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + /** + * @brief Create Extension. + * + * @param runtime The runtime. + * @return The WindowExtension instance. + */ + static WindowExtension* Create(const std::unique_ptr& runtime); +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/window_extension_context.h b/window_manager/extension/window_extension/include/window_extension_context.h new file mode 100644 index 0000000..81ce579 --- /dev/null +++ b/window_manager/extension/window_extension/include/window_extension_context.h @@ -0,0 +1,50 @@ +/* + * 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 WINDOW_EXTENSION_CONTEXT_H +#define WINDOW_EXTENSION_CONTEXT_H + +#include +#include +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionContext : public AbilityRuntime::ExtensionContext { +public: + WindowExtensionContext() = default; + ~WindowExtensionContext() = default; + + /** + * @brief Starts a new ability. + * An ability using the AbilityInfo.AbilityType.SERVICE or AbilityInfo.AbilityType.PAGE template uses this method + * to start a specific ability. The system locates the target ability from installed abilities based on the value + * of the want parameter and the startOptions parameter and then starts it. You can specify the ability to start + * using the want parameter. + * + * @param want Indicates the Want containing information about the target ability to start. + * @param startOptions Indicates the startOptions containing information about WindowMode and displayId to start. + * + * @return errCode WM_OK on success, others on failure. + */ + WMError StartAbility(const AAFwk::Want &want, const AAFwk::StartOptions &startOptions) const; + + static const size_t CONTEXT_TYPE_ID; +private: + static int ILLEGAL_REQUEST_CODE; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_CONTEXT_HP \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/window_extension_module_loader.h b/window_manager/extension/window_extension/include/window_extension_module_loader.h new file mode 100644 index 0000000..8c7b9ac --- /dev/null +++ b/window_manager/extension/window_extension/include/window_extension_module_loader.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 WINDOW_EXTENSION_MODULE_LOADER_H +#define WINDOW_EXTENSION_MODULE_LOADER_H + +#include + +namespace OHOS::Rosen { +class WindowExtensionModuleLoader : public AbilityRuntime::ExtensionModuleLoader, +public Singleton { + DECLARE_SINGLETON(WindowExtensionModuleLoader); + +public: + /** + * @brief Create Extension. + * + * @param runtime The runtime. + * @return The Extension instance. + */ + virtual AbilityRuntime::Extension *Create(const std::unique_ptr& runtime) const override; + virtual std::map GetParams() override; +}; +} // namespace OHOS::Rosen +#endif // WINDOW_EXTENSION_MODULE_LOADER_H \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/window_extension_stub_impl.h b/window_manager/extension/window_extension/include/window_extension_stub_impl.h new file mode 100644 index 0000000..a6ce586 --- /dev/null +++ b/window_manager/extension/window_extension/include/window_extension_stub_impl.h @@ -0,0 +1,51 @@ +/* + * 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 WINDOW_EXTENSION_STUB_IMPL_H +#define WINDOW_EXTENSION_STUB_IMPL_H + +#include + +#include "window.h" +#include "window_extension_stub.h" +#include "window_extension_client_interface.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionStubImpl : public WindowExtensionStub { +public: + WindowExtensionStubImpl(const std::string& windowName); + ~WindowExtensionStubImpl(); + + virtual void SetBounds(const Rect& rect) override; + virtual void Hide() override; + virtual void Show() override; + virtual void RequestFocus() override; + virtual void GetExtensionWindow(sptr& token) override; + + sptr CreateWindow( + const Rect& rect, uint32_t parentWindowId, const std::shared_ptr& context); + void DestroyWindow(); + sptr GetWindow() const; +private: + sptr dispatchInputEventListener_; + sptr window_; + std::string windowName_; + sptr token_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_STUB_IMPL_H \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/zidl/window_extension_interface.h b/window_manager/extension/window_extension/include/zidl/window_extension_interface.h new file mode 100644 index 0000000..7410c90 --- /dev/null +++ b/window_manager/extension/window_extension/include/zidl/window_extension_interface.h @@ -0,0 +1,48 @@ +/* + * 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 WINDOW_EXTENSION_INTERFACE_H +#define WINDOW_EXTENSION_INTERFACE_H + +#include +#include + +#include "window.h" +#include "window_extension_client_interface.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class IWindowExtension : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.IWindowExtension"); + + enum { + TRANS_ID_SETBOUNDS = 0, + TRANS_ID_HIDE_WINDOW, + TRANS_ID_SHOW_WINDOW, + TRANS_ID_REQUESTFOCUS, + TRANS_ID_CONNECT_TO_EXTENSION, + }; + + virtual void SetBounds(const Rect& rect) = 0; + virtual void Hide() = 0; + virtual void Show() = 0; + virtual void RequestFocus() = 0; + virtual void GetExtensionWindow(sptr& token) = 0; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_INTERFACE_H \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/zidl/window_extension_proxy.h b/window_manager/extension/window_extension/include/zidl/window_extension_proxy.h new file mode 100644 index 0000000..3441712 --- /dev/null +++ b/window_manager/extension/window_extension/include/zidl/window_extension_proxy.h @@ -0,0 +1,40 @@ +/* + * 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 WINDOW_EXTENSION_PROXY_H +#define WINDOW_EXTENSION_PROXY_H + +#include +#include "window_extension_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionProxy : public IRemoteProxy { +public: + explicit WindowExtensionProxy(const sptr& impl) + : IRemoteProxy(impl) {}; + ~WindowExtensionProxy() {}; + + void SetBounds(const Rect& rect) override; + void Hide() override; + void Show() override; + void RequestFocus() override; + void GetExtensionWindow(sptr& token) override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_PROXY_H \ No newline at end of file diff --git a/window_manager/extension/window_extension/include/zidl/window_extension_stub.h b/window_manager/extension/window_extension/include/zidl/window_extension_stub.h new file mode 100644 index 0000000..2b2b1eb --- /dev/null +++ b/window_manager/extension/window_extension/include/zidl/window_extension_stub.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 WINDOW_EXTENSION_STUB_H +#define WINDOW_EXTENSION_STUB_H + +#include +#include +#include "window_extension_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowExtensionStub : public IRemoteStub { +public: + WindowExtensionStub() = default; + ~WindowExtensionStub() = default; + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption& option) override; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_STUB_H \ No newline at end of file diff --git a/window_manager/extension/window_extension/src/js_window_extension.cpp b/window_manager/extension/window_extension/src/js_window_extension.cpp new file mode 100644 index 0000000..524b87c --- /dev/null +++ b/window_manager/extension/window_extension/src/js_window_extension.cpp @@ -0,0 +1,347 @@ +/* + * 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_window_extension.h" + +#include +#include +#include +#include +#include +#include + +#include "js_window.h" +#include "js_window_extension_context.h" +#include "window_extension_connection.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JSWindowExtension"}; +} +int JsWindowExtension::extensionCnt_ = 0; + +class DispatchInputEventListener : public IDispatchInputEventListener { +public: + void OnDispatchPointerEvent(std::shared_ptr& inputEvent) override + { + WLOGFI("called"); + } + void OnDispatchKeyEvent(std::shared_ptr& keyEvent) override + { + WLOGFI("called"); + } +}; + +NativeValue *AttachWindowExtensionContext(NativeEngine *engine, void *value, void *) +{ + WLOGFI("AttachWindowExtensionContext"); + if (value == nullptr) { + WLOGFE("invalid parameter."); + return nullptr; + } + auto ptr = reinterpret_cast *>(value)->lock(); + if (ptr == nullptr) { + WLOGFE("invalid context."); + return nullptr; + } + NativeValue* object = CreateJsWindowExtensionContext(*engine, ptr); + if (object == nullptr) { + WLOGFE("Failed to get js window extension context"); + return nullptr; + } + auto contextObj = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(engine, + "application.WindowExtensionContext", &object, 1)->Get(); + NativeObject* nObject = AbilityRuntime::ConvertNativeValueTo(contextObj); + if (nObject == nullptr) { + WLOGFE("Failed to get context native object"); + return nullptr; + } + nObject->ConvertToNativeBindingObject(engine, AbilityRuntime::DetachCallbackFunc, AttachWindowExtensionContext, + value, nullptr); + auto workContext = new (std::nothrow) std::weak_ptr(ptr); + if (workContext == nullptr) { + WLOGFE("Failed to get window extension context"); + return nullptr; + } + nObject->SetNativePointer(workContext, + [](NativeEngine *, void *data, void *) { + WLOGFI("Finalizer for weak_ptr service extension context is called"); + delete static_cast *>(data); + }, nullptr); + return contextObj; +} + +JsWindowExtension* JsWindowExtension::Create(const std::unique_ptr& runtime) +{ + WLOGFD("Create runtime"); + return new JsWindowExtension(static_cast(*runtime)); +} + +JsWindowExtension::JsWindowExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {} +JsWindowExtension::~JsWindowExtension() = default; + +void JsWindowExtension::Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowExtension Init"); + WindowExtension::Init(record, application, handler, token); + std::string srcPath; + GetSrcPath(srcPath); + if (srcPath.empty()) { + WLOGFE("Failed to get srcPath"); + return; + } + + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + WLOGFI("JsWindowExtension::Init module:%{public}s,srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str()); + AbilityRuntime::HandleScope handleScope(jsRuntime_); + + jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath); + if (jsObj_ == nullptr) { + WLOGFE("Failed to get jsObj_"); + return; + } + WLOGFI("JsWindowExtension::Init ConvertNativeValueTo."); + auto& engine = jsRuntime_.GetNativeEngine(); + NativeObject* obj = AbilityRuntime::ConvertNativeValueTo(jsObj_->Get()); + if (obj == nullptr) { + WLOGFE("Failed to get JsWindowExtension object"); + return; + } + + BindContext(engine, obj); +} + +void JsWindowExtension::BindContext(NativeEngine& engine, NativeObject* obj) +{ + auto context = GetContext(); + if (context == nullptr) { + WLOGFE("Failed to get context"); + return; + } + + NativeValue* contextObj = CreateJsWindowExtensionContext(jsRuntime_.GetNativeEngine(), context); + if (contextObj == nullptr) { + WLOGFE("Failed to get js window extension context"); + return; + } + shellContextRef_ = jsRuntime_.LoadSystemModule("application.WindowExtensionContext", &contextObj, 1); + contextObj = shellContextRef_->Get(); + NativeObject* nativeObj = AbilityRuntime::ConvertNativeValueTo(contextObj); + if (nativeObj == nullptr) { + WLOGFE("Failed to get context native object"); + return; + } + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + WLOGFE("Failed to get window extension context"); + return; + } + nativeObj->ConvertToNativeBindingObject(&engine, AbilityRuntime::DetachCallbackFunc, AttachWindowExtensionContext, + workContext, nullptr); + WLOGFI("JsWindowExtension::Init Bind."); + context->Bind(jsRuntime_, shellContextRef_.get()); + WLOGFI("JsWindowExtension::SetProperty."); + obj->SetProperty("context", contextObj); + + nativeObj->SetNativePointer(workContext, + [](NativeEngine *, void *data, void *) { + WLOGFI("Finalizer for weak_ptr extension context is called"); + delete static_cast*>(data); + }, nullptr); + + WLOGFI("JsWindowExtension::Init end."); +} + +void JsWindowExtension::GetSrcPath(std::string& srcPath) const +{ + if (!Extension::abilityInfo_) { + WLOGFE("abilityInfo_ is nullptr"); + return; + } + + if (!Extension::abilityInfo_->isModuleJson) { + srcPath.append(Extension::abilityInfo_->package); + srcPath.append("/assets/js/"); + if (!Extension::abilityInfo_->srcPath.empty()) { + srcPath.append(Extension::abilityInfo_->srcPath); + } + srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc"); + return; + } + + if (!Extension::abilityInfo_->srcEntrance.empty()) { + srcPath.append(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + srcPath.erase(srcPath.rfind('.')); + srcPath.append(".abc"); + } +} + +sptr JsWindowExtension::OnConnect(const AAFwk::Want& want) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowExtension OnConnect %s-%s", + want.GetElement().GetAbilityName().c_str(), want.GetElement().GetAbilityName().c_str()); + WLOGFI("called."); + Extension::OnConnect(want); + NativeEngine& engine = jsRuntime_.GetNativeEngine(); + std::unique_ptr complete = + std::make_unique( + [=] (NativeEngine& engine, AbilityRuntime::AsyncTask& task, int32_t status) { + NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine(); + napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast(nativeEngine), want); + NativeValue* nativeWant = reinterpret_cast(napiWant); + NativeValue* argv[] = { nativeWant }; + CallJsMethod("onConnect", argv, AbilityRuntime::ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AbilityRuntime::AsyncTask::Schedule("JsWindowExtension::OnConnect", engine, + std::make_unique(callback, std::move(execute), std::move(complete))); + + if (!stub_) { + WLOGFE("stub is nullptr."); + return nullptr; + } + WLOGFD("Create stub successfully!"); + return stub_->AsObject(); +} + +void JsWindowExtension::OnDisconnect(const AAFwk::Want& want) +{ + Extension::OnDisconnect(want); + NativeEngine& engine = jsRuntime_.GetNativeEngine(); + std::unique_ptr complete = + std::make_unique( + [=] (NativeEngine& engine, AbilityRuntime::AsyncTask& task, int32_t status) { + NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine(); + napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast(nativeEngine), want); + NativeValue* nativeWant = reinterpret_cast(napiWant); + NativeValue* argv[] = { nativeWant }; + CallJsMethod("onDisconnect", argv, AbilityRuntime::ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AbilityRuntime::AsyncTask::Schedule("JsWindowExtension::OnDisconnect", engine, + std::make_unique(callback, std::move(execute), std::move(complete))); + + auto window = stub_ != nullptr ? stub_->GetWindow() : nullptr; + if (window != nullptr) { + window->Destroy(); + WLOGFI("Destroy window."); + } + WLOGFI("called."); +} + +void JsWindowExtension::OnStart(const AAFwk::Want& want) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowExtension OnStart %s-%s", + want.GetElement().GetAbilityName().c_str(), want.GetElement().GetAbilityName().c_str()); + Extension::OnStart(want); + + AbilityRuntime::ElementName elementName = want.GetElement(); + std::string windowName = elementName.GetBundleName() + elementName.GetModuleName() + + elementName.GetAbilityName() + std::to_string(extensionCnt_); + extensionCnt_++; + + stub_ = new(std::nothrow) WindowExtensionStubImpl(windowName); + WLOGFI("JsWindowExtension OnStart begin.."); + Rect rect { want.GetIntParam(RECT_FORM_KEY_POS_X, 0), + want.GetIntParam(RECT_FORM_KEY_POS_Y, 0), + want.GetIntParam(RECT_FORM_KEY_WIDTH, 0), + want.GetIntParam(RECT_FORM_KEY_HEIGHT, 0) }; + uint32_t windowId = static_cast(want.GetIntParam(WINDOW_ID, INVALID_WINDOW_ID)); + if (stub_ != nullptr) { + auto context = GetContext(); + if (context == nullptr) { + WLOGFE("get context failed"); + return; + } + sptr window = stub_->CreateWindow(rect, windowId, context); + if (window == nullptr) { + WLOGFE("create window failed"); + return; + } + OnWindowCreated(); + WLOGFI("ability context onWindowReady rect x =%{public}d y=%{public}d w=%{public}d h=%{public}d ", + rect.posX_, rect.posY_, rect.width_, rect.height_); + } +} + +void JsWindowExtension::OnWindowCreated() const +{ + NativeEngine& engine = jsRuntime_.GetNativeEngine(); + std::unique_ptr complete = + std::make_unique( + [=] (NativeEngine& engine, AbilityRuntime::AsyncTask& task, int32_t status) { + auto window = stub_->GetWindow(); + if (window == nullptr) { + WLOGFE("get window failed"); + return; + } + NativeValue* value = CreateJsWindowObject(engine, window); + if (value == nullptr) { + WLOGFE("Create js window failed"); + return; + } + NativeValue* argv[] = { value }; + CallJsMethod("onWindowReady", argv, AbilityRuntime::ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AbilityRuntime::AsyncTask::Schedule("JsWindowExtension::OnWindowCreated", engine, + std::make_unique(callback, std::move(execute), std::move(complete))); +} + +NativeValue* JsWindowExtension::CallJsMethod(const char* name, NativeValue* const* argv, size_t argc) const +{ + WLOGFI("called (%{public}s), begin", name); + + if (!jsObj_) { + WLOGFW("Not found WindowExtension.js"); + return nullptr; + } + + AbilityRuntime::HandleScope handleScope(jsRuntime_); + auto& nativeEngine = jsRuntime_.GetNativeEngine(); + + NativeValue* value = jsObj_->Get(); + NativeObject* obj = AbilityRuntime::ConvertNativeValueTo(value); + if (obj == nullptr) { + WLOGFE("Failed to get WindowExtension object"); + return nullptr; + } + + NativeValue* method = obj->GetProperty(name); + if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) { + WLOGFE("Failed to get '%{public}s' from WindowExtension object", name); + return nullptr; + } + WLOGFI("(%{public}s), success", name); + return nativeEngine.CallFunction(value, method, argv, argc); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/extension/window_extension/src/js_window_extension_context.cpp b/window_manager/extension/window_extension/src/js_window_extension_context.cpp new file mode 100644 index 0000000..0859986 --- /dev/null +++ b/window_manager/extension/window_extension/src/js_window_extension_context.cpp @@ -0,0 +1,162 @@ +/* + * 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_window_extension_context.h" + +#include +#include + +#include "napi_common_start_options.h" +#include "napi_common_want.h" +#include "service_extension_context.h" +#include "start_options.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; + +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JSWindowExtensionContext"}; + std::shared_ptr handler_; +} + +class JsWindowExtensionContext final { +public: + explicit JsWindowExtensionContext( + const std::shared_ptr& context) : context_(context) {} + ~JsWindowExtensionContext() = default; + + static void Finalizer(NativeEngine* engine, void* data, void* hint) + { + WLOGFI("JsWindowExtensionContext::Finalizer is called"); + std::unique_ptr(static_cast(data)); + } + + static NativeValue* StartAbility(NativeEngine* engine, NativeCallbackInfo* info) + { + JsWindowExtensionContext* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnStartAbility(*engine, *info) : nullptr; + } +private: + std::weak_ptr context_; + + bool CheckStartAbilityInputParam( + NativeEngine& engine, NativeCallbackInfo& info, + AAFwk::Want& want, AAFwk::StartOptions& startOptions) const + { + if (info.argc < 1) { + return false; + } + // Check input want + if (!CheckWantParam(engine, info.argv[0], want)) { + return false; + } + if (info.argc > 1 && info.argv[1]->TypeOf() == NATIVE_OBJECT) { + WLOGFI("OnStartAbility start options is used."); + AppExecFwk::UnwrapStartOptions(reinterpret_cast(&engine), + reinterpret_cast(info.argv[1]), startOptions); + } + return true; + } + + bool CheckWantParam(NativeEngine& engine, NativeValue* value, AAFwk::Want& want) const + { + if (!OHOS::AppExecFwk::UnwrapWant(reinterpret_cast(&engine), + reinterpret_cast(value), want)) { + WLOGFE("The input want is invalid."); + return false; + } + WLOGFI("UnwrapWant, BundleName: %{public}s, AbilityName: %{public}s.", + want.GetBundle().c_str(), + want.GetElement().GetAbilityName().c_str()); + return true; + } + + NativeValue* OnStartAbility(NativeEngine& engine, NativeCallbackInfo& info) + { + WLOGFI("OnStartAbility is called"); + if (info.argc < 2) {// at least two argc + WLOGFE("Start ability failed, not enough params."); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AAFwk::Want want; + AAFwk::StartOptions startOptions; + if (!CheckStartAbilityInputParam(engine, info, want, startOptions)) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AsyncTask::CompleteCallback complete = + [weak = context_, want, startOptions](NativeEngine& engine, AsyncTask& task, int32_t status) { + WLOGFI("startAbility begin"); + auto context = weak.lock(); + if (!context) { + WLOGFW("context is released"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(context->StartAbility(want, startOptions)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret))); + } + }; + + NativeValue* lastParam = (info.argc <= 2) ? nullptr : info.argv[2];// at least two argc + NativeValue* result = nullptr; + AsyncTask::Schedule("JSServiceExtensionContext::OnStartAbility", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; + } +}; + +void JsWindowConnectCallback::OnAbilityConnectDone(const AppExecFwk::ElementName& element, + const sptr& remoteObject, int resultCode) +{ + WLOGFI("called"); +} + +void JsWindowConnectCallback::OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode) +{ + WLOGFI("called"); +} + +NativeValue* CreateJsWindowExtensionContext(NativeEngine& engine, + const std::shared_ptr& context) +{ + WLOGFI("CreateJsWindowExtensionContext begin"); + NativeValue* objValue = CreateJsExtensionContext(engine, context); + NativeObject* object = AbilityRuntime::ConvertNativeValueTo(objValue); + + std::unique_ptr jsContext + = std::make_unique(context); + object->SetNativePointer(jsContext.release(), JsWindowExtensionContext::Finalizer, nullptr); + + // make handler + handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); + + const char *moduleName = "JsWindowExtensionContext"; + BindNativeFunction(engine, *object, "startAbility", moduleName, JsWindowExtensionContext::StartAbility); + + return objValue; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/window_extension/src/window_extension.cpp b/window_manager/extension/window_extension/src/window_extension.cpp new file mode 100644 index 0000000..593d744 --- /dev/null +++ b/window_manager/extension/window_extension/src/window_extension.cpp @@ -0,0 +1,67 @@ +/* + * 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 "window_extension.h" + +#include "js_window_extension.h" +#include "window_extension_context.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtension"}; +} + +WindowExtension* WindowExtension::Create(const std::unique_ptr& runtime) +{ + if (!runtime) { + return new WindowExtension(); + } + WLOGFI("create window extension"); + switch (runtime->GetLanguage()) { + case AbilityRuntime::Runtime::Language::JS: { + WLOGFI("create js windowExtension"); + return JsWindowExtension::Create(runtime); + } + default: { + return new WindowExtension(); + } + } + return nullptr; +} + +void WindowExtension::Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) +{ + ExtensionBase::Init(record, application, handler, token); + WLOGFI("WindowExtension begin init"); +} + +std::shared_ptr WindowExtension::CreateAndInitContext( + const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) +{ + if (!record) { + WLOGFE("WindowExtension::CreateAndInitContext record is nullptr"); + } + return ExtensionBase::CreateAndInitContext(record, application, handler, token); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/window_extension/src/window_extension_context.cpp b/window_manager/extension/window_extension/src/window_extension_context.cpp new file mode 100644 index 0000000..b2a3409 --- /dev/null +++ b/window_manager/extension/window_extension/src/window_extension_context.cpp @@ -0,0 +1,44 @@ +/* + * 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 "window_extension_context.h" + +#include "ability_info.h" +#include "native_engine/native_reference.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { + +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionContext"}; +} + +const size_t WindowExtensionContext::CONTEXT_TYPE_ID(std::hash {} ("WindowExtensionContext")); +int WindowExtensionContext::ILLEGAL_REQUEST_CODE(-1); + +WMError WindowExtensionContext::StartAbility(const AAFwk::Want &want, const AAFwk::StartOptions &startOptions) const +{ + WLOGFD("Start ability begin, ability:%{public}s.", want.GetElement().GetAbilityName().c_str()); + ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want, startOptions, token_, + ILLEGAL_REQUEST_CODE); + if (err != ERR_OK) { + WLOGFE("WindowContext::StartAbility is failed %{public}d", err); + return WMError::WM_ERROR_START_ABILITY_FAILED; + } + return WMError::WM_OK; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/extension/window_extension/src/window_extension_module_loader.cpp b/window_manager/extension/window_extension/src/window_extension_module_loader.cpp new file mode 100644 index 0000000..ecbef26 --- /dev/null +++ b/window_manager/extension/window_extension/src/window_extension_module_loader.cpp @@ -0,0 +1,52 @@ +/* + * 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 "window_extension_module_loader.h" + +#include "window_extension.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionStub"}; +} +WindowExtensionModuleLoader::WindowExtensionModuleLoader() = default; +WindowExtensionModuleLoader::~WindowExtensionModuleLoader() = default; + +AbilityRuntime::Extension *WindowExtensionModuleLoader::Create( + const std::unique_ptr& runtime) const +{ + WLOGFI("called"); + return WindowExtension::Create(runtime); +} + +std::map WindowExtensionModuleLoader::GetParams() +{ + std::map params; + // type means extension type in ExtensionAbilityType of extension_ability_info.h, 10 means window. + params.insert(std::pair("type", "10")); + // extension name + params.insert(std::pair("name", "WindowExtension")); + WLOGFI("called"); + return params; +} + +extern "C" __attribute__((visibility("default"))) void* OHOS_EXTENSION_GetExtensionModule() +{ + WLOGFI("called"); + return &WindowExtensionModuleLoader::GetInstance(); +} +} // namespace OHOS::Window + diff --git a/window_manager/extension/window_extension/src/window_extension_stub_impl.cpp b/window_manager/extension/window_extension/src/window_extension_stub_impl.cpp new file mode 100644 index 0000000..4dd9e81 --- /dev/null +++ b/window_manager/extension/window_extension/src/window_extension_stub_impl.cpp @@ -0,0 +1,114 @@ +/* + * 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 "window_extension_stub_impl.h" + +#include "js_window_extension.h" +#include "window_extension_connection.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionStubImpl"}; +} + +WindowExtensionStubImpl::WindowExtensionStubImpl(const std::string& windowName) : windowName_(windowName) +{ +} + +WindowExtensionStubImpl::~WindowExtensionStubImpl() +{ + if (window_ != nullptr) { + window_->Destroy(); + } +} + +sptr WindowExtensionStubImpl::CreateWindow( + const Rect& rect, uint32_t parentWindowId, const std::shared_ptr& context) +{ + sptr option = new(std::nothrow) WindowOption(); + if (option == nullptr) { + WLOGFE("Get option failed"); + return nullptr; + } + + option->SetWindowType(WindowType::WINDOW_TYPE_APP_COMPONENT); + option->SetWindowRect(rect); + option->SetParentId(parentWindowId); + WLOGFI("Window::Create"); + window_ = Window::Create(windowName_, option, context); + return window_; +} + +void WindowExtensionStubImpl::SetBounds(const Rect& rect) +{ + if (window_ == nullptr) { + return; + } + Rect orgRect = window_->GetRect(); + if (rect.width_ != orgRect.width_ || rect.height_ != orgRect.height_) { + window_->Resize(rect.width_, rect.height_); + } + if (rect.posX_ != orgRect.posX_ || rect.posY_ != orgRect.posY_) { + window_->MoveTo(rect.posX_, rect.posY_); + } +} + +void WindowExtensionStubImpl::Hide() +{ + if (window_ != nullptr) { + window_->Hide(); + } +} + +void WindowExtensionStubImpl::Show() +{ + if (window_ != nullptr) { + window_->Show(); + } +} + +void WindowExtensionStubImpl::RequestFocus() +{ + if (window_ != nullptr) { + window_->RequestFocus(); + } +} + +void WindowExtensionStubImpl::GetExtensionWindow(sptr& token) +{ + token_ = token; + if (token_ == nullptr) { + WLOGFE("token is null"); + return; + } + + std::shared_ptr node = (window_ != nullptr ? window_->GetSurfaceNode() : nullptr); + if (node == nullptr) { + WLOGFE("node is null"); + return; + } + token_->OnWindowReady(node); + WLOGFI("called"); +} + +sptr WindowExtensionStubImpl::GetWindow() const +{ + return window_; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/window_extension/src/zidl/window_extension_proxy.cpp b/window_manager/extension/window_extension/src/zidl/window_extension_proxy.cpp new file mode 100644 index 0000000..efc2224 --- /dev/null +++ b/window_manager/extension/window_extension/src/zidl/window_extension_proxy.cpp @@ -0,0 +1,101 @@ +/* + * 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 "window_extension_proxy.h" + +#include +#include + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionProxy"}; +} + +void WindowExtensionProxy::SetBounds(const Rect& rect) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write interface token failed"); + return; + } + if (!(data.WriteInt32(rect.posX_) && data.WriteInt32(rect.posY_) && + data.WriteInt32(rect.width_) && data.WriteInt32(rect.height_))) { + WLOGFE("write rect failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_SETBOUNDS, data, reply, option) != ERR_NONE) { + WLOGFE("send request failed"); + return; + } +} + +void WindowExtensionProxy::Hide() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write interface token failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_HIDE_WINDOW, data, reply, option) != ERR_NONE) { + WLOGFE("send request failed"); + } +} + +void WindowExtensionProxy::Show() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write interface token failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_SHOW_WINDOW, data, reply, option) != ERR_NONE) { + WLOGFE("send request failed"); + } +} + +void WindowExtensionProxy::GetExtensionWindow(sptr& token) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("write interface token failed"); + return; + } + if (!data.WriteRemoteObject(token->AsObject())) { + WLOGFE("write object failed"); + return; + } + if (Remote()->SendRequest(TRANS_ID_CONNECT_TO_EXTENSION, data, replay, option) != ERR_NONE) { + WLOGFE("send request failed"); + } +} + +void WindowExtensionProxy::RequestFocus() +{ + WLOGFI("called."); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/extension/window_extension/src/zidl/window_extension_stub.cpp b/window_manager/extension/window_extension/src/zidl/window_extension_stub.cpp new file mode 100644 index 0000000..7523ce8 --- /dev/null +++ b/window_manager/extension/window_extension/src/zidl/window_extension_stub.cpp @@ -0,0 +1,65 @@ +/* + * 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 "window_extension_stub.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowExtensionStub"}; +} + +int WindowExtensionStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + WLOGFI("code is %{public}u", code); + switch (code) { + case TRANS_ID_SETBOUNDS: { + Rect rect {data.ReadInt32(), data.ReadInt32(), + data.ReadInt32(), data.ReadInt32()}; + SetBounds(rect); + break; + } + case TRANS_ID_HIDE_WINDOW: { + Hide(); + break; + } + case TRANS_ID_SHOW_WINDOW: { + Show(); + break; + } + case TRANS_ID_REQUESTFOCUS: { + RequestFocus(); + break; + } + case TRANS_ID_CONNECT_TO_EXTENSION: { + sptr object = data.ReadRemoteObject(); + sptr token = iface_cast(object); + GetExtensionWindow(token); + break; + } + default: { + break; + } + } + return 0; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/extension/window_extension/test/BUILD.gn b/window_manager/extension/window_extension/test/BUILD.gn new file mode 100644 index 0000000..0abe745 --- /dev/null +++ b/window_manager/extension/window_extension/test/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright (c) 2021-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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/extension/window_extension/test/unittest/BUILD.gn b/window_manager/extension/window_extension/test/unittest/BUILD.gn new file mode 100644 index 0000000..e85ce3d --- /dev/null +++ b/window_manager/extension/window_extension/test/unittest/BUILD.gn @@ -0,0 +1,79 @@ +# Copyright (c) 2021-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. + +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") +module_out_path = "window_manager/extension/window_extension" + +group("unittest") { + testonly = true + + deps = [ ":extension_window_extension_proxy_test" ] +} + +ohos_unittest("extension_window_extension_proxy_test") { + module_out_path = module_out_path + + sources = [ "window_extension_proxy_test.cpp" ] + + deps = [ ":window_extension_unittest_common" ] +} + +## Build window_extension_unittest_common.a {{{ +config("window_extension_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/extension/window_extension/include", + "//foundation/window/window_manager/extension/window_extension/include/zidl", + "//foundation/window/window_manager/extension/extension_connection/include", + "//foundation/window/window_manager/extension/extension_connection/include/zidl", + "//foundation/window/window_manager/interfaces/innerkits/extension", + "//third_party/googletest/googlemock/include", + ] +} + +ohos_static_library("window_extension_unittest_common") { + visibility = [ ":*" ] + testonly = true + + public_configs = [ + ":window_extension_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//commonlibrary/c_utils/base:utils", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/multimedia/image_framework/interfaces/innerkits:image_native", + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + deps = [ + "//foundation/window/window_manager/extension/extension_connection:libwindow_extension_client", + "//foundation/window/window_manager/extension/window_extension:libwindow_extension", + "//foundation/window/window_manager/interfaces/kits/napi/window_runtime:window_native_kit", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "hilog_native:libhilog", + "input:libmmi-client", + "ipc:ipc_core", + ] + subsystem_name = "window" + part_name = "window_manager" +} diff --git a/window_manager/extension/window_extension/test/unittest/window_extension_proxy_test.cpp b/window_manager/extension/window_extension/test/unittest/window_extension_proxy_test.cpp new file mode 100644 index 0000000..f1e438d --- /dev/null +++ b/window_manager/extension/window_extension/test/unittest/window_extension_proxy_test.cpp @@ -0,0 +1,75 @@ +/* + * 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 "window_extension_proxy.h" +#include "window_extension_stub.h" +#include "window_extension_stub_impl.h" +#include "window_extension_client_interface.h" +#include "window_extension_client_stub_impl.h" +#include "window_extension_connection.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowExtensionProxyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr mockWindowExtensionStub_; + sptr windowExtensionProxy_; +}; + +void WindowExtensionProxyTest::SetUpTestCase() +{ +} + +void WindowExtensionProxyTest::TearDownTestCase() +{ +} + +void WindowExtensionProxyTest::SetUp() +{ + mockWindowExtensionStub_ = new WindowExtensionStubImpl("name"); + windowExtensionProxy_ = new WindowExtensionProxy(mockWindowExtensionStub_); +} + +void WindowExtensionProxyTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: SetBounds + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowExtensionProxyTest, SetBounds, Function | SmallTest | Level2) +{ + windowExtensionProxy_->Show(); + windowExtensionProxy_->Hide(); + sptr componentCallback_ = nullptr; + sptr clientToken(new WindowExtensionClientStubImpl(componentCallback_)); + windowExtensionProxy_->GetExtensionWindow(clientToken); + Rect rect; + windowExtensionProxy_->SetBounds(rect); +} +} +} +} \ No newline at end of file diff --git a/window_manager/figures/WindowManager.png b/window_manager/figures/WindowManager.png new file mode 100644 index 0000000000000000000000000000000000000000..e6ca1d5ceb59e33fb37400eacfc3c8d823c60e49 GIT binary patch literal 125465 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
H~bv`=Hyt9*i;q26~yvsz=|=3?AdI((OCfW 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 oYce>^i5@{B1TEy`J{*!qkwvy02TD^ad6PE$Pl# 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ÍlJ;NLLq<|-ZC%_zhnD~Xna-YBB#_$b=|4y<3X({0L{YMXZN3d z!j5h(DGDyewk?D;mv{l3HRS>3R|Dw^pjyDPbFw18+*L~Ghd@WmYum!n@ZG*T4LZ9A><2EPDbI2&N-We8<{;8PQI>lX@Ac%?pL2^8 z&pK0)vBYJeQ?+~bl^Nr;8n1J)3Q0j{uckQ2En~}AJrO1OSG7W)ReRrT0ki zz?`m(Pe2^NnAj=Y%nr&+q7-AE=Ixk;2`y$yrMRiorAhO~f^}){f~A6W2?I!9gDGn2 zs+ae6Puxu)5+#F9p0_x7%K`ef%N zwvoTYNF=1_6fJ^Eu1R{Y8}GN4OdEQb`T9n9Qj}ZBy$KxwzVdGWrMKC~JZ8+;<5kO+ zI+dcIdmaii(qG(v`(m#FSTWs*SQk69@HB+AV#0heT6!3?! ziFwe(OT83T>KdvR!BxTO{}ec%`>DA;=54NMT!l{6?W-itZ%Yq-@V(+f7X9Wit4X`n zolk)zL$Dh;?4zS*dCY6uV&F6Vm{#|vsd?ulo{vhHqOh&C$xFIZih9OdVt&QWK{GMw zoQ?{h(5%bQVW!}))WH7G7QSCVt}?o}8Dc%5h&E0nPslTVm!`B0jO(LqQ|&REZ^;8T zsGBL9CQh_b1=?%gyBwc`!Z{9x4Xm=J$e`jgnqtRU63I+uvUl}+J4WS3|1Rv3*et_J z_-2B~_8s5b+r#V3$|Y#UjCob{z21sSAHOH&kT9R*QMO&jl13v1E|x(x#PIIsw; zafMvsizs(0_&fmxb4pqA#WRWfK9~NK*kTR}sgs7RApUMKtYV0CvO?L#x<(QWpHgk| zS_(0O^-XJ~>DBOs)2EZyiborE7#@Q0J59p_2{);IhT6g#t+jef4oNNkSZ?2c!klC!qCPZWz>#kH%>5O@JvXSQ9gU1*+i@)C8=-kTT0(2MDb{&fMu_a#H8 zJR*_&ZBkEDsBW!k?*LL^R#E=p`CZ8CnZ{b|a1mxI<=so<4^NgLFq*K;zYifg1|n>;_?kYy}G12#Lja#+zjGek=b$ACE4ph&dFEWd_Mt}xCd}+UEV*{ zVVTlVaOZt2cs+J)nb*Od@R&f^gD`5>7K3FLKMhzmG^Pe?6xG}3_BG`qNsXUpD5fw< zDYbEM0_7MPj=z3O-byJYCLN>SWEMN+H-U3K$-4SU%wxBMM7clS@H<<*|L zHO}wAP84el&L?LM9kaZ&sQoQp5stM7S#hkD;@`3eR_^YT$MQsNGwiI~9Icu}_bonc z)~%>Q5B!nLfU9prRTU-YQ0M7jtaX}?Yz-Qr$3b^GDDxWI1~MBHeN@rqvx9dlecVjq z<5W^5M=AT*h|w(iP>?N>I=0e7#(PI1DnB}PR?kFtuTZ%&4rPqd<{<8{v$woo&!5@$ zw;~1UG)AyE)b7DvKIV(Iz+B+&*DBQ0RP{D=NbwS67l8Pg4%~A4(Z<)ayVYHV{4bry z*giEEq5Wrw=WEW*T2wKWeN2$&m#z1#Ji#C<5z{ntDnkmWX$~xV(;s=>HSZ~)e#$@0 zf%gqK7AYuZoAft|hEFyl?^_jr)=v`Z_7(CvX)dAqz);dc2Vd7}prW&aPpjA-FIdG& z#E*0bcsso&E-s_t5*e!4(WGn>I&Gk8<}h!qF3(=w&~`NN)n;$xI?cLPufgvky5gYq zBNMQ>0}y_U*yL#?GmF}sb)0EU+7GbRL2S9i83YwNQH`6)-2gee{cPrY-@e^UHnyLh zQ*}^f2l`hBIeI82&+H4eW(Tv`!Yf-tr3G&^%IhmD8l(Gdec`xDnUxttVk)L*5b~(?({$&%8 zlVj|uM+c9r$Gc7lvabyvKu?_0eDI|{2D2;38yL%0gqIZ+TFr!#-q#63xP=q%L*L&N z4>2b6sFa;za-MF;F&-$ss0+A%L)hrItO2L8FsBVvxv8(`@ee%QQ}2U*t)V#))^KS` zlW5$<_+;FUR9qzV_I>{+&|bWn6Kocxn*+WG2|| zgG0(f!4IwKKb8~}sz0o>_X~;Gx*)K{hE)0n(-GlTkTgI46@41^(t9*%-v$`XCUl^0 z5>yGZhm<29ZIVV`^s}rp3+H4ENW++{+sWb_;``9!$MUA3?MAJ=Q28JwrHB|afgMYe zQ>iG|)m+_eCw#oKdDPYsGIiJACb%4=_9@fkpbaGQOo7ifMmX{mE(TAFC#`yqz?mf8$x1y{mD|TX zHWFKUd%Taaelg>A(G!q8Vzn>W-D7gCGTd;=M&7uXRNKY6x&3=$aJ~dB>dRY^5Mx7o zu?ios-*T>uANpVZr!Pk38j}Vb~J26>GE@(U!V?3tyJ`G}y zn_i#~)i|vyDrbeQUyPZUk{N%?U8*^;HiQAmu2eWN!W}4=HOiIVDA&m6CB(O>irx?e zn%NTIIM#38AFF2rL384rb5cpv37l{Hv<(o17%?tK7DBJcKIJGXRehHKtri)Tq&`$t zSD@5&^jXdCxWqR`1)Ax)s1qt0A6h4>YJAT;ldV(Vt`5VyfzK`s>SNlykSPnd?1e%v z|HAvdSAL@P-iJh(mrWg5+YHb%tHXY^M#%Nu!QiA z^pTBVAd+17Funcpj*pft;Y;q#Xw+Z6j4SnzJ$K*1R_fqV6{Lh26aklkXqEdHB4-x z(Gi|H$ej-!iFu&f*?5cIypGSHjleSx#MFOZ9(L-g2GyBOUUnO;1&qxOy!BOt4Pc%% z@XvLfMZz}@C0YvgUtRptv%Cmo_P%IB=VV_f!C)m4Xgh!SVKj$q-r35JdP0$uz@a+!< z1}(kw#FI5pZYnx7GN>H^u-BOI$a=S$=Fqk)G-qv*#c)e(!RYa1h>{|~2lcVg14AhE zK}ksdx-asp7?!%28{c<7*&*<@i_>aXlnn0diO4QK94K(ir^nE&2)=jh+h4V4gymk{ zxfA(7`bLV)tKTGHLM6v>;1`~iCNIm0&l230JL3%Z>_;Ppd^n!!sk-j)zUUz9^ZqK0 z`XxDuB#uP<%TpNV<~d`4_ZZ66x$6JQr|Zlrt?h*`R~730xdOb|>F;Ii(`fR{LNSCF zgP}GK2XuH{h)cgH66qd#{Rau+<=k%=(aT5uI!?-0pDFTokua2x zC+LedcXdWAjo?<9>z8z(tKFK5=`r;6NPp^{@nl{f{aWLl+XrvVD>Ck%jc zH&kGnV81b5K@dszI=FZO>>X{`FGxnLkC=Uc8#qfoPWFkwZhz|5)Niss6FMz9*$DWN zW`Jjc?yfYHJTwvTvW%-cd)MdXyk<}7xYzMZye$=3f;tiEGxVa)b6DWda$_|EbRvM2 z-7q@d7UDWN7m5W?be$y*cu)xz#*K`|yruqjP^x0$7p+kvE1?_0dgmdZQX3z~>d3^| zLbG?Tk71e(dQ!(NDW&hKpiiORZXM?ptW)YrFSyv^dTMn{?5ClaK-+0Jw-0*Vgi)6q z;JorokwI)Vj=fd-Rcg`K)NBPP9zY*R8d)s=Z7)_w^Kj>h&&ok+K(mh(BT+20)?!QZ z+^29$q2&C~SW97yt6lBk`MUCBj-=jU zjgfOr7<;J&Y}M5|1;72c*BiuNGfkK}CmB}dlAZ8|N93R_VbR5t+mlwIr4AKPs<-Wb zxF(Iv5#d<7eaF=6Z?-ZUG=3O~!O-ojyx?6W3fTNyThpM3^scK}7h4S%nl9~n2(wpqP5rH?@WfYkfc zJHua^nl@+LH@fY6$KlQeI~P)30F<9NZAMRFmTj%v$Co^jYK4vEOj_&yIUIH1{v|BQHwz>xptbcA9*cm2( z-OehCtIt(0j!q(&{$9Z9;EXM_w^qtwPw`q33DvZ078Y-jfUpmknho$wED^FCx*y38Y(*3_HXRP7;6w_o>5 znR}spNOqb{{=pOS#GaF1c#OXi%a;n`hu_ch6e6u_oc;D2P#rgc%}cV~1HZGqeIxCr z8eteZwywdl6J|hpnOf_XNk-D&Y?q3oX1|e|dh*MTyEhcPIsD-!sY#elZ(zq@pcK<+ zN7HHoTehO>1iu*!-Yo#L(i8nWjc1Ea{nemS7y2i9T3Z>`u%cWls}8xZawj?2^>W(t z2WBY`kDGecd`cxhfFyY3YI(o(HnKj^pZ-$m%>K5r3k4Ht_{7)a%y+cI$#!3npbz1d zs*@bAYKqla*~9f+&(br=3e)!6_nbAat1mRqI@~^_oZwcjby4Hu)skPTG`^VJLn)$3 z``vQv+zP>W)V$qXyvOYfg-*(sQnjrm`F6R+12tt3AI}@~W})25kN%LUW^^~G)wxv- z5B^d-VQL@zjnh06(|aa`bozm$%N~n1Md$J~fR${Pc@bjT?95t@)EHm+D;lNG)JhIM z-kHs@blkvMLyhB?IR35IAE3U1q<`SO2iY#qgh+V4X3*WX*%S_u!!@Q@4>J~c( zIAKjae>$DKtKnxF-&Q)qk++l7FewR6(<7bf^WHynD^>2=)yw<5@A@A9&G~8qbfc+~ zTUAYdySVP!Tl$x0*NNwLUxr~5X9gD^{OAX&qh?Z$GHPxO(#uGy#jnOq@29w)54$I8 z+4*Nv-FDh&odS=|##tY>PGe^*2jO7B)N0wjO_T)IY#EUm>K`RBzQ zwIOrDrEd?F{wU@B@-~I!gsmL!&U@f>%=-kMQ(H;>YiuttRp$Dnp%sXphZ3QC1-^8v z4AA4=?#=s)FPujRj^mDbRPtX_JP@nM)`yX`QBmI)AlQ*$4(Tkg8 zqwAyVvwpVv9JE|2c=4K-44G6um=04q^Ee%%zP?kVtd&3dSu7Lun~Mid4d(go&f?iP zpI(s7W>0DTAy!&6HHJ=&wcb7xnfv4Vf`c1z_*dl9>_1CSU4tC=JMwo`;pa1d+MUS# z5KQ@zJH4<+Qb@P5jz-|4AEOq7QME)L1N&B5H6qOVC`uvW4elPQ>U6{e`*J>S#=|$j zdLYeerT4m+%NJB(}SO6>Q)I5C&?m*3>Yw&E#r=~(x5xALFm zG)$MS-O>I$^}xlc;&%O$Y(JUoLxpBWR?FvOT89oN*8d%tNA>b;H_E%(=vd*mv#fDD zK$N8+SIx~fsr0ES0F2>FvG4&P*sC{Voz~G%K*G0gDlfySe}9Z~uDBEX^={Ekp7-(7 zIX~kaVaShU%-oyLca2mys)i^GAHtG8cv zkW3!sMEIBZQoqd`Z^*YFIhM5WEJT=R}Q)m@&lvk8N^Q+m4+jh9{atg zrYEnd%FpxE!nJOY$75)3Eb47uGFdS4Il6=ye$6d!s3~UyITSi*jUu#khY?2#f*!Ie zMr9VKAE-VFncsjoKh~|PQ@W=8c(p{s=Hk-R?u$PBjREY{vnN$&sXUG|9A|$9;f`o9 z^4lLd`zx^L5~61AUErN=WL5YpUMT`zRSU^J)uSyM^-7U1o+v)He>YwngUQZKqI-?J zY%P^rvpBlF^RlwQ=~a{L2(lyW@lJE`mx>}6ron=B+UDD$Z1{8) zzNvl+dz&6>!G18dl&2_lR_RtlaA9YeEFN+}#mB(}1xbhpIuKyVcB^N5U53UceTs%s zwX$TJoyZL}rC!ni9A;RG*KKwvlRgqYsR8+&k6?|ltn!kt9(VQ1ywe$gjSFv0QK$jY zhNrwhKt^27#y2|?>KQ|~@b}(nY$ez>)Wm2NNP zPXcD}@*n=e2F2i@S)sohH`Vb6PbyWH`3 z-t|sUFcCF>Oj|GqZe>L&CT} zh?}|9)Fw_3%-YJ(+U8VDG|{zRjpW*Hu8&^G@n?r>yNX5A?3KUw^?E7!OH> z@8yg5ywY?+FX$t;O-g?1?*DD>CnrJ34iK=6vxuOP1rIgcIu$-mr6Uc(kz;0W9+?^ctHGA8-&bQbsuUX}} zr($s;BULEgm2Q9W{BbZO?ZvKNWnfw2I|)h0Q%BfL{G%M;#)#>o=}za-p4 zGh3E9HI!+(SbSCpc$A&i@L-WYYpfsGXX1UTsW$9E6 zRyGY)eQh-6m+eRw*MSBUc*ToQGV$>%AiL2UIa;I~#aW{jX%pBFJ-w%I!(#6Ewb0Cy znzmHvLsqrdQv2q@)L)-o{btCo^Y^N7(Xt8;@9%YLpc}oqLo4LjpyqtiItmWgTU{!B z0Pdo5q`&TWvCd+k*yAkQ?Ro2iX466M&kfmKuR%P@ zA#uk+CFv@SKU=4gofpy*Tc@$=&`KyaJdbnhTKTxNATxTAZA6yLba8-=tCS)3T-^9&E@wygxwbhxY znJsb`jvw(udi-kJ+pu%cXcb?ja-L}J*ECbOKfe39xBSP8=tkFfpIy+Ekzmt?>hZRG zwKxhyx?|hk$Dvm+gLt-ZqQVw~&MLl>6blV@3{7KG!)70_+$)pm@6o zKq$nm2Ip{70KDjErjF^4-g`H&>*d=st1Ni-~- zbQrbChoo?xT9qE}q=YyOXSSB*5+g@oHGu7$4g9(dte&3RXa3*0!Bu@`s0VuZy79yB z67rC*iDl5jX5n|%LH#U@(mP=j^GfG*3w21e4k4({L9xMcs>XbG!QV?gXHe{&^3uyi!0wZEUUA;(YS_~E4zgg=k*vjmq13!x4SsogJlJlxAaR?>*f`^ z?_j3kVNIL&xEG1H9NmhkuS_JY6|HzMWRLsNt+lh?zCq4_VoO7S^$imq<{^LAScVS3 zWa?X$&jl@EP7e;?b2BW?K&cHGYuG&Njb^%eTQ z%ZL|!%-8SLZKV{HNtlz+AN9e37QptUCRe?d?F;aRw0j2iWtu;_&r6ubS#&?ozCJfT z-z6{7)#m1`G>Z0C=8#S@dzOL+bb+b|8&2&}vN-FCyiOr@Ycksg!qWwZO8-%nXKOsg zp@mhu)hDL&^Th-I!HLJH7k=;Q6EqUlGhCRxM5$oobk+2*=uQkVG z6ig_^2+3+}PW!^EnQFslNjx%6Lnv0FXT zuu82*%tR_8f{(3EY>f9nYiXR*o@DAExtVr=`35&*+Js?l3=OPhTjU8Wl7LdrYy$v& z=Jqt)N3U5@k(yOX57AP^8mt*kL$E$qf2HN@rr0EnQF`^2AlmYO$@^c%?(zQDmUC+L zBQO5Olqc$r8t4yv@5#brs%K z>2=EaP$bqCFPn+|5bT+E{`oznCtWiI^YI{=^N0R8k#$)leA#+mOk%&GK5ymuaUG-7 z`_CxlvKHYQi|03Z7B-BgBk{%ia)(}J0n9DwhG1asZ|*9*>aJ7h6_I9u-z=me$3fE` zq^|W9D%eGNbyc^zUy-{QZhArn=)AF2_YBn%ddK8#jUP5pbrp_A&?F5v4K76z9n(AU z?wcNpRpfARPdNlw(gV^%qeCH_Jq0 zkT+^r>8+dJB?|~=aK%>L3SEnL@udg*&n8k8xRB3H4R>_VXVLpiSeL%1H>Id0OtB@VS@!H#Lz&R00g`O*ON5?UQ9YNJKxspk(F(;2o&1s~243gAu?h|0Uvau%|3(?+%7Ei0Nu^QE2N z9>=yameyoTTCbkUJUI>v$Jg+Xu#~?)?MW2r0hn8PK`zXsWcyh*N!HD@nhZo%p%7b> zo*hQEjk|5`%cxtI9lUgHF)}-|?S)xC?+{#27GYJFxm5`hGRZcnJtP`Bf^mE=bU3NJ#;puaB#lM3?KWgw9milC<1ZIjmO?7r9t8I@(Cl=r zvYoKstAjSZ1mPoqrhCo_D91Z6)FpVl`g!fQJc9Q>@N0iPn|FPrR#g$Ht&Sx=&A;w? zyb~wKuo$RNs1en&gR#elTRd;~qg6Y1UhU}s!lRjms=wBFmXY2XIjXHZ{46k>GIp6L zjCzu{Z7~66+A}Y}Y{?zC>*vW)+<%DJe@rN&CF3c*Q}mnQ$j>SQo#E{q(37bUeIH+h zMwOC_t>hgSj*T{+wN+WTgdRq8Va^fcrH?_F`S_B4i0=(5h%9YYQw_vb2@cBfQ^r@~ zRZL4&orlviCuf60vomG|Vj~$vj`4&FAh>d~C%Cx#{w^6hA&yed9lN2ERZkm!2%~^D++6!nf^||I6ODuOgD038D0*lRDrA@_WiNOc;>*k( zVATkJ^qn47c(Ix_8P=nq2)!}7>5RE*Ngw^hzXO5jSucjpWo1GRxx?@&0a2^F+6jJ> z=m?>X-|8nXWC-6kF)`%r#oU{udM2)%VVfWh>2kTRN61KsaF}gS2{o-eAzz2*vn&v` zj%R0Dhin=aZ#=iVdWFj1J!$CCw;dUb+{CKKOxe-X-P{}!4O*jJ1e|2S=hQtbV4u=TA}V7=+zrht$wj-#g0Kpbs~ z*u510)U>|4#%O%p*&we%C;_vN^Wk4EtFykn{fJVL19G#T(Qo+lqOC;A>j(XL16r%B z15c;FI%WizT4pGGcu)$+>b`sPiPdc*o1WnM&IcP>3+d4y^CG}9VEvi3bj+Dlz(36qN-`@3r z8Uv?ke^jWnPgpFkqW#DcAWizh@>>q)vK}$OE!_ThyS%qaZ2|m!A0l0R8VdS%GE zHG~5QXeziz_U^|7xS#ih!Kbvox;fF4(%xf#d*{n&})@6%*fSj`ZC_4y?sHeAueb-`y27CQ;Yd7TcP!h*E z9VkAF1N5Q@HqU$89+;Mya`b`AAdvKE$?V(Hh?-<*w2rog{k%9rJ@DlrP$U5U1|0tv z)RF&XCE0r;`lg@EZr5?mkoef15oA*+pI5NiMA_xSBR2_cBTD;y^QWa1JO2QblE3pW znE@I)@RVzOJPH}O2z+O(J~XDa^vVH1WZC5sC<-X+M))`+pvKLG^%%)F{ikpO2Hu z9_FthXq%ki)dcLlQNFdNpJZke0cB*87N7`P@W=%T+GI4U@*XKG#O~WCoH3pE(f@aT z+f@%_(2&udQuh0i*$()&;*BBXj~5*F?-MRG?IF(qC!rDnz4nDk^9~*BG=qKnglO{O=Vj{6X%xFCT_)Oxx4h8>`^g=dIuG!+1l_!jlI1~1>=A}S!P3rt&PX_lM%?pu{TU)Dn+_{%N)tn` zp1a@~3!^;}^}XK~dOC&s`Ho*$lX)IajY3`@J(E97&b|*x>)zMK1-F8R z8OB97PhRD`Ta(d`WQigoh8}{1^8r~)&Y%_mnj!qj?O>Kh z&4ga@+<_b?^D{m1?8gk9zUr;^G~f%x5FVh~blM~VUDKxf>mnx@`E+wB*@_uk3-tfd zV>1R>oBni+H6}7SEfWS1S&&hS=D3nh)y3-X(nMpR)1Z4DZj#BSpWx2wS?{uUBhTQb zzwh45_y7dRTBKsM=4iX`#JkkP(|fo~c(f>2{N**;vkY}w2 z&cfJ5Ge`GHUV=8E^!W;F5~X7Z=Pj1FyYu#tHK1tS{wM-#w4ZuooX_nrbdEB~Z+O8J ze~4IcI26jd8pbu;>$p{Jer5T`x6JG5nNq(*mY}&>mn~GFV zwP`V*8QwB<`d%$1SnF`KMa-_tuVN0y8nB~m*EbS3o%E6P^LbFy9wfg$Y-CTOr=!8& z()IwjP>w+!ChT856JQdqX*x&v^jLH@@!@M+^lF-pzy9h%5;4iScXJi&wQGEKfBVE8 ziuMBx2A!Hh3||SxLPA`BHDSXY|7hiIZBK$%*hM`)@!4gRvS=|IJ%{O1PY2XtCT8Us8H;ji0T7{ZgaebamK5 zI%Y=uu&s!Nzm$wjCt9(Kl_GwnWeSU|hYfYP(eh1J%uB?5m}A%bQt>>W ztKrtYuh-_E&o!W3E2)CvcNh4U@ ztH;~D291lzssIY@9Jvr09T3z!zW=9ozVS;qzt`!>1Hwd(Gq=k>ZhE0~GMKcK$hIs! z>~C>^aeA*XpyxdI@a>Yzp2#!h@ICy@ka1%6Mc4Uz4*OVnDb33?{jCH^|9LTyvmcVqCO4c0_&wO2Wc5*5xmx3&S5cor6qcw9mG-d~Zp@W%84{nhn$y=5-Wba*ehUuibM+3}u~vT}s=DY!MRUI& zE@oyRpVPLdNnsR8#=3?CRs50E>OXJe>b$$x1O$;$tWP>{HDxn=Ic+&l84DSmL

- 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 literal 0 HcmV?d00001 diff --git a/window_manager/figures/WindowManager_EN.png b/window_manager/figures/WindowManager_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce181d41fb2163b948e7a1295fe7f3ae3579656 GIT binary patch literal 127072 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 +#include "dm_common.h" +#include "noncopyable.h" + +namespace OHOS::Rosen { +class DisplayInfo; +class CutoutInfo; + +enum class DisplayType : uint32_t { + DEFAULT = 0, +}; + +class Display : public RefBase { +friend class DisplayManager; +public: + ~Display(); + Display(const Display&) = delete; + Display(Display&&) = delete; + Display& operator=(const Display&) = delete; + Display& operator=(Display&&) = delete; + DisplayId GetId() const; + std::string GetName() const; + int32_t GetWidth() const; + int32_t GetHeight() const; + uint32_t GetRefreshRate() const; + ScreenId GetScreenId() const; + float GetVirtualPixelRatio() const; + int GetDpi() const; + Rotation GetRotation() const; + Orientation GetOrientation() const; + sptr GetDisplayInfo() const; + sptr GetCutoutInfo() const; +protected: + // No more methods or variables can be defined here. + Display(const std::string& name, sptr info); +private: + // No more methods or variables can be defined here. + void UpdateDisplayInfo(sptr) const; + void UpdateDisplayInfo() const; + class Impl; + sptr pImpl_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DM_DISPLAY_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/dm/display_manager.h b/window_manager/interfaces/innerkits/dm/display_manager.h new file mode 100644 index 0000000..599cccb --- /dev/null +++ b/window_manager/interfaces/innerkits/dm/display_manager.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DM_DISPLAY_MANAGER_H +#define FOUNDATION_DM_DISPLAY_MANAGER_H + +#include +#include +#include + +#include "display.h" +#include "dm_common.h" +#include "wm_single_instance.h" +#include "screenshot_info.h" + +namespace OHOS::Rosen { +class DisplayManager { +WM_DECLARE_SINGLE_INSTANCE_BASE(DisplayManager); +friend class DMSDeathRecipient; +public: + class IDisplayListener : public virtual RefBase { + public: + virtual void OnCreate(DisplayId) = 0; + virtual void OnDestroy(DisplayId) = 0; + virtual void OnChange(DisplayId) = 0; + }; + + class IScreenshotListener : public virtual RefBase { + public: + virtual void OnScreenshot(const ScreenshotInfo info) {} + }; + + std::vector> GetAllDisplays(); + DisplayId GetDefaultDisplayId(); + sptr GetDefaultDisplay(); + sptr GetDefaultDisplaySync(); + sptr GetDisplayById(DisplayId displayId); + sptr GetDisplayByScreen(ScreenId screenId); + std::vector GetAllDisplayIds(); + DMError HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow); + + std::shared_ptr GetScreenshot(DisplayId displayId); + std::shared_ptr GetScreenshot(DisplayId displayId, const Media::Rect &rect, + const Media::Size &size, int rotation); + bool WakeUpBegin(PowerStateChangeReason reason); + bool WakeUpEnd(); + bool SuspendBegin(PowerStateChangeReason reason); + bool SuspendEnd(); + bool SetDisplayState(DisplayState state, DisplayStateCallback callback); + DisplayState GetDisplayState(DisplayId displayId); + bool SetScreenBrightness(uint64_t screenId, uint32_t level); + uint32_t GetScreenBrightness(uint64_t screenId) const; + void NotifyDisplayEvent(DisplayEvent event); + bool Freeze(std::vector displayIds); + bool Unfreeze(std::vector displayIds); + + bool RegisterDisplayListener(sptr listener); + bool UnregisterDisplayListener(sptr listener); + bool RegisterDisplayPowerEventListener(sptr listener); + bool UnregisterDisplayPowerEventListener(sptr listener); + bool RegisterScreenshotListener(sptr listener); + bool UnregisterScreenshotListener(sptr listener); + + constexpr static int32_t MAX_RESOLUTION_SIZE_SCREENSHOT = 3840; // max resolution, 4K + +private: + DisplayManager(); + ~DisplayManager(); + void OnRemoteDied(); + + class Impl; + std::recursive_mutex mutex_; + bool destroyed_ = false; + sptr pImpl_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DM_DISPLAY_MANAGER_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/dm/display_property.h b/window_manager/interfaces/innerkits/dm/display_property.h new file mode 100644 index 0000000..692eecf --- /dev/null +++ b/window_manager/interfaces/innerkits/dm/display_property.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DM_DISPLAY_PROPERTY_H +#define FOUNDATION_DM_DISPLAY_PROPERTY_H + +#include + +namespace OHOS::Rosen { +class DisplayProperty : public RefBase { +public: + DisplayProperty() = default; + ~DisplayProperty() = default; + + DisplayType type_; + std::string name_; + + int width_; + int height_; + float xDpi_; + float yDpi_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DM_DISPLAY_PROPERTY_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/dm/dm_common.h b/window_manager/interfaces/innerkits/dm/dm_common.h new file mode 100644 index 0000000..a3e8a6b --- /dev/null +++ b/window_manager/interfaces/innerkits/dm/dm_common.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021-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_ROSEN_DM_COMMON_H +#define OHOS_ROSEN_DM_COMMON_H + +#include +#include +#include + +namespace OHOS { +namespace Rosen { +using DisplayId = uint64_t; +using ScreenId = uint64_t; +namespace { + constexpr DisplayId DISPLAY_ID_INVALID = -1ULL; + constexpr ScreenId SCREEN_ID_INVALID = -1ULL; + constexpr int DOT_PER_INCH = 160; + const static std::string DEFAULT_SCREEN_NAME = "buildIn"; + constexpr int DOT_PER_INCH_MAXIMUM_VALUE = 640; + constexpr int DOT_PER_INCH_MINIMUM_VALUE = 80; + constexpr uint32_t BASELINE_DENSITY = 160; +} + +enum class PowerStateChangeReason : uint32_t { + POWER_BUTTON, +}; + +enum class ScreenPowerState : uint32_t { + POWER_ON, + POWER_STAND_BY, + POWER_SUSPEND, + POWER_OFF, + POWER_BUTT, + INVALID_STATE, +}; + +enum class DisplayState : uint32_t { + ON, + OFF, + UNKNOWN, +}; + +enum class DisplayEvent : uint32_t { + UNLOCK, + KEYGUARD_DRAWN, +}; + +enum class DMError : int32_t { + DM_OK = 0, + DM_ERROR_INIT_DMS_PROXY_LOCKED = 100, + DM_ERROR_IPC_FAILED = 101, + DM_ERROR_REMOTE_CREATE_FAILED = 110, + DM_ERROR_NULLPTR = 120, + DM_ERROR_INVALID_PARAM = 130, + DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED = 140, + DM_ERROR_DEATH_RECIPIENT = 150, + DM_ERROR_INVALID_MODE_ID = 160, + DM_ERROR_WRITE_DATA_FAILED = 170, + DM_ERROR_RENDER_SERVICE_FAILED = 180, + DM_ERROR_UNREGISTER_AGENT_FAILED = 190, + DM_ERROR_INVALID_CALLING = 200, + DM_ERROR_INVALID_PERMISSION = 201, + DM_ERROR_UNKNOWN = -1, +}; + +enum class DmErrorCode : int32_t { + DM_OK = 0, + DM_ERROR_NO_PERMISSION = 201, + DM_ERROR_INVALID_PARAM = 401, + DM_ERROR_DEVICE_NOT_SUPPORT = 801, + DM_ERROR_INVALID_SCREEN = 1400001, + DM_ERROR_INVALID_CALLING = 1400002, + DM_ERROR_SYSTEM_INNORMAL = 1400003, +}; + +const std::map DM_JS_TO_ERROR_CODE_MAP { + {DMError::DM_OK, DmErrorCode::DM_OK }, + {DMError::DM_ERROR_INVALID_PERMISSION, DmErrorCode::DM_ERROR_NO_PERMISSION }, + {DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_IPC_FAILED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_REMOTE_CREATE_FAILED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_NULLPTR, DmErrorCode::DM_ERROR_INVALID_SCREEN }, + {DMError::DM_ERROR_INVALID_PARAM, DmErrorCode::DM_ERROR_INVALID_PARAM }, + {DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_DEATH_RECIPIENT, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_INVALID_MODE_ID, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_WRITE_DATA_FAILED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_RENDER_SERVICE_FAILED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_UNREGISTER_AGENT_FAILED, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, + {DMError::DM_ERROR_INVALID_CALLING, DmErrorCode::DM_ERROR_INVALID_CALLING }, + {DMError::DM_ERROR_UNKNOWN, DmErrorCode::DM_ERROR_SYSTEM_INNORMAL }, +}; + +using DisplayStateCallback = std::function; + +enum class DisplayPowerEvent : uint32_t { + WAKE_UP, + SLEEP, + DISPLAY_ON, + DISPLAY_OFF, + DESKTOP_READY, +}; + +enum class EventStatus : uint32_t { + BEGIN, + END, +}; + +class IDisplayPowerEventListener : public RefBase { +public: + virtual void OnDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) = 0; +}; + +enum class ScreenChangeEvent : uint32_t { + UPDATE_ORIENTATION, + UPDATE_ROTATION, + CHANGE_MODE, + VIRTUAL_PIXEL_RATIO_CHANGED, +}; + +enum class ScreenGroupChangeEvent : uint32_t { + ADD_TO_GROUP, + REMOVE_FROM_GROUP, + CHANGE_GROUP, +}; + +enum class Rotation : uint32_t { + ROTATION_0, + ROTATION_90, + ROTATION_180, + ROTATION_270, +}; + +enum class Orientation : uint32_t { + BEGIN = 0, + UNSPECIFIED = BEGIN, + VERTICAL = 1, + HORIZONTAL = 2, + REVERSE_VERTICAL = 3, + REVERSE_HORIZONTAL = 4, + SENSOR = 5, + SENSOR_VERTICAL = 6, + SENSOR_HORIZONTAL = 7, + AUTO_ROTATION_RESTRICTED = 8, + AUTO_ROTATION_PORTRAIT_RESTRICTED = 9, + AUTO_ROTATION_LANDSCAPE_RESTRICTED = 10, + LOCKED = 11, + END = LOCKED, +}; + +enum class DisplayChangeEvent : uint32_t { + UPDATE_ORIENTATION, + UPDATE_ROTATION, + DISPLAY_SIZE_CHANGED, + DISPLAY_FREEZED, + DISPLAY_UNFREEZED, + DISPLAY_VIRTUAL_PIXEL_RATIO_CHANGED, + UNKNOWN, +}; +} +} +#endif // OHOS_ROSEN_DM_COMMON_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/dm/screen.h b/window_manager/interfaces/innerkits/dm/screen.h new file mode 100644 index 0000000..245ba6f --- /dev/null +++ b/window_manager/interfaces/innerkits/dm/screen.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DM_SCREEN_H +#define FOUNDATION_DM_SCREEN_H + +#include +#include +#include +#include + +#include "dm_common.h" +#include "noncopyable.h" + +namespace OHOS::Rosen { +class ScreenInfo; + +struct Point { + int32_t posX_; + int32_t posY_; + Point() : posX_(0), posY_(0) {}; + Point(int32_t posX, int32_t posY) : posX_(posX), posY_(posY) {}; +}; + +struct SupportedScreenModes : public RefBase { + uint32_t width_; + uint32_t height_; + uint32_t refreshRate_; +}; + +struct VirtualScreenOption { + std::string name_; + uint32_t width_; + uint32_t height_; + float density_; + sptr surface_; + int32_t flags_; + bool isForShot_ {true}; +}; + +struct ExpandOption { + ScreenId screenId_; + uint32_t startX_; + uint32_t startY_; +}; + +class Screen : public RefBase { +friend class ScreenManager; +public: + ~Screen(); + Screen(const Screen&) = delete; + Screen(Screen&&) = delete; + Screen& operator=(const Screen&) = delete; + Screen& operator=(Screen&&) = delete; + bool IsGroup() const; + std::string GetName() const; + ScreenId GetId() const; + uint32_t GetWidth() const; + uint32_t GetHeight() const; + uint32_t GetVirtualWidth() const; + uint32_t GetVirtualHeight() const; + float GetVirtualPixelRatio() const; + Rotation GetRotation() const; + Orientation GetOrientation() const; + bool IsReal() const; + ScreenId GetParentId() const; + uint32_t GetModeId() const; + std::vector> GetSupportedModes() const; + bool SetScreenActiveMode(uint32_t modeId); + bool SetOrientation(Orientation orientation) const; + bool SetDensityDpi(uint32_t dpi) const; + sptr GetScreenInfo() const; + + // colorspace, gamut + DMError GetScreenSupportedColorGamuts(std::vector& colorGamuts) const; + DMError GetScreenColorGamut(ScreenColorGamut& colorGamut) const; + DMError SetScreenColorGamut(int32_t colorGamutIdx); + DMError GetScreenGamutMap(ScreenGamutMap& gamutMap) const; + DMError SetScreenGamutMap(ScreenGamutMap gamutMap); + DMError SetScreenColorTransform(); +protected: + // No more methods or variables can be defined here. + Screen(sptr info); + void UpdateScreenInfo() const; + void UpdateScreenInfo(sptr info) const; +private: + // No more methods or variables can be defined here. + class Impl; + sptr pImpl_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DM_SCREEN_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/dm/screen_group.h b/window_manager/interfaces/innerkits/dm/screen_group.h new file mode 100644 index 0000000..0a33053 --- /dev/null +++ b/window_manager/interfaces/innerkits/dm/screen_group.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DM_SCREEN_GROUP_H +#define FOUNDATION_DM_SCREEN_GROUP_H + +#include +#include +#include "screen.h" + +namespace OHOS::Rosen { +class ScreenGroupInfo; +enum class ScreenCombination : uint32_t { + SCREEN_ALONE, + SCREEN_EXPAND, + SCREEN_MIRROR, +}; + +class ScreenGroup : public Screen { +friend class ScreenManager; +public: + ~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; + +private: + // No more methods or variables can be defined here. + ScreenGroup(sptr info); + void UpdateScreenGroupInfo(sptr info) const; + void UpdateScreenGroupInfo() const; + class Impl; + sptr pImpl_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DM_SCREEN_GROUP_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/dm/screen_manager.h b/window_manager/interfaces/innerkits/dm/screen_manager.h new file mode 100644 index 0000000..2c1b83c --- /dev/null +++ b/window_manager/interfaces/innerkits/dm/screen_manager.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DM_SCREEN_MANAGER_H +#define FOUNDATION_DM_SCREEN_MANAGER_H + +#include +#include "screen.h" +#include "dm_common.h" +#include "screen_group.h" +#include "wm_single_instance.h" +#include "wm_single_instance.h" + +namespace OHOS::Rosen { +class ScreenManager : public RefBase { +WM_DECLARE_SINGLE_INSTANCE_BASE(ScreenManager); +friend class DMSDeathRecipient; +public: + class IScreenListener : public virtual RefBase { + public: + virtual void OnConnect(ScreenId) = 0; + virtual void OnDisconnect(ScreenId) = 0; + virtual void OnChange(ScreenId) = 0; + }; + + class IScreenGroupListener : public virtual RefBase { + public: + virtual void OnChange(const std::vector&, ScreenGroupChangeEvent) = 0; + }; + + class IVirtualScreenGroupListener : public virtual RefBase { + public: + struct ChangeInfo { + ScreenGroupChangeEvent event; + std::string trigger; + std::vector ids; + }; + virtual void OnMirrorChange(const ChangeInfo& info) {} + }; + + sptr GetScreenById(ScreenId screenId); + sptr GetScreenGroup(ScreenId groupId); + std::vector> GetAllScreens(); + + ScreenId MakeExpand(const std::vector& options); + ScreenId MakeMirror(ScreenId mainScreenId, std::vector mirrorScreenId); + DMError RemoveVirtualScreenFromGroup(std::vector screens); + ScreenId CreateVirtualScreen(VirtualScreenOption option); + DMError DestroyVirtualScreen(ScreenId screenId); + DMError SetVirtualScreenSurface(ScreenId screenId, sptr surface); + bool SetScreenPowerForAll(ScreenPowerState state, PowerStateChangeReason reason); + ScreenPowerState GetScreenPower(ScreenId screenId); + DMError SetScreenRotationLocked(bool isLocked); + bool IsScreenRotationLocked(); + + bool RegisterScreenListener(sptr listener); + bool UnregisterScreenListener(sptr listener); + bool RegisterScreenGroupListener(sptr listener); + bool UnregisterScreenGroupListener(sptr listener); + bool RegisterVirtualScreenGroupListener(sptr listener); + bool UnregisterVirtualScreenGroupListener(sptr listener); +private: + ScreenManager(); + ~ScreenManager(); + void OnRemoteDied(); + + class Impl; + sptr pImpl_; +}; +} // namespace OHOS::Rosen + +#endif // FOUNDATION_DM_SCREEN_MANAGER_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/extension/window_extension_connection.h b/window_manager/interfaces/innerkits/extension/window_extension_connection.h new file mode 100644 index 0000000..b22023d --- /dev/null +++ b/window_manager/interfaces/innerkits/extension/window_extension_connection.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 WINDOW_EXTENSION_CONNECTION_H +#define WINDOW_EXTENSION_CONNECTION_H + +#include +#include +#include +#include +#include +#include +#include + +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + const std::string RECT_FORM_KEY_POS_X = "ext_pos_x"; + const std::string RECT_FORM_KEY_POS_Y = "ext_pos_y"; + const std::string RECT_FORM_KEY_HEIGHT = "ext_pos_heigh"; + const std::string RECT_FORM_KEY_WIDTH = "ext_pos_width"; + const std::string WINDOW_ID = "ext_window_id"; +} + +class RSSurfaceNode; +class IWindowExtensionCallback : virtual public RefBase { +public: + virtual void OnWindowReady(const std::shared_ptr& rsSurfaceNode) = 0; + virtual void OnExtensionDisconnected() = 0; + virtual void OnKeyEvent(const std::shared_ptr& event) = 0; + virtual void OnPointerEvent(const std::shared_ptr& event) = 0; + virtual void OnBackPress() = 0; +}; + +class WindowExtensionConnection : public RefBase { +public: + WindowExtensionConnection(); + ~WindowExtensionConnection(); + int ConnectExtension(const AppExecFwk::ElementName& element, const Rect& rect, + uint32_t uid, uint32_t windowId, const sptr& callback) const; + void DisconnectExtension() const; + void Show() const; + void Hide() const; + void RequestFocus() const; + void SetBounds(const Rect& rect) const; +private: + class Impl; + sptr pImpl_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // WINDOW_EXTENSION_CONNECTION_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/wm/window.h b/window_manager/interfaces/innerkits/wm/window.h new file mode 100644 index 0000000..2ec00d9 --- /dev/null +++ b/window_manager/interfaces/innerkits/wm/window.h @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_H +#define OHOS_ROSEN_WINDOW_H + +#include +#include +#include +#include + +#include "wm_common.h" +#include "window_option.h" + +class NativeValue; +class NativeEngine; +namespace OHOS::MMI { + class PointerEvent; + class KeyEvent; + class AxisEvent; +} +namespace OHOS::AppExecFwk { + class Configuration; + class Ability; +} + +namespace OHOS::AbilityRuntime { + class AbilityContext; + class Context; +} + +namespace OHOS::AAFwk { + class Want; +} + +namespace OHOS::Ace { + class UIContent; +} + +namespace OHOS { +namespace Rosen { +using NotifyNativeWinDestroyFunc = std::function; +class RSSurfaceNode; + +class IWindowLifeCycle : virtual public RefBase { +public: + virtual void AfterForeground() {} + virtual void AfterBackground() {} + virtual void AfterFocused() {} + virtual void AfterUnfocused() {} + virtual void ForegroundFailed(int32_t ret) {} + virtual void AfterActive() {} + virtual void AfterInactive() {} +}; + +class IWindowChangeListener : virtual public RefBase { +public: + virtual void OnSizeChange(Rect rect, WindowSizeChangeReason reason) {} + virtual void OnModeChange(WindowMode mode) {} +}; + +class IAvoidAreaChangedListener : virtual public RefBase { +public: + virtual void OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type) {} +}; + +class IWindowDragListener : virtual public RefBase { +public: + virtual void OnDrag(int32_t x, int32_t y, DragEvent event) {} +}; + +class IDisplayMoveListener : virtual public RefBase { +public: + virtual void OnDisplayMove(DisplayId from, DisplayId to) {} +}; + +class IDispatchInputEventListener : virtual public RefBase { +public: + virtual void OnDispatchPointerEvent(std::shared_ptr& inputEvent) = 0; + virtual void OnDispatchKeyEvent(std::shared_ptr& keyEvent) = 0; +}; + +class OccupiedAreaChangeInfo : public Parcelable { +public: + OccupiedAreaChangeInfo() = default; + OccupiedAreaChangeInfo(OccupiedAreaType type, Rect rect) : type_(type), rect_(rect) {}; + ~OccupiedAreaChangeInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + static OccupiedAreaChangeInfo* Unmarshalling(Parcel& parcel); + + OccupiedAreaType type_ = OccupiedAreaType::TYPE_INPUT; + Rect rect_ = { 0, 0, 0, 0 }; +}; + +class IOccupiedAreaChangeListener : virtual public RefBase { +public: + virtual void OnSizeChange(const sptr& info) {} +}; + +class IAceAbilityHandler : virtual public RefBase { +public: + virtual void SetBackgroundColor(uint32_t color) = 0; + virtual uint32_t GetBackgroundColor() = 0; +}; + +class IInputEventConsumer { +public: + IInputEventConsumer() = default; + virtual ~IInputEventConsumer() = default; + virtual bool OnInputEvent(const std::shared_ptr& keyEvent) const = 0; + virtual bool OnInputEvent(const std::shared_ptr& pointerEvent) const = 0; + virtual bool OnInputEvent(const std::shared_ptr& axisEvent) const = 0; +}; + +class ITouchOutsideListener : virtual public RefBase { +public: + virtual void OnTouchOutside() const {} +}; + +class IAnimationTransitionController : virtual public RefBase { +public: + virtual void AnimationForShown() = 0; + virtual void AnimationForHidden() = 0; +}; + +class IScreenshotListener : virtual public RefBase { +public: + virtual void OnScreenshot() {} +}; + +class IDialogTargetTouchListener : virtual public RefBase { +public: + virtual void OnDialogTargetTouch() const {} +}; + +class IDialogDeathRecipientListener : virtual public RefBase { +public: + virtual void OnDialogDeathRecipient() const = 0; +}; + +class Window : public RefBase { +public: + /** + * @brief create window, include main_window/sub_window/system_window + * + * @param windowName window name, identify window instance + * @param option window propertion + * @param context ability context + * @return sptr If create window success,return window instance;Otherwise, return nullptr + */ + static sptr Create(const std::string& windowName, + sptr& option, const std::shared_ptr& context = nullptr); + /** + * @brief find window by windowName + * + * @param windowName + * @return sptr Return the window instance founded + */ + static sptr Find(const std::string& windowName); + /** + * @brief Get the final show window by context. Its implemented in api8 + * + * @param context Indicates the context on which the window depends + * @return sptr + */ + static sptr GetTopWindowWithContext(const std::shared_ptr& context = nullptr); + /** + * @brief Get the final show window by id. Its implemented in api8 + * + * @param mainWinId main window id? + * @return sptr + */ + static sptr GetTopWindowWithId(uint32_t mainWinId); + /** + * @brief Get the all sub windows by parent + * + * @param parentId parent window id + * @return std::vector> + */ + static std::vector> GetSubWindow(uint32_t parentId); + + /** + * @brief Update configuration for all windows + * + * @param configuration configuration for app + */ + static void UpdateConfigurationForAll(const std::shared_ptr& configuration); + virtual std::shared_ptr GetSurfaceNode() const = 0; + virtual const std::shared_ptr GetContext() const = 0; + /** + * @brief Get the window show rect + * + * @return Rect window rect + */ + virtual Rect GetRect() const = 0; + virtual Rect GetRequestRect() const = 0; + /** + * @brief Get the window type + * + * @return WindowType window type + */ + virtual WindowType GetType() const = 0; + virtual WindowMode GetMode() const = 0; + virtual float GetAlpha() const = 0; + virtual const std::string& GetWindowName() const = 0; + virtual uint32_t GetWindowId() const = 0; + virtual uint32_t GetWindowFlags() const = 0; + virtual WindowState GetWindowState() const = 0; + virtual WMError SetFocusable(bool isFocusable) = 0; + virtual bool GetFocusable() const = 0; + virtual WMError SetTouchable(bool isTouchable) = 0; + virtual bool GetTouchable() const = 0; + virtual SystemBarProperty GetSystemBarPropertyByType(WindowType type) const = 0; + /** + * @brief judge this window is full screen. + * + * @return true If SetFullScreen(true) is called , return true. + * @return false default return false + */ + virtual bool IsFullScreen() const = 0; + /** + * @brief judge window layout is full screen + * + * @return true this window layout is full screen + * @return false this window layout is not full screen + */ + virtual bool IsLayoutFullScreen() const = 0; + /** + * @brief Set the Window Type + * + * @param type window type + * @return WMError + */ + virtual WMError SetWindowType(WindowType type) = 0; + /** + * @brief Set the Window Mode + * + * @param mode window mode + * @return WMError + */ + virtual WMError SetWindowMode(WindowMode mode) = 0; + virtual void SetAlpha(float alpha) = 0; + virtual void SetTransform(const Transform& trans) = 0; + virtual const Transform& GetTransform() const = 0; + virtual WMError AddWindowFlag(WindowFlag flag) = 0; + virtual WMError RemoveWindowFlag(WindowFlag flag) = 0; + virtual WMError SetWindowFlags(uint32_t flags) = 0; + /** + * @brief Set the System Bar(include status bar and nav bar) Property + * + * @param type WINDOW_TYPE_STATUS_BAR or WINDOW_TYPE_NAVIGATION_BAR + * @param property system bar prop,include content color, background color + * @return WMError + */ + virtual WMError SetSystemBarProperty(WindowType type, const SystemBarProperty& property) = 0; + /** + * @brief Get the Avoid Area By Type object + * + * @param type avoid area type.@see reference + * @param avoidArea + * @return WMError + */ + virtual WMError GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea) = 0; + /** + * @brief Set this window layout full screen, with hide status bar and nav bar above on this window + * + * @param status + * @return WMError + */ + virtual WMError SetLayoutFullScreen(bool status) = 0; + /** + * @brief Set this window full screen, with hide status bar and nav bar + * + * @param status if true, hide status bar and nav bar; Otherwise, show status bar and nav bar + * @return WMError + */ + virtual WMError SetFullScreen(bool status) = 0; + /** + * @brief destroy window + * + * @return WMError + */ + virtual WMError Destroy() = 0; + virtual WMError Show(uint32_t reason = 0, bool withAnimation = false) = 0; + virtual WMError Hide(uint32_t reason = 0, bool withAnimation = false) = 0; + /** + * @brief move the window to (x, y) + * + * @param x + * @param y + * @return WMError + */ + virtual WMError MoveTo(int32_t x, int32_t y) = 0; + /** + * @brief resize the window instance (w,h) + * + * @param width + * @param height + * @return WMError + */ + virtual WMError Resize(uint32_t width, uint32_t height) = 0; + /** + * @brief Set the screen always on + * + * @param keepScreenOn + * @return WMError + */ + virtual WMError SetKeepScreenOn(bool keepScreenOn) = 0; + virtual bool IsKeepScreenOn() const = 0; + virtual WMError SetTurnScreenOn(bool turnScreenOn) = 0; + virtual bool IsTurnScreenOn() const = 0; + virtual WMError SetBackgroundColor(const std::string& color) = 0; + virtual WMError SetTransparent(bool isTransparent) = 0; + virtual bool IsTransparent() const = 0; + virtual WMError SetBrightness(float brightness) = 0; + virtual float GetBrightness() const = 0; + virtual WMError SetCallingWindow(uint32_t windowId) = 0; + virtual void SetPrivacyMode(bool isPrivacyMode) = 0; + virtual bool IsPrivacyMode() const = 0; + virtual void SetSystemPrivacyMode(bool isSystemPrivacyMode) = 0; + virtual WMError BindDialogTarget(sptr targetToken) = 0; + virtual void SetSnapshotSkip(bool isSkip) = 0; + + // window effect + virtual WMError SetCornerRadius(float cornerRadius) = 0; + virtual WMError SetShadowRadius(float radius) = 0; + virtual WMError SetShadowColor(std::string color) = 0; + virtual void SetShadowOffsetX(float offsetX) = 0; + virtual void SetShadowOffsetY(float offsetY) = 0; + virtual WMError SetBlur(float radius) = 0; + virtual WMError SetBackdropBlur(float radius) = 0; + virtual WMError SetBackdropBlurStyle(WindowBlurStyle blurStyle) = 0; + + virtual WMError RequestFocus() const = 0; + virtual bool IsFocused() const = 0; + virtual WMError UpdateSurfaceNodeAfterCustomAnimation(bool isAdd) = 0; + virtual void SetInputEventConsumer(const std::shared_ptr& inputEventConsumer) = 0; + virtual void ConsumeKeyEvent(std::shared_ptr& inputEvent) = 0; + virtual void ConsumePointerEvent(const std::shared_ptr& inputEvent) = 0; + virtual void RequestVsync(const std::shared_ptr& vsyncCallback) = 0; + virtual void UpdateConfiguration(const std::shared_ptr& configuration) = 0; + /** + * @brief register window lifecycle listener. + * + * @param listener + */ + virtual bool RegisterLifeCycleListener(const sptr& listener) = 0; + virtual bool RegisterWindowChangeListener(const sptr& listener) = 0; + virtual bool UnregisterLifeCycleListener(const sptr& listener) = 0; + virtual bool UnregisterWindowChangeListener(const sptr& listener) = 0; + virtual bool RegisterAvoidAreaChangeListener(sptr& listener) = 0; + virtual bool UnregisterAvoidAreaChangeListener(sptr& listener) = 0; + virtual bool RegisterDragListener(const sptr& listener) = 0; + virtual bool UnregisterDragListener(const sptr& listener) = 0; + virtual bool RegisterDisplayMoveListener(sptr& listener) = 0; + virtual bool UnregisterDisplayMoveListener(sptr& listener) = 0; + virtual void RegisterWindowDestroyedListener(const NotifyNativeWinDestroyFunc& func) = 0; + virtual bool RegisterOccupiedAreaChangeListener(const sptr& listener) = 0; + virtual bool UnregisterOccupiedAreaChangeListener(const sptr& listener) = 0; + virtual bool RegisterTouchOutsideListener(const sptr& listener) = 0; + virtual bool UnregisterTouchOutsideListener(const sptr& listener) = 0; + virtual bool RegisterAnimationTransitionController(const sptr& listener) = 0; + virtual bool RegisterScreenshotListener(const sptr& listener) = 0; + virtual bool UnregisterScreenshotListener(const sptr& listener) = 0; + virtual bool RegisterDialogTargetTouchListener(const sptr& listener) = 0; + virtual bool UnregisterDialogTargetTouchListener(const sptr& listener) = 0; + virtual void RegisterDialogDeathRecipientListener(const sptr& listener) = 0; + virtual void UnregisterDialogDeathRecipientListener(const sptr& listener) = 0; + virtual void NotifyTouchDialogTarget() = 0; + virtual void SetAceAbilityHandler(const sptr& handler) = 0; + /** + * @brief set window ui content + * + * @param contentInfo content info path + * @param engine + * @param storage + * @param isDistributed + * @param ability + * @return WMError + */ + virtual WMError SetUIContent(const std::string& contentInfo, NativeEngine* engine, + NativeValue* storage, bool isDistributed = false, AppExecFwk::Ability* ability = nullptr) = 0; + virtual std::string GetContentInfo() = 0; + virtual Ace::UIContent* GetUIContent() const = 0; + virtual void OnNewWant(const AAFwk::Want& want) = 0; + virtual void SetRequestedOrientation(Orientation) = 0; + virtual Orientation GetRequestedOrientation() = 0; + virtual void SetRequestModeSupportInfo(uint32_t modeSupportInfo) = 0; + virtual uint32_t GetRequestModeSupportInfo() const = 0; + virtual WMError SetTouchHotAreas(const std::vector& rects) = 0; + virtual void GetRequestedTouchHotAreas(std::vector& rects) const = 0; + virtual bool IsMainHandlerAvailable() const = 0; + virtual WMError SetAPPWindowLabel(const std::string& label) = 0; + virtual WMError SetAPPWindowIcon(const std::shared_ptr& icon) = 0; + + /** + * @brief disable main window decoration. It must be callled before loadContent. + * + */ + virtual void DisableAppWindowDecor() = 0; + /** + * @brief return window decoration is enabled. It is called by ACE + * + * @return true means window decoration is enabled. Otherwise disabled + */ + virtual bool IsDecorEnable() const = 0; + /** + * @brief maximize the main window. It is called by ACE when maximize button is clicked. + * + * @return WMError + */ + virtual WMError Maximize() = 0; + /** + * @brief minimize the main window. It is called by ACE when minimize button is clicked. + * + * @return WMError + */ + virtual WMError Minimize() = 0; + /** + * @brief recovery the main window. It is called by ACE when recovery button is clicked. + * + * @return WMError + */ + virtual WMError Recover() = 0; + /** + * @brief close the main window. It is called by ACE when close button is clicked. + * + * @return WMError + */ + virtual WMError Close() = 0; + /** + * @brief start move main window. It is called by ACE when title is moved. + * + */ + virtual void StartMove() = 0; + virtual void SetNeedRemoveWindowInputChannel(bool needRemoveWindowInputChannel) = 0; + + // colorspace, gamut + virtual bool IsSupportWideGamut() = 0; + virtual void SetColorSpace(ColorSpace colorSpace) = 0; + virtual ColorSpace GetColorSpace() = 0; + + virtual void DumpInfo(const std::vector& params, std::vector& info) = 0; + /** + * @brief window snapshot + * + * @return std::shared_ptr snapshot pixel + */ + virtual std::shared_ptr Snapshot() = 0; + + /** + * @brief Handle and notify memory level. + * + * @param level memory level + * @return the error code of window + */ + virtual WMError NotifyMemoryLevel(int32_t level) const = 0; + + /** + * @brief Update configuration for all windows + * + * @param configuration configuration for app + */ + virtual bool IsAllowHaveSystemSubWindow() = 0; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_H diff --git a/window_manager/interfaces/innerkits/wm/window_accessibility_controller.h b/window_manager/interfaces/innerkits/wm/window_accessibility_controller.h new file mode 100644 index 0000000..66683db --- /dev/null +++ b/window_manager/interfaces/innerkits/wm/window_accessibility_controller.h @@ -0,0 +1,35 @@ +/* + * 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_ROSEN_WINDOW_ACCESSIBILITY_CONTROLLER_H +#define OHOS_ROSEN_WINDOW_ACCESSIBILITY_CONTROLLER_H + +#include +#include "wm_single_instance.h" + +namespace OHOS::Rosen { +class WindowAccessibilityController { +WM_DECLARE_SINGLE_INSTANCE_BASE(WindowAccessibilityController); +public: + // below three interfaces only take effect for the main display + void SetAnchorAndScale(int32_t x, int32_t y, float scale); + void SetAnchorOffset(int32_t deltaX, int32_t deltaY); + void OffWindowZoom(); +private: + WindowAccessibilityController(); + ~WindowAccessibilityController() = default; +}; +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_WINDOW_ACCESSIBILITY_CONTROLLER_H \ No newline at end of file diff --git a/window_manager/interfaces/innerkits/wm/window_manager.h b/window_manager/interfaces/innerkits/wm/window_manager.h new file mode 100644 index 0000000..b42f12a --- /dev/null +++ b/window_manager/interfaces/innerkits/wm/window_manager.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_MANAGER_H +#define OHOS_ROSEN_WINDOW_MANAGER_H + +#include +#include +#include +#include +#include "wm_single_instance.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +struct SystemBarRegionTint { + WindowType type_; + SystemBarProperty prop_; + Rect region_; + SystemBarRegionTint() : prop_(SystemBarProperty()) {} + SystemBarRegionTint(WindowType type, SystemBarProperty prop, Rect region) + : type_(type), prop_(prop), region_(region) {} +}; +using SystemBarRegionTints = std::vector; + +class FocusChangeInfo : public Parcelable { +public: + FocusChangeInfo() = default; + FocusChangeInfo(uint32_t winId, DisplayId displayId, int32_t pid, int32_t uid, WindowType type, + const sptr& abilityToken): windowId_(winId), displayId_(displayId), pid_(pid), uid_(uid), + windowType_(type), abilityToken_(abilityToken) {}; + ~FocusChangeInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + static FocusChangeInfo* Unmarshalling(Parcel& parcel); + + uint32_t windowId_ = INVALID_WINDOW_ID; + DisplayId displayId_ = 0; + int32_t pid_ = 0; + int32_t uid_ = 0; + WindowType windowType_ = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW; + sptr abilityToken_; +}; + +class IFocusChangedListener : virtual public RefBase { +public: + virtual void OnFocused(const sptr& focusChangeInfo) = 0; + + virtual void OnUnfocused(const sptr& focusChangeInfo) = 0; +}; + +class ISystemBarChangedListener : virtual public RefBase { +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, WindowType winType) + : windowId_(winId), pid_(pid), uid_(uid), isVisible_(visibility), windowType_(winType) {}; + ~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 }; + WindowType windowType_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; +}; + +class IVisibilityChangedListener : virtual public RefBase { +public: + virtual void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) = 0; +}; + +class AccessibilityWindowInfo : public Parcelable { +public: + AccessibilityWindowInfo() = default; + ~AccessibilityWindowInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + static AccessibilityWindowInfo* Unmarshalling(Parcel& parcel); + + int32_t wid_; + Rect windowRect_; + bool focused_ { false }; + bool isDecorEnable_ { false }; + DisplayId displayId_; + uint32_t layer_; + WindowMode mode_; + WindowType type_; +}; + +class IWindowUpdateListener : virtual public RefBase { +public: + virtual void OnWindowUpdate(const std::vector>& infos, WindowUpdateType type) = 0; +}; + +class ICameraFloatWindowChangedListener : virtual public RefBase { +public: + virtual void OnCameraFloatWindowChange(uint32_t accessTokenId, bool isShowing) = 0; +}; + +class WindowManager { +WM_DECLARE_SINGLE_INSTANCE_BASE(WindowManager); +friend class WindowManagerAgent; +friend class WMSDeathRecipient; +public: + bool RegisterFocusChangedListener(const sptr& listener); + bool UnregisterFocusChangedListener(const sptr& listener); + bool RegisterSystemBarChangedListener(const sptr& listener); + bool UnregisterSystemBarChangedListener(const sptr& listener); + bool RegisterWindowUpdateListener(const sptr& listener); + bool UnregisterWindowUpdateListener(const sptr& listener); + bool RegisterVisibilityChangedListener(const sptr& listener); + bool UnregisterVisibilityChangedListener(const sptr& listener); + bool RegisterCameraFloatWindowChangedListener(const sptr& listener); + bool UnregisterCameraFloatWindowChangedListener(const sptr& listener); + void MinimizeAllAppWindows(DisplayId displayId); + WMError ToggleShownStateForAllAppWindows(); + WMError SetWindowLayoutMode(WindowLayoutMode mode); + WMError GetAccessibilityWindowInfo(std::vector>& infos) const; + WMError GetVisibilityWindowInfo(std::vector>& infos) const; + +private: + WindowManager(); + ~WindowManager() = default; + class Impl; + std::unique_ptr pImpl_; + + void UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, + DisplayId displayId, bool focused) const; + void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) const; + void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) const; + void NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) const; + void UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) const; + void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) const; + void OnRemoteDied() const; +}; +} // namespace Rosen +} // namespace OHOS + +#endif // OHOS_ROSEN_WINDOW_MANAGER_H diff --git a/window_manager/interfaces/innerkits/wm/window_option.h b/window_manager/interfaces/innerkits/wm/window_option.h new file mode 100644 index 0000000..5eed53b --- /dev/null +++ b/window_manager/interfaces/innerkits/wm/window_option.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_OPTION_H +#define OHOS_ROSEN_WINDOW_OPTION_H +#include +#include +#include + +#include "../dm/dm_common.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowOption : public RefBase { +public: + WindowOption(); + virtual ~WindowOption() = default; + + void SetWindowRect(const struct Rect& rect); + void SetWindowType(WindowType type); + void SetWindowMode(WindowMode mode); + void SetFocusable(bool isFocusable); + void SetTouchable(bool isTouchable); + void SetDisplayId(DisplayId displayId); + void SetParentId(uint32_t parentId); + void SetWindowName(const std::string& windowName); + void AddWindowFlag(WindowFlag flag); + void RemoveWindowFlag(WindowFlag flag); + void SetWindowFlags(uint32_t flags); + void SetSystemBarProperty(WindowType type, const SystemBarProperty& property); + void SetHitOffset(int32_t x, int32_t y); + void SetWindowTag(WindowTag windowTag); + void SetKeepScreenOn(bool keepScreenOn); + bool IsKeepScreenOn() const; + void SetTurnScreenOn(bool turnScreenOn); + bool IsTurnScreenOn() const; + void SetBrightness(float brightness); + void SetRequestedOrientation(Orientation orientation); + void SetCallingWindow(uint32_t windowId); + void SetMainHandlerAvailable(bool isMainHandlerAvailable); + + Rect GetWindowRect() const; + WindowType GetWindowType() const; + WindowMode GetWindowMode() const; + bool GetFocusable() const; + bool GetTouchable() const; + DisplayId GetDisplayId() const; + uint32_t GetParentId() const; + const std::string& GetWindowName() const; + uint32_t GetWindowFlags() const; + const std::unordered_map& GetSystemBarProperty() const; + const PointInfo& GetHitOffset() const; + WindowTag GetWindowTag() const; + float GetBrightness() const; + Orientation GetRequestedOrientation() const; + uint32_t GetCallingWindow() const; + bool GetMainHandlerAvailable() const; + +private: + Rect windowRect_ { 0, 0, 0, 0 }; + WindowType type_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; + WindowMode mode_ { WindowMode::WINDOW_MODE_UNDEFINED }; + bool focusable_ { true }; + bool touchable_ { true }; + DisplayId displayId_ { 0 }; + uint32_t parentId_ = INVALID_WINDOW_ID; + std::string windowName_ { "" }; + uint32_t flags_ { 0 }; + PointInfo hitOffset_ { 0, 0 }; + WindowTag windowTag_; + bool keepScreenOn_ = false; + bool turnScreenOn_ = false; + bool isMainHandlerAvailable_ = true; + float brightness_ = UNDEFINED_BRIGHTNESS; + uint32_t callingWindow_ = INVALID_WINDOW_ID; + std::unordered_map sysBarPropMap_ { + { WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarProperty() }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarProperty() }, + }; + Orientation requestedOrientation_ { Orientation::UNSPECIFIED }; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_OPTION_H diff --git a/window_manager/interfaces/innerkits/wm/window_scene.h b/window_manager/interfaces/innerkits/wm/window_scene.h new file mode 100644 index 0000000..a355b50 --- /dev/null +++ b/window_manager/interfaces/innerkits/wm/window_scene.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021-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 INTERFACES_INNERKITS_WINDOW_SCENE_H +#define INTERFACES_INNERKITS_WINDOW_SCENE_H + +#include +#include + +#include "window.h" +#include "window_option.h" + +namespace OHOS::AppExecFwk { + class Configuration; +} + +namespace OHOS { +namespace Rosen { +class WindowScene : public RefBase { +public: + /** + * Default constructor used to create an empty WindowScene instance. + */ + WindowScene() = default; + + /** + * Default deconstructor used to deconstruct. + * + */ + ~WindowScene(); + + /** + * Init a WindowScene instance based on the parameters displayId, context, listener and option. + * + * @param displayId the id of current display + * @param context current ability context + * @param listener the life cycle listener of the window + * @param option the settings for window, such as WindowType, width, height, etc + * @return the error code of window + */ + WMError Init(DisplayId displayId, const std::shared_ptr& context, + sptr& listener, sptr option = nullptr); + + /** + * Create a window instance based on the parameters windowName and option. + * + * @param windowName the id of this window + * @param option the settings for window, such as WindowType, width, height, etc. + * @return the shared pointer of window + */ + sptr CreateWindow(const std::string& windowName, sptr& option) const; + + /** + * Get shared pointer of main window. + * + * @return the shared pointer of window + */ + const sptr& GetMainWindow() const; + + /** + * Get a set of sub window. + * + * @return a set of sub window + */ + std::vector> GetSubWindow(); + + /** + * window go foreground. + * + * @param reason the reason of window to go to foreground, default 0. + * @return the error code of window + */ + WMError GoForeground(uint32_t reason = 0); + + /** + * Window go background. + * + * @param reason the reason of window to go to background, default 0. + * @return the error code of window + */ + WMError GoBackground(uint32_t reason = 0); + + /** + * Window go distroy. + * + * @return the error code of window + */ + WMError GoDestroy(); + + /** + * Window handle new want. + * + * @param want ability want. + * @return the error code of window + */ + WMError OnNewWant(const AAFwk::Want& want); + + /** + * Request to get the focus. + * + * @return the error code of window + */ + WMError RequestFocus() const; + + /** + * Update ability configuration. + * + * @param configuration the configuration of ability + */ + void UpdateConfiguration(const std::shared_ptr& configuration); + + /** + * Set main window system bar property + * + * @param type the type of window + * @param property the property of system bar + * @return the error code of window + */ + WMError SetSystemBarProperty(WindowType type, const SystemBarProperty& property) const; + + /** + * Get content info of main window. + * + * @return content info of main window + */ + std::string GetContentInfo() const; + + /** + * @brief Handle and notify memory. + * + * @param level memory level + * @return the error code of window + */ + WMError NotifyMemoryLevel(int32_t level) const; + +public: + static const DisplayId DEFAULT_DISPLAY_ID = 0; + static const std::string MAIN_WINDOW_ID; + +private: + /** + * @param context the context of a main window + * @return the name of main window + */ + std::string GenerateMainWindowName(const std::shared_ptr& context) const; + +private: + sptr mainWindow_ = nullptr; + static inline std::atomic count { 0 }; + DisplayId displayId_ = DEFAULT_DISPLAY_ID; + std::shared_ptr context_ = nullptr; +}; +} // namespace Rosen +} // namespace OHOS +#endif // INTERFACES_INNERKITS_WINDOW_SCENE_H diff --git a/window_manager/interfaces/innerkits/wm/wm_common.h b/window_manager/interfaces/innerkits/wm/wm_common.h new file mode 100644 index 0000000..0373842 --- /dev/null +++ b/window_manager/interfaces/innerkits/wm/wm_common.h @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2021-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_ROSEN_WM_COMMON_H +#define OHOS_ROSEN_WM_COMMON_H + +#include +#include + +namespace OHOS { +namespace Rosen { +using DisplayId = uint64_t; +enum class WindowType : uint32_t { + APP_WINDOW_BASE = 1, + APP_MAIN_WINDOW_BASE = APP_WINDOW_BASE, + WINDOW_TYPE_APP_MAIN_WINDOW = APP_MAIN_WINDOW_BASE, + APP_MAIN_WINDOW_END, + + APP_SUB_WINDOW_BASE = 1000, + WINDOW_TYPE_MEDIA = APP_SUB_WINDOW_BASE, + WINDOW_TYPE_APP_SUB_WINDOW, + WINDOW_TYPE_APP_COMPONENT, + APP_SUB_WINDOW_END, + APP_WINDOW_END = APP_SUB_WINDOW_END, + + SYSTEM_WINDOW_BASE = 2000, + BELOW_APP_SYSTEM_WINDOW_BASE = SYSTEM_WINDOW_BASE, + WINDOW_TYPE_WALLPAPER = SYSTEM_WINDOW_BASE, + WINDOW_TYPE_DESKTOP, + BELOW_APP_SYSTEM_WINDOW_END, + + ABOVE_APP_SYSTEM_WINDOW_BASE = 2100, + WINDOW_TYPE_APP_LAUNCHING = ABOVE_APP_SYSTEM_WINDOW_BASE, + WINDOW_TYPE_DOCK_SLICE, + WINDOW_TYPE_INCOMING_CALL, + WINDOW_TYPE_SEARCHING_BAR, + WINDOW_TYPE_SYSTEM_ALARM_WINDOW, + WINDOW_TYPE_INPUT_METHOD_FLOAT, + WINDOW_TYPE_FLOAT, + WINDOW_TYPE_TOAST, + WINDOW_TYPE_STATUS_BAR, + WINDOW_TYPE_PANEL, + WINDOW_TYPE_KEYGUARD, + WINDOW_TYPE_VOLUME_OVERLAY, + WINDOW_TYPE_NAVIGATION_BAR, + WINDOW_TYPE_DRAGGING_EFFECT, + WINDOW_TYPE_POINTER, + WINDOW_TYPE_LAUNCHER_RECENT, + WINDOW_TYPE_LAUNCHER_DOCK, + WINDOW_TYPE_BOOT_ANIMATION, + WINDOW_TYPE_FREEZE_DISPLAY, + WINDOW_TYPE_VOICE_INTERACTION, + WINDOW_TYPE_FLOAT_CAMERA, + WINDOW_TYPE_PLACEHOLDER, + WINDOW_TYPE_DIALOG, + WINDOW_TYPE_SCREENSHOT, + ABOVE_APP_SYSTEM_WINDOW_END, + + SYSTEM_SUB_WINDOW_BASE = 2500, + WINDOW_TYPE_SYSTEM_SUB_WINDOW = SYSTEM_SUB_WINDOW_BASE, + SYSTEM_SUB_WINDOW_END, + + SYSTEM_WINDOW_END = SYSTEM_SUB_WINDOW_END, +}; + +enum class WindowMode : uint32_t { + WINDOW_MODE_UNDEFINED = 0, + WINDOW_MODE_FULLSCREEN = 1, + WINDOW_MODE_SPLIT_PRIMARY = 100, + WINDOW_MODE_SPLIT_SECONDARY, + WINDOW_MODE_FLOATING, + WINDOW_MODE_PIP +}; + +enum WindowModeSupport : uint32_t { + WINDOW_MODE_SUPPORT_FULLSCREEN = 1 << 0, + WINDOW_MODE_SUPPORT_FLOATING = 1 << 1, + WINDOW_MODE_SUPPORT_SPLIT_PRIMARY = 1 << 2, + WINDOW_MODE_SUPPORT_SPLIT_SECONDARY = 1 << 3, + WINDOW_MODE_SUPPORT_PIP = 1 << 4, + WINDOW_MODE_SUPPORT_ALL = WINDOW_MODE_SUPPORT_FULLSCREEN | + WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | + WINDOW_MODE_SUPPORT_SPLIT_SECONDARY | + WINDOW_MODE_SUPPORT_FLOATING | + WINDOW_MODE_SUPPORT_PIP +}; + +enum class WindowBlurStyle : uint32_t { + WINDOW_BLUR_OFF = 0, + WINDOW_BLUR_THIN, + WINDOW_BLUR_REGULAR, + WINDOW_BLUR_THICK +}; + +enum class WindowState : uint32_t { + STATE_INITIAL, + STATE_CREATED, + STATE_SHOWN, + STATE_HIDDEN, + STATE_FROZEN, + STATE_DESTROYED, + STATE_BOTTOM = STATE_DESTROYED, + STATE_UNFROZEN, +}; + +enum class WMError : int32_t { + WM_OK = 0, + WM_DO_NOTHING, + WM_ERROR_NO_MEM, + WM_ERROR_DESTROYED_OBJECT, + WM_ERROR_INVALID_WINDOW, + WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE, + WM_ERROR_INVALID_OPERATION, + WM_ERROR_INVALID_PERMISSION, + WM_ERROR_NO_REMOTE_ANIMATION, + + WM_ERROR_DEVICE_NOT_SUPPORT = 801, // the value do not change.It is defined on all system + + WM_ERROR_NEED_REPORT_BASE = 1000, // error code > 1000 means need report + WM_ERROR_NULLPTR, + WM_ERROR_INVALID_TYPE, + WM_ERROR_INVALID_PARAM, + WM_ERROR_SAMGR, + WM_ERROR_IPC_FAILED, + WM_ERROR_NEED_REPORT_END, + WM_ERROR_START_ABILITY_FAILED, +}; + +enum class WmErrorCode : int32_t { + WM_OK = 0, + WM_ERROR_NO_PERMISSION = 201, + WM_ERROR_INVALID_PARAM = 401, + WM_ERROR_DEVICE_NOT_SUPPORT = 801, + WM_ERROR_REPEAT_OPERATION = 1300001, + WM_ERROR_STATE_ABNORMALLY = 1300002, + WM_ERROR_SYSTEM_ABNORMALLY = 1300003, + WM_ERROR_INVALID_CALLING = 1300004, + WM_ERROR_STAGE_ABNORMALLY = 1300005, + WM_ERROR_CONTEXT_ABNORMALLY = 1300006, + WM_ERROR_START_ABILITY_FAILED = 1300007, +}; + +const std::map WM_JS_TO_ERROR_CODE_MAP { + {WMError::WM_OK, WmErrorCode::WM_OK }, + {WMError::WM_DO_NOTHING, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_DESTROYED_OBJECT, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_DEVICE_NOT_SUPPORT, WmErrorCode::WM_ERROR_DEVICE_NOT_SUPPORT }, + {WMError::WM_ERROR_INVALID_OPERATION, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_INVALID_PARAM, WmErrorCode::WM_ERROR_INVALID_PARAM }, + {WMError::WM_ERROR_INVALID_PERMISSION, WmErrorCode::WM_ERROR_NO_PERMISSION }, + {WMError::WM_ERROR_INVALID_TYPE, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_INVALID_WINDOW, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_IPC_FAILED, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY }, + {WMError::WM_ERROR_NO_MEM, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY }, + {WMError::WM_ERROR_NO_REMOTE_ANIMATION, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY }, + {WMError::WM_ERROR_NULLPTR, WmErrorCode::WM_ERROR_STATE_ABNORMALLY }, + {WMError::WM_ERROR_SAMGR, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY }, + {WMError::WM_ERROR_START_ABILITY_FAILED, WmErrorCode::WM_ERROR_START_ABILITY_FAILED }, +}; + +enum class WindowFlag : uint32_t { + WINDOW_FLAG_NEED_AVOID = 1, + WINDOW_FLAG_PARENT_LIMIT = 1 << 1, + WINDOW_FLAG_SHOW_WHEN_LOCKED = 1 << 2, + WINDOW_FLAG_FORBID_SPLIT_MOVE = 1 << 3, + WINDOW_FLAG_END = 1 << 4, +}; + +enum class WindowSizeChangeReason : uint32_t { + UNDEFINED = 0, + MAXIMIZE, + RECOVER, + ROTATION, + DRAG, + DRAG_START, + DRAG_END, + RESIZE, + MOVE, + HIDE, + TRANSFORM, + CUSTOM_ANIMATION_SHOW, + END, +}; + +enum class WindowLayoutMode : uint32_t { + BASE = 0, + CASCADE = BASE, + TILE = 1, + END, +}; + +enum class DragEvent : uint32_t { + DRAG_EVENT_IN = 1, + DRAG_EVENT_OUT, + DRAG_EVENT_MOVE, + DRAG_EVENT_END, +}; + +enum class WindowTag : uint32_t { + MAIN_WINDOW = 0, + SUB_WINDOW = 1, + SYSTEM_WINDOW = 2, +}; + +struct PointInfo { + int32_t x; + int32_t y; +}; + +namespace { + constexpr uint32_t SYSTEM_COLOR_WHITE = 0xE5FFFFFF; + constexpr uint32_t SYSTEM_COLOR_BLACK = 0x66000000; + constexpr uint32_t INVALID_WINDOW_ID = 0; + constexpr float UNDEFINED_BRIGHTNESS = -1.0f; + constexpr float MINIMUM_BRIGHTNESS = 0.0f; + constexpr float MAXIMUM_BRIGHTNESS = 1.0f; + constexpr int32_t INVALID_PID = -1; + constexpr int32_t INVALID_UID = -1; +} + +class Transform { +public: + Transform() + : pivotX_(0.5f), pivotY_(0.5f), scaleX_(1.f), scaleY_(1.f), scaleZ_(1.f), rotationX_(0.f), + rotationY_(0.f), rotationZ_(0.f), translateX_(0.f), translateY_(0.f), translateZ_(0.f) + {} + ~Transform() {} + + bool operator==(const Transform& right) const + { + return NearZero(pivotX_ - right.pivotX_) && + NearZero(pivotY_ - right.pivotY_) && + NearZero(scaleX_ - right.scaleX_) && + NearZero(scaleY_ - right.scaleY_) && + NearZero(scaleZ_ - right.scaleZ_) && + NearZero(rotationX_ - right.rotationX_) && + NearZero(rotationY_ - right.rotationY_) && + NearZero(rotationZ_ - right.rotationZ_) && + NearZero(translateX_ - right.translateX_) && + NearZero(translateY_ - right.translateY_) && + NearZero(translateZ_ - right.translateZ_); + } + + bool operator!=(const Transform& right) const + { + return !(*this == right); + } + + float pivotX_; + float pivotY_; + float scaleX_; + float scaleY_; + float scaleZ_; + float rotationX_; + float rotationY_; + float rotationZ_; + float translateX_; + float translateY_; + float translateZ_; + + static const Transform& Identity() + { + static Transform I; + return I; + } + + bool Marshalling(Parcel& parcel) const + { + return parcel.WriteFloat(pivotX_) && parcel.WriteFloat(pivotY_) && + parcel.WriteFloat(scaleX_) && parcel.WriteFloat(scaleY_) && parcel.WriteFloat(scaleZ_) && + parcel.WriteFloat(rotationX_) && parcel.WriteFloat(rotationY_) && + parcel.WriteFloat(rotationZ_) && parcel.WriteFloat(translateX_) && + parcel.WriteFloat(translateY_) && parcel.WriteFloat(translateZ_); + } + + void Unmarshalling(Parcel& parcel) + { + pivotX_ = parcel.ReadFloat(); + pivotY_ = parcel.ReadFloat(); + scaleX_ = parcel.ReadFloat(); + scaleY_ = parcel.ReadFloat(); + scaleZ_ = parcel.ReadFloat(); + rotationX_ = parcel.ReadFloat(); + rotationY_ = parcel.ReadFloat(); + rotationZ_ = parcel.ReadFloat(); + translateX_ = parcel.ReadFloat(); + translateY_ = parcel.ReadFloat(); + translateZ_ = parcel.ReadFloat(); + } +private: + static inline bool NearZero(float val) + { + return val < 0.001f && val > -0.001f; + } +}; + +struct SystemBarProperty { + bool enable_; + uint32_t backgroundColor_; + uint32_t contentColor_; + 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 + { + return (enable_ == a.enable_ && backgroundColor_ == a.backgroundColor_ && contentColor_ == a.contentColor_); + } +}; + +struct Rect { + int32_t posX_; + int32_t posY_; + uint32_t width_; + uint32_t height_; + + bool operator==(const Rect& a) const + { + return (posX_ == a.posX_ && posY_ == a.posY_ && width_ == a.width_ && height_ == a.height_); + } + + bool operator!=(const Rect& a) const + { + return !this->operator==(a); + } + + bool isUninitializedRect() const + { + return (posX_ == 0 && posY_ == 0 && width_ == 0 && height_ == 0); + } + + 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_); + } +}; + +enum class AvoidAreaType : uint32_t { + TYPE_SYSTEM, // area of SystemUI + TYPE_CUTOUT, // cutout of screen + TYPE_SYSTEM_GESTURE, // area for system gesture + TYPE_KEYBOARD, // area for soft input keyboard +}; + +enum class OccupiedAreaType : uint32_t { + TYPE_INPUT, // area of input window +}; + +enum class ColorSpace : uint32_t { + COLOR_SPACE_DEFAULT = 0, // Default color space. + COLOR_SPACE_WIDE_GAMUT, // Wide gamut color space. The specific wide color gamut depends on the screen. +}; + +enum class WindowAnimation : uint32_t { + NONE, + DEFAULT, + INPUTE, + CUSTOM, +}; + +class AvoidArea : public Parcelable { +public: + Rect topRect_ { 0, 0, 0, 0 }; + Rect leftRect_ { 0, 0, 0, 0 }; + Rect rightRect_ { 0, 0, 0, 0 }; + Rect bottomRect_ { 0, 0, 0, 0 }; + + bool operator==(const AvoidArea& a) const + { + return (leftRect_ == a.leftRect_ && topRect_ == a.topRect_ && + rightRect_ == a.rightRect_ && bottomRect_ == a.bottomRect_); + } + + bool operator!=(const AvoidArea& a) const + { + return !this->operator==(a); + } + + bool isEmptyAvoidArea() const + { + return topRect_.isUninitializedRect() && leftRect_.isUninitializedRect() && + rightRect_.isUninitializedRect() && bottomRect_.isUninitializedRect(); + } + + static inline bool WriteParcel(Parcel& parcel, const Rect& rect) + { + return parcel.WriteInt32(rect.posX_) && parcel.WriteInt32(rect.posY_) && + parcel.WriteUint32(rect.width_) && parcel.WriteUint32(rect.height_); + } + + static inline bool ReadParcel(Parcel& parcel, Rect& rect) + { + return parcel.ReadInt32(rect.posX_) && parcel.ReadInt32(rect.posY_) && + parcel.ReadUint32(rect.width_) && parcel.ReadUint32(rect.height_); + } + + virtual bool Marshalling(Parcel& parcel) const override + { + return (WriteParcel(parcel, leftRect_) && WriteParcel(parcel, topRect_) && + WriteParcel(parcel, rightRect_) && WriteParcel(parcel, bottomRect_)); + } + + static AvoidArea* Unmarshalling(Parcel& parcel) + { + AvoidArea *avoidArea = new(std::nothrow) AvoidArea(); + if (avoidArea == nullptr) { + return nullptr; + } + if (ReadParcel(parcel, avoidArea->leftRect_) && ReadParcel(parcel, avoidArea->topRect_) && + ReadParcel(parcel, avoidArea->rightRect_) && ReadParcel(parcel, avoidArea->bottomRect_)) { + return avoidArea; + } + delete avoidArea; + return nullptr; + } +}; + +enum class WindowUpdateType : int32_t { + WINDOW_UPDATE_ADDED = 1, + WINDOW_UPDATE_REMOVED, + WINDOW_UPDATE_FOCUSED, + WINDOW_UPDATE_BOUNDS, + WINDOW_UPDATE_ACTIVE, + WINDOW_UPDATE_PROPERTY, +}; + +using OnCallback = std::function; +struct VsyncCallback { + OnCallback onCallback; +}; +} +} +#endif // OHOS_ROSEN_WM_COMMON_H diff --git a/window_manager/interfaces/kits/js/declaration/BUILD.gn b/window_manager/interfaces/kits/js/declaration/BUILD.gn new file mode 100644 index 0000000..d63c1a2 --- /dev/null +++ b/window_manager/interfaces/kits/js/declaration/BUILD.gn @@ -0,0 +1,29 @@ +# 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") + +js_declaration("window") { + sources = [ "./api" ] + + part_name = "window_manager" +} + +ohos_copy("window_declaration") { + sources = [ "./api" ] + + outputs = [ target_out_dir + "/$target_name/" ] + + module_source_dir = target_out_dir + "/$target_name" + module_install_name = "" +} diff --git a/window_manager/interfaces/kits/js/declaration/api/@ohos.display.d.ts b/window_manager/interfaces/kits/js/declaration/api/@ohos.display.d.ts new file mode 100644 index 0000000..c23ad58 --- /dev/null +++ b/window_manager/interfaces/kits/js/declaration/api/@ohos.display.d.ts @@ -0,0 +1,291 @@ +/* +* 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 { AsyncCallback, Callback } from './basic'; + +/** + * Interface of display manager. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ +declare namespace display { + /** + * display error code + * @since 7 + * @deprecated since 9 + */ + enum DMError { + DM_ERROR_INIT_DMS_PROXY_LOCKED, + DM_ERROR_IPC_FAILED, + DM_ERROR_REMOTE_CREATE_FAILED, + DM_ERROR_NULLPTR, + DM_ERROR_INVALID_PARAM, + DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED, + DM_ERROR_DEATH_RECIPIENT, + DM_ERROR_INVALID_MODE_ID, + DM_ERROR_WRITE_DATA_FAILED, + DM_ERROR_RENDER_SERVICE_FAILED, + DM_ERROR_UNREGISTER_AGENT_FAILED, + DM_ERROR_INVALID_CALLING, + DM_ERROR_UNKNOWN, + } + + /** + * display error code + * @since 9 + */ + enum DmErrorCode { + DM_ERROR_NO_PERMISSION, + DM_ERROR_INVALID_PARAM, + DM_ERROR_DEVICE_NOT_SUPPORT, + DM_ERROR_INVALID_SCREEN, + DM_ERROR_SYSTEM_INNORMAL, + DM_ERROR_INVALID_CALLING, + } + + /** + * Obtain the default display. + * @since 7 + * @deprecated since 9, please use getDefaultDisplaySync instead. + */ + function getDefaultDisplay(callback: AsyncCallback): void; + + /** + * Obtain the default display. + * @since 7 + * @deprecated since 9, please use getDefaultDisplaySync instead. + */ + function getDefaultDisplay(): Promise; + + /** + * Obtain the default display. + * @since 9 + */ + function getDefaultDisplaySync(): Display; + + /** + * Obtain all displays. + * @since 7 + * @deprecated since 9, please use getAllDisplays instead. + */ + function getAllDisplay(callback: AsyncCallback>): void; + + /** + * Obtain all displays. + * @since 7 + * @deprecated since 9, please use getAllDisplays instead. + */ + function getAllDisplay(): Promise>; + + /** + * Obtain all displays. + * @since 9 + */ + function getAllDisplays(callback: AsyncCallback>): void; + + /** + * Obtain all displays. + * @since 9 + */ + function getAllDisplays(): Promise>; + + /** + * Check whether there is a privacy window on the current display. + * @param displayId Display id to query + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @systemapi Hide this for inner system use. + * @since 9 + */ + function hasPrivateWindow(displayId: number): boolean; + + /** + * Register the callback for display changes. + * @param type: type of callback + * @since 7 + * @throws DM_ERROR_INVALID_PARAM If param is not valid + */ + function on(type: 'add' | 'remove' | 'change', callback: Callback): void; + + /** + * Unregister the callback for display changes. + * @param type: type of callback + * @since 7 + * @throws DM_ERROR_INVALID_PARAM If param is not valid + */ + function off(type: 'add' | 'remove' | 'change', callback?: Callback): void; + + /** + * Enumerates the display states. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + enum DisplayState { + /** + * Unknown. + */ + STATE_UNKNOWN = 0, + /** + * Screen off. + */ + STATE_OFF, + /** + * Screen on. + */ + STATE_ON, + /** + * Doze, but it will update for some important system messages. + */ + STATE_DOZE, + /** + * Doze and not update. + */ + STATE_DOZE_SUSPEND, + /** + * VR node. + */ + STATE_VR, + /** + * Screen on and not update. + */ + STATE_ON_SUSPEND, + } + + /** + * Rectangle + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface Rect { + left: number; + top: number; + width: number; + height: number; + } + + /** + * Curved area rects of the waterfall display. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface WaterfallDisplayAreaRects { + readonly left: Rect; + readonly right: Rect; + readonly top: Rect; + readonly bottom: Rect; + } + + /** + * cutout information of the display. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface CutoutInfo { + /** + * Bounding rectangles of the cutout areas of the display. + */ + readonly boundingRects: Array; + + /** + * Rectangles of curved parts on each side of a waterfall display. + */ + readonly waterfallDisplayAreaRects: WaterfallDisplayAreaRects; + } + + /** + * Define properties of the display. They cannot be updated automatically. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + interface Display { + /** + * Display ID. + */ + id: number; + + /** + * Display name. + */ + name: string; + + /** + * The display is alive. + */ + alive: boolean; + + /** + * The state of display. + */ + state: DisplayState; + + /** + * Refresh rate, in Hz. + */ + refreshRate: number; + + /** + * Rotation degrees of the display. + */ + rotation: number; + + /** + * Display width, in pixels. + */ + width: number; + + /** + * Display height, in pixels. + */ + height: number; + + /** + * Display resolution. + */ + densityDPI: number; + + /** + * Display density, in pixels. The value for a low-resolution display is 1.0. + */ + densityPixels: number; + + /** + * Text scale density of the display. + */ + scaledDensity: number; + + /** + * DPI on the x-axis. + */ + xDPI: number; + + /** + * DPI on the y-axis. + */ + yDPI: number; + + /** + * Obtain the cutout info of the display. + * @since 9 + */ + getCutoutInfo(callback: AsyncCallback): void; + + /** + * Obtain the cutout info of the display. + * @since 9 + */ + getCutoutInfo(): Promise; + } +} + +export default display; \ No newline at end of file diff --git a/window_manager/interfaces/kits/js/declaration/api/@ohos.screenshot.d.ts b/window_manager/interfaces/kits/js/declaration/api/@ohos.screenshot.d.ts new file mode 100644 index 0000000..b76c18d --- /dev/null +++ b/window_manager/interfaces/kits/js/declaration/api/@ohos.screenshot.d.ts @@ -0,0 +1,89 @@ +/* + * 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. + */ + +import { AsyncCallback, ErrorCallback } from './basic'; +import image from './@ohos.multimedia.image'; + +/** + * Declares the screenshot APIs. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi Hide this for inner system use. + * @since 7 + */ +declare namespace screenshot { + /** + * Takes a screenshot and saves it as a PixelMap object. + * @param options Screenshot options, which consist of screenRect, imageSize, and rotation. You need to set these parameters + * @permission ohos.permission.CAPTURE_SCREEN + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 7 + */ + function save(options?: ScreenshotOptions, callback: AsyncCallback): void; + + /** + * Takes a screenshot and saves it as a PixelMap object. + * @param options Screenshot options, which consist of screenRect, imageSize, and rotation. You need to set these parameters + * @permission ohos.permission.CAPTURE_SCREEN + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 7 + */ + function save(options?: ScreenshotOptions): Promise; + + /** + * Describes the region of the screen to capture. + * @since 7 + */ + interface Rect { + left: number; + top: number; + width: number; + height: number; + } + + /** + * Describes the size of the screen region to capture. + * @since 7 + */ + interface Size { + width: number; + height: number; + } + + /** + * Describes screenshot options. + * @since 7 + */ + interface ScreenshotOptions { + /** + * Region of the screen to capture. If this parameter is null, the full screen will be captured. + */ + screenRect?: Rect; + /** + * Region of the screen to capture. If this parameter is null, the full screen will be captured. + */ + imageSize?: Size; + /** + * Rotation angle of the screenshot. The value can be 0, 90, 180, or 270. The default value is 0. + */ + rotation?: number; + /** + * ID of the screen to be captured. + * @since 8 + */ + displayId?: number; + } +} + +export default screenshot; diff --git a/window_manager/interfaces/kits/napi/BUILD.gn b/window_manager/interfaces/kits/napi/BUILD.gn new file mode 100644 index 0000000..b9e7f71 --- /dev/null +++ b/window_manager/interfaces/kits/napi/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2021-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. + +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") +import("//build/ohos.gni") + +group("napi_packages") { + deps = [ + "display_runtime:display_napi", + "screen_runtime:screen_napi", + "screenshot:screenshot", + "window_extension_ability:windowextensionability_napi", + "window_extension_context:windowextensioncontext_napi", + "window_runtime:window_napi", + "window_runtime:window_native_kit", + "window_runtime:windowstage_kit", + ] +} diff --git a/window_manager/interfaces/kits/napi/common/BUILD.gn b/window_manager/interfaces/kits/napi/common/BUILD.gn new file mode 100644 index 0000000..32eca90 --- /dev/null +++ b/window_manager/interfaces/kits/napi/common/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") + +## Build dm_napi_common.a {{{ +config("dm_napi_common_config") { + visibility = [ ":*" ] + + cflags = [ + "-Wall", + "-Werror", + "-g3", + ] +} + +config("dm_napi_common_public_config") { + include_dirs = [ + ".", + "//third_party/node/src", + "//foundation/window/window_manager/interfaces/innerkits/dm", + ] +} + +ohos_static_library("dm_napi_common") { + sources = [ "dm_napi_common.cpp" ] + + configs = [ + ":dm_napi_common_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + public_configs = [ ":dm_napi_common_public_config" ] + + deps = [ + "//foundation/arkui/napi:ace_napi", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_base", + "hilog_native:libhilog", + "ipc:ipc_core", + ] + + subsystem_name = "window" + part_name = "window_manager" +} +## Build dm_napi_common.a }}} diff --git a/window_manager/interfaces/kits/napi/common/dm_napi_common.cpp b/window_manager/interfaces/kits/napi/common/dm_napi_common.cpp new file mode 100644 index 0000000..8ef326a --- /dev/null +++ b/window_manager/interfaces/kits/napi/common/dm_napi_common.cpp @@ -0,0 +1,129 @@ +/* + * 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_napi_common.h" + +#include +#include + +#include "accesstoken_kit.h" +#include "bundle_constants.h" +#include "ipc_skeleton.h" + +const int ERROR_CODE_LEN = 16; // 16 is the max len of error code + +namespace OHOS { +napi_status SetMemberInt32(napi_env env, napi_value result, const char *key, int32_t value) +{ + napi_value num; + GNAPI_INNER(napi_create_int32(env, value, &num)); + GNAPI_INNER(napi_set_named_property(env, result, key, num)); + return napi_ok; +} + +napi_status SetMemberUint32(napi_env env, napi_value result, const char *key, uint32_t value) +{ + napi_value num; + GNAPI_INNER(napi_create_uint32(env, value, &num)); + GNAPI_INNER(napi_set_named_property(env, result, key, num)); + return napi_ok; +} + +napi_status SetMemberUndefined(napi_env env, napi_value result, const char *key) +{ + napi_value undefined; + GNAPI_INNER(napi_get_undefined(env, &undefined)); + GNAPI_INNER(napi_set_named_property(env, result, key, undefined)); + return napi_ok; +} + +bool CheckCallingPermission(const std::string &permission) +{ + WLOGFI("CheckCallingPermission, permission:%{public}s", permission.c_str()); + if (!permission.empty() && + Security::AccessToken::AccessTokenKit::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission) + != AppExecFwk::Constants::PERMISSION_GRANTED) { + WLOGFE("%{public}s permission not granted.", permission.c_str()); + return false; + } + WLOGFI("CheckCallingPermission end."); + return true; +} + +void SetErrorInfo(napi_env env, Rosen::DmErrorCode wret, const std::string& errMessage, napi_value result[], int count) +{ + if (count != 2 || result == nullptr) { // input param number is 2 + GNAPI_LOG("Error, input param number must be 2"); + return; + } + napi_value code = nullptr; + napi_value message = nullptr; + char errorCode[ERROR_CODE_LEN]; + (void)sprintf_s(errorCode, sizeof(errorCode), "%d", static_cast(wret)); + napi_create_string_utf8(env, errorCode, strlen(errorCode), &code); + napi_create_string_utf8(env, errMessage.c_str(), strlen(errMessage.c_str()), &message); + napi_create_error(env, code, message, &result[0]); + napi_get_undefined(env, &result[1]); +} + +void ProcessPromise(napi_env env, Rosen::DmErrorCode wret, napi_deferred deferred, napi_value result[], int count) +{ + if (count != 2 || result == nullptr) { // input param number is 2 + GNAPI_LOG("Error, input param number must be 2"); + return; + } + GNAPI_LOG("AsyncProcess: Promise"); + if (wret == Rosen::DmErrorCode::DM_OK) { + GNAPI_LOG("AsyncProcess: Promise resolve"); + napi_resolve_deferred(env, deferred, result[1]); + } else { + GNAPI_LOG("AsyncProcess: Promise reject"); + napi_reject_deferred(env, deferred, result[0]); + } +} + +void ProcessCallback(napi_env env, napi_ref ref, napi_value result[], int count) +{ + if (count != 2 || result == nullptr) { // input param number is 2 + GNAPI_LOG("Error, input param number must be 2"); + return; + } + GNAPI_LOG("AsyncProcess Callback"); + napi_value callback = nullptr; + napi_value returnVal = nullptr; + napi_get_reference_value(env, ref, &callback); + napi_call_function(env, nullptr, callback, 2, result, &returnVal); // 2: callback func input number + napi_delete_reference(env, ref); +} + +bool NAPICall(napi_env env, napi_status status) +{ + if (status == napi_ok) { + return true; + } + + const napi_extended_error_info *errorInfo = nullptr; + bool isPending = false; + napi_get_last_error_info(env, &errorInfo); + napi_is_exception_pending(env, &isPending); + if (!isPending && errorInfo != nullptr) { + const char *errorMessage = + errorInfo->error_message != nullptr ? errorInfo->error_message : "empty error message"; + napi_throw_error(env, nullptr, errorMessage); + } + + return false; +} +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/common/dm_napi_common.h b/window_manager/interfaces/kits/napi/common/dm_napi_common.h new file mode 100644 index 0000000..eecdb42 --- /dev/null +++ b/window_manager/interfaces/kits/napi/common/dm_napi_common.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021-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 INTERFACES_KITS_NAPI_GRAPHIC_COMMON_COMMON_H +#define INTERFACES_KITS_NAPI_GRAPHIC_COMMON_COMMON_H + +#include +#include +#include +#include +#include + +#include "js_native_api.h" +#include "js_native_api_types.h" +#include "window_manager_hilog.h" +#include "dm_common.h" + +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, OHOS::Rosen::HILOG_DOMAIN_WINDOW, + "NapiWindowManagerCommonLayer" }; + +const int PARAM_NUMBER = 2; // 2: callback func input number, also reused by Promise + +#define GNAPI_LOG(fmt, ...) OHOS::HiviewDFX::HiLog::Info(LABEL, \ + "%{public}s:%{public}d " fmt, __func__, __LINE__, ##__VA_ARGS__) + +#define GNAPI_ASSERT(env, assertion, fmt, ...) \ + do { \ + if (assertion) { \ + GNAPI_LOG(fmt, ##__VA_ARGS__); \ + return nullptr; \ + } \ + } while (0) + +#define GNAPI_INNER(call) \ + do { \ + napi_status s = (call); \ + if (s != napi_ok) { \ + GNAPI_LOG(#call " is %{public}d", s); \ + return s; \ + } \ + } while (0) + +namespace OHOS { +napi_status SetMemberInt32(napi_env env, napi_value result, const char *key, int32_t value); +napi_status SetMemberUint32(napi_env env, napi_value result, const char *key, uint32_t value); +napi_status SetMemberUndefined(napi_env env, napi_value result, const char *key); + +bool CheckCallingPermission(const std::string& permission); +void SetErrorInfo(napi_env env, Rosen::DmErrorCode wret, const std::string& errMessage, + napi_value result[], int count); +void ProcessPromise(napi_env env, Rosen::DmErrorCode wret, napi_deferred deferred, + napi_value result[], int count); +void ProcessCallback(napi_env env, napi_ref ref, napi_value result[], int count); +bool NAPICall(napi_env env, napi_status status); + +template +napi_value AsyncProcess(napi_env env, + const std::string& funcname, + void(*async)(napi_env env, std::unique_ptr& param), + napi_value(*resolve)(napi_env env, std::unique_ptr& param), + napi_ref& callbackRef, + std::unique_ptr& param) +{ + struct AsyncCallbackInfo { + napi_async_work asyncWork; + napi_deferred deferred; + void (*async)(napi_env env, std::unique_ptr& param); + napi_value (*resolve)(napi_env env, std::unique_ptr& param); + std::unique_ptr param; + napi_ref ref; + }; + + AsyncCallbackInfo *info = new AsyncCallbackInfo { + .async = async, + .resolve = resolve, + .param = std::move(param), + .ref = callbackRef, + }; + + napi_value resourceName = nullptr; + if (!NAPICall(env, napi_create_string_latin1(env, funcname.c_str(), NAPI_AUTO_LENGTH, &resourceName))) { + delete info; + return nullptr; + } + + // decide use promise or callback + napi_value result = nullptr; + if (info->ref == nullptr) { + if (!NAPICall(env, napi_create_promise(env, &info->deferred, &result))) { + delete info; + return nullptr; + } + } else { + if (!NAPICall(env, napi_get_undefined(env, &result))) { + delete info; + return nullptr; + } + } + + auto asyncFunc = [](napi_env env, void *data) { + AsyncCallbackInfo *info = reinterpret_cast(data); + if (info->async) { + info->async(env, info->param); + } + }; + + auto completeFunc = [](napi_env env, napi_status status, void *data) { + AsyncCallbackInfo *info = reinterpret_cast(data); + napi_value result[PARAM_NUMBER] = {0}; + if (info->param->wret == Rosen::DmErrorCode::DM_OK) { + napi_get_undefined(env, &result[0]); + result[1] = info->resolve(env, info->param); + } else { + SetErrorInfo(env, info->param->wret, info->param->errMessage, result, PARAM_NUMBER); + } + if (info->deferred) { + ProcessPromise(env, info->param->wret, info->deferred, result, PARAM_NUMBER); + } else { + ProcessCallback(env, info->ref, result, PARAM_NUMBER); + } + napi_delete_async_work(env, info->asyncWork); + delete info; + }; + if (!NAPICall(env, napi_create_async_work(env, nullptr, resourceName, asyncFunc, + completeFunc, reinterpret_cast(info), &info->asyncWork))) { + delete info; + return nullptr; + } + if (!NAPICall(env, napi_queue_async_work(env, info->asyncWork))) { + delete info; + return nullptr; + } + + return result; +}; +} // namespace OHOS + +#endif // INTERFACES_KITS_NAPI_GRAPHIC_COMMON_COMMON_H diff --git a/window_manager/interfaces/kits/napi/display_runtime/BUILD.gn b/window_manager/interfaces/kits/napi/display_runtime/BUILD.gn new file mode 100644 index 0000000..d8df127 --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +config("display_config") { + visibility = [ ":*" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/kits/napi/display_runtime", + "//foundation/window/window_manager/utils/include", + + # because of pixle_map.h + "//foundation/multimedia/image_framework/interfaces/innerkits/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", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "../common:dm_napi_common", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + ] + + external_deps = [ + "ability_runtime:runtime", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "napi:ace_napi", + ] + + relative_install_dir = "module" + part_name = "window_manager" + subsystem_name = "window" +} +## Build display_napi.so }}} diff --git a/window_manager/interfaces/kits/napi/display_runtime/js_display.cpp b/window_manager/interfaces/kits/napi/display_runtime/js_display.cpp new file mode 100644 index 0000000..a1f9f7a --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/js_display.cpp @@ -0,0 +1,224 @@ +/* + * 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 "cutout_info.h" +#include "display.h" +#include "display_info.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +constexpr size_t ARGC_ONE = 1; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "JsDisplay"}; + const std::map NATIVE_TO_JS_DISPLAY_STATE_MAP { + { DisplayState::UNKNOWN, DisplayStateMode::STATE_UNKNOWN }, + { DisplayState::OFF, DisplayStateMode::STATE_OFF }, + { DisplayState::ON, DisplayStateMode::STATE_ON }, + }; +} + +static thread_local 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* JsDisplay::GetCutoutInfo(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFI("GetCutoutInfo is called"); + JsDisplay* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetCutoutInfo(*engine, *info) : nullptr; +} + +NativeValue* JsDisplay::OnGetCutoutInfo(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnGetCutoutInfo is called"); + AsyncTask::CompleteCallback complete = + [this](NativeEngine& engine, AsyncTask& task, int32_t status) { + sptr cutoutInfo = display_->GetCutoutInfo(); + if (cutoutInfo != nullptr) { + task.Resolve(engine, CreateJsCutoutInfoObject(engine, cutoutInfo)); + WLOGFI("JsDisplay::OnGetCutoutInfo success"); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN), "JsDisplay::OnGetCutoutInfo failed.")); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr && + info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_ONE - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsDisplay::OnGetCutoutInfo", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +std::shared_ptr FindJsDisplayObject(DisplayId displayId) +{ + WLOGFI("[NAPI]Try to find display %{public}" PRIu64" in g_JsDisplayMap", displayId); + std::lock_guard lock(g_mutex); + if (g_JsDisplayMap.find(displayId) == g_JsDisplayMap.end()) { + WLOGFI("[NAPI]Can not find display %{public}" PRIu64" in g_JsDisplayMap", displayId); + return nullptr; + } + return g_JsDisplayMap[displayId]; +} + +NativeValue* CreateJsCutoutInfoObject(NativeEngine& engine, sptr cutoutInfo) +{ + WLOGFI("JsDisplay::CreateJsCutoutInfoObject is called"); + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return engine.CreateUndefined(); + } + if (cutoutInfo == nullptr) { + WLOGFE("Get null cutout info"); + return engine.CreateUndefined(); + } + std::vector boundingRects = cutoutInfo->GetBoundingRects(); + WaterfallDisplayAreaRects waterfallDisplayAreaRects = cutoutInfo->GetWaterfallDisplayAreaRects(); + object->SetProperty("boundingRects", CreateJsBoundingRectsArrayObject(engine, boundingRects)); + object->SetProperty("waterfallDisplayAreaRects", + CreateJsWaterfallDisplayAreaRectsObject(engine, waterfallDisplayAreaRects)); + return objValue; +} + +NativeValue* CreateJsRectObject(NativeEngine& engine, DMRect rect) +{ + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + object->SetProperty("left", CreateJsValue(engine, rect.posX_)); + object->SetProperty("top", CreateJsValue(engine, rect.posY_)); + object->SetProperty("width", CreateJsValue(engine, rect.width_)); + object->SetProperty("height", CreateJsValue(engine, rect.height_)); + return objValue; +} + +NativeValue* CreateJsWaterfallDisplayAreaRectsObject(NativeEngine& engine, + WaterfallDisplayAreaRects waterfallDisplayAreaRects) +{ + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + object->SetProperty("left", CreateJsRectObject(engine, waterfallDisplayAreaRects.left)); + object->SetProperty("top", CreateJsRectObject(engine, waterfallDisplayAreaRects.top)); + object->SetProperty("right", CreateJsRectObject(engine, waterfallDisplayAreaRects.right)); + object->SetProperty("bottom", CreateJsRectObject(engine, waterfallDisplayAreaRects.bottom)); + return objValue; +} + +NativeValue* CreateJsBoundingRectsArrayObject(NativeEngine& engine, std::vector boundingRects) +{ + NativeValue* arrayValue = engine.CreateArray(boundingRects.size()); + NativeArray* array = ConvertNativeValueTo(arrayValue); + size_t i = 0; + for (const auto& rect : boundingRects) { + array->SetElement(i++, CreateJsRectObject(engine, rect)); + } + return arrayValue; +} + +NativeValue* CreateJsDisplayObject(NativeEngine& engine, sptr& display) +{ + WLOGFI("JsDisplay::CreateJsDisplay is called"); + NativeValue* objValue = nullptr; + std::shared_ptr jsDisplayObj = FindJsDisplayObject(display->GetId()); + if (jsDisplayObj != nullptr && jsDisplayObj->Get() != nullptr) { + WLOGFI("[NAPI]FindJsDisplayObject %{public}" PRIu64"", display->GetId()); + objValue = jsDisplayObj->Get(); + } + if (objValue == nullptr) { + objValue = engine.CreateObject(); + } + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return engine.CreateUndefined(); + } + auto info = display->GetDisplayInfo(); + if (info == nullptr) { + WLOGFE("Failed to GetDisplayInfo"); + return engine.CreateUndefined(); + } + object->SetProperty("id", CreateJsValue(engine, static_cast(info->GetDisplayId()))); + object->SetProperty("width", CreateJsValue(engine, info->GetWidth())); + object->SetProperty("height", CreateJsValue(engine, info->GetHeight())); + object->SetProperty("refreshRate", CreateJsValue(engine, info->GetRefreshRate())); + object->SetProperty("name", CreateJsValue(engine, info->GetName())); + object->SetProperty("alive", CreateJsValue(engine, true)); + if (NATIVE_TO_JS_DISPLAY_STATE_MAP.count(info->GetDisplayState()) != 0) { + object->SetProperty("state", CreateJsValue(engine, NATIVE_TO_JS_DISPLAY_STATE_MAP.at(info->GetDisplayState()))); + } else { + object->SetProperty("state", CreateJsValue(engine, DisplayStateMode::STATE_UNKNOWN)); + } + + object->SetProperty("rotation", CreateJsValue(engine, info->GetRotation())); + object->SetProperty("densityDPI", CreateJsValue(engine, info->GetVirtualPixelRatio() * DOT_PER_INCH)); + object->SetProperty("densityPixels", CreateJsValue(engine, info->GetVirtualPixelRatio())); + object->SetProperty("scaledDensity", CreateJsValue(engine, info->GetVirtualPixelRatio())); + object->SetProperty("xDPI", CreateJsValue(engine, 0.0f)); + object->SetProperty("yDPI", CreateJsValue(engine, 0.0f)); + if (jsDisplayObj == nullptr || jsDisplayObj->Get() == nullptr) { + std::unique_ptr jsDisplay = std::make_unique(display); + object->SetNativePointer(jsDisplay.release(), JsDisplay::Finalizer, nullptr); + BindNativeFunction(engine, *object, "getCutoutInfo", "JsDisplay", JsDisplay::GetCutoutInfo); + 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/window_manager/interfaces/kits/napi/display_runtime/js_display.h b/window_manager/interfaces/kits/napi/display_runtime/js_display.h new file mode 100644 index 0000000..dce9324 --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/js_display.h @@ -0,0 +1,56 @@ +/* + * 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 +#include +#include +#include + +#include "cutout_info.h" +#include "display.h" + +namespace OHOS { +namespace Rosen { +std::shared_ptr FindJsDisplayObject(DisplayId displayId); +NativeValue* CreateJsDisplayObject(NativeEngine& engine, sptr& display); +NativeValue* CreateJsCutoutInfoObject(NativeEngine& engine, sptr cutoutInfo); +NativeValue* CreateJsRectObject(NativeEngine& engine, DMRect rect); +NativeValue* CreateJsWaterfallDisplayAreaRectsObject(NativeEngine& engine, + WaterfallDisplayAreaRects waterfallDisplayAreaRects); +NativeValue* CreateJsBoundingRectsArrayObject(NativeEngine& engine, std::vector boundingRects); +class JsDisplay final { +public: + explicit JsDisplay(const sptr& display); + ~JsDisplay(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* GetCutoutInfo(NativeEngine* engine, NativeCallbackInfo* info); +private: + sptr display_ = nullptr; + NativeValue* OnGetCutoutInfo(NativeEngine& engine, NativeCallbackInfo& info); +}; +enum class DisplayStateMode : uint32_t { + STATE_UNKNOWN = 0, + STATE_OFF, + STATE_ON, + STATE_DOZE, + STATE_DOZE_SUSPEND, + STATE_VR, + STATE_ON_SUSPEND +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/display_runtime/js_display_listener.cpp b/window_manager/interfaces/kits/napi/display_runtime/js_display_listener.cpp new file mode 100644 index 0000000..98e7443 --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/js_display_listener.cpp @@ -0,0 +1,165 @@ +/* + * 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, HILOG_DOMAIN_DISPLAY, "JsDisplayListener"}; +} + +void JsDisplayListener::AddCallback(const std::string& type, 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_[type].emplace_back(std::move(callbackRef)); + WLOGFI("JsDisplayListener::AddCallback success jsCallBack_ size: %{public}u!", + static_cast(jsCallBack_[type].size())); +} + +void JsDisplayListener::RemoveAllCallback() +{ + std::lock_guard lock(mtx_); + jsCallBack_.clear(); +} + +void JsDisplayListener::RemoveCallback(const std::string& type, NativeValue* jsListenerObject) +{ + std::lock_guard lock(mtx_); + auto it = jsCallBack_.find(type); + if (it == jsCallBack_.end()) { + WLOGE("JsDisplayListener::RemoveCallback no callback to remove"); + return; + } + auto& listeners = it->second; + for (auto iter = listeners.begin(); iter != listeners.end();) { + if (jsListenerObject->StrictEquals((*iter)->Get())) { + listeners.erase(iter); + } else { + iter++; + } + } + WLOGFI("JsDisplayListener::RemoveCallback success jsCallBack_ size: %{public}u!", + static_cast(listeners.size())); +} + +void JsDisplayListener::CallJsMethod(const std::string& methodName, NativeValue* const* argv, size_t argc) +{ + if (methodName.empty()) { + WLOGFE("empty method name str, call method failed"); + return; + } + WLOGFI("CallJsMethod methodName = %{public}s", methodName.c_str()); + if (engine_ == nullptr) { + WLOGFE("engine_ nullptr"); + return; + } + for (auto& callback : jsCallBack_[methodName]) { + 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; + } + if (jsCallBack_.find(EVENT_ADD) == jsCallBack_.end()) { + WLOGE("JsDisplayListener::OnCreate not this event, return"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod(EVENT_ADD, argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsDisplayListener::OnCreate", *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; + } + if (jsCallBack_.find(EVENT_REMOVE) == jsCallBack_.end()) { + WLOGE("JsDisplayListener::OnDestroy not this event, return"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod(EVENT_REMOVE, argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsDisplayListener::OnDestroy", *engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} + +void JsDisplayListener::OnChange(DisplayId id) +{ + 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; + } + if (jsCallBack_.find(EVENT_CHANGE) == jsCallBack_.end()) { + WLOGE("JsDisplayListener::OnChange not this event, return"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod(EVENT_CHANGE, argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsDisplayListener::OnChange", *engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/display_runtime/js_display_listener.h b/window_manager/interfaces/kits/napi/display_runtime/js_display_listener.h new file mode 100644 index 0000000..bceac65 --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/js_display_listener.h @@ -0,0 +1,50 @@ +/* + * 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(const std::string& type, NativeValue* jsListenerObject); + void RemoveAllCallback(); + void RemoveCallback(const std::string& type, NativeValue* jsListenerObject); + void OnCreate(DisplayId id) override; + void OnDestroy(DisplayId id) override; + void OnChange(DisplayId id) override; + +private: + void CallJsMethod(const std::string& methodName, NativeValue* const* argv = nullptr, size_t argc = 0); + NativeEngine* engine_ = nullptr; + std::mutex mtx_; + std::map>> jsCallBack_; + NativeValue* CreateDisplayIdArray(NativeEngine& engine, const std::vector& data); +}; +const std::string EVENT_ADD = "add"; +const std::string EVENT_REMOVE = "remove"; +const std::string EVENT_CHANGE = "change"; +} // namespace Rosen +} // namespace OHOS +#endif /* OHOS_JS_DISPLAY_LISTENER_H */ \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/display_runtime/js_display_manager.cpp b/window_manager/interfaces/kits/napi/display_runtime/js_display_manager.cpp new file mode 100644 index 0000000..a8be3aa --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/js_display_manager.cpp @@ -0,0 +1,539 @@ +/* + * 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 "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, HILOG_DOMAIN_DISPLAY, "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* GetDefaultDisplaySync(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetDefaultDisplaySync(*engine, *info) : nullptr; +} + +static NativeValue* GetAllDisplay(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetAllDisplay(*engine, *info) : nullptr; +} + +static NativeValue* GetAllDisplays(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetAllDisplays(*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; +} + +static NativeValue* HasPrivateWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsDisplayManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnHasPrivateWindow(*engine, *info) : nullptr; +} + +private: +std::map, sptr>> jsCbMap_; +std::mutex mtx_; + +NativeValue* OnGetDefaultDisplay(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnGetDefaultDisplay is called"); + DMError errCode = DMError::DM_OK; + if (info.argc != 0 && info.argc != ARGC_ONE) { + WLOGFE("JsDisplayManager::OnGetDefaultDisplay params not match"); + errCode = DMError::DM_ERROR_INVALID_PARAM; + } + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != DMError::DM_OK) { + task.Reject(engine, CreateJsError(engine, + static_cast(errCode), "JsDisplayManager::OnGetDefaultDisplay failed.")); + } + 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; + if (info.argc == ARGC_ONE && info.argv[0]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[0]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsDisplayManager::OnGetDefaultDisplay", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* OnGetDefaultDisplaySync(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnGetDefaultDisplaySync is called"); + sptr display = SingletonContainer::Get().GetDefaultDisplaySync(); + if (display == nullptr) { + WLOGFE("JsDisplayManager::OnGetDefaultDisplaySync, display is nullptr."); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN))); + return engine.CreateUndefined(); + } + return CreateJsDisplayObject(engine, display); +} + +NativeValue* OnGetAllDisplay(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnGetAllDisplay is called"); + DMError errCode = DMError::DM_OK; + if (info.argc != 0 && info.argc != ARGC_ONE) { + WLOGFE("JsDisplayManager::OnGetAllDisplay params not match"); + errCode = DMError::DM_ERROR_INVALID_PARAM; + } + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != DMError::DM_OK) { + task.Reject(engine, CreateJsError(engine, + static_cast(errCode), "JsDisplayManager::OnGetAllDisplay failed.")); + } + std::vector> displays = SingletonContainer::Get().GetAllDisplays(); + if (!displays.empty()) { + task.Resolve(engine, CreateJsDisplayArrayObject(engine, displays)); + WLOGFI("JsDisplayManager::GetAllDisplays success"); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DMError::DM_ERROR_NULLPTR), "JsDisplayManager::OnGetAllDisplay failed.")); + } + }; + + NativeValue* lastParam = nullptr; + if (info.argc == ARGC_ONE && info.argv[0]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[0]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsDisplayManager::OnGetAllDisplay", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* OnGetAllDisplays(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsDisplayManager::OnGetAllDisplays is called"); + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + std::vector> displays = SingletonContainer::Get().GetAllDisplays(); + if (!displays.empty()) { + task.Resolve(engine, CreateJsDisplayArrayObject(engine, displays)); + WLOGFI("JsDisplayManager::GetAllDisplays success"); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN), + "JsDisplayManager::OnGetAllDisplays failed.")); + } + }; + + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr && + info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[0]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsDisplayManager::OnGetAllDisplays", + 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(std::nothrow) JsDisplayListener(&engine); + if (displayListener == nullptr) { + WLOGFE("displayListener is nullptr"); + return; + } + if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_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(type, 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 == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_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(type, value); + if (type == EVENT_ADD || type == EVENT_REMOVE || type == EVENT_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); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + 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"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (!value->IsCallable()) { + WLOGFI("JsDisplayManager::OnRegisterDisplayManagerCallback info->argv[1] is not callable"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + 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 < ARGC_ONE) { + WLOGFE("JsDisplayManager Params not match %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + 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) || (!value->IsCallable())) { + UnregisterAllDisplayListenerWithType(cbType); + } else { + UnRegisterDisplayListenerWithType(cbType, value); + } + } + return engine.CreateUndefined(); +} + +NativeValue* OnHasPrivateWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + bool hasPrivateWindow = false; + if (info.argc < ARGC_ONE) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + int64_t displayId = static_cast(DISPLAY_ID_INVALID); + if (!ConvertFromJsValue(engine, info.argv[0], displayId)) { + WLOGFE("[NAPI]Failed to convert parameter to displayId"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (displayId < 0) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + DmErrorCode errCode = DM_JS_TO_ERROR_CODE_MAP.at( + SingletonContainer::Get().HasPrivateWindow(displayId, hasPrivateWindow)); + WLOGFI("[NAPI]Display id = %{public}" PRIu64", hasPrivateWindow = %{public}u err = %{public}d", + static_cast(displayId), hasPrivateWindow, errCode); + if (errCode != DmErrorCode::DM_OK) { + engine.Throw(CreateJsError(engine, static_cast(errCode))); + return engine.CreateUndefined(); + } + return engine.CreateBoolean(hasPrivateWindow); +} + +NativeValue* CreateJsDisplayArrayObject(NativeEngine& engine, std::vector>& displays) +{ + WLOGFI("JsDisplayManager::CreateJsDisplayArrayObject is called"); + NativeValue* arrayValue = engine.CreateArray(displays.size()); + NativeArray* array = ConvertNativeValueTo(arrayValue); + if (array == nullptr) { + WLOGFE("Failed to create display array"); + return engine.CreateUndefined(); + } + int32_t i = 0; + for (auto& display : displays) { + if (display == nullptr) { + continue; + } + array->SetElement(i++, CreateJsDisplayObject(engine, display)); + } + return arrayValue; +} +}; + +NativeValue* InitDisplayState(NativeEngine* engine) +{ + WLOGFI("JsDisplayManager::InitDisplayState called"); + + if (engine == nullptr) { + WLOGFE("engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return nullptr; + } + + object->SetProperty("STATE_UNKNOWN", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_UNKNOWN))); + object->SetProperty("STATE_OFF", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_OFF))); + object->SetProperty("STATE_ON", CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_ON))); + object->SetProperty("STATE_DOZE", + CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_DOZE))); + object->SetProperty("STATE_DOZE_SUSPEND", + CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_DOZE_SUSPEND))); + object->SetProperty("STATE_VR", + CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_VR))); + object->SetProperty("STATE_ON_SUSPEND", + CreateJsValue(*engine, static_cast(DisplayStateMode::STATE_ON_SUSPEND))); + return objValue; +} + +NativeValue* InitDisplayErrorCode(NativeEngine* engine) +{ + WLOGFI("JsDisplayManager::InitDisplayErrorCode called"); + + if (engine == nullptr) { + WLOGFE("engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return nullptr; + } + + object->SetProperty("DM_ERROR_NO_PERMISSION", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_NO_PERMISSION))); + object->SetProperty("DM_ERROR_INVALID_PARAM", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + object->SetProperty("DM_ERROR_DEVICE_NOT_SUPPORT", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT))); + object->SetProperty("DM_ERROR_INVALID_SCREEN", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN))); + object->SetProperty("DM_ERROR_INVALID_CALLING", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_INVALID_CALLING))); + object->SetProperty("DM_ERROR_SYSTEM_INNORMAL", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL))); + + return objValue; +} + +NativeValue* InitDisplayError(NativeEngine* engine) +{ + WLOGFI("JsDisplayManager::InitDisplayError called"); + + if (engine == nullptr) { + WLOGFE("engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return nullptr; + } + + object->SetProperty("DM_ERROR_INIT_DMS_PROXY_LOCKED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED))); + object->SetProperty("DM_ERROR_IPC_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_IPC_FAILED))); + object->SetProperty("DM_ERROR_REMOTE_CREATE_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_REMOTE_CREATE_FAILED))); + object->SetProperty("DM_ERROR_NULLPTR", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_NULLPTR))); + object->SetProperty("DM_ERROR_INVALID_PARAM", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INVALID_PARAM))); + object->SetProperty("DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED))); + object->SetProperty("DM_ERROR_DEATH_RECIPIENT", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_DEATH_RECIPIENT))); + object->SetProperty("DM_ERROR_INVALID_MODE_ID", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INVALID_MODE_ID))); + object->SetProperty("DM_ERROR_WRITE_DATA_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_WRITE_DATA_FAILED))); + object->SetProperty("DM_ERROR_RENDER_SERVICE_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_RENDER_SERVICE_FAILED))); + object->SetProperty("DM_ERROR_UNREGISTER_AGENT_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_UNREGISTER_AGENT_FAILED))); + object->SetProperty("DM_ERROR_INVALID_CALLING", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INVALID_CALLING))); + object->SetProperty("DM_ERROR_UNKNOWN", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_UNKNOWN))); + + return objValue; +} + +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); + + object->SetProperty("DisplayState", InitDisplayState(engine)); + object->SetProperty("DmErrorCode", InitDisplayErrorCode(engine)); + object->SetProperty("DMError", InitDisplayError(engine)); + + const char *moduleName = "JsDisplayManager"; + BindNativeFunction(*engine, *object, "getDefaultDisplay", moduleName, JsDisplayManager::GetDefaultDisplay); + BindNativeFunction(*engine, *object, "getDefaultDisplaySync", moduleName, JsDisplayManager::GetDefaultDisplaySync); + BindNativeFunction(*engine, *object, "getAllDisplay", moduleName, JsDisplayManager::GetAllDisplay); + BindNativeFunction(*engine, *object, "getAllDisplays", moduleName, JsDisplayManager::GetAllDisplays); + BindNativeFunction(*engine, *object, "hasPrivateWindow", moduleName, JsDisplayManager::HasPrivateWindow); + BindNativeFunction(*engine, *object, "on", moduleName, JsDisplayManager::RegisterDisplayManagerCallback); + BindNativeFunction(*engine, *object, "off", moduleName, JsDisplayManager::UnregisterDisplayManagerCallback); + return engine->CreateUndefined(); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/display_runtime/js_display_manager.h b/window_manager/interfaces/kits/napi/display_runtime/js_display_manager.h new file mode 100644 index 0000000..30f1981 --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/js_display_manager.h @@ -0,0 +1,28 @@ +/* + * 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/window_manager/interfaces/kits/napi/display_runtime/js_display_module.cpp b/window_manager/interfaces/kits/napi/display_runtime/js_display_module.cpp new file mode 100644 index 0000000..83e7418 --- /dev/null +++ b/window_manager/interfaces/kits/napi/display_runtime/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/window_manager/interfaces/kits/napi/screen_runtime/BUILD.gn b/window_manager/interfaces/kits/napi/screen_runtime/BUILD.gn new file mode 100644 index 0000000..13563ff --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/BUILD.gn @@ -0,0 +1,57 @@ +# 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. + +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +config("screen_runtime_config") { + visibility = [ ":*" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/kits/napi/screen_runtime/api", + "//foundation/window/window_manager/interfaces/kits/napi/screen_runtime/napi", + ] +} + +ohos_shared_library("screen_napi") { + sources = [ + "napi/js_screen.cpp", + "napi/js_screen_listener.cpp", + "napi/js_screen_manager.cpp", + "napi/screen_manager_module.cpp", + ] + + configs = [ + ":screen_runtime_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + ] + + external_deps = [ + "ability_runtime:runtime", + "c_utils:utils", + "graphic_standard:surface", # use for SurfaceUtils + "hiviewdfx_hilog_native:libhilog", + "napi:ace_napi", + ] + + relative_install_dir = "module" + + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/interfaces/kits/napi/screen_runtime/api/@ohos.screen.d.ts b/window_manager/interfaces/kits/napi/screen_runtime/api/@ohos.screen.d.ts new file mode 100644 index 0000000..d3701ca --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/api/@ohos.screen.d.ts @@ -0,0 +1,243 @@ +/* +* 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. +*/ + +import { AsyncCallback, Callback } from './basic'; + +/** + * interface of screen manager + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi Hide this for inner system use. + * @since 9 + */ +declare namespace screen { + /** + * get all screen + * @since 9 + */ + function getAllScreens(callback: AsyncCallback>): void; + function getAllScreens(): Promise>; + + /** + * Register the callback for screen changes. + * @param eventType: type of callback + * @since 9 + */ + function on(eventType: 'connect' | 'disconnect' | 'change', callback: Callback): void; + + /** + * Unregister the callback for screen changes. + * @param eventType: type of callback + * @since 9 + */ + function off(eventType: 'connect' | 'disconnect' | 'change', callback?: Callback): void; + + /** + * make screens as expand-screen + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + function makeExpand(options:Array, callback: AsyncCallback): void; + function makeExpand(options:Array): Promise; + + /** + * make screens as mirror-screen + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + function makeMirror(mainScreen:number, mirrorScreen:Array, callback: AsyncCallback): void; + function makeMirror(mainScreen:number, mirrorScreen:Array): Promise; + + /** + * Create virtual screen. + * @param options Indicates the options of the virtual screen. + * @permission ohos.permission.CAPTURE_SCREEN. if VirtualScreenOption.surfaceId is valid, + * this permission is necessary. + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + function createVirtualScreen(options:VirtualScreenOption, callback: AsyncCallback): void; + function createVirtualScreen(options:VirtualScreenOption): Promise; + + /** + * Destroy virtual screen. + * @param screenId Indicates the screen id of the virtual screen. + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + function destroyVirtualScreen(screenId:number, callback: AsyncCallback): void; + function destroyVirtualScreen(screenId:number): Promise; + + /** + * Set surface for the virtual screen. + * @param screenId Indicates the screen id of the virtual screen. + * @param surfaceId Indicates the surface id. + * @permission ohos.permission.CAPTURE_SCREEN + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + function setVirtualScreenSurface(screenId:number, surfaceId: string, callback: AsyncCallback): void; + function setVirtualScreenSurface(screenId:number, surfaceId: string): Promise; + + /** + * Get screen rotation lock status. + * @since 9 + */ + function isScreenRotationLocked(callback: AsyncCallback): void; + function isScreenRotationLocked(): Promise; + + /** + * Set screen rotation lock status. + * @param isLocked Indicates whether the screen rotation switch is locked. + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + function setScreenRotationLocked(isLocked:boolean, callback: AsyncCallback): void; + function setScreenRotationLocked(isLocked:boolean): Promise; + + /** + * the parameter of making expand screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface ExpandOption { + /** + * screen id + */ + screenId: number; + + /** + * the start coordinate X of the screen origin + */ + startX: number; + + /** + * the start coordinate Y of the screen origin + */ + startY: number; + } + + /** + * The parameter for creating virtual screen. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface VirtualScreenOption { + /** + * Indicates the name of the virtual screen. + */ + name: string + + /** + * Indicates the width of the virtual screen. + */ + width: number + + /** + * Indicates the height of the virtual screen. + */ + height: number + + /** + * Indicates the density of the virtual screen. + */ + density: number + + /** + * Indicates the surface id of the virtual screen. + */ + surfaceId: string + } + + /** + * interface for screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface Screen { + /** + * screen id + */ + readonly id: number; + + /** + * group id + */ + readonly parent: number; + + /** + * mode supported by the screen + */ + readonly supportedModeInfo: Array; + + /** + * currently active mode + */ + readonly activeModeIndex: number; + + /** + * orientation of the screen + */ + readonly orientation: Orientation; + + /** + * set the orientation of the screen + * @throws DM_ERROR_INVALID_PARAM If param is not valid + * @since 9 + */ + setOrientation(orientation: Orientation, callback: AsyncCallback): void; + setOrientation(orientation: Orientation): Promise; + + /** + * active the mode + * @throws DM_ERROR_INVALID_PARAM If param is not valid + */ + setScreenActiveMode(modeIndex: number, callback: AsyncCallback): void; + setScreenActiveMode(modeIndex: number): Promise; + + /** + * set display density of the screen + * @throws DM_ERROR_INVALID_PARAM If param is not valid + */ + setDensityDpi(densityDpi: number, callback: AsyncCallback): void; + setDensityDpi(densityDpi: number): Promise; + } + + /** + * screen orientation + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + enum Orientation { + UNSPECIFIED = 0, + VERTICAL = 1, + HORIZONTAL = 2, + REVERSE_VERTICAL = 3, + REVERSE_HORIZONTAL = 4, + } + + /** + * the information of the screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + interface ScreenModeInfo { + id: number; + width: number; + height: number; + refreshRate: number; + } +} + +export default screen; diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.cpp b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.cpp new file mode 100644 index 0000000..4c7b818 --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.cpp @@ -0,0 +1,309 @@ +/* + * 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_screen.h" + +#include +#include "screen.h" +#include "screen_info.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +constexpr size_t ARGC_ONE = 1; +constexpr size_t ARGC_TWO = 2; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "JsScreen"}; +} + +static thread_local std::map> g_JsScreenMap; +std::recursive_mutex g_mutex; + +JsScreen::JsScreen(const sptr& screen) : screen_(screen) +{ +} + +JsScreen::~JsScreen() +{ + WLOGFI("JsScreen::~JsScreen is called"); +} + +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"); + return; + } + ScreenId screenId = screen->GetId(); + WLOGFI("JsScreen::Finalizer screenId : %{public}" PRIu64"", screenId); + std::lock_guard lock(g_mutex); + if (g_JsScreenMap.find(screenId) != g_JsScreenMap.end()) { + WLOGFI("JsScreen::Finalizer screen is destroyed: %{public}" PRIu64"", screenId); + g_JsScreenMap.erase(screenId); + } +} + +NativeValue* JsScreen::SetOrientation(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreen* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetOrientation(*engine, *info) : nullptr; +} + +NativeValue* JsScreen::OnSetOrientation(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnSetOrientation is called"); + bool paramValidFlag = true; + Orientation orientation = Orientation::UNSPECIFIED; + if (info.argc < ARGC_ONE) { + WLOGFE("OnSetOrientation Params not match, info argc: %{public}zu", info.argc); + paramValidFlag = false; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], orientation)) { + paramValidFlag = false; + WLOGFE("Failed to convert parameter to orientation"); + } + } + if (!paramValidFlag) { + WLOGE("OnSetOrientation paramValidFlag error"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (orientation < Orientation::BEGIN || orientation > Orientation::END) { + WLOGE("Orientation param error! orientation value must from enum Orientation"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + bool res = screen_->SetOrientation(orientation); + if (res) { + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("OnSetOrientation success"); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), + "JsScreen::OnSetOrientation failed.")); + WLOGFE("OnSetOrientation failed"); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr && + info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_TWO - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreen::OnSetOrientation", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + + +NativeValue* JsScreen::SetScreenActiveMode(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFI("SetScreenActiveMode is called"); + JsScreen* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetScreenActiveMode(*engine, *info) : nullptr; +} + +NativeValue* JsScreen::OnSetScreenActiveMode(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnSetScreenActiveMode is called"); + bool paramValidFlag = true; + uint32_t modeId = 0; + if (info.argc < ARGC_ONE) { + WLOGFE("OnSetScreenActiveMode Params not match %{public}zu", info.argc); + paramValidFlag = false; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], modeId)) { + WLOGFE("Failed to convert parameter to modeId"); + paramValidFlag = false; + } + } + if (!paramValidFlag) { + WLOGFE("OnSetScreenActiveMode paramValidFlag error"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + bool res = screen_->SetScreenActiveMode(modeId); + if (res) { + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("OnSetScreenActiveMode success"); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), + "JsScreen::OnSetScreenActiveMode failed.")); + WLOGFE("OnSetScreenActiveMode failed"); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr && + info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_TWO - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreen::OnSetScreenActiveMode", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsScreen::SetDensityDpi(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFI("SetDensityDpi is called"); + JsScreen* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetDensityDpi(*engine, *info) : nullptr; +} + +NativeValue* JsScreen::OnSetDensityDpi(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnSetDensityDpi is called"); + bool paramValidFlag = true; + uint32_t densityDpi = 0; + if (info.argc < ARGC_ONE) { + WLOGFE("OnSetDensityDpi Params not match %{public}zu", info.argc); + paramValidFlag = false; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], densityDpi)) { + WLOGFE("Failed to convert parameter to densityDpi"); + paramValidFlag = false; + } + } + if (!paramValidFlag) { + WLOGFE("OnSetDensityDpi paramValidFlag error"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + bool res = screen_->SetDensityDpi(densityDpi); + if (res) { + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("OnSetDensityDpi success"); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL), + "JsScreen::OnSetDensityDpi failed.")); + WLOGFE("OnSetDensityDpi failed"); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr && + info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_TWO - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreen::OnSetDensityDpi", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +std::shared_ptr FindJsDisplayObject(ScreenId screenId) +{ + WLOGFI("[NAPI]Try to find screen %{public}" PRIu64" in g_JsScreenMap", screenId); + std::lock_guard lock(g_mutex); + if (g_JsScreenMap.find(screenId) == g_JsScreenMap.end()) { + WLOGFI("[NAPI]Can not find screen %{public}" PRIu64" in g_JsScreenMap", screenId); + return nullptr; + } + return g_JsScreenMap[screenId]; +} + +NativeValue* CreateJsScreenObject(NativeEngine& engine, sptr& screen) +{ + WLOGFI("JsScreen::CreateJsScreen is called"); + NativeValue* objValue = nullptr; + std::shared_ptr jsScreenObj = FindJsDisplayObject(screen->GetId()); + if (jsScreenObj != nullptr && jsScreenObj->Get() != nullptr) { + WLOGFI("[NAPI]FindJsScreenObject %{public}" PRIu64"", screen->GetId()); + objValue = jsScreenObj->Get(); + } + if (objValue == nullptr) { + objValue = engine.CreateObject(); + } + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return engine.CreateUndefined(); + } + std::unique_ptr jsScreen = std::make_unique(screen); + object->SetNativePointer(jsScreen.release(), JsScreen::Finalizer, nullptr); + auto info = screen->GetScreenInfo(); + if (info == nullptr) { + WLOGFE("Failed to GetScreenInfo"); + return engine.CreateUndefined(); + } + ScreenId screenId = info->GetScreenId(); + object->SetProperty("id", + CreateJsValue(engine, screenId == SCREEN_ID_INVALID ? -1 : static_cast(screenId))); + ScreenId parentId = info->GetParentId(); + object->SetProperty("parent", + CreateJsValue(engine, parentId == SCREEN_ID_INVALID ? -1 : static_cast(parentId))); + object->SetProperty("orientation", CreateJsValue(engine, info->GetOrientation())); + object->SetProperty("activeModeIndex", CreateJsValue(engine, info->GetModeId())); + object->SetProperty("supportedModeInfo", CreateJsScreenModeArrayObject(engine, info->GetModes())); + object->SetProperty("densityDpi", CreateJsValue(engine, + static_cast(info->GetVirtualPixelRatio() * DOT_PER_INCH))); // Dpi = Density(VPR) * 160. + if (jsScreenObj == nullptr || jsScreenObj->Get() == nullptr) { + std::shared_ptr JsScreenRef; + JsScreenRef.reset(engine.CreateReference(objValue, 1)); + std::lock_guard lock(g_mutex); + g_JsScreenMap[screenId] = JsScreenRef; + const char *moduleName = "JsScreen"; + BindNativeFunction(engine, *object, "setScreenActiveMode", moduleName, JsScreen::SetScreenActiveMode); + BindNativeFunction(engine, *object, "setOrientation", moduleName, JsScreen::SetOrientation); + BindNativeFunction(engine, *object, "setDensityDpi", moduleName, JsScreen::SetDensityDpi); + } + return objValue; +} + +NativeValue* CreateJsScreenModeArrayObject(NativeEngine& engine, std::vector> screenModes) +{ + NativeValue* arrayValue = engine.CreateArray(screenModes.size()); + NativeArray* array = ConvertNativeValueTo(arrayValue); + size_t i = 0; + for (const auto& mode : screenModes) { + array->SetElement(i++, CreateJsScreenModeObject(engine, mode)); + } + return arrayValue; +} + +NativeValue* CreateJsScreenModeObject(NativeEngine& engine, const sptr& mode) +{ + WLOGFI("JsScreen::CreateJsScreenMode is called"); + NativeValue* objValue = engine.CreateObject(); + NativeObject* optionObject = ConvertNativeValueTo(objValue); + if (optionObject == nullptr) { + WLOGFE("Failed to convert prop to jsObject"); + return engine.CreateUndefined(); + } + uint32_t width = mode->width_; + uint32_t height = mode->height_; + uint32_t refreshRate = mode->refreshRate_; + optionObject->SetProperty("width", CreateJsValue(engine, width)); + optionObject->SetProperty("height", CreateJsValue(engine, height)); + optionObject->SetProperty("refreshRate", CreateJsValue(engine, refreshRate)); + return objValue; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.h b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.h new file mode 100644 index 0000000..1ce035b --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen.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_SCREEN_H +#define OHOS_JS_SCREEN_H +#include +#include +#include +#include + +#include "screen.h" + +namespace OHOS { +namespace Rosen { +NativeValue* CreateJsScreenObject(NativeEngine& engine, sptr& screen); +NativeValue* CreateJsScreenModeArrayObject(NativeEngine& engine, std::vector> screenModes); +NativeValue* CreateJsScreenModeObject(NativeEngine &engine, const sptr& mode); +class JsScreen final { +public: + explicit JsScreen(const sptr& screen); + ~JsScreen(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* SetScreenActiveMode(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetOrientation(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetDensityDpi(NativeEngine* engine, NativeCallbackInfo* info); + +private: + sptr screen_ = nullptr; + NativeValue* OnSetOrientation(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetScreenActiveMode(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetDensityDpi(NativeEngine& engine, NativeCallbackInfo& info); +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.cpp b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.cpp new file mode 100644 index 0000000..ced71ec --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.cpp @@ -0,0 +1,178 @@ +/* + * 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_screen_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, "JsScreenListener"}; +} +inline uint32_t SCREEN_DISCONNECT_TYPE = 0; +inline uint32_t SCREEN_CONNECT_TYPE = 1; + +void JsScreenListener::AddCallback(const std::string& type, NativeValue* jsListenerObject) +{ + WLOGFI("JsScreenListener::AddCallback is called"); + std::lock_guard lock(mtx_); + std::unique_ptr callbackRef; + callbackRef.reset(engine_->CreateReference(jsListenerObject, 1)); + jsCallBack_[type].emplace_back(std::move(callbackRef)); + WLOGFI("JsScreenListener::AddCallback success jsCallBack_ size: %{public}u!", + static_cast(jsCallBack_[type].size())); +} + +void JsScreenListener::RemoveAllCallback() +{ + std::lock_guard lock(mtx_); + jsCallBack_.clear(); +} + +void JsScreenListener::RemoveCallback(const std::string& type, NativeValue* jsListenerObject) +{ + std::lock_guard lock(mtx_); + auto it = jsCallBack_.find(type); + if (it == jsCallBack_.end()) { + WLOGE("JsScreenListener::RemoveCallback no callback to remove"); + return; + } + auto& listeners = it->second; + for (auto iter = listeners.begin(); iter != listeners.end();) { + if (jsListenerObject->StrictEquals((*iter)->Get())) { + listeners.erase(iter); + } else { + iter++; + } + } + WLOGFI("JsScreenListener::RemoveCallback success jsCallBack_ size: %{public}u!", + static_cast(listeners.size())); +} + +void JsScreenListener::CallJsMethod(const std::string& methodName, NativeValue* const* argv, size_t argc) +{ + if (methodName.empty()) { + WLOGFE("empty method name str, call method failed"); + return; + } + WLOGFI("CallJsMethod methodName = %{public}s", methodName.c_str()); + if (engine_ == nullptr) { + WLOGFE("engine_ nullptr"); + return; + } + for (auto& callback : jsCallBack_[methodName]) { + NativeValue* method = callback->Get(); + if (method == nullptr) { + WLOGFE("Failed to get method callback from object"); + continue; + } + engine_->CallFunction(engine_->CreateUndefined(), method, argv, argc); + } +} + +void JsScreenListener::OnConnect(ScreenId id) +{ + std::lock_guard lock(mtx_); + WLOGFI("JsScreenListener::OnConnect is called"); + if (jsCallBack_.empty()) { + WLOGFE("JsScreenListener::OnConnect not register!"); + return; + } + if (jsCallBack_.find(EVENT_CONNECT) == jsCallBack_.end()) { + WLOGE("JsScreenListener::OnConnect not this event, return"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod(EVENT_CONNECT, argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsScreenListener::OnConnect", *engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} + +void JsScreenListener::OnDisconnect(ScreenId id) +{ + std::lock_guard lock(mtx_); + WLOGFI("JsScreenListener::OnDisconnect is called"); + if (jsCallBack_.empty()) { + WLOGFE("JsScreenListener::OnDisconnect not register!"); + return; + } + if (jsCallBack_.find(EVENT_DISCONNECT) == jsCallBack_.end()) { + WLOGE("JsScreenListener::OnDisconnect not this event, return"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod(EVENT_DISCONNECT, argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsScreenListener::OnDisconnect", *engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} + +void JsScreenListener::OnChange(ScreenId id) +{ + std::lock_guard lock(mtx_); + WLOGFI("JsScreenListener::OnChange is called"); + if (jsCallBack_.empty()) { + WLOGFE("JsScreenListener::OnChange not register!"); + return; + } + if (jsCallBack_.find(EVENT_CHANGE) == jsCallBack_.end()) { + WLOGE("JsScreenListener::OnChange not this event, return"); + return; + } + + std::unique_ptr complete = std::make_unique ( + [=] (NativeEngine &engine, AsyncTask &task, int32_t status) { + NativeValue* argv[] = {CreateJsValue(*engine_, static_cast(id))}; + CallJsMethod(EVENT_CHANGE, argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsScreenListener::OnChange", *engine_, std::make_unique( + callback, std::move(execute), std::move(complete))); +} + +NativeValue* JsScreenListener::CreateScreenIdArray(NativeEngine& engine, const std::vector& data) +{ + NativeValue* arrayValue = engine.CreateArray(data.size()); + NativeArray* array = ConvertNativeValueTo(arrayValue); + if (array == nullptr) { + WLOGFE("Failed to create screenid array"); + return engine.CreateUndefined(); + } + uint32_t index = 0; + for (const auto& item : data) { + array->SetElement(index++, CreateJsValue(engine, static_cast(item))); + } + return arrayValue; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.h b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.h new file mode 100644 index 0000000..faff66d --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_listener.h @@ -0,0 +1,49 @@ +/* + * 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_SCREEN_LISTENER_H +#define OHOS_JS_SCREEN_LISTENER_H + +#include +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "screen_manager.h" + +namespace OHOS { +namespace Rosen { +class JsScreenListener : public ScreenManager::IScreenListener { +public: + explicit JsScreenListener(NativeEngine* engine) : engine_(engine) {} + ~JsScreenListener() override = default; + void AddCallback(const std::string& type, NativeValue* jsListenerObject); + void RemoveAllCallback(); + void RemoveCallback(const std::string& type, NativeValue* jsListenerObject); + void OnConnect(ScreenId id) override; + void OnDisconnect(ScreenId id) override; + void OnChange(ScreenId id) override; + +private: + void CallJsMethod(const std::string& methodName, NativeValue* const* argv = nullptr, size_t argc = 0); + NativeEngine* engine_ = nullptr; + std::mutex mtx_; + std::map>> jsCallBack_; + NativeValue* CreateScreenIdArray(NativeEngine& engine, const std::vector& data); +}; +const std::string EVENT_CONNECT = "connect"; +const std::string EVENT_DISCONNECT = "disconnect"; +const std::string EVENT_CHANGE = "change"; +} // namespace Rosen +} // namespace OHOS +#endif /* OHOS_JS_SCREEN_LISTENER_H */ \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.cpp b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.cpp new file mode 100644 index 0000000..476275f --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.cpp @@ -0,0 +1,830 @@ +/* + * 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_screen_manager.h" + +#include +#include +#include +#include "js_runtime_utils.h" +#include "js_screen.h" +#include "js_screen_listener.h" +#include "native_engine/native_reference.h" +#include "screen_manager.h" +#include "singleton_container.h" +#include "surface_utils.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +constexpr size_t ARGC_ONE = 1; +constexpr size_t ARGC_TWO = 2; +constexpr size_t ARGC_THREE = 3; +constexpr int32_t INDEX_ONE = 1; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "JsScreenManager"}; +} + +class JsScreenManager { +public: +explicit JsScreenManager(NativeEngine* engine) { +} + +~JsScreenManager() = default; + +static void Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFI("JsScreenManager::Finalizer is called"); + std::unique_ptr(static_cast(data)); +} + +static NativeValue* GetAllScreens(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetAllScreens(*engine, *info) : nullptr; +} + +static NativeValue* RegisterScreenManagerCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnRegisterScreenMangerCallback(*engine, *info) : nullptr; +} + +static NativeValue* UnregisterScreenMangerCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnUnregisterScreenManagerCallback(*engine, *info) : nullptr; +} + +static NativeValue* MakeMirror(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnMakeMirror(*engine, *info) : nullptr; +} + +static NativeValue* MakeExpand(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnMakeExpand(*engine, *info) : nullptr; +} + +static NativeValue* CreateVirtualScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnCreateVirtualScreen(*engine, *info) : nullptr; +} + +static NativeValue* DestroyVirtualScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnDestroyVirtualScreen(*engine, *info) : nullptr; +} + +static NativeValue* SetVirtualScreenSurface(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetVirtualScreenSurface(*engine, *info) : nullptr; +} + +static NativeValue* IsScreenRotationLocked(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnIsScreenRotationLocked(*engine, *info) : nullptr; +} + +static NativeValue* SetScreenRotationLocked(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsScreenManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetScreenRotationLocked(*engine, *info) : nullptr; +} +private: +std::map, sptr>> jsCbMap_; +std::mutex mtx_; + +NativeValue* OnGetAllScreens(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnGetAllScreens is called"); + AsyncTask::CompleteCallback complete = + [this](NativeEngine& engine, AsyncTask& task, int32_t status) { + std::vector> screens = SingletonContainer::Get().GetAllScreens(); + if (!screens.empty()) { + task.Resolve(engine, CreateJsScreenVectorObject(engine, screens)); + WLOGFI("JsScreenManager::OnGetAllScreens success"); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN), + "JsScreenManager::OnGetAllScreens failed.")); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr && + info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_ONE - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnGetAllScreens", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* CreateJsScreenVectorObject(NativeEngine& engine, std::vector>& screens) +{ + NativeValue* arrayValue = engine.CreateArray(screens.size()); + NativeArray* array = ConvertNativeValueTo(arrayValue); + if (array == nullptr) { + WLOGFE("Failed to get screens"); + return engine.CreateUndefined(); + } + size_t i = 0; + for (auto& screen : screens) { + if (screen == nullptr) { + continue; + } + array->SetElement(i++, CreateJsScreenObject(engine, screen)); + } + return arrayValue; +} + +bool IfCallbackRegistered(const std::string& type, NativeValue* jsListenerObject) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("JsScreenManager::IfCallbackRegistered methodName %{public}s not registered!", type.c_str()); + return false; + } + + for (auto& iter : jsCbMap_[type]) { + if (jsListenerObject->StrictEquals(iter.first->Get())) { + WLOGFE("JsScreenManager::IfCallbackRegistered callback already registered!"); + return true; + } + } + return false; +} + +void RegisterScreenListenerWithType(NativeEngine& engine, const std::string& type, NativeValue* value) +{ + if (IfCallbackRegistered(type, value)) { + WLOGFE("JsScreenManager::RegisterScreenListenerWithType callback already registered!"); + return; + } + std::unique_ptr callbackRef; + callbackRef.reset(engine.CreateReference(value, 1)); + sptr screenListener = new(std::nothrow) JsScreenListener(&engine); + if (screenListener == nullptr) { + WLOGFE("screenListener is nullptr"); + return; + } + if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) { + SingletonContainer::Get().RegisterScreenListener(screenListener); + WLOGFI("JsScreenManager::RegisterScreenListenerWithType success"); + } else { + WLOGFE("JsScreenManager::RegisterScreenListenerWithType failed method: %{public}s not support!", + type.c_str()); + return; + } + screenListener->AddCallback(type, value); + jsCbMap_[type][std::move(callbackRef)] = screenListener; +} + +void UnregisterAllScreenListenerWithType(const std::string& type) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("JsScreenManager::UnregisterAllScreenListenerWithType methodName %{public}s not registered!", + type.c_str()); + return; + } + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + it->second->RemoveAllCallback(); + if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) { + sptr thisListener(it->second); + SingletonContainer::Get().UnregisterScreenListener(thisListener); + WLOGFI("JsScreenManager::UnregisterAllScreenListenerWithType success"); + } + jsCbMap_[type].erase(it++); + } + jsCbMap_.erase(type); +} + +void UnRegisterScreenListenerWithType(const std::string& type, NativeValue* value) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("JsScreenManager::UnRegisterScreenListenerWithType methodName %{public}s not registered!", + type.c_str()); + return; + } + if (value == nullptr) { + WLOGFE("JsScreenManager::UnRegisterScreenListenerWithType value is nullptr"); + return; + } + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + if (value->StrictEquals(it->first->Get())) { + it->second->RemoveCallback(type, value); + if (type == EVENT_CONNECT || type == EVENT_DISCONNECT || type == EVENT_CHANGE) { + sptr thisListener(it->second); + SingletonContainer::Get().UnregisterScreenListener(thisListener); + WLOGFI("JsScreenManager::UnRegisterScreenListenerWithType success"); + } + jsCbMap_[type].erase(it++); + break; + } else { + it++; + } + } + if (jsCbMap_[type].empty()) { + jsCbMap_.erase(type); + } +} + +NativeValue* OnRegisterScreenMangerCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback is called"); + if (info.argc < ARGC_TWO) { + WLOGFE("Params not match"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeValue* value = info.argv[INDEX_ONE]; + if (value == nullptr) { + WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback info->argv[1] is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (!value->IsCallable()) { + WLOGFI("JsScreenManager::OnRegisterScreenMangerCallback info->argv[1] is not callable"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::lock_guard lock(mtx_); + RegisterScreenListenerWithType(engine, cbType, value); + return engine.CreateUndefined(); +} + +NativeValue* OnUnregisterScreenManagerCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsScreenManager::OnUnregisterScreenCallback is called"); + if (info.argc < ARGC_ONE) { + WLOGFE("Params not match"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::lock_guard lock(mtx_); + if (info.argc == ARGC_ONE) { + UnregisterAllScreenListenerWithType(cbType); + } else { + NativeValue* value = info.argv[INDEX_ONE]; + if ((value == nullptr) || (!value->IsCallable())) { + UnregisterAllScreenListenerWithType(cbType); + } else { + UnRegisterScreenListenerWithType(cbType, value); + } + } + return engine.CreateUndefined(); +} + +NativeValue* OnMakeMirror(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnMakeMirror is called"); + if (info.argc < ARGC_TWO) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + int64_t mainScreenId; + if (!ConvertFromJsValue(engine, info.argv[0], mainScreenId)) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeArray* array = ConvertNativeValueTo(info.argv[INDEX_ONE]); + if (array == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + uint32_t size = array->GetLength(); + std::vector screenIds; + for (uint32_t i = 0; i < size; i++) { + uint32_t screenId; + NativeValue* value = array->GetElement(i); + if (!ConvertFromJsValue(engine, value, screenId)) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + screenIds.emplace_back(static_cast(screenId)); + } + + AsyncTask::CompleteCallback complete = + [mainScreenId, screenIds](NativeEngine& engine, AsyncTask& task, int32_t status) { + ScreenId id = SingletonContainer::Get().MakeMirror(mainScreenId, screenIds); + if (id != SCREEN_ID_INVALID) { + task.Resolve(engine, CreateJsValue(engine, static_cast(id))); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN), + "JsScreenManager::OnMakeMirror failed.")); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_THREE && info.argv[ARGC_THREE - 1] != nullptr && + info.argv[ARGC_THREE - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_THREE - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnMakeMirror", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* OnMakeExpand(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnMakeExpand is called"); + if (info.argc < ARGC_ONE) { + WLOGFE("Params not match"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + NativeArray* array = ConvertNativeValueTo(info.argv[0]); + if (array == nullptr) { + WLOGFE("Failed to get options"); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + uint32_t size = array->GetLength(); + std::vector options; + for (uint32_t i = 0; i < size; ++i) { + NativeObject* object = ConvertNativeValueTo(array->GetElement(i)); + ExpandOption expandOption; + int32_t res = GetExpandOptionFromJs(engine, object, expandOption); + if (res == -1) { + WLOGE("expandoption param %{public}d error!", i); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + options.emplace_back(expandOption); + } + + AsyncTask::CompleteCallback complete = + [options](NativeEngine& engine, AsyncTask& task, int32_t status) { + ScreenId id = SingletonContainer::Get().MakeExpand(options); + if (id != SCREEN_ID_INVALID) { + task.Resolve(engine, CreateJsValue(engine, static_cast(id))); + WLOGFI("MakeExpand success"); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN), + "JsScreenManager::OnMakeExpand failed.")); + WLOGFE("MakeExpand failed"); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr && + info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_TWO - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnMakeExpand", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +static int32_t GetExpandOptionFromJs(NativeEngine& engine, NativeObject* optionObject, ExpandOption& option) +{ + NativeValue* screedIdValue = optionObject->GetProperty("screenId"); + NativeValue* startXValue = optionObject->GetProperty("startX"); + NativeValue* startYValue = optionObject->GetProperty("startY"); + uint32_t screenId; + uint32_t startX; + uint32_t startY; + if (!ConvertFromJsValue(engine, screedIdValue, screenId)) { + WLOGFE("Failed to convert screedIdValue to callbackType"); + return -1; + } + if (!ConvertFromJsValue(engine, startXValue, startX)) { + WLOGFE("Failed to convert startXValue to callbackType"); + return -1; + } + if (!ConvertFromJsValue(engine, startYValue, startY)) { + WLOGFE("Failed to convert startYValue to callbackType"); + return -1; + } + option = {screenId, startX, startY}; + return 0; +} + +NativeValue* OnCreateVirtualScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsScreenManager::OnCreateVirtualScreen is called"); + DmErrorCode errCode = DmErrorCode::DM_OK; + VirtualScreenOption option; + if (info.argc < ARGC_ONE) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } else { + NativeObject* object = ConvertNativeValueTo(info.argv[0]); + if (object == nullptr) { + WLOGFE("Failed to convert parameter to VirtualScreenOption."); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } else { + errCode = GetVirtualScreenOptionFromJs(engine, object, option); + } + } + if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + AsyncTask::CompleteCallback complete = + [option](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto screenId = SingletonContainer::Get().CreateVirtualScreen(option); + auto screen = SingletonContainer::Get().GetScreenById(screenId); + if (screen == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN), + "ScreenManager::CreateVirtualScreen failed.")); + WLOGFE("ScreenManager::CreateVirtualScreen failed."); + return; + } + task.Resolve(engine, CreateJsScreenObject(engine, screen)); + WLOGFI("JsScreenManager::OnCreateVirtualScreen success"); + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr && + info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_TWO - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnCreateVirtualScreen", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +DmErrorCode GetVirtualScreenOptionFromJs(NativeEngine& engine, NativeObject* optionObject, VirtualScreenOption& option) +{ + NativeValue* name = optionObject->GetProperty("name"); + if (!ConvertFromJsValue(engine, name, option.name_)) { + WLOGFE("Failed to convert parameter to name."); + return DmErrorCode::DM_ERROR_INVALID_PARAM; + } + NativeValue* width = optionObject->GetProperty("width"); + if (!ConvertFromJsValue(engine, width, option.width_)) { + WLOGFE("Failed to convert parameter to width."); + return DmErrorCode::DM_ERROR_INVALID_PARAM; + } + NativeValue* height = optionObject->GetProperty("height"); + if (!ConvertFromJsValue(engine, height, option.height_)) { + WLOGFE("Failed to convert parameter to height."); + return DmErrorCode::DM_ERROR_INVALID_PARAM; + } + NativeValue* density = optionObject->GetProperty("density"); + double densityValue; + if (!ConvertFromJsValue(engine, density, densityValue)) { + WLOGFE("Failed to convert parameter to density."); + return DmErrorCode::DM_ERROR_INVALID_PARAM; + } + option.density_ = static_cast(densityValue); + + NativeValue* surfaceIdNativeValue = optionObject->GetProperty("surfaceId"); + if (!GetSurfaceFromJs(engine, surfaceIdNativeValue, option.surface_)) { + return DmErrorCode::DM_ERROR_INVALID_PARAM; + } + return DmErrorCode::DM_OK; +} + +bool GetSurfaceFromJs(NativeEngine& engine, NativeValue* surfaceIdNativeValue, sptr& surface) +{ + if (surfaceIdNativeValue == nullptr || surfaceIdNativeValue->TypeOf() != NATIVE_STRING) { + WLOGFE("Failed to convert parameter to surface. Invalidate params."); + return false; + } + char buffer[PATH_MAX]; + size_t length = 0; + uint64_t surfaceId = 0; + napi_env env = reinterpret_cast(&engine); + napi_value surfaceIdValue = reinterpret_cast(surfaceIdNativeValue); + if (napi_get_value_string_utf8(env, surfaceIdValue, buffer, PATH_MAX, &length) != napi_ok) { + WLOGFE("Failed to convert parameter to surface."); + return false; + } + std::istringstream inputStream(buffer); + inputStream >> surfaceId; + surface = SurfaceUtils::GetInstance()->GetSurface(surfaceId); + if (surface == nullptr) { + WLOGFI("GetSurfaceFromJs failed, surfaceId:%{public}" PRIu64"", surfaceId); + } + return true; +} + +NativeValue* OnDestroyVirtualScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsScreenManager::OnDestroyVirtualScreen is called"); + DmErrorCode errCode = DmErrorCode::DM_OK; + int64_t screenId = -1LL; + if (info.argc < ARGC_ONE) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], screenId)) { + WLOGFE("Failed to convert parameter to screen id."); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } + } + if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM || screenId == -1LL) { + WLOGFE("JsScreenManager::OnDestroyVirtualScreen failed, Invalidate params."); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + AsyncTask::CompleteCallback complete = + [screenId](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto res = DM_JS_TO_ERROR_CODE_MAP.at( + SingletonContainer::Get().DestroyVirtualScreen(screenId)); + if (res != DmErrorCode::DM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(res), + "ScreenManager::DestroyVirtualScreen failed.")); + WLOGFE("ScreenManager::DestroyVirtualScreen failed."); + return; + } + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("JsScreenManager::OnDestroyVirtualScreen success"); + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_TWO && info.argv[ARGC_TWO - 1] != nullptr && + info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_TWO - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnDestroyVirtualScreen", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* OnSetVirtualScreenSurface(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsScreenManager::OnSetVirtualScreenSurface is called"); + DmErrorCode errCode = DmErrorCode::DM_OK; + int64_t screenId = -1LL; + sptr surface; + if (info.argc < ARGC_TWO) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], screenId)) { + WLOGFE("Failed to convert parameter to screen id."); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } + if (!GetSurfaceFromJs(engine, info.argv[1], surface)) { + WLOGFE("Failed to convert parameter to surface"); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } + } + if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM || surface == nullptr) { + WLOGFE("JsScreenManager::OnSetVirtualScreenSurface failed, Invalidate params."); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + AsyncTask::CompleteCallback complete = + [screenId, surface](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto res = DM_JS_TO_ERROR_CODE_MAP.at( + SingletonContainer::Get().SetVirtualScreenSurface(screenId, surface)); + if (res != DmErrorCode::DM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(res), + "ScreenManager::SetVirtualScreenSurface failed.")); + WLOGFE("ScreenManager::SetVirtualScreenSurface failed."); + return; + } + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("JsScreenManager::OnSetVirtualScreenSurface success"); + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_THREE && info.argv[ARGC_THREE - 1] != nullptr && + info.argv[ARGC_THREE - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_THREE - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnSetVirtualScreenSurface", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* OnIsScreenRotationLocked(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("OnIsScreenRotationLocked is called"); + AsyncTask::CompleteCallback complete = + [](NativeEngine& engine, AsyncTask& task, int32_t status) { + bool isLocked = SingletonContainer::Get().IsScreenRotationLocked(); + task.Resolve(engine, CreateJsValue(engine, isLocked)); + }; + NativeValue* lastParam = nullptr; + if (info.argc >= ARGC_ONE && info.argv[ARGC_ONE - 1] != nullptr && + info.argv[ARGC_ONE - 1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[ARGC_ONE - 1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnIsScreenRotationLocked", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* OnSetScreenRotationLocked(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("JsScreenManager::OnSetScreenRotationLocked is called"); + DmErrorCode errCode = DmErrorCode::DM_OK; + if (info.argc < ARGC_ONE) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } + bool isLocked = false; + if (errCode == DmErrorCode::DM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isLocked"); + errCode = DmErrorCode::DM_ERROR_INVALID_PARAM; + } else { + isLocked = static_cast(*nativeVal); + } + } + if (errCode == DmErrorCode::DM_ERROR_INVALID_PARAM) { + WLOGFE("JsScreenManager::OnSetScreenRotationLocked failed, Invalidate params."); + engine.Throw(CreateJsError(engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AsyncTask::CompleteCallback complete = + [isLocked](NativeEngine& engine, AsyncTask& task, int32_t status) { + SingletonContainer::Get().SetScreenRotationLocked(isLocked); + task.Resolve(engine, engine.CreateUndefined()); + }; + NativeValue* lastParam = (info.argc <= ARGC_ONE) ? nullptr : + ((info.argv[ARGC_TWO - 1] != nullptr && info.argv[ARGC_TWO - 1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsScreenManager::OnSetScreenRotationLocked", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} +}; + +NativeValue* InitScreenOrientation(NativeEngine* engine) +{ + WLOGFI("JsScreenManager::InitScreenOrientation called"); + + if (engine == nullptr) { + WLOGFE("engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return nullptr; + } + + object->SetProperty("UNSPECIFIED", CreateJsValue(*engine, static_cast(Orientation::UNSPECIFIED))); + object->SetProperty("VERTICAL", CreateJsValue(*engine, static_cast(Orientation::VERTICAL))); + object->SetProperty("HORIZONTAL", CreateJsValue(*engine, static_cast(Orientation::HORIZONTAL))); + object->SetProperty("REVERSE_VERTICAL", + CreateJsValue(*engine, static_cast(Orientation::REVERSE_VERTICAL))); + object->SetProperty("REVERSE_HORIZONTAL", + CreateJsValue(*engine, static_cast(Orientation::REVERSE_HORIZONTAL))); + return objValue; +} + +NativeValue* InitDisplayErrorCode(NativeEngine* engine) +{ + WLOGFI("JsDisplayManager::InitDisplayErrorCode called"); + + if (engine == nullptr) { + WLOGFE("engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return nullptr; + } + + object->SetProperty("DM_ERROR_NO_PERMISSION", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_NO_PERMISSION))); + object->SetProperty("DM_ERROR_INVALID_PARAM", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_INVALID_PARAM))); + object->SetProperty("DM_ERROR_DEVICE_NOT_SUPPORT", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT))); + object->SetProperty("DM_ERROR_INVALID_SCREEN", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_INVALID_SCREEN))); + object->SetProperty("DM_ERROR_INVALID_CALLING", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_INVALID_CALLING))); + object->SetProperty("DM_ERROR_SYSTEM_INNORMAL", + CreateJsValue(*engine, static_cast(DmErrorCode::DM_ERROR_SYSTEM_INNORMAL))); + return objValue; +} + +NativeValue* InitDisplayError(NativeEngine* engine) +{ + WLOGFI("JsDisplayManager::InitDisplayError called"); + + if (engine == nullptr) { + WLOGFE("engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return nullptr; + } + + object->SetProperty("DM_ERROR_INIT_DMS_PROXY_LOCKED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED))); + object->SetProperty("DM_ERROR_IPC_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_IPC_FAILED))); + object->SetProperty("DM_ERROR_REMOTE_CREATE_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_REMOTE_CREATE_FAILED))); + object->SetProperty("DM_ERROR_NULLPTR", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_NULLPTR))); + object->SetProperty("DM_ERROR_INVALID_PARAM", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INVALID_PARAM))); + object->SetProperty("DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED))); + object->SetProperty("DM_ERROR_DEATH_RECIPIENT", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_DEATH_RECIPIENT))); + object->SetProperty("DM_ERROR_INVALID_MODE_ID", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INVALID_MODE_ID))); + object->SetProperty("DM_ERROR_WRITE_DATA_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_WRITE_DATA_FAILED))); + object->SetProperty("DM_ERROR_RENDER_SERVICE_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_RENDER_SERVICE_FAILED))); + object->SetProperty("DM_ERROR_UNREGISTER_AGENT_FAILED", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_UNREGISTER_AGENT_FAILED))); + object->SetProperty("DM_ERROR_INVALID_CALLING", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_INVALID_CALLING))); + object->SetProperty("DM_ERROR_UNKNOWN", + CreateJsValue(*engine, static_cast(DMError::DM_ERROR_UNKNOWN))); + return objValue; +} + +NativeValue* JsScreenManagerInit(NativeEngine* engine, NativeValue* exportObj) +{ + WLOGFI("JsScreenManagerInit is called"); + + if (engine == nullptr || exportObj == nullptr) { + WLOGFE("JsScreenManagerInit engine or exportObj is nullptr"); + return nullptr; + } + + NativeObject* object = ConvertNativeValueTo(exportObj); + if (object == nullptr) { + WLOGFE("JsScreenManagerInit object is nullptr"); + return nullptr; + } + + std::unique_ptr jsScreenManager = std::make_unique(engine); + object->SetNativePointer(jsScreenManager.release(), JsScreenManager::Finalizer, nullptr); + + object->SetProperty("Orientation", InitScreenOrientation(engine)); + object->SetProperty("DmErrorCode", InitDisplayErrorCode(engine)); + object->SetProperty("DMError", InitDisplayError(engine)); + + const char *moduleName = "JsScreenManager"; + BindNativeFunction(*engine, *object, "getAllScreens", moduleName, JsScreenManager::GetAllScreens); + BindNativeFunction(*engine, *object, "on", moduleName, JsScreenManager::RegisterScreenManagerCallback); + BindNativeFunction(*engine, *object, "off", moduleName, JsScreenManager::UnregisterScreenMangerCallback); + BindNativeFunction(*engine, *object, "makeMirror", moduleName, JsScreenManager::MakeMirror); + BindNativeFunction(*engine, *object, "makeExpand", moduleName, JsScreenManager::MakeExpand); + BindNativeFunction(*engine, *object, "createVirtualScreen", moduleName, JsScreenManager::CreateVirtualScreen); + BindNativeFunction(*engine, *object, "destroyVirtualScreen", moduleName, JsScreenManager::DestroyVirtualScreen); + BindNativeFunction(*engine, *object, "setVirtualScreenSurface", moduleName, + JsScreenManager::SetVirtualScreenSurface); + BindNativeFunction(*engine, *object, "setScreenRotationLocked", moduleName, + JsScreenManager::SetScreenRotationLocked); + BindNativeFunction(*engine, *object, "isScreenRotationLocked", moduleName, + JsScreenManager::IsScreenRotationLocked); + return engine->CreateUndefined(); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.h b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.h new file mode 100644 index 0000000..ce56b7e --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/js_screen_manager.h @@ -0,0 +1,28 @@ +/* + * 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_SCREEN_MANAGER_H +#define OHOS_JS_SCREEN_MANAGER_H + +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" + +namespace OHOS { +namespace Rosen { +NativeValue* JsScreenManagerInit(NativeEngine* engine, NativeValue* exportObj); +} // namespace Rosen +} // namespace OHOS + +#endif diff --git a/window_manager/interfaces/kits/napi/screen_runtime/napi/screen_manager_module.cpp b/window_manager/interfaces/kits/napi/screen_runtime/napi/screen_manager_module.cpp new file mode 100644 index 0000000..7a76af1 --- /dev/null +++ b/window_manager/interfaces/kits/napi/screen_runtime/napi/screen_manager_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_screen_manager.h" +#include "native_engine/native_engine.h" + +extern "C" __attribute__((constructor)) void NAPI_application_screenmanager_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "screen", + .fileName = "module/libscreen_napi.so/screen.js", + .registerCallback = OHOS::Rosen::JsScreenManagerInit, + }; + + moduleManager->Register(&newModuleInfo); +} diff --git a/window_manager/interfaces/kits/napi/screenshot/BUILD.gn b/window_manager/interfaces/kits/napi/screenshot/BUILD.gn new file mode 100644 index 0000000..9ec0d4f --- /dev/null +++ b/window_manager/interfaces/kits/napi/screenshot/BUILD.gn @@ -0,0 +1,40 @@ +# 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. + +import("//build/ohos.gni") + +## Build screenshot.so {{{ +ohos_shared_library("screenshot") { + sources = [ "native_screenshot_module.cpp" ] + + configs = [ + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "../common:dm_napi_common", + "//foundation/window/window_manager/dm:libdm", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "multimedia_image_framework:image", + "multimedia_image_framework:image_native", + "napi:ace_napi", + ] + + relative_install_dir = "module" + part_name = "window_manager" + subsystem_name = "window" +} +## Build screenshot.so }}} diff --git a/window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.cpp b/window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.cpp new file mode 100644 index 0000000..d99c131 --- /dev/null +++ b/window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.cpp @@ -0,0 +1,346 @@ +/* + * 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 "native_screenshot_module.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "display_manager.h" +#include "pixel_map.h" +#include "pixel_map_napi.h" +#include "window_manager_hilog.h" +#include "dm_common.h" +#include "dm_napi_common.h" + +namespace OHOS::Rosen { +namespace save { +struct Option { + Media::Rect rect; + Media::Size size; + int rotation = 0; + DisplayId displayId = 0; +}; + +struct Param { + DmErrorCode wret; + Option option; + std::string errMessage; + bool useInputOption; + bool validInputParam; + std::shared_ptr image; +}; + +static napi_valuetype GetType(napi_env env, napi_value root) +{ + napi_valuetype res = napi_undefined; + napi_typeof(env, root, &res); + return res; +} + +static void GetDisplayId(napi_env env, std::unique_ptr ¶m, napi_value &argv) +{ + GNAPI_LOG("Get Screenshot Option: GetDisplayId"); + napi_value displayId; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "displayId", &displayId)); + if (displayId != nullptr && GetType(env, displayId) == napi_number) { + int64_t dispId; + NAPI_CALL_RETURN_VOID(env, napi_get_value_int64(env, displayId, &dispId)); + param->option.displayId = static_cast(dispId); + GNAPI_LOG("GetDisplayId success, displayId = %{public}" PRIu64"", param->option.displayId); + } else { + GNAPI_LOG("GetDisplayId failed, invalid param, use default displayId = 0"); + } +} + +static void GetRotation(napi_env env, std::unique_ptr ¶m, napi_value &argv) +{ + GNAPI_LOG("Get Screenshot Option: GetRotation"); + napi_value rotation; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "rotation", &rotation)); + if (rotation != nullptr && GetType(env, rotation) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, rotation, ¶m->option.rotation)); + GNAPI_LOG("GetRotation success, rotation = %{public}d", param->option.rotation); + } else { + GNAPI_LOG("GetRotation failed, invalid param, use default rotation = 0"); + } +} + +static void GetScreenRect(napi_env env, std::unique_ptr ¶m, napi_value &argv) +{ + GNAPI_LOG("Get Screenshot Option: GetScreenRect"); + napi_value screenRect; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "screenRect", &screenRect)); + if (screenRect != nullptr && GetType(env, screenRect) == napi_object) { + GNAPI_LOG("get ScreenRect success"); + + napi_value left; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, screenRect, "left", &left)); + if (left != nullptr && GetType(env, left) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, left, ¶m->option.rect.left)); + GNAPI_LOG("get ScreenRect.left success, left = %{public}d", param->option.rect.left); + } else { + GNAPI_LOG("get ScreenRect.left failed, invalid param, use default left = 0"); + } + + napi_value top; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, screenRect, "top", &top)); + if (top != nullptr && GetType(env, top) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, top, ¶m->option.rect.top)); + GNAPI_LOG("get ScreenRect.top success, top = %{public}d", param->option.rect.top); + } else { + GNAPI_LOG("get ScreenRect.top failed, invalid param, use default top = 0"); + } + + napi_value width; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, screenRect, "width", &width)); + if (width != nullptr && GetType(env, width) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, width, ¶m->option.rect.width)); + GNAPI_LOG("get ScreenRect.width success, width = %{public}d", param->option.rect.width); + } else { + GNAPI_LOG("get ScreenRect.width failed, invalid param, use default width = 0"); + } + + napi_value height; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, screenRect, "height", &height)); + if (height != nullptr && GetType(env, height) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, height, ¶m->option.rect.height)); + GNAPI_LOG("get ScreenRect.height success, height = %{public}d", param->option.rect.height); + } else { + GNAPI_LOG("get ScreenRect.height failed, invalid param, use default height = 0"); + } + } else { + GNAPI_LOG("get ScreenRect failed, use default ScreenRect param"); + } +} + +static void GetImageSize(napi_env env, std::unique_ptr ¶m, napi_value &argv) +{ + GNAPI_LOG("Get Screenshot Option: ImageSize"); + napi_value imageSize; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, argv, "imageSize", &imageSize)); + if (imageSize != nullptr && GetType(env, imageSize) == napi_object) { + napi_value width; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, imageSize, "width", &width)); + if (width != nullptr && GetType(env, width) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, width, ¶m->option.size.width)); + GNAPI_LOG("get ImageSize.width success, width = %{public}d", param->option.size.width); + } else { + GNAPI_LOG("get ImageSize.width failed, invalid param, use default width = 0"); + } + + napi_value height; + NAPI_CALL_RETURN_VOID(env, napi_get_named_property(env, imageSize, "height", &height)); + if (height != nullptr && GetType(env, height) == napi_number) { + NAPI_CALL_RETURN_VOID(env, napi_get_value_int32(env, height, ¶m->option.size.height)); + GNAPI_LOG("get ImageSize.height success, height = %{public}d", param->option.size.height); + } else { + GNAPI_LOG("get ImageSize.height failed, invalid param, use default height = 0"); + } + } +} + +static void GetScreenshotParam(napi_env env, std::unique_ptr ¶m, napi_value &argv) +{ + if (param == nullptr) { + GNAPI_LOG("param == nullptr, use default param"); + return; + } + GetDisplayId(env, param, argv); + GetRotation(env, param, argv); + GetScreenRect(env, param, argv); + GetImageSize(env, param, argv); +} + +static void AsyncGetScreenshot(napi_env env, std::unique_ptr ¶m) +{ + if (!param->validInputParam) { + WLOGFE("Invalid Input Param!"); + param->image = nullptr; + param->wret = DmErrorCode::DM_ERROR_INVALID_PARAM; + param->errMessage = "Get Screenshot Failed: Invalid input param"; + return; + } + if (param->useInputOption) { + GNAPI_LOG("Get Screenshot by input option"); + param->image = DisplayManager::GetInstance().GetScreenshot(param->option.displayId, + param->option.rect, param->option.size, param->option.rotation); + } else { + GNAPI_LOG("Get Screenshot by default option"); + param->image = DisplayManager::GetInstance().GetScreenshot(param->option.displayId); + } + if (param->image == nullptr) { + GNAPI_LOG("Get Screenshot failed!"); + param->wret = DmErrorCode::DM_ERROR_INVALID_SCREEN; + param->errMessage = "Get Screenshot failed: Screenshot image is nullptr"; + return; + } + param->wret = DmErrorCode::DM_OK; +} + +napi_value Resolve(napi_env env, std::unique_ptr ¶m) +{ + napi_value result; + napi_value error; + napi_value code; + if (param->wret == DmErrorCode::DM_ERROR_INVALID_PARAM) { + napi_create_error(env, nullptr, nullptr, &error); + napi_create_int32(env, (int32_t)DmErrorCode::DM_ERROR_INVALID_PARAM, &code); + napi_set_named_property(env, error, "DM_ERROR_INVALID_PARAM", code); + napi_throw(env, error); + return error; + } else if (param->wret != DmErrorCode::DM_OK) { + NAPI_CALL(env, napi_get_undefined(env, &result)); + return result; + } + + GNAPI_LOG("Screenshot image Width %{public}d, Height %{public}d", + param->image->GetWidth(), param->image->GetHeight()); + napi_value jsImage = OHOS::Media::PixelMapNapi::CreatePixelMap(env, param->image); + return jsImage; +} + +napi_value MainFunc(napi_env env, napi_callback_info info) +{ + GNAPI_LOG("%{public}s called", __PRETTY_FUNCTION__); + napi_value argv[2] = {0}; // the max number of input parameters is 2 + size_t argc = 2; // the max number of input parameters is 2 + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); + + auto param = std::make_unique(); + if (param == nullptr) { + WLOGFE("Create param failed."); + return nullptr; + } + param->option.displayId = DisplayManager::GetInstance().GetDefaultDisplayId(); + napi_ref ref = nullptr; + if (argc == 0) { // 0 valid parameters + GNAPI_LOG("argc == 0"); + param->validInputParam = true; + } else if (GetType(env, argv[0]) == napi_function) { // 1 valid parameters napi_function + GNAPI_LOG("argc >= 1, argv[0]'s type is napi_function"); + param->validInputParam = true; + NAPI_CALL(env, napi_create_reference(env, argv[0], 1, &ref)); + } else if (GetType(env, argv[0]) == napi_object) { + if ((argc >= 2) && (GetType(env, argv[1]) == napi_function)) { // 2 valid parameters napi_object napi_function + GNAPI_LOG("argc >= 2, argv[0]'s type is napi_object, argv[1]'s type is napi_function"); + param->validInputParam = true; + param->useInputOption = true; + GetScreenshotParam(env, param, argv[0]); + NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &ref)); + } else { // 1 valid parameters napi_object + GNAPI_LOG("argc >= 1, argv[0]'s type is napi_object"); + param->validInputParam = true; + param->useInputOption = true; + GetScreenshotParam(env, param, argv[0]); + } + } else { // 0 valid parameters + GNAPI_LOG("argc == 0"); + param->validInputParam = true; + } + + return AsyncProcess(env, __PRETTY_FUNCTION__, AsyncGetScreenshot, Resolve, ref, param); +} +} // namespace save + +void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName) +{ + napi_value prop = nullptr; + napi_create_int32(env, objValue, &prop); + napi_set_named_property(env, dstObj, propName, prop); +} + +napi_value ScreenshotModuleInit(napi_env env, napi_value exports) +{ + GNAPI_LOG("%{public}s called", __PRETTY_FUNCTION__); + + napi_value errorCode = nullptr; + napi_value dmErrorCode = nullptr; + napi_create_object(env, &errorCode); + napi_create_object(env, &dmErrorCode); + + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_INIT_DMS_PROXY_LOCKED, "DM_ERROR_INIT_DMS_PROXY_LOCKED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_IPC_FAILED, "DM_ERROR_IPC_FAILED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_REMOTE_CREATE_FAILED, "DM_ERROR_REMOTE_CREATE_FAILED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_NULLPTR, "DM_ERROR_NULLPTR"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_INVALID_PARAM, "DM_ERROR_INVALID_PARAM"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED, "DM_ERROR_WRITE_INTERFACE_TOKEN_FAILED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_DEATH_RECIPIENT, "DM_ERROR_DEATH_RECIPIENT"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_INVALID_MODE_ID, "DM_ERROR_INVALID_MODE_ID"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_WRITE_DATA_FAILED, "DM_ERROR_WRITE_DATA_FAILED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_RENDER_SERVICE_FAILED, "DM_ERROR_RENDER_SERVICE_FAILED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_UNREGISTER_AGENT_FAILED, "DM_ERROR_UNREGISTER_AGENT_FAILED"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_INVALID_CALLING, "DM_ERROR_INVALID_CALLING"); + SetNamedProperty(env, errorCode, + (int32_t)DMError::DM_ERROR_UNKNOWN, "DM_ERROR_UNKNOWN"); + + SetNamedProperty(env, dmErrorCode, + (int32_t)DmErrorCode::DM_ERROR_NO_PERMISSION, "DM_ERROR_NO_PERMISSION"); + SetNamedProperty(env, dmErrorCode, + (int32_t)DmErrorCode::DM_ERROR_INVALID_PARAM, "DM_ERROR_INVALID_PARAM"); + SetNamedProperty(env, dmErrorCode, + (int32_t)DmErrorCode::DM_ERROR_DEVICE_NOT_SUPPORT, "DM_ERROR_DEVICE_NOT_SUPPORT"); + SetNamedProperty(env, dmErrorCode, + (int32_t)DmErrorCode::DM_ERROR_INVALID_SCREEN, "DM_ERROR_INVALID_SCREEN"); + SetNamedProperty(env, dmErrorCode, + (int32_t)DmErrorCode::DM_ERROR_INVALID_CALLING, "DM_ERROR_INVALID_CALLING"); + SetNamedProperty(env, dmErrorCode, + (int32_t)DmErrorCode::DM_ERROR_SYSTEM_INNORMAL, "DM_ERROR_SYSTEM_INNORMAL"); + + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("save", save::MainFunc), + DECLARE_NAPI_PROPERTY("DMError", errorCode), + DECLARE_NAPI_PROPERTY("DmErrorCode", dmErrorCode), + }; + + NAPI_CALL(env, napi_define_properties(env, + exports, sizeof(properties) / sizeof(properties[0]), properties)); + return exports; +} +} // namespace OHOS::Rosen + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module screenshotModule = { + .nm_version = 1, // NAPI v1 + .nm_flags = 0, // normal + .nm_filename = nullptr, + .nm_register_func = OHOS::Rosen::ScreenshotModuleInit, + .nm_modname = "screenshot", + .nm_priv = nullptr, + }; + napi_module_register(&screenshotModule); +} diff --git a/window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.h b/window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.h new file mode 100644 index 0000000..4e8b2b1 --- /dev/null +++ b/window_manager/interfaces/kits/napi/screenshot/native_screenshot_module.h @@ -0,0 +1,19 @@ +/* + * 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 NATIVE_SCREENSHOT_MODULE_H +#define NATIVE_SCREENSHOT_MODULE_H + +#endif // NATIVE_SCREENSHOT_MODULE_H diff --git a/window_manager/interfaces/kits/napi/window_extension_ability/BUILD.gn b/window_manager/interfaces/kits/napi/window_extension_ability/BUILD.gn new file mode 100644 index 0000000..bc1a859 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_extension_ability/BUILD.gn @@ -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. + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/ohos.gni") + +es2abc_gen_abc("gen_window_extension_ability_abc") { + src_js = rebase_path("window_extension_ability.js") + dst_file = rebase_path(target_out_dir + "/window_extension_ability.abc") + in_puts = [ "window_extension_ability.js" ] + out_puts = [ target_out_dir + "/window_extension_ability.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("window_extension_ability_js") { + input = "window_extension_ability.js" + output = target_out_dir + "/window_extension_ability.o" +} + +gen_js_obj("window_extension_ability_abc") { + input = get_label_info(":gen_window_extension_ability_abc", + "target_out_dir") + "/window_extension_ability.abc" + output = target_out_dir + "/window_extension_ability_abc.o" + dep = ":gen_window_extension_ability_abc" +} + +ohos_shared_library("windowextensionability_napi") { + sources = [ "window_extension_ability_module.cpp" ] + + configs = [ + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + ":window_extension_ability_abc", + ":window_extension_ability_js", + ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/application" + subsystem_name = "window" + part_name = "window_manager" +} diff --git a/window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability.js b/window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability.js new file mode 100644 index 0000000..29fd932 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability.js @@ -0,0 +1,30 @@ +/* + * 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. + */ + +class WindowExtensionAbility { + onWindowReady(window) { + console.log('WindowExtension windowReady'); + } + + onConnect(want) { + console.log('WindowExtension onConnect, want:' + want.abilityName); + } + + onDisconnect(want) { + console.log('WindowExtension onDisconnect' + want.abilityName); + } +} + +export default WindowExtensionAbility \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability_module.cpp b/window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability_module.cpp new file mode 100644 index 0000000..8625522 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_extension_ability/window_extension_ability_module.cpp @@ -0,0 +1,56 @@ +/* + * 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 "native_engine/native_engine.h" + +extern const char _binary_window_extension_ability_js_start[]; +extern const char _binary_window_extension_ability_js_end[]; +extern const char _binary_window_extension_ability_abc_start[]; +extern const char _binary_window_extension_ability_abc_end[]; + +extern "C" __attribute__((constructor)) +void NAPI_application_WindowExtensionAbility_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "application.WindowExtensionAbility", + .fileName = "application/libwindowextensionability_napi.so/window_extension_ability.js", + }; + + moduleManager->Register(&newModuleInfo); +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_application_WindowExtensionAbility_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_window_extension_ability_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_window_extension_ability_js_end - _binary_window_extension_ability_js_start; + } +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_application_WindowExtensionAbility_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_window_extension_ability_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_window_extension_ability_abc_end - _binary_window_extension_ability_abc_start; + } +} \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_extension_context/BUILD.gn b/window_manager/interfaces/kits/napi/window_extension_context/BUILD.gn new file mode 100644 index 0000000..00f25a1 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_extension_context/BUILD.gn @@ -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. + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/ohos.gni") + +es2abc_gen_abc("gen_window_extension_context_abc") { + src_js = rebase_path("window_extension_context.js") + dst_file = rebase_path(target_out_dir + "/window_extension_context.abc") + in_puts = [ "window_extension_context.js" ] + out_puts = [ target_out_dir + "/window_extension_context.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("window_extension_context_js") { + input = "window_extension_context.js" + output = target_out_dir + "/window_extension_context.o" +} + +gen_js_obj("window_extension_context_abc") { + input = get_label_info(":gen_window_extension_context_abc", + "target_out_dir") + "/window_extension_context.abc" + output = target_out_dir + "/window_extension_context_abc.o" + dep = ":gen_window_extension_context_abc" +} + +ohos_shared_library("windowextensioncontext_napi") { + sources = [ "window_extension_context_module.cpp" ] + + configs = [ + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + ":window_extension_context_abc", + ":window_extension_context_js", + ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/application" + subsystem_name = "window" + part_name = "window_manager" +} diff --git a/window_manager/interfaces/kits/napi/window_extension_context/window_extension_context.js b/window_manager/interfaces/kits/napi/window_extension_context/window_extension_context.js new file mode 100644 index 0000000..820634e --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_extension_context/window_extension_context.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +var ExtensionContext = requireNapi("application.ExtensionContext") + +class WindowExtensionContext extends ExtensionContext { + constructor(obj) { + super(obj); + } + + startAbility(want, options, callback) { + console.log("startAbility"); + return this.__context_impl__.startAbility(want, options, callback); + } +} + +export default WindowExtensionContext \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_extension_context/window_extension_context_module.cpp b/window_manager/interfaces/kits/napi/window_extension_context/window_extension_context_module.cpp new file mode 100644 index 0000000..991d05c --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_extension_context/window_extension_context_module.cpp @@ -0,0 +1,56 @@ +/* + * 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 + +extern const char _binary_window_extension_context_js_start[]; +extern const char _binary_window_extension_context_js_end[]; +extern const char _binary_window_extension_context_abc_start[]; +extern const char _binary_window_extension_context_abc_end[]; + +extern "C" __attribute__((constructor)) void NAPI_application_WindowExtensionContext_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "application.WindowExtensionContext", + .fileName = "application/libwindowextensioncontext_napi.so/WindowExtensionContext.js", + }; + + moduleManager->Register(&newModuleInfo); +} + +extern "C" __attribute__((visibility("default"))) void NAPI_application_WindowExtensionContext_GetJSCode( + const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_window_extension_context_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_window_extension_context_js_end - _binary_window_extension_context_js_start; + } +} + +// window extension context JS register +extern "C" __attribute__((visibility("default"))) void NAPI_application_WindowExtensionContext_GetABCCode( + const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_window_extension_context_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_window_extension_context_abc_end - _binary_window_extension_context_abc_start; + } +} \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_runtime/BUILD.gn b/window_manager/interfaces/kits/napi/window_runtime/BUILD.gn new file mode 100644 index 0000000..e022ada --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/BUILD.gn @@ -0,0 +1,140 @@ +# Copyright (c) 2021-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. + +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +config("window_manager_napi_config") { + visibility = [ ":*" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_napi", + "//foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/utils/include", + ] +} + +config("window_native_kit_config") { + visibility = [ ":*" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_napi", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/wmserver/include", + + # because of pixle_map.h + "//foundation/multimedia/image_framework/interfaces/innerkits/include", + ] +} + +ohos_shared_library("window_native_kit") { + sources = [ + "window_napi/js_transition_controller.cpp", + "window_napi/js_window.cpp", + "window_napi/js_window_listener.cpp", + "window_napi/js_window_register_manager.cpp", + "window_napi/js_window_utils.cpp", + ] + + configs = [ + ":window_native_kit_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "ability_runtime:dialog_request_info", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "ipc_js:rpc", + "multimedia_image_framework:image", + "multimedia_image_framework:image_native", + "napi:ace_napi", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_shared_library("window_napi") { + sources = [ + "window_manager_napi/js_window_manager.cpp", + "window_manager_napi/window_manager_module.cpp", + ] + + configs = [ + ":window_manager_napi_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + ":window_native_kit", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "ability_runtime:ability_context_native", + "ability_runtime:abilitykit_native", + "ability_runtime:runtime", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "napi:ace_napi", + ] + + relative_install_dir = "module" + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_shared_library("windowstage_kit") { + sources = [ "window_stage_napi/js_window_stage.cpp" ] + + configs = [ + ":window_native_kit_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + include_dirs = [ "//foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi" ] + deps = [ + ":window_native_kit", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "ability_runtime:runtime", + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "napi:ace_napi", + ] + + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts b/window_manager/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts new file mode 100644 index 0000000..39c76a5 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts @@ -0,0 +1,1393 @@ +/* +* Copyright (c) 2021-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. +*/ +import { AsyncCallback, Callback } from './basic' ; +import { Context } from './app/context'; +import { ContenStorage } from './@internal/component/ets/stateManagement' +import image from './@ohos.multimedia.image'; +import rpc from './@ohos.rpc' + +/** + * Window manager. + * @syscap SystemCapability.WindowManager.WindowManager.Core +*/ +declare namespace window { + /** + * Describes the window manager error code + * @since 7 + * @deprecated since 9 + */ + enum WMError { + WM_DO_NOTHING, + WM_ERROR_NO_MEM, + WM_ERROR_DESTROYED_OBJECT, + WM_ERROR_INVALID_WINDOW, + WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE, + WM_ERROR_INVALID_OPERATION, + WM_ERROR_INVALID_PERMISSION, + WM_ERROR_NO_REMOTE_ANIMATION, + WM_ERROR_DEVICE_NOT_SUPPORT, + WM_ERROR_NULLPTR, + WM_ERROR_INVALID_TYPE, + WM_ERROR_INVALID_PARAM, + WM_ERROR_SAMGR, + WM_ERROR_IPC_FAILED, + } + + /** + * Describes the window manager error code + * @since 9 + */ + enum WmErrorCode { + WM_ERROR_NO_PERMISSION, + WM_ERROR_INVALID_PARAM, + WM_ERROR_DEVICE_NOT_SUPPORT, + WM_ERROR_REPEAT_OPERATION, + WM_ERROR_STATE_ABNORMALLY, + WM_ERROR_SYSTEM_ABNORMALLY, + WM_ERROR_INVALID_CALLING, + } + + /** + * The type of a window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + */ + enum WindowType { + /** + * App. + */ + TYPE_APP, + /** + * System alert. + */ + TYPE_SYSTEM_ALERT, + /** + * Input method. + */ + TYPE_INPUT_METHOD, + /** + * Status bar. + */ + TYPE_STATUS_BAR, + /** + * Notification hubs. + */ + TYPE_PANEL, + /** + * Screen lock. + */ + TYPE_KEYGUARD, + /** + * Volume bar. + */ + TYPE_VOLUME_OVERLAY, + /** + * Navigation bar. + */ + TYPE_NAVIGATION_BAR, + /** + * Dialog window. + */ + TYPE_DIALOG, + + /** + * System gesture. + */ + TYPE_SYSTEM_GESTURE, + } + + /** + * Describes the type of avoid area + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + enum AvoidAreaType { + /** + * Default area of the system + */ + TYPE_SYSTEM, + + /** + * Notch + */ + TYPE_CUTOUT, + + /** + * area for system gesture + */ + TYPE_SYSTEM_GESTURE, + + /** + * area for soft input keyboard + * @since 9 + */ + TYPE_KEYBOARD + } + + /** + * Describes the scale Transition Options of window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + * @systemapi + */ + declare interface ScaleOptions { + /** + * The scale param of x direction. Default is 1.f + */ + x?: number; + /** + * The scale param of y direction. Default is 1.f + */ + y?: number; + /** + * The scale param of pivot point of x. Default is 0.5f, Interval is 0.f - 1.f + */ + pivotX?: number; + /** + * The scale param of pivot point of y. Default is 0.5f, Interval is 0.f - 1.f + */ + pivotY?: number; + } + + /** + * Describes the rotate Transition Options of window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + * @systemapi + */ + declare interface RotateOptions { + /** + * The rotate degree of x direction. Default value is 0.f + */ + x?: number; + /** + * The rotate degree of y direction. Default value is 0.f + */ + y?: number; + /** + * The rotate degree of z direction. Default value is 0.f + */ + z?: number; + /** + * The param of pivot point of x. Default is 0.5f, Interval is 0.f - 1.f + */ + pivotX?: number; + /** + * The param of pivot point of y. Default is 0.5f, Interval is 0.f - 1.f + */ + pivotY?: number; + } + + /** + * Describes the translate Transition Options of window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + * @systemapi + */ + declare interface TranslateOptions { + /** + * The translate pixel param of x direction. Default is 0.f + */ + x?: number; + /** + * The translate pixel param of y direction. Default is 0.f + */ + y?: number; + /** + * The translate pixel param of z direction. Default is 0.f + */ + z?: number; + } + + /** + * Describes the window mode of an application + * @systemapi Hide this for inner system use. + * @since 7 + */ + enum WindowMode { + UNDEFINED = 1, + FULLSCREEN, + PRIMARY, + SECONDARY, + FLOATING + } + + /** + * Describes the mode of window layout + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi Hide this for inner system use. + * @since 9 + */ + enum WindowLayoutMode { + /** + * CASCADE + * @systemapi Hide this for inner system use. + * @since 9 + */ + WINDOW_LAYOUT_MODE_CASCADE, + /** + * TILE + * @systemapi Hide this for inner system use. + * @since 9 + */ + WINDOW_LAYOUT_MODE_TILE + } + + /** + * Create a sub window with a specific id and type. + * @param id Indicates window id. + * @param type Indicates window type. + * @since 7 + */ + function create(id: string, type: WindowType, callback: AsyncCallback): void; + + /** + * Create a sub window with a specific id and type. + * @param id Indicates window id. + * @param type Indicates window type. + * @since 7 + */ + function create(id: string, type: WindowType): Promise; + + /** + * Create a system window with a specific id and type. + * @param ctx Indicates the context on which the window depends + * @param id Indicates window id. + * @param type Indicates window type. + * @systemapi Hide this for inner system use. + * @since 8 + */ + function create(ctx: Context, id: string, type: WindowType): Promise; + + /** + * Find the window by id. + * @param id Indicates window id. + * @since 7 + */ + function find(id: string, callback: AsyncCallback): void; + + /** + * Find the window by id. + * @param id Indicates window id. + * @since 7 + */ + function find(id: string): Promise; + + /** + * Get the final show window. + * @param id Indicates window id. + * @since 6 + */ + function getTopWindow(callback: AsyncCallback): void; + + /** + * Get the final show window. + * @since 6 + */ + function getTopWindow(): Promise; + + /** + * Get the final show window. + * @param ctx Indicates the context on which the window depends + * @since 8 + */ + function getTopWindow(ctx: Context): Promise; + + /** + * Get the final show window. + * @param ctx Indicates the context on which the window depends + * @since 8 + */ + function getTopWindow(ctx: Context, callback: AsyncCallback): void; + + /** + * minimize all app windows. + * @systemapi Hide this for inner system use. + * @since 8 + */ + function minimizeAll(id: number, callback: AsyncCallback): void; + + /** + * minimize all app windows. + * @systemapi Hide this for inner system use. + * @since 8 + */ + function minimizeAll(id: number): Promise; + + /** + * Toggle shown state for all app windows. Minimize or restore all app windows. + * @systemapi Minimize or restore all app windows for inner system use. + * @since 9 + */ + function toggleShownStateForAllAppWindows(callback: AsyncCallback): void; + + /** + * Toggle shown state for all app windows. Minimize or restore all app windows. + * @systemapi Minimize or restore all app windows for inner system use. + * @since 9 + */ + function toggleShownStateForAllAppWindows(): Promise; + + /** + * Set the layout mode of a window. + * @param mode the layout mode of a window. + * @systemapi Hide this for inner system use. + * @since 9 + */ + function setWindowLayoutMode(mode: WindowLayoutMode, callback: AsyncCallback): void; + + /** + * Set the layout mode of a window. + * @param mode the layout mode of a window. + * @systemapi Hide this for inner system use. + * @since 9 + */ + function setWindowLayoutMode(mode: WindowLayoutMode): Promise; + + /** + * register the callback of systemBarTintChange + * @param type: 'systemBarTintChange' + * @systemapi Hide this for inner system use. + * @since 8 + */ + function on(type: 'systemBarTintChange', callback: Callback): void; + + /** + * register the callback of keyboardHeightChange + * @param type: 'keyboardHeightChange' + * @since 7 + */ + function on(type: 'keyboardHeightChange', callback: Callback): void; + + /** + * unregister the callback of systemBarTintChange + * @param type: 'systemBarTintChange' + * @systemapi Hide this for inner system use. + * @since 8 + */ + function off(type: 'systemBarTintChange', callback?: Callback): void; + + + /** + * unregister the callback of keyboardHeightChange + * @param type: 'keyboardHeightChange' + * @since 7 + */ + function off(type: 'keyboardHeightChange', callback?: Callback): void; + + /** + * Properties of status bar and navigation bar, it couldn't update automatically + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + interface SystemBarProperties { + /** + * the color of the status bar. + * @since 6 + */ + statusBarColor?: string; + + /** + * the light icon of the status bar. + * @since 7 + */ + isStatusBarLightIcon?: boolean; + + /** + * the content color of the status bar + * @since 8 + */ + statusBarContentColor?: string; + + /** + * the color of the navigation bar. + * @since 6 + */ + navigationBarColor?: string; + + /** + * the light icon of the navigation bar. + * @since 7 + */ + isNavigationBarLightIcon?: boolean; + + /** + * the content color of the navigation bar + * @since 8 + */ + navigationBarContentColor?: string; + } + + /** + * system bar tint of region + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi Hide this for inner system use. + * @since 8 + */ + interface SystemBarRegionTint { + /** + * system bar type + */ + type: WindowType; + + /** + * the visibility of system bar + */ + isEnable?: boolean; + + /** + * the region of system bar + */ + region?: Rect; + + /** + * the background color of the system bar. + */ + backgroundColor?: string; + + /** + * the content color of the system bar. + */ + contentColor?: string + } + + /** + * system bar tint state for systemui + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi Hide this for inner system use. + * @since 8 + */ + interface SystemBarTintState { + /** + * id of display + */ + displayId: number; + /** + * region tint of systembar + */ + regionTint: Array; + } + + /** + * Rectangle + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + interface Rect { + left: number; + + top: number; + + width: number; + + height: number; + } + + /** + * avoid area + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + interface AvoidArea { + /** + * Whether avoidArea is visible on screen + * @since 9 + */ + visible: boolean; + + /** + * Rectangle on the left of the screen + */ + leftRect: Rect; + + /** + * Rectangle on the top of the screen + */ + topRect: Rect; + + /** + * Rectangle on the right of the screen + */ + rightRect: Rect; + + /** + * Rectangle on the bottom of the screen + */ + bottomRect: Rect; + } + + /** + * window size + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + interface Size { + /** + * the width of the window. + */ + width: number; + + /** + * the height of the window. + */ + height: number; + } + + /** + * Properties of window, it couldn't update automatically + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + interface WindowProperties { + /** + * the position and size of the window + * @since 7 + */ + windowRect: Rect; + + /** + * window type + * @since 7 + */ + type: WindowType; + + /** + * window name + * @since 8 + */ + name: string; + + /** + * Whether the window is displayed in full screen mode. The default value is false. + * @since 6 + */ + isFullScreen: boolean + + /** + * Whether the window layout is in full screen mode(whether the window is immersive). The default value is false. + * @since 6 + */ + isLayoutFullScreen: boolean + + /** + * Whether the window can gain focus. The default value is true + * @since 7 + */ + focusable: boolean + + /** + * Whether the window is touchable. The default value is false + * @since 6 + */ + touchable: boolean + + + /** + * Brightness value of window. + * @since 7 + */ + brightness: number + + /** + * The dimbehind value of window. + * @since 7 + */ + dimBehindValue: number + + /** + * Whether keep screen on. + * @since 7 + */ + isKeepScreenOn: boolean + + /** + * Whether make window in privacy mode or not. + * @since 7 + */ + isPrivacyMode: boolean + + /** + * Whether is round corner or not. + * @since 7 + */ + isRoundCorner: boolean + + /** + * Whether is transparent or not. + * @since 7 + */ + isTransparent: boolean + } + + /** + * Type of allowing the specified of color space. + * @since 8 + */ + enum ColorSpace { + /** + * Default color space. + */ + DEFAULT, + /** + * Wide gamut color space. The specific wide color gamut depends on thr screen. + */ + WIDE_GAMUT, + } + + interface Window { + /** + * hide sub window. + * @systemapi Hide this for inner system use. + * @since 7 + */ + hide (callback: AsyncCallback): void; + + /** + * hide sub window. + * @systemapi Hide this for inner system use. + * @since 7 + */ + hide(): Promise; + + /** + * hide window with animation. + * @since 9 + * @systemapi + */ + hideWithAnimation(callback: AsyncCallback): void; + + /** + * hide window with animation. + * @since 9 + * @systemapi + */ + hideWithAnimation(): Promise; + + /** + * show sub window. + * @since 7 + */ + show(callback: AsyncCallback): void; + + /** + * show window. + * @since 7 + */ + show(): Promise; + + /** + * show window with animation. + * @since 9 + * @systemapi + */ + showWithAnimation(callback: AsyncCallback): void; + + /** + * show window with animation. + * @since 9 + * @systemapi + */ + showWithAnimation(): Promise; + + /** + * Destroy the sub window. + * @since 7 + */ + destroy(callback: AsyncCallback): void; + + /** + * Destroy the sub window. + * @since 7 + */ + destroy(): Promise; + + /** + * Set the position of a window. + * @param x Indicate the X-coordinate of the window. + * @param y Indicate the Y-coordinate of the window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + moveTo(x: number, y: number): Promise; + + /** + * Set the position of a window. + * @param x Indicate the X-coordinate of the window. + * @param y Indicate the Y-coordinate of the window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + moveTo(x: number, y: number, callback: AsyncCallback): void; + + /** + * Set the size of a window . + * @param width Indicates the width of the window. + * @param height Indicates the height of the window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + resize(width: number, height: number): Promise; + + /** + * Set the size of a window . + * @param width Indicates the width of the window. + * @param height Indicates the height of the window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + resize(width: number, height: number, callback: AsyncCallback): void; + + /** + * Set the type of a window. + * @param windowType Indicate the type of a window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + setWindowType(windowType: WindowType): Promise; + + /** + * Set the type of a window. + * @param windowType Indicate the type of a window. + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + setWindowType(windowType: WindowType, callback: AsyncCallback): void; + + /** + * get the properties of current window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + getProperties(callback: AsyncCallback): void; + + /** + * get the properties of current window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + getProperties(): Promise; + + /** + * get the avoid area + * @param type Type of the area + * @since 7 + */ + getAvoidArea(type: AvoidAreaType, callback: AsyncCallback): void; + + /** + * get the avoid area + * @param type Type of the area + * @since 7 + */ + getAvoidArea(type: AvoidAreaType): Promise; + + /** + * set the flag of the window is shown full screen + * @param isFullScreen the flag of the window is shown full screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + setFullScreen(isFullScreen: boolean, callback: AsyncCallback): void; + + /** + * set the flag of the window is shown full screen + * @param isFullScreen the flag of the window is shown full screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + setFullScreen(isFullScreen: boolean): Promise; + + /** + * set the property of the window can layout in full screen + * @param isLayoutFullScreen the window can layout in full screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + setLayoutFullScreen(isLayoutFullScreen: boolean, callback: AsyncCallback): void; + + /** + * set the property of the window can layout in full screen + * @param isLayoutFullScreen the window can layout in full screen + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + setLayoutFullScreen(isLayoutFullScreen: boolean): Promise; + + /** + * set the system bar to have visible. + * @param names the set of system bar + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + setSystemBarEnable(names: Array<'status'|'navigation'>, callback: AsyncCallback): void; + + /** + * set the system bar to have visible. + * @param names the set of system bar + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + setSystemBarEnable(names: Array<'status'|'navigation'>): Promise; + + /** + * set the background color of statusbar + * @param color the background color of statusbar + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + setSystemBarProperties(systemBarProperties: SystemBarProperties, callback: AsyncCallback): void; + + /** + * set the background color of statusbar + * @param color the background color of statusbar + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 6 + */ + setSystemBarProperties(systemBarProperties: SystemBarProperties): Promise; + + /** + * Loads content + * @param path path Path of the page to which the content will be loaded + * @param storage storage The data object shared within the content instance loaded by the window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 8 + */ + loadContent(path: string, storage: ContenStorage, callback: AsyncCallback): void; + + /** + * Loads content + * @param path path of the page to which the content will be loaded + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + loadContent(path: string, callback: AsyncCallback): void; + + /** + * Loads content + * @param path path of the page to which the content will be loaded + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + loadContent(path: string, storage?: ContenStorage): Promise; + + /** + * register the callback of windowSizeChange + * @param type: 'windowSizeChange' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + on(type: 'windowSizeChange', callback: Callback): void; + + /** + * unregister the callback of windowSizeChange + * @param type: 'windowSizeChange' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + */ + off(type: 'windowSizeChange', callback?: Callback): void; + + /** + * register the callback of systemAvoidAreaChange + * @param type: 'systemAvoidAreaChange' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + * @deprecated since 9, please use on_avoidAreaChange instead. + */ + on(type: 'systemAvoidAreaChange', callback: Callback): void; + + /** + * unregister the callback of systemAvoidAreaChange + * @param type: 'systemAvoidAreaChange' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 7 + * @deprecated since 9, please use off_avoidAreaChange instead. + */ + off(type: 'systemAvoidAreaChange', callback?: Callback): void; + + /** + * register the callback of avoidAreaChange + * @param type: 'avoidAreaChange' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + on(type: 'avoidAreaChange', callback: Callback<{ type: AvoidAreaType, area: AvoidArea }>): void; + + /** + * unregister the callback of avoidAreaChange + * @param type: 'avoidAreaChange' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + off(type: 'avoidAreaChange', callback?: Callback<{ type: AvoidAreaType, area: AvoidArea }>): void; + + /** + * register the callback of screenshotEvent, only the focused window called back + * @param type: 'screenshotEvent' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + on(type: 'screenshotEvent', callback: Callback): void; + + /** + * unregister the callback of screenshotEvent + * @param type: 'screenshotEvent' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + off(type: 'screenshotEvent', callback?: Callback): void; + + /** + * register the callback of dialogTargetTouch + * @param type: 'dialogTargetTouch' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + on(type: 'dialogTargetTouch', callback: Callback): void; + + /** + * unregister the callback of dialogTargetTouch + * @param type: 'dialogTargetTouch' + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + off(type: 'dialogTargetTouch', callback?: Callback): void; + + /** + * bind dialog to the target window. + * @param token token of the target window. + * @param deathCallback the callback of dialogDeath. + * @systemapi + * @since 9 + */ + bindDialogTarget(token: rpc.RemoteObject, deathCallback: Callback): Promise; + + /** + * bind dialog to the target window. + * @param token token of the target window. + * @param deathCallback the callback of dialogDeath. + * @systemapi + * @since 9 + */ + bindDialogTarget(token: rpc.RemoteObject, deathCallback: Callback, callback: AsyncCallback); + + /** + * Whether the window supports thr wide gamut setting. + * @since 8 + */ + isSupportWideGamut(): Promise; + + /** + * Whether the window supports thr wide gamut setting. + * @since 8 + */ + isSupportWideGamut(callback: AsyncCallback): void; + + /** + * Sets the specified color space. + * @param colorSpace the specified color space. + * @since 8 + */ + setColorSpace(colorSpace:ColorSpace): Promise; + + /** + * Sets the specified color space. + * @param colorSpace the specified color space. + * @since 8 + */ + setColorSpace(colorSpace:ColorSpace, callback: AsyncCallback): void; + + /** + * Obtains thr set color space. + * @since 8 + */ + getColorSpace(): Promise; + + /** + * Obtains thr set color space. + * @since 8 + */ + getColorSpace(callback: AsyncCallback): void; + + /** + * Sets the background color of window. + * @param color the specified color. + * @since 7 + */ + setBackgroundColor(color: string): Promise; + + /** + * Sets the background color of window. + * @param color the specified color. + * @since 7 + */ + setBackgroundColor(color: string, callback: AsyncCallback): void; + + /** + * Sets the brightness of window. + * @param brightness the specified brightness value. + * @since 7 + */ + setBrightness(brightness: number): Promise; + + /** + * Sets the brightness of window. + * @param brightness the specified brightness value. + * @since 7 + */ + setBrightness(brightness: number, callback: AsyncCallback): void; + + /** + * Sets the dimBehind of window. + * @param dimBehindValue the specified dimBehind. + * @since 7 + */ + setDimBehind(dimBehindValue: number, callback: AsyncCallback): void; + + /** + * Sets the dimBehind of window. + * @param dimBehind the specified dimBehind. + * @since 7 + */ + setDimBehind(dimBehindValue: number): Promise; + + /** + * Sets whether focusable or not. + * @param isFocusable can be focus if true, or can not be focus if false. + * @since 7 + */ + setFocusable(isFocusable: boolean): Promise; + + /** + * Sets whether focusable or not. + * @param isFocusable can be focus if true, or can not be focus if false. + * @since 7 + */ + setFocusable(isFocusable: boolean, callback: AsyncCallback): void; + + /** + * Sets whether keep screen on or not. + * @param isKeepScreenOn keep screen on if true, or not if false. + * @since 7 + */ + setKeepScreenOn(isKeepScreenOn: boolean): Promise; + + /** + * Sets whether keep screen on or not. + * @param isKeepScreenOn keep screen on if true, or not if false. + * @since 7 + */ + setKeepScreenOn(isKeepScreenOn: boolean, callback: AsyncCallback): void; + + /** + * Sets whether outside can be touch or not. + * @param touchable outside can be touch if true, or not if false. + * @since 7 + */ + setOutsideTouchable(touchable: boolean): Promise; + + /** + * Sets whether outside can be touch or not. + * @param touchable outside can be touch if true, or not if false. + * @since 7 + */ + setOutsideTouchable(touchable: boolean, callback: AsyncCallback): void; + + /** + * Sets whether is private mode or not. + * @param isPrivacyMode in private mode if true, or not if false. + * @since 7 + */ + setPrivacyMode(isPrivacyMode: boolean): Promise; + + /** + * Sets whether is private mode or not. + * @param isPrivacyMode in private mode if true, or not if false. + * @since 7 + */ + setPrivacyMode(isPrivacyMode: boolean, callback: AsyncCallback): void; + + /** + * Sets whether is touchable or not. + * @param isTouchable is touchable if true, or not if false. + * @since 7 + */ + setTouchable(isTouchable: boolean): Promise; + + /** + * Sets whether is touchable or not. + * @param isTouchable is touchable if true, or not if false. + * @since 7 + */ + setTouchable(isTouchable: boolean, callback: AsyncCallback): void; + + /** + * Sets whether is transparent or not. + * @param isTransparent is transparent if true, or not if false. + * @since 7 + */ + setTransparent(isTransparent: boolean): Promise; + + /** + * Sets whether is transparent or not. + * @param isTransparent is transparent if true, or not if false. + * @since 7 + */ + setTransparent(isTransparent: boolean, callback: AsyncCallback): void; + + /** + * Set the preferred orientation config of a window + * @param orientation the orientation config of a window + * @since 9 + */ + setPreferredOrientation(orientation: Orientation): Promise; + + /** + * Set the preferred orientation config of a window + * @param orientation the orientation config of a window + * @since 9 + */ + setPreferredOrientation(orientation: Orientation, callback: AsyncCallback): void; + + /** + * disable window decoration. It must be called before loadContent. + * @systemapi + * @since 9 + */ + disableWindowDecor(): void; + + /** + * Dump window client information. + * Called in the dump callback of ability is the typical usage scenario. + * @since 9 + * @param params Indicates the params from command. + * @return The dump info array. + */ + dump(params: Array): Array; + + /** + * set the flag of the window is forbidden to move in split screen mode + * @param isForbidSplitMove the flag of the window is forbidden to move in split screen mode + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi + * @since 9 + */ + setForbidSplitMove(isForbidSplitMove: boolean, callback: AsyncCallback): void; + + /** + * set the flag of the window is forbidden to move in split screen mode + * @param isForbidSplitMove the flag of the window is forbidden to move in split screen mode + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi + * @since 9 + */ + setForbidSplitMove(isForbidSplitMove: boolean): Promise; + /** + * Sets opacity of window + * @param opacity Interval is 0.f-1.f. + * @systemapi + * @since 9 + */ + opacity(opacity: number): void; + /** + * Sets scale options of window. + * @param scaleOptions scale param of window. + * @systemapi + * @since 9 + */ + scale(scaleOptions: ScaleOptions): void; + /** + * Sets rotate options of window. + * @param rotateOptions rotate param of window. + * @systemapi + * @since 9 + */ + setRotateSync(rotateOptions: RotateOptions): void; + /** + * Sets whether is transparent or not. + * @param translateOptions translate param of window. + * @systemapi + * @since 9 + */ + setTranslateSync(translateOptions: TranslateOptions): void; + /** + * Get Transition Controller. + * @systemapi + * @since 9 + */ + getTransitionControllerSync(): TransitionController; + + /** + * Obtains snapshot of window + * @syscap SystemCapability.WindowManager.WindowManager.Cor + * @since 9 + */ + snapshot(callback: AsyncCallback): void; + + /** + * Obtains snapshot of window + * @syscap SystemCapability.WindowManager.WindowManager.Co + * @since 9 + */ + snapshot(): Promise; + } + /** + * Transition Context + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systempi + * @since 9 + */ + interface TransitionContext { + /** + * The target window with animation + */ + toWindow: Window + /** + * Set complete state of animation transition + * @param isCompleted is Completed if true, or not if false. + */ + completeTransition(isCompleted: boolean): void; + } + + /** + * Transition Controller + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systempi + * @since 9 + */ + interface TransitionController { + /** + * Animation configuration when showing window + * @param context transition Context. + */ + animationForShown(context: TransitionContext): void; + /** + * Animation configuration when hiding window + * @param context transition context. + */ + animationForHidden(context: TransitionContext): void; + } + + enum WindowStageEventType { + FOREGROUND = 1, + ACTIVE, + INACTIVE, + BACKGROUND, + } + /** + * WindowStage + * @syscap SystemCapability.WindowManager.WindowManager.Core + */ + interface WindowStage { + /** + * Get main window of the stage. + * @since 8 + */ + getMainWindow(): Promise; + /** + * Get main window of the stage. + * @since 8 + */ + getMainWindow(callback: AsyncCallback): void; + /** + * Create sub window of the stage. + * @param name window name of sub window + * @since 8 + */ + createSubWindow(name: string): Promise; + /** + * Create sub window of the stage. + * @param name window name of sub window + * @since 8 + */ + createSubWindow(name: string, callback: AsyncCallback): void; + /** + * Get sub window of the stage. + * @since 8 + */ + getSubWindow(): Promise>; + /** + * Get sub window of the stage. + * @since 8 + */ + getSubWindow(callback: AsyncCallback>): void; + /** + * Loads content + * @param path path Path of the page to which the content will be loaded + * @param storage storage The data object shared within the content instance loaded by the window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 8 + */ + loadContent(path: string, storage: ContenStorage, callback: AsyncCallback): void; + /** + * Loads content + * @param path path of the page to which the content will be loaded + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 8 + */ + loadContent(path: string, callback: AsyncCallback): void; + /** + * Loads content + * @param path path of the page to which the content will be loaded + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 8 + */ + loadContent(path: string, storage?: ContenStorage): Promise; + /** + * get the windowmode of current window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi + * @since 8 + */ + getWindowMode(callback: AsyncCallback): void; + /** + * get the windowmode of current window + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @systemapi + * @since 8 + */ + getWindowMode(): Promise; + /** + * window stage event callback on. + * @since 8 + */ + on(eventType: 'windowStageEvent', callback: Callback): void; + /** + * window stage event callback off. + * @since 8 + */ + off(eventType: 'windowStageEvent', callback?: Callback): void; + } + + /** + * screen orientation + * @syscap SystemCapability.WindowManager.WindowManager.Core + * @since 9 + */ + enum Orientation { + UNSPECIFIED = 0, + PORTRAIT = 1, + LANDSCAPE = 2, + PORTRAIT_INVERTED = 3, + LANDSCAPE_INVERTED = 4, + AUTO_ROTATION = 5, + AUTO_ROTATION_PORTRAIT = 6, + AUTO_ROTATION_LANDSCAPE = 7, + AUTO_ROTATION_RESTRICTED = 8, + AUTO_ROTATION_PORTRAIT_RESTRICTED = 9, + AUTO_ROTATION_LANDSCAPE_RESTRICTED = 10, + LOCKED = 11, + } +} + +export default window; diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp new file mode 100644 index 0000000..eaff5b8 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.cpp @@ -0,0 +1,907 @@ +/* + * Copyright (c) 2021-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_window_manager.h" +#include +#include +#include +#include "ability_context.h" +#include "display_manager.h" +#include "dm_common.h" +#include "wm_common.h" +#include "js_window.h" +#include "js_window_utils.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +#include "window_option.h" +#include "singleton_container.h" +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowManager"}; +} + +JsWindowManager::JsWindowManager() : registerManager_(std::make_unique()) +{ +} + +JsWindowManager::~JsWindowManager() +{ +} + +void JsWindowManager::Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFI("[NAPI]Finalizer"); + std::unique_ptr(static_cast(data)); +} + +NativeValue* JsWindowManager::Create(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnCreate(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::CreateWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnCreateWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::FindWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnFindWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::FindWindowSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnFindWindowSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::MinimizeAll(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnMinimizeAll(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::ToggleShownStateForAllAppWindows(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnToggleShownStateForAllAppWindows(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::RegisterWindowManagerCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnRegisterWindowMangerCallback(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::UnregisterWindowMangerCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnUnregisterWindowManagerCallback(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::GetTopWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetTopWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::GetLastWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetLastWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowManager::SetWindowLayoutMode(NativeEngine* engine, NativeCallbackInfo* info) +{ + JsWindowManager* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowLayoutMode(*engine, *info) : nullptr; +} + +static void GetNativeContext(NativeEngine& engine, NativeValue* nativeContext, void*& contextPtr, WMError& errCode) +{ + AppExecFwk::Ability* ability = nullptr; + bool isOldApi = GetAPI7Ability(engine, ability); + WLOGFI("[NAPI]FA mode:%{public}u", isOldApi); + if (isOldApi) { + return; + } + if (nativeContext != nullptr) { + auto objContext = AbilityRuntime::ConvertNativeValueTo(nativeContext); + if (objContext == nullptr) { + WLOGFE("[NAPI]ConvertNativeValueTo Context Object failed"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + return; + } + contextPtr = objContext->GetNativePointer(); + } +} + +static uint32_t GetParentId(NativeEngine& engine) +{ + AppExecFwk::Ability* ability = nullptr; + uint32_t parentId = 0; + bool isOldApi = GetAPI7Ability(engine, ability); + if (isOldApi) { + if (ability == nullptr) { + WLOGE("[NAPI]FA mode GetAPI7Ability failed"); + return parentId; + } + auto window = ability->GetWindow(); + if (window == nullptr) { + WLOGE("[NAPI]Get mainWindow failed"); + return parentId; + } + parentId = window->GetWindowId(); + } + return parentId; +} + +static bool GetWindowTypeAndParentId(NativeEngine& engine, uint32_t& parentId, WindowType& winType, + NativeValue* nativeString, NativeValue* nativeType) +{ + NativeNumber* type = ConvertNativeValueTo(nativeType); + if (type == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to windowType"); + return false; + } + // adapt to the old version + if (static_cast(*type) >= static_cast(WindowType::SYSTEM_WINDOW_BASE)) { + winType = static_cast(static_cast(*type)); + } else { + if (static_cast(*type) >= static_cast(ApiWindowType::TYPE_BASE) && + static_cast(*type) < static_cast(ApiWindowType::TYPE_END)) { + winType = JS_TO_NATIVE_WINDOW_TYPE_MAP.at(static_cast(static_cast(*type))); + } else { + WLOGFE("[NAPI]Type %{public}u is not supported", static_cast(*type)); + return false; + } + } + AppExecFwk::Ability* ability = nullptr; + bool isOldApi = GetAPI7Ability(engine, ability); + if (isOldApi) { + if (ability == nullptr || !WindowHelper::IsSubWindow(winType)) { + WLOGE("[NAPI]FA mode GetAPI7Ability failed or type %{public}u is not subWinodw", winType); + return false; + } + auto window = ability->GetWindow(); + if (window == nullptr) { + WLOGE("[NAPI]Get mainWindow failed"); + return false; + } + parentId = window->GetWindowId(); + } else { + if (!WindowHelper::IsSystemWindow(winType)) { + WLOGFE("[NAPI]Only SystemWindow support create in stage mode, type is %{public}u", winType); + return false; + } + } + return true; +} + +static void CreateNewSystemWindowTask(void* contextPtr, sptr windowOption, + NativeEngine& engine, AsyncTask& task) +{ + WLOGFI("[NAPI]CreateSystemWindowTask"); + if (windowOption == nullptr) { + int32_t err = static_cast(WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY); + task.Reject(engine, CreateJsError(engine, err, "New window option failed")); + WLOGFE("[NAPI]New window option failed"); + return; + } + auto context = static_cast*>(contextPtr); + if (contextPtr == nullptr || context == nullptr) { + int32_t err = static_cast(WmErrorCode::WM_ERROR_CONTEXT_ABNORMALLY); + task.Reject(engine, CreateJsError(engine, err, "Context is nullptr")); + WLOGFE("[NAPI]Context is nullptr"); + return; + } + if (windowOption->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT || + windowOption->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + auto abilityContext = Context::ConvertTo(context->lock()); + if (abilityContext != nullptr) { + if (!CheckCallingPermission("ohos.permission.SYSTEM_FLOAT_WINDOW")) { + int32_t err = static_cast(WmErrorCode::WM_ERROR_NO_PERMISSION); + task.Reject(engine, CreateJsError(engine, err, "TYPE_FLOAT CheckCallingPermission failed")); + return; + } + } + } + + sptr window = Window::Create(windowOption->GetWindowName(), windowOption, context->lock()); + if (window != nullptr) { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + } else { + WLOGFE("[NAPI]Create window failed"); + int32_t err = static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + task.Reject(engine, CreateJsError(engine, err, "Create window failed")); + } +} + +static void CreateSystemWindowTask(void* contextPtr, std::string windowName, WindowType winType, + NativeEngine& engine, AsyncTask& task) +{ + WLOGFI("[NAPI]CreateSystemWindowTask"); + auto context = static_cast*>(contextPtr); + if (contextPtr == nullptr || context == nullptr) { + int32_t err = static_cast(WMError::WM_ERROR_NULLPTR); + task.Reject(engine, CreateJsError(engine, err, "Context is nullptr")); + WLOGFE("[NAPI]Context is nullptr"); + return; + } + if (winType == WindowType::WINDOW_TYPE_FLOAT || winType == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + auto abilityContext = Context::ConvertTo(context->lock()); + if (abilityContext != nullptr) { + if (!CheckCallingPermission("ohos.permission.SYSTEM_FLOAT_WINDOW")) { + int32_t err = static_cast(WMError::WM_ERROR_INVALID_PERMISSION); + task.Reject(engine, CreateJsError(engine, err, "TYPE_FLOAT CheckCallingPermission failed")); + return; + } + } + } + sptr windowOption = new(std::nothrow) WindowOption(); + if (windowOption == nullptr) { + int32_t err = static_cast(WMError::WM_ERROR_NULLPTR); + task.Reject(engine, CreateJsError(engine, err, "New window option failed")); + WLOGFE("[NAPI]New window option failed"); + return; + } + windowOption->SetWindowType(winType); + sptr window = Window::Create(windowName, windowOption, context->lock()); + if (window != nullptr) { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + } else { + WLOGFE("[NAPI]Create window failed"); + int32_t err = static_cast(WMError::WM_ERROR_NULLPTR); + task.Reject(engine, CreateJsError(engine, err, "Create window failed")); + } +} + +static void CreateNewSubWindowTask(sptr windowOption, NativeEngine& engine, AsyncTask& task) +{ + if (windowOption == nullptr) { + int32_t err = static_cast(WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY); + task.Reject(engine, CreateJsError(engine, err, "New window option failed")); + WLOGFE("[NAPI]New window option failed"); + return; + } + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + if (windowOption->GetParentId() == INVALID_WINDOW_ID) { + uint32_t parentId = GetParentId(engine); + if (!parentId) { + int32_t err = static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + task.Reject(engine, CreateJsError(engine, err, "parent window missed")); + WLOGFE("[NAPI]can not find parent window"); + return; + } + windowOption->SetParentId(parentId); + } + sptr window = Window::Create(windowOption->GetWindowName(), windowOption); + if (window != nullptr) { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + } else { + WLOGFE("[NAPI]Create window failed"); + int32_t err = static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + task.Reject(engine, CreateJsError(engine, err, "Create window failed")); + } +} + +static void CreateSubWindowTask(uint32_t parentWinId, std::string windowName, WindowType winType, + NativeEngine& engine, AsyncTask& task, bool newErrorCode = false) +{ + WLOGFI("[NAPI]CreateSubWindowTask, parent id = %{public}u", parentWinId); + sptr windowOption = new(std::nothrow) WindowOption(); + if (windowOption == nullptr) { + int32_t err = newErrorCode ? static_cast(WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY) + : static_cast(WMError::WM_ERROR_NULLPTR); + task.Reject(engine, CreateJsError(engine, err, "New window option failed")); + WLOGFE("[NAPI]New window option failed"); + return; + } + windowOption->SetWindowType(winType); + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetParentId(parentWinId); + sptr window = Window::Create(windowName, windowOption); + if (window != nullptr) { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + } else { + WLOGFE("[NAPI]Create window failed"); + int32_t err = newErrorCode ? static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY) + : static_cast(WMError::WM_ERROR_NULLPTR); + task.Reject(engine, CreateJsError(engine, err, "Create window failed")); + } +} + +NativeValue* JsWindowManager::OnCreate(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnCreate"); + NativeValue* nativeString = nullptr; + NativeValue* nativeContext = nullptr; + NativeValue* nativeType = nullptr; + NativeValue* callback = nullptr; + if (info.argc >= 2 && info.argv[0]->TypeOf() == NATIVE_STRING) { // 2: minimum params num + nativeString = info.argv[0]; + nativeType = info.argv[1]; + // 2: minimum params num + callback = (info.argc == 2) ? nullptr : + (info.argv[2]->TypeOf() == NATIVE_FUNCTION ? info.argv[2] : nullptr); // 2: index of callback + } else if (info.argc >= 3) { // 3: minimum params num + nativeContext = info.argv[0]->TypeOf() == NATIVE_OBJECT ? info.argv[0] : nullptr; + nativeString = info.argv[1]; + nativeType = info.argv[2]; // 2: index of type + // 3: minimum params num; + callback = (info.argc == 3) ? nullptr : + (info.argv[3]->TypeOf() == NATIVE_FUNCTION ? info.argv[3] : nullptr); // 3: index of callback + } + std::string windowName; + WMError errCode = WMError::WM_OK; + if (!ConvertFromJsValue(engine, nativeString, windowName)) { + WLOGFE("[NAPI]Failed to convert parameter to windowName"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + uint32_t parentId = INVALID_WINDOW_ID; + WindowType winType = WindowType::SYSTEM_WINDOW_BASE; + if (errCode == WMError::WM_OK && + !GetWindowTypeAndParentId(engine, parentId, winType, nativeString, nativeType)) { + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + void* contextPtr = nullptr; + GetNativeContext(engine, nativeContext, contextPtr, errCode); + + WLOGFI("[NAPI]Window name = %{public}s, type = %{public}u, err = %{public}d", windowName.c_str(), winType, errCode); + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params")); + return; + } + if (parentId == INVALID_WINDOW_ID) { + return CreateSystemWindowTask(contextPtr, windowName, winType, engine, task); + } else { + return CreateSubWindowTask(parentId, windowName, winType, engine, task); + } + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnCreate", engine, + CreateAsyncTaskWithLastParam(engine, callback, nullptr, std::move(complete), &result)); + return result; +} + +bool JsWindowManager::ParseConfigOption(NativeEngine& engine, NativeObject* jsObject, + WindowOption& option, void*& contextPtr) +{ + std::string windowName; + if (ParseJsValue(jsObject, engine, "name", windowName)) { + option.SetWindowName(windowName); + } else { + WLOGFE("[NAPI]Failed to convert parameter to windowName"); + return false; + } + + uint32_t winType; + if (ParseJsValue(jsObject, engine, "windowType", winType)) { + if (winType >= static_cast(ApiWindowType::TYPE_BASE) && + winType < static_cast(ApiWindowType::TYPE_END)) { + option.SetWindowType(JS_TO_NATIVE_WINDOW_TYPE_MAP.at(static_cast(winType))); + } else { + option.SetWindowType(static_cast(winType)); + } + } else { + WLOGFE("[NAPI]Failed to convert parameter to winType"); + return false; + } + if (!(WindowHelper::IsSystemWindow(option.GetWindowType()) || + WindowHelper::IsSubWindow(option.GetWindowType()))) { + WLOGFE("[NAPI]Convert parameter to invalid winType"); + return false; + } + + NativeValue* value = jsObject->GetProperty("ctx"); + if (value->TypeOf() == NATIVE_UNDEFINED) { + return true; + } + WMError errCode = WMError::WM_OK; + GetNativeContext(engine, value, contextPtr, errCode); + if (errCode != WMError::WM_OK) { + return false; + } + + int64_t displayId = static_cast(DISPLAY_ID_INVALID); + if (ParseJsValue(jsObject, engine, "displayId", displayId)) { + if (displayId < 0 || + SingletonContainer::Get().GetDisplayById(static_cast(displayId)) == nullptr) { + return false; + } + option.SetDisplayId(displayId); + } else { + return true; + } + + int64_t parentId = -1; + if (ParseJsValue(jsObject, engine, "parentId", parentId)) { + option.SetParentId(parentId); + } + + return true; +} + +NativeValue* JsWindowManager::OnCreateWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]Called"); + if (info.argc < 1) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeObject* nativeObj = ConvertNativeValueTo(info.argv[0]); + if (nativeObj == nullptr) { + WLOGFE("[NAPI]Failed to convert object to CreateWindow"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + WindowOption option; + void* contextPtr = nullptr; + if (!ParseConfigOption(engine, nativeObj, option, contextPtr)) { + WLOGFE("[NAPI]Failed to parse config"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeValue* callback = nullptr; + if (info.argc > 1) { + callback = info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr; // 1: index of callback + } + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + sptr windowOption = new WindowOption(option); + if (WindowHelper::IsSystemWindow(option.GetWindowType())) { + return CreateNewSystemWindowTask(contextPtr, windowOption, engine, task); + } + if (WindowHelper::IsSubWindow(option.GetWindowType())) { + return CreateNewSubWindowTask(windowOption, engine, task); + } + }; + + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnCreateWindow", engine, + CreateAsyncTaskWithLastParam(engine, callback, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManager::OnFindWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnFindWindow"); + std::string windowName; + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], windowName)) { + WLOGFE("[NAPI]Failed to convert parameter to windowName"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + } + WLOGFI("[NAPI]Window name = %{public}s, err = %{public}d", windowName.c_str(), errCode); + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params")); + return; + } + std::shared_ptr jsWindowObj = FindJsWindowObject(windowName); + if (jsWindowObj != nullptr && jsWindowObj->Get() != nullptr) { + WLOGFI("[NAPI]Find window: %{public}s, use exist js window", windowName.c_str()); + task.Resolve(engine, jsWindowObj->Get()); + } else { + sptr window = Window::Find(windowName); + if (window == nullptr) { + WLOGFE("[NAPI]Cannot find window: %{public}s", windowName.c_str()); + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "Cannot find window")); + } else { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + WLOGFI("[NAPI]Find window: %{public}s, create js window", windowName.c_str()); + } + } + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnFindWindow", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManager::OnFindWindowSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnFindWindowSync"); + std::string windowName; + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + if (!ConvertFromJsValue(engine, info.argv[0], windowName)) { + WLOGFE("[NAPI]Failed to convert parameter to windowName"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + WLOGFI("[NAPI]Window name = %{public}s, err = %{public}d", windowName.c_str(), errCode); + std::shared_ptr jsWindowObj = FindJsWindowObject(windowName); + if (jsWindowObj != nullptr && jsWindowObj->Get() != nullptr) { + WLOGFI("[NAPI]Find window: %{public}s, use exist js window", windowName.c_str()); + return jsWindowObj->Get(); + } else { + sptr window = Window::Find(windowName); + if (window == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } else { + return CreateJsWindowObject(engine, window); + } + } +} + +NativeValue* JsWindowManager::OnMinimizeAll(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("[NAPI]OnMinimizeAll"); + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + int64_t displayId = static_cast(DISPLAY_ID_INVALID); + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], displayId)) { + WLOGFE("[NAPI]Failed to convert parameter to displayId"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (displayId < 0 || + SingletonContainer::Get().GetDisplayById(static_cast(displayId)) == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + WLOGFE("JsWindowManager::OnMinimizeAll failed, Invalidate params."); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + WLOGFI("[NAPI]Display id = %{public}" PRIu64", err = %{public}d", static_cast(displayId), errCode); + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + SingletonContainer::Get().MinimizeAllAppWindows(static_cast(displayId)); + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("[NAPI]OnMinimizeAll success"); + }; + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnMinimizeAll", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManager::OnToggleShownStateForAllAppWindows(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFI("[NAPI]OnToggleShownStateForAllAppWindows"); + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + SingletonContainer::Get().ToggleShownStateForAllAppWindows()); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("[NAPI]OnToggleShownStateForAllAppWindows success"); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), + "OnToggleShownStateForAllAppWindows failed")); + } + }; + NativeValue* lastParam = (info.argc <= 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnToggleShownStateForAllAppWindows", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManager::OnRegisterWindowMangerCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnRegisterWindowMangerCallback"); + if (info.argc < 2) { // 2: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("[NAPI]Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeValue* value = info.argv[1]; + if (!value->IsCallable()) { + WLOGFI("[NAPI]Callback(argv[1]) is not callable"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + registerManager_->RegisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, engine, value); + WLOGFI("[NAPI]Register end, type = %{public}s, callback = %{public}p", cbType.c_str(), value); + return engine.CreateUndefined(); +} + +NativeValue* JsWindowManager::OnUnregisterWindowManagerCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnUnregisterWindowManagerCallback"); + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("[NAPI]Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + NativeValue* value = nullptr; + if (info.argc == 1) { + registerManager_->UnregisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, value); + } else { + value = info.argv[1]; + if ((value== nullptr) || (!value->IsCallable())) { + registerManager_->UnregisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, nullptr); + } else { + registerManager_->UnregisterListener(nullptr, cbType, CaseType::CASE_WINDOW_MANAGER, value); + } + } + WLOGFI("[NAPI]Unregister end, type = %{public}s, callback = %{public}p", cbType.c_str(), value); + return engine.CreateUndefined(); +} + +static void GetTopWindowTask(void* contextPtr, NativeEngine& engine, AsyncTask& task) +{ + std::string windowName; + sptr window = nullptr; + AppExecFwk::Ability* ability = nullptr; + bool isOldApi = GetAPI7Ability(engine, ability); + if (isOldApi) { + if (ability->GetWindow() == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "FA mode can not get ability window")); + WLOGE("[NAPI]FA mode can not get ability window"); + return; + } + window = Window::GetTopWindowWithId(ability->GetWindow()->GetWindowId()); + } else { + auto context = static_cast*>(contextPtr); + if (contextPtr == nullptr || context == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "Stage mode without context")); + WLOGFE("[NAPI]Stage mode without context"); + return; + } + window = Window::GetTopWindowWithContext(context->lock()); + } + if (window == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "Get top window failed")); + WLOGFE("[NAPI]Get top window failed"); + return; + } + windowName = window->GetWindowName(); + std::shared_ptr jsWindowObj = FindJsWindowObject(windowName); + if (jsWindowObj != nullptr && jsWindowObj->Get() != nullptr) { + task.Resolve(engine, jsWindowObj->Get()); + } else { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + } + WLOGFI("[NAPI]Get top window %{public}s success", windowName.c_str()); + return; +} + +NativeValue* JsWindowManager::OnGetTopWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnGetTopWindow"); + WMError errCode = WMError::WM_OK; + NativeValue* nativeContext = nullptr; + NativeValue* nativeCallback = nullptr; + void* contextPtr = nullptr; + if (info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + if (info.argc > 0 && info.argv[0]->TypeOf() == NATIVE_OBJECT) { // (context, callback?) + nativeContext = info.argv[0]; + nativeCallback = (info.argc == 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + } else { // (callback?) + nativeCallback = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + } + GetNativeContext(engine, nativeContext, contextPtr, errCode); + } + + WLOGFI("[NAPI]Context %{public}p, err %{public}u", contextPtr, errCode); + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params")); + return; + } + return GetTopWindowTask(contextPtr, engine, task); + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnGetTopWindow", + engine, CreateAsyncTaskWithLastParam(engine, nativeCallback, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManager::OnGetLastWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnGetLastWindow"); + WMError errCode = WMError::WM_OK; + NativeValue* nativeContext = nullptr; + NativeValue* nativeCallback = nullptr; + void* contextPtr = nullptr; + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } else { + nativeContext = info.argv[0]; + nativeCallback = (info.argc == 1) ? nullptr : info.argv[1]; + GetNativeContext(engine, nativeContext, contextPtr, errCode); + } + if (errCode != WMError::WM_OK) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + std::string windowName; + sptr window = nullptr; + auto context = static_cast*>(contextPtr); + if (contextPtr == nullptr || context == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_CONTEXT_ABNORMALLY), + "Stage mode without context")); + return; + } + window = Window::GetTopWindowWithContext(context->lock()); + if (window == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Get top window failed")); + return; + } + windowName = window->GetWindowName(); + std::shared_ptr jsWindowObj = FindJsWindowObject(windowName); + if (jsWindowObj != nullptr && jsWindowObj->Get() != nullptr) { + task.Resolve(engine, jsWindowObj->Get()); + } else { + task.Resolve(engine, CreateJsWindowObject(engine, window)); + } + WLOGFI("[NAPI]Get top window %{public}s success", windowName.c_str()); + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnGetTopWindow", + engine, CreateAsyncTaskWithLastParam(engine, nativeCallback, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManager::OnSetWindowLayoutMode(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]OnSetWindowLayoutMode"); + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: minimum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + WindowLayoutMode winLayoutMode = WindowLayoutMode::CASCADE; + if (errCode == WmErrorCode::WM_OK) { + NativeNumber* nativeMode = ConvertNativeValueTo(info.argv[0]); + if (nativeMode == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to windowLayoutMode"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + winLayoutMode = static_cast(static_cast(*nativeMode)); + } + } + if (winLayoutMode != WindowLayoutMode::CASCADE && winLayoutMode != WindowLayoutMode::TILE) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + WLOGFE("JsWindowManager::OnSetWindowLayoutMode failed, Invalidate params."); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + WLOGFI("[NAPI]LayoutMode = %{public}u, err = %{public}d", winLayoutMode, errCode); + AsyncTask::CompleteCallback complete = + [=](NativeEngine& engine, AsyncTask& task, int32_t status) { + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + SingletonContainer::Get().SetWindowLayoutMode(winLayoutMode)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + WLOGFI("[NAPI]SetWindowLayoutMode success"); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "SetWindowLayoutMode failed")); + } + }; + // 1: maximum params num; 1: index of callback + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowManager::OnSetWindowLayoutMode", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowManagerInit(NativeEngine* engine, NativeValue* exportObj) +{ + WLOGFD("[NAPI]JsWindowManagerInit"); + + if (engine == nullptr || exportObj == nullptr) { + WLOGFE("[NAPI]JsWindowManagerInit engine or exportObj is nullptr"); + return nullptr; + } + + NativeObject* object = ConvertNativeValueTo(exportObj); + if (object == nullptr) { + WLOGFE("[NAPI]JsWindowManagerInit object is nullptr"); + return nullptr; + } + + std::unique_ptr jsWinManager = std::make_unique(); + object->SetNativePointer(jsWinManager.release(), JsWindowManager::Finalizer, nullptr); + object->SetProperty("WindowType", WindowTypeInit(engine)); + object->SetProperty("AvoidAreaType", AvoidAreaTypeInit(engine)); + object->SetProperty("WindowMode", WindowModeInit(engine)); + object->SetProperty("ColorSpace", ColorSpaceInit(engine)); + object->SetProperty("WindowStageEventType", WindowStageEventTypeInit(engine)); + object->SetProperty("WindowLayoutMode", WindowLayoutModeInit(engine)); + object->SetProperty("Orientation", OrientationInit(engine)); + object->SetProperty("BlurStyle", BlurStyleInit(engine)); + object->SetProperty("WmErrorCode", WindowErrorCodeInit(engine)); + object->SetProperty("WMError", WindowErrorInit(engine)); + const char *moduleName = "JsWindowManager"; + BindNativeFunction(*engine, *object, "create", moduleName, JsWindowManager::Create); + BindNativeFunction(*engine, *object, "createWindow", moduleName, JsWindowManager::CreateWindow); + BindNativeFunction(*engine, *object, "find", moduleName, JsWindowManager::FindWindow); + BindNativeFunction(*engine, *object, "findWindow", moduleName, JsWindowManager::FindWindowSync); + BindNativeFunction(*engine, *object, "on", moduleName, JsWindowManager::RegisterWindowManagerCallback); + BindNativeFunction(*engine, *object, "off", moduleName, JsWindowManager::UnregisterWindowMangerCallback); + BindNativeFunction(*engine, *object, "getTopWindow", moduleName, JsWindowManager::GetTopWindow); + BindNativeFunction(*engine, *object, "getLastWindow", moduleName, JsWindowManager::GetLastWindow); + BindNativeFunction(*engine, *object, "minimizeAll", moduleName, JsWindowManager::MinimizeAll); + BindNativeFunction(*engine, *object, "toggleShownStateForAllAppWindows", moduleName, + JsWindowManager::ToggleShownStateForAllAppWindows); + BindNativeFunction(*engine, *object, "setWindowLayoutMode", moduleName, JsWindowManager::SetWindowLayoutMode); + return engine->CreateUndefined(); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h b/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h new file mode 100644 index 0000000..b68d21d --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/js_window_manager.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-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_runtime_utils.h" +#include "js_window_register_manager.h" +#include "native_engine/native_engine.h" +#include "native_engine/native_reference.h" +#include "native_engine/native_value.h" +#include "wm_common.h" + +#ifndef OHOS_JS_WINDOW_MANAGER_H +#define OHOS_JS_WINDOW_MANAGER_H +namespace OHOS { +namespace Rosen { +NativeValue* JsWindowManagerInit(NativeEngine* engine, NativeValue* exportObj); +class JsWindowManager { +public: + JsWindowManager(); + ~JsWindowManager(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* Create(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* CreateWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* FindWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* FindWindowSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* MinimizeAll(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* ToggleShownStateForAllAppWindows(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* RegisterWindowManagerCallback(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* UnregisterWindowMangerCallback(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetTopWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetLastWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowLayoutMode(NativeEngine* engine, NativeCallbackInfo* info); + +private: + static NativeValue* OnCreate(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnCreateWindow(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnFindWindow(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnFindWindowSync(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnMinimizeAll(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnToggleShownStateForAllAppWindows(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnRegisterWindowMangerCallback(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnUnregisterWindowManagerCallback(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnGetTopWindow(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnGetLastWindow(NativeEngine& engine, NativeCallbackInfo& info); + static NativeValue* OnSetWindowLayoutMode(NativeEngine& engine, NativeCallbackInfo& info); + static bool ParseConfigOption( + NativeEngine& engine, NativeObject* jsObject, WindowOption& option, void*& contextPtr); + std::unique_ptr registerManager_ = nullptr; +}; +} // namespace Rosen +} // namespace OHOS + +#endif diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/window_manager_module.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/window_manager_module.cpp new file mode 100644 index 0000000..3efee93 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_manager_napi/window_manager_module.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021-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_window_manager.h" +#include "native_engine/native_engine.h" + +extern "C" __attribute__((constructor)) void NAPI_application_windowmanager_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "window", + .fileName = "module/libwindow_napi.so/window.js", + .registerCallback = OHOS::Rosen::JsWindowManagerInit, + }; + + moduleManager->Register(&newModuleInfo); +} diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.cpp new file mode 100644 index 0000000..0f93315 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.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. + */ + +#include "js_transition_controller.h" +#include "js_runtime_utils.h" +#include "window.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +#include "window_option.h" +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsTransitionController"}; +} + +static int jsTransCxtCtorCnt = 0; +static int jsTransCxtDtorCnt = 0; +static int jsTransCtrlCtorCnt = 0; +static int jsTransCtrlDtorCnt = 0; + +JsTransitionContext::JsTransitionContext(sptr window, bool isShownTransContext) + : windowToken_(window), isShownTransContext_(isShownTransContext) +{ + WLOGFI("[NAPI] JsTransitionContext constructorCnt: %{public}d", ++jsTransCxtCtorCnt); +} + +JsTransitionContext::~JsTransitionContext() +{ + WLOGFI("[NAPI] ~JsTransitionContext deConstructorCnt: %{public}d", ++jsTransCxtDtorCnt); +} + +void JsTransitionContext::Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFI("[NAPI]JsTransitionContext::Finalizer"); + std::unique_ptr(static_cast(data)); +} + +NativeValue* JsTransitionContext::CompleteTransition(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFI("[NAPI]CompleteTransition"); + JsTransitionContext* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnCompleteTransition(*engine, *info) : nullptr; +} + +NativeValue* JsTransitionContext::OnCompleteTransition(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool transitionCompleted = false; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], transitionCompleted)) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + WMError ret = WMError::WM_OK; + auto state = windowToken_->GetWindowState(); + if (!isShownTransContext_) { + if (state != WindowState::STATE_HIDDEN) { + WLOGFI("[NAPI]Window [%{public}u, %{public}s] Hidden context called but window is not hidden: %{public}u", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), static_cast(state)); + return engine.CreateUndefined(); + } + windowToken_->UpdateSurfaceNodeAfterCustomAnimation(false); // remove from rs tree after animation + if (!transitionCompleted) { + ret = windowToken_->Show(); // hide aborted + } + } else { + if (state != WindowState::STATE_SHOWN) { + WLOGFI("[NAPI]Window [%{public}u, %{public}s] shown context called but window is not shown: %{public}u", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), static_cast(state)); + return engine.CreateUndefined(); + } + if (!transitionCompleted) { + ret = windowToken_->Hide(); // show aborted + } + } + if (ret != WMError::WM_OK) { + engine.Throw(CreateJsError(engine, static_cast(WM_JS_TO_ERROR_CODE_MAP.at(ret)))); + return engine.CreateUndefined(); + } + WLOGFI("[NAPI]Window [%{public}u, %{public}s] CompleteTransition %{public}d end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), transitionCompleted); + return engine.CreateUndefined(); +} + +static NativeValue* CreateJsTransitionContextObject(NativeEngine& engine, std::shared_ptr jsWin, + sptr window, bool isShownTransContext) +{ + WLOGFI("[NAPI]CreateJsTransitionContextObject"); + NativeValue *objValue = engine.CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + std::unique_ptr jsTransContext = std::make_unique(window, + isShownTransContext); + object->SetNativePointer(jsTransContext.release(), JsTransitionContext::Finalizer, nullptr); + if (jsWin != nullptr && jsWin->Get() != nullptr) { + object->SetProperty("toWindow", jsWin->Get()); + } else { + WLOGFE("[NAPI]jsWin is nullptr"); + return nullptr; + } + + const char *moduleName = "JsTransitionContext"; + BindNativeFunction(engine, *object, "completeTransition", moduleName, JsTransitionContext::CompleteTransition); + return objValue; +} + +JsTransitionController::JsTransitionController(NativeEngine& engine, std::shared_ptr jsWin, + sptr window) + : engine_(engine), jsWin_(jsWin), windowToken_(window), weakRef_(wptr (this)) +{ + WLOGFI("[NAPI] JsTransitionController constructorCnt: %{public}d", ++jsTransCtrlCtorCnt); +} + +JsTransitionController::~JsTransitionController() +{ + WLOGFI("[NAPI] ~JsTransitionController deConstructorCnt: %{public}d", ++jsTransCtrlDtorCnt); +} + +void JsTransitionController::AnimationForShown() +{ + WLOGFI("[NAPI]AnimationForShown"); + std::unique_ptr complete = std::make_unique ( + [self = weakRef_](NativeEngine&, AsyncTask&, int32_t) { + auto thisController = self.promote(); + if (thisController == nullptr) { + WLOGFE("this transition Controller is null!"); + return; + } + HandleScope handleScope(thisController->engine_); + auto jsWin = thisController->jsWin_.lock(); + auto window = thisController->windowToken_.promote(); + if (jsWin == nullptr || window == nullptr) { + WLOGFE("native window or jsWindow is null!"); + return; + } + auto state = window->GetWindowState(); + if (state != WindowState::STATE_SHOWN) { + WLOGFE("animation shown configuration for state %{public}u not support!", static_cast(state)); + return; + } + NativeValue* jsTransContextObj = CreateJsTransitionContextObject( + thisController->engine_, jsWin, window, true); + if (jsTransContextObj == nullptr) { + return; + } + NativeValue *argv[] = { jsTransContextObj }; + thisController->CallJsMethod("animationForShown", argv, ArraySize(argv)); + // add to rs tree before animation + window->UpdateSurfaceNodeAfterCustomAnimation(true); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsTransitionController::AnimationForShown", engine_, + std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsTransitionController::AnimationForHidden() +{ + WLOGFI("[NAPI]AnimationForHidden"); + std::unique_ptr complete = std::make_unique ( + [self = weakRef_](NativeEngine&, AsyncTask&, int32_t) { + auto thisController = self.promote(); + if (thisController == nullptr) { + WLOGFE("this transition Controller is null!"); + return; + } + HandleScope handleScope(thisController->engine_); + auto jsWin = thisController->jsWin_.lock(); + auto window = thisController->windowToken_.promote(); + if (jsWin == nullptr || window == nullptr) { + WLOGFE("native window or jsWindow is null!"); + return; + } + auto state = window->GetWindowState(); + if (state != WindowState::STATE_HIDDEN) { + WLOGFE("animation hidden configuration for state %{public}u not support!", + static_cast(state)); + return; + } + NativeValue* jsTransContextObj = CreateJsTransitionContextObject( + thisController->engine_, jsWin, window, false); + if (jsTransContextObj == nullptr) { + return; + } + NativeValue *argv[] = { jsTransContextObj }; + thisController->CallJsMethod("animationForHidden", argv, ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsTransitionController::AnimationForHidden", engine_, + std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsTransitionController::CallJsMethod(const std::string& methodName, NativeValue* const* argv, size_t argc) +{ + WLOGFI("Call js function:%{public}s.", methodName.c_str()); + auto self = jsTransControllerObj_.lock(); + if (self == nullptr) { + WLOGFE("JsController is null!"); + return; + } + auto jsControllerValue = self->Get(); + auto jsControllerObj = ConvertNativeValueTo(jsControllerValue); + if (jsControllerObj == nullptr) { + WLOGFE("JsControllerObj is null!"); + return; + } + auto method = jsControllerObj->GetProperty(methodName.c_str()); + if (method == nullptr || method->TypeOf() == NATIVE_UNDEFINED) { + WLOGFE("Failed to get %{public}s from object", methodName.c_str()); + return; + } + engine_.CallFunction(jsControllerValue, method, argv, argc); +} + +void JsTransitionController::SetJsController(std::shared_ptr jsVal) +{ + jsTransControllerObj_ = jsVal; +} +} +} \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.h b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.h new file mode 100644 index 0000000..6dd9e83 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_transition_controller.h @@ -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. + */ + +#ifndef OHOS_JS_TRANSITION_CONTROLLER_H +#define OHOS_JS_TRANSITION_CONTROLLER_H + +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +class JsTransitionContext { +public: + JsTransitionContext(sptr window, bool isShownTransContext); + ~JsTransitionContext(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* CompleteTransition(NativeEngine* engine, NativeCallbackInfo* info); +private: + NativeValue* OnCompleteTransition(NativeEngine& engine, NativeCallbackInfo& info); + wptr windowToken_; + bool isShownTransContext_ = false; +}; + +class JsTransitionController : public IAnimationTransitionController { +public: + JsTransitionController(NativeEngine& engine, std::shared_ptr jsWin, sptr window); + ~JsTransitionController(); + void AnimationForShown() override; + void AnimationForHidden() override; + void SetJsController(std::shared_ptr jsVal); +private: + void CallJsMethod(const std::string& methodName, NativeValue* const* argv, size_t argc); + NativeEngine& engine_; + std::weak_ptr jsTransControllerObj_; + std::weak_ptr jsWin_; + wptr windowToken_; + wptr weakRef_ = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp new file mode 100644 index 0000000..e10a3c8 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -0,0 +1,3694 @@ +/* + * Copyright (c) 2021-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_window.h" +#include + +#ifndef WINDOW_PREVIEW +#include "js_transition_controller.h" +#else +#include "mock/js_transition_controller.h" +#endif + +#include "js_window_utils.h" +#include "window.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +#include "window_option.h" +#include "wm_math.h" +#include "pixel_map.h" +#include "pixel_map_napi.h" +#include "napi_remote_object.h" +#include "permission.h" +#include "request_info.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindow"}; + constexpr Rect g_emptyRect = {0, 0, 0, 0}; +} + +static thread_local std::map> g_jsWindowMap; +std::recursive_mutex g_mutex; +static int ctorCnt = 0; +static int dtorCnt = 0; +static int finalizerCnt = 0; +JsWindow::JsWindow(const sptr& window) + : windowToken_(window), registerManager_(std::make_unique()) +{ + NotifyNativeWinDestroyFunc func = [](std::string windowName) { + std::lock_guard lock(g_mutex); + if (windowName.empty() || g_jsWindowMap.count(windowName) == 0) { + WLOGFE("[NAPI]Can not find window %{public}s ", windowName.c_str()); + return; + } + g_jsWindowMap.erase(windowName); + WLOGFD("[NAPI]Destroy window %{public}s in js window", windowName.c_str()); + }; + windowToken_->RegisterWindowDestroyedListener(func); + WLOGFD("[NAPI] constructorCnt: %{public}d", ++ctorCnt); +} + +JsWindow::~JsWindow() +{ + WLOGFD("[NAPI] deConstructorCnt:%{public}d", ++dtorCnt); + windowToken_ = nullptr; +} + +std::string JsWindow::GetWindowName() +{ + if (windowToken_ == nullptr) { + return ""; + } + return windowToken_->GetWindowName(); +} + +void JsWindow::Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFD("[NAPI]finalizerCnt:%{public}d", ++finalizerCnt); + auto jsWin = std::unique_ptr(static_cast(data)); + if (jsWin == nullptr) { + WLOGFE("[NAPI]jsWin is nullptr"); + return; + } + std::string windowName = jsWin->GetWindowName(); + WLOGFD("[NAPI]Window %{public}s", windowName.c_str()); + std::lock_guard lock(g_mutex); + g_jsWindowMap.erase(windowName); + WLOGFD("[NAPI]Remove window %{public}s from g_jsWindowMap", windowName.c_str()); +} + +NativeValue* JsWindow::Show(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Show"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnShow(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::ShowWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Show"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnShowWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::ShowWithAnimation(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]ShowWithAnimation"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnShowWithAnimation(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Destroy(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Destroy"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnDestroy(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::DestroyWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Destroy"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnDestroyWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Hide(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Hide"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnHide(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::HideWithAnimation(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]HideWithAnimation"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnHideWithAnimation(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::MoveTo(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]MoveTo"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnMoveTo(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::MoveWindowTo(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]MoveTo"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnMoveWindowTo(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Resize(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Resize"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnResize(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::ResizeWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Resize"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnResizeWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowType(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetWindowType"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowType(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowMode(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetWindowMode"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowMode(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetProperties(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetProperties"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetProperties(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetWindowPropertiesSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetProperties"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetWindowPropertiesSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::RegisterWindowCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]RegisterWindowCallback"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnRegisterWindowCallback(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::UnregisterWindowCallback(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]UnregisterWindowCallback"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnUnregisterWindowCallback(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::BindDialogTarget(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]BindDialogTarget"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnBindDialogTarget(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::LoadContent(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]LoadContent"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnLoadContent(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetUIContent(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]LoadContent"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetUIContent(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetFullScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetFullScreen"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetFullScreen(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetLayoutFullScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetLayoutFullScreen"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetLayoutFullScreen(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowLayoutFullScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetLayoutFullScreen"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowLayoutFullScreen(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetSystemBarEnable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetSystemBarEnable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetSystemBarEnable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowSystemBarEnable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetSystemBarEnable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowSystemBarEnable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetSystemBarProperties(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetSystemBarProperties"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetSystemBarProperties(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowSystemBarProperties(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetWindowSystemBarProperties"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowSystemBarProperties(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetAvoidArea(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetAvoidArea"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetAvoidArea(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetWindowAvoidAreaSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetAvoidArea"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetWindowAvoidAreaSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::IsShowing(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]IsShowing"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnIsShowing(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::IsWindowShowingSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]IsShowing"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnIsWindowShowingSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::IsSupportWideGamut(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]IsSupportWideGamut"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnIsSupportWideGamut(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::IsWindowSupportWideGamut(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]IsSupportWideGamut"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnIsWindowSupportWideGamut(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetBackgroundColor(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBackgroundColor"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetBackgroundColor(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowBackgroundColorSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBackgroundColor"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowBackgroundColorSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetBrightness(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBrightness"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetBrightness(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowBrightness(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBrightness"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowBrightness(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetDimBehind(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetDimBehind"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetDimBehind(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetFocusable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetFocusable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetFocusable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowFocusable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetFocusable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowFocusable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetKeepScreenOn(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetKeepScreenOn"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetKeepScreenOn(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowKeepScreenOn(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetKeepScreenOn"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowKeepScreenOn(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWakeUpScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetWakeUpScreen"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWakeUpScreen(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetOutsideTouchable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetOutsideTouchable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetOutsideTouchable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetPrivacyMode(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetPrivacyMode"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetPrivacyMode(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowPrivacyMode(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetPrivacyMode"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowPrivacyMode(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetTouchable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetTouchable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetTouchable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowTouchable(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetTouchable"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowTouchable(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetTransparent(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetTransparent"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetTransparent(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetCallingWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetCallingWindow"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetCallingWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetPreferredOrientation(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetPreferredOrientation"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetPreferredOrientation(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetSnapshotSkip(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("NAPI"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetSnapshotSkip(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::DisableWindowDecor(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]DisableWindowDecor"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnDisableWindowDecor(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetColorSpace(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetColorSpace"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetColorSpace(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetWindowColorSpace(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetColorSpace"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetWindowColorSpace(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetColorSpace(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetColorSpace"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetColorSpace(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetWindowColorSpaceSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetColorSpace"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetWindowColorSpaceSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Dump(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Dump"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnDump(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetForbidSplitMove(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetForbidSplitMove"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetForbidSplitMove(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Opacity(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Opacity"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnOpacity(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Scale(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Scale"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnScale(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Rotate(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Rotate"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnRotate(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::Translate(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Translate"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnTranslate(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::GetTransitionController(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetTransitionController"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetTransitionController(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetCornerRadius(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetCornerRadius"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetCornerRadius(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetShadow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetShadow"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetShadow(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetBlur(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBlur"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetBlur(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetBackdropBlur(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBackdropBlur"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetBackdropBlur(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::SetBackdropBlurStyle(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetBackdropBlurStyle"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetBackdropBlurStyle(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::OnShow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->Show(0, false); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window show failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] show end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* result = nullptr; + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + AsyncTask::Schedule("JsWindow::OnShow", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnShowWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->Show(0, false); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(WM_JS_TO_ERROR_CODE_MAP.at(ret)), "Window show failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] show end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* result = nullptr; + NativeValue* lastParam = (info.argc == 0) ? nullptr : + ((info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr); + AsyncTask::Schedule("JsWindow::OnShow", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnShowWithAnimation(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + auto winType = windowToken_->GetType(); + if (!WindowHelper::IsSystemWindow(winType)) { + WLOGFE("[NAPI]window Type %{public}u is not supported", static_cast(winType)); + errCode = WmErrorCode::WM_ERROR_INVALID_CALLING; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != WmErrorCode::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + return; + } + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->Show(0, true)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window show failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] ShowWithAnimation end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* result = nullptr; + NativeValue* lastParam = (info.argc == 0) ? nullptr : + ((info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr); + AsyncTask::Schedule("JsWindow::OnShowWithAnimation", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnDestroy(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [this, weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->Destroy(); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] destroy end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + if (ret != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window destroy failed")); + return; + } + windowToken_ = nullptr; // ensure window dtor when finalizer invalid + task.Resolve(engine, engine.CreateUndefined()); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnDestroy", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnDestroyWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [this, weakToken](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr or get invalid param"); + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->Destroy()); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] destroy end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + if (ret != WmErrorCode::WM_OK) { + task.Reject(engine, + CreateJsError(engine, static_cast(ret), + "Window destroy failed")); + return; + } + windowToken_ = nullptr; // ensure window dtor when finalizer invalid + task.Resolve(engine, engine.CreateUndefined()); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + ((info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnDestroyWindow", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnHide(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr or get invalid param"); + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->Hide(0, false)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window hide failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] hide end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* result = nullptr; + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + AsyncTask::Schedule("JsWindow::OnHide", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnHideWithAnimation(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (windowToken_) { + auto winType = windowToken_->GetType(); + if (!WindowHelper::IsSystemWindow(winType)) { + WLOGFE("[NAPI]window Type %{public}u is not supported", static_cast(winType)); + errCode = WmErrorCode::WM_ERROR_INVALID_CALLING; + } + } else { + errCode = WmErrorCode::WM_ERROR_INVALID_CALLING; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + if (errCode != WmErrorCode::WM_OK) { + task.Reject(engine, + CreateJsError(engine, static_cast(errCode))); + return; + } + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->Hide(0, true)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window show failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] HideWithAnimation end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* result = nullptr; + NativeValue* lastParam = (info.argc == 0) ? nullptr : + ((info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr); + AsyncTask::Schedule("JsWindow::OnHideWithAnimation", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnMoveTo(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 2 || info.argc > 3) { // 2:minimum param num, 3: maximum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + int32_t x = 0; + if (errCode == WMError::WM_OK && !ConvertFromJsValue(engine, info.argv[0], x)) { + WLOGFE("[NAPI]Failed to convert parameter to x"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + + int32_t y = 0; + if (errCode == WMError::WM_OK && !ConvertFromJsValue(engine, info.argv[1], y)) { + WLOGFE("[NAPI]Failed to convert parameter to y"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode, x, y](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->MoveTo(x, y); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window move failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] move end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + // 2: params num; 2: index of callback + NativeValue* lastParam = (info.argc <= 2) ? nullptr : + (info.argv[2]->TypeOf() == NATIVE_FUNCTION ? info.argv[2] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnMoveTo", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnMoveWindowTo(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 2) { // 2:minimum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + int32_t x = 0; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], x)) { + WLOGFE("[NAPI]Failed to convert parameter to x"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + int32_t y = 0; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[1], y)) { + WLOGFE("[NAPI]Failed to convert parameter to y"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, x, y](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->MoveTo(x, y)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, + CreateJsError(engine, static_cast(ret), + "Window move failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] move end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + // 2: params num; 2: index of callback + NativeValue* lastParam = (info.argc <= 2) ? nullptr : + ((info.argv[2] != nullptr && info.argv[2]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[2] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnMoveWindowTo", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnResize(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 2 || info.argc > 3) { // 2: minimum param num, 3: maximum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + int32_t width = 0; + if (errCode == WMError::WM_OK && !ConvertFromJsValue(engine, info.argv[0], width)) { + WLOGFE("[NAPI]Failed to convert parameter to width"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + int32_t height = 0; + if (errCode == WMError::WM_OK && !ConvertFromJsValue(engine, info.argv[1], height)) { + WLOGFE("[NAPI]Failed to convert parameter to height"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + if (width <= 0 || height <= 0) { + WLOGFE("[NAPI]width or height should greater than 0!"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode, width, height](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->Resize(static_cast(width), static_cast(height)); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window resize failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] resize end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + // 2: params num; 2: index of callback + NativeValue* lastParam = (info.argc <= 2) ? nullptr : + (info.argv[2]->TypeOf() == NATIVE_FUNCTION ? info.argv[2] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnResize", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnResizeWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 2) { // 2: minimum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + int32_t width = 0; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], width)) { + WLOGFE("[NAPI]Failed to convert parameter to width"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + int32_t height = 0; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[1], height)) { + WLOGFE("[NAPI]Failed to convert parameter to height"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (width <= 0 || height <= 0) { + WLOGFE("[NAPI]width or height should greater than 0!"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, width, height](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->Resize(static_cast(width), static_cast(height))); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window resize failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] resize end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + // 2: params num; 2: index of callback + NativeValue* lastParam = (info.argc <= 2) ? nullptr : + ((info.argv[2] != nullptr && info.argv[2]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[2] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnResizeWindow", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowType(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2 is max num of argc + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + WindowType winType = WindowType::SYSTEM_WINDOW_BASE; + if (errCode == WMError::WM_OK) { + NativeNumber* nativeType = ConvertNativeValueTo(info.argv[0]); + if (nativeType == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to windowType"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else if (static_cast(*nativeType) >= static_cast(WindowType::SYSTEM_WINDOW_BASE)) { + winType = static_cast(static_cast(*nativeType)); // adapt to the old version + } else { + if (JS_TO_NATIVE_WINDOW_TYPE_MAP.count( + static_cast(static_cast(*nativeType))) != 0) { + winType = JS_TO_NATIVE_WINDOW_TYPE_MAP.at( + static_cast(static_cast(*nativeType))); + } else { + WLOGFE("[NAPI]Do not surppot this type: %{public}u", static_cast(*nativeType)); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, winType, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->SetWindowType(winType); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set type failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set type end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowType", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowMode(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set window mode permission denied!"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + WindowMode winMode = WindowMode::WINDOW_MODE_FULLSCREEN; + if (errCode == WmErrorCode::WM_OK) { + NativeNumber* nativeMode = ConvertNativeValueTo(info.argv[0]); + if (nativeMode == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + if (static_cast(*nativeMode) >= static_cast(WindowMode::WINDOW_MODE_SPLIT_PRIMARY)) { + winMode = static_cast(static_cast(*nativeMode)); + } else if (static_cast(*nativeMode) >= static_cast(ApiWindowMode::UNDEFINED) && + static_cast(*nativeMode) <= static_cast(ApiWindowMode::MODE_END)) { + winMode = JS_TO_NATIVE_WINDOW_MODE_MAP.at( + static_cast(static_cast(*nativeMode))); + } else { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, winMode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->SetWindowMode(winMode)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, + CreateJsError(engine, static_cast(ret), "Window set mode failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set type end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc == 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowMode", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnGetProperties(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + auto objValue = CreateJsWindowPropertiesObject(engine, weakWindow); + if (objValue != nullptr) { + task.Resolve(engine, objValue); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "Window get properties failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] get properties end, objValue = %{public}p", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), objValue); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnGetProperties", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnGetWindowPropertiesSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + if (window == nullptr) { + WLOGFE("[NAPI]window is nullptr or get invalid param"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + auto objValue = CreateJsWindowPropertiesObject(engine, window); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] get properties end, objValue = %{public}p", + window->GetWindowId(), window->GetWindowName().c_str(), objValue); + if (objValue != nullptr) { + return objValue; + } else { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } +} + +NativeValue* JsWindow::OnRegisterWindowCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (info.argc < 2) { // 2: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("[NAPI]Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeValue* value = info.argv[1]; + if (!value->IsCallable()) { + WLOGFD("[NAPI]Callback(info->argv[1]) is not callable"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + registerManager_->RegisterListener(windowToken_, cbType, CaseType::CASE_WINDOW, engine, value); + WLOGFD("[NAPI]Register end, window [%{public}u, %{public}s], type = %{public}s, callback = %{public}p", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), cbType.c_str(), value); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnUnregisterWindowCallback(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (windowToken_ == nullptr || info.argc < 1) { // 2: maximum params nums + WLOGFE("[NAPI]Window is nullptr or argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::string cbType; + if (!ConvertFromJsValue(engine, info.argv[0], cbType)) { + WLOGFE("[NAPI]Failed to convert parameter to callbackType"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + NativeValue* value = nullptr; + if (info.argc == 1) { + registerManager_->UnregisterListener(windowToken_, cbType, CaseType::CASE_WINDOW, value); + } else { + value = info.argv[1]; + if (value == nullptr || !value->IsCallable()) { + registerManager_->UnregisterListener(windowToken_, cbType, CaseType::CASE_WINDOW, nullptr); + } else { + registerManager_->UnregisterListener(windowToken_, cbType, CaseType::CASE_WINDOW, value); + } + } + + WLOGFD("[NAPI]Unregister end, window [%{public}u, %{public}s], type = %{public}s, callback = %{public}p", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), cbType.c_str(), value); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnBindDialogTarget(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (windowToken_ == nullptr || info.argc <= 1) { // 1: invalid params nums + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + + NativeValue* value = nullptr; + sptr token = nullptr; + token = NAPI_ohos_rpc_getNativeRemoteObject( + reinterpret_cast(&engine), reinterpret_cast(info.argv[0])); + if (token == nullptr) { + std::shared_ptr requestInfo = AbilityRuntime::RequestInfo::UnwrapRequestInfo(engine, info.argv[0]); + if (requestInfo != nullptr) { + token = requestInfo->GetToken(); + } + } + if (token == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + value = info.argv[1]; + if (value == nullptr || !value->IsCallable()) { + registerManager_->RegisterListener(windowToken_, + "dialogDeathRecipient", CaseType::CASE_WINDOW, engine, nullptr); + } else { + registerManager_->RegisterListener(windowToken_, + "dialogDeathRecipient", CaseType::CASE_WINDOW, engine, value); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, token](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->BindDialogTarget(token)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Bind Dialog Target failed")); + } + + WLOGFD("[NAPI]BindDialogTarget end, window [%{public}u, %{public}s]", + weakToken->GetWindowId(), weakToken->GetWindowName().c_str()); + }; + + NativeValue* result = nullptr; + NativeValue* lastParam = (info.argc == 2) ? nullptr : + (info.argv[2]->TypeOf() == NATIVE_FUNCTION ? info.argv[2] : nullptr); + AsyncTask::Schedule("JsWindow::OnBindDialogTarget", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +static void LoadContentTask(std::shared_ptr contentStorage, std::string contextUrl, + sptr weakWindow, NativeEngine& engine, AsyncTask& task) +{ + NativeValue* nativeStorage = (contentStorage == nullptr) ? nullptr : contentStorage->Get(); + AppExecFwk::Ability* ability = nullptr; + GetAPI7Ability(engine, ability); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->SetUIContent(contextUrl, &engine, nativeStorage, false, ability)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window load content failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] load content end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + return; +} + +NativeValue* JsWindow::LoadContentScheduleOld(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2 maximum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + std::string contextUrl; + if (errCode == WMError::WM_OK && !ConvertFromJsValue(engine, info.argv[0], contextUrl)) { + WLOGFE("[NAPI]Failed to convert parameter to context url"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + NativeValue* storage = nullptr; + NativeValue* callBack = nullptr; + if (info.argc == 2) { // 2 param num + callBack = info.argv[1]; + } + std::shared_ptr contentStorage = (storage == nullptr) ? nullptr : + std::shared_ptr(engine.CreateReference(storage, 1)); + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, contentStorage, contextUrl, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]Window is nullptr or get invalid param"); + return; + } + LoadContentTask(contentStorage, contextUrl, weakWindow, engine, task); + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnLoadContent", + engine, CreateAsyncTaskWithLastParam(engine, callBack, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::LoadContentScheduleNew(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 2) { // 2 param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + std::string contextUrl; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], contextUrl)) { + WLOGFE("[NAPI]Failed to convert parameter to context url"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + NativeValue* storage = nullptr; + NativeValue* callBack = nullptr; + if (info.argc == 2) { // 2: num of params + storage = info.argv[1]; + } else if (info.argc >= 3) { // 3: num of params + storage = info.argv[1]; + callBack = ((info.argv[2] != nullptr && info.argv[2]->TypeOf() == NATIVE_FUNCTION) ? // 2 param num + info.argv[2] : nullptr); // 2 param num + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + WLOGFE("[NAPI]Window is nullptr or get invalid param"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::shared_ptr contentStorage = (storage == nullptr) ? nullptr : + std::shared_ptr(engine.CreateReference(storage, 1)); + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, contentStorage, contextUrl](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]Window is nullptr or get invalid param"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + LoadContentTask(contentStorage, contextUrl, weakWindow, engine, task); + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnLoadContent", + engine, CreateAsyncTaskWithLastParam(engine, callBack, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnLoadContent(NativeEngine& engine, NativeCallbackInfo& info) +{ + bool oldApi = false; + if (info.argc == 1) { + oldApi = true; + } else if (info.argc == 2) { // 2 param num + NativeValue* value = info.argv[1]; + if (value== nullptr || value->TypeOf() != NATIVE_FUNCTION) { + oldApi = false; + } else { + oldApi = true; + } + } + if (oldApi) { + return LoadContentScheduleOld(engine, info); + } else { + return LoadContentScheduleNew(engine, info); + } +} + +NativeValue* JsWindow::OnSetUIContent(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 2 maximum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + std::string contextUrl; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], contextUrl)) { + WLOGFE("[NAPI]Failed to convert parameter to context url"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + NativeValue* storage = nullptr; + NativeValue* callBack = nullptr; + if (info.argc >= 2) { // 2 param num + callBack = info.argv[1]; + } + std::shared_ptr contentStorage = (storage == nullptr) ? nullptr : + std::shared_ptr(engine.CreateReference(storage, 1)); + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, contentStorage, contextUrl](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + LoadContentTask(contentStorage, contextUrl, weakWindow, engine, task); + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetUIContent", + engine, CreateAsyncTaskWithLastParam(engine, callBack, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetFullScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool isFullScreen = false; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isFullScreen"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + isFullScreen = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isFullScreen, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetFullScreen(isFullScreen); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window SetFullScreen failed.")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set full screen end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetFullScreen", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetLayoutFullScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool isLayoutFullScreen = false; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isLayoutFullScreen"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + isLayoutFullScreen = static_cast(*nativeVal); + } + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isLayoutFullScreen, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetLayoutFullScreen(isLayoutFullScreen); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(ret), "Window OnSetLayoutFullScreen failed.")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set layout full screen end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetLayoutFullScreen", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowLayoutFullScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool isLayoutFullScreen = false; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isLayoutFullScreen"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + isLayoutFullScreen = static_cast(*nativeVal); + } + } + if (errCode != WmErrorCode::WM_OK) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isLayoutFullScreen](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Invalidate params.")); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->SetLayoutFullScreen(isLayoutFullScreen)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(ret), "Window OnSetLayoutFullScreen failed.")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set layout full screen end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowLayoutFullScreen", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetSystemBarEnable(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 2 || windowToken_ == nullptr) { // 2: maximum params num + WLOGFE("[NAPI]Window is nullptr or argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + std::map systemBarProperties; + if (errCode == WMError::WM_OK && !GetSystemBarStatus(systemBarProperties, engine, info, windowToken_)) { + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, systemBarProperties, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_STATUS_BAR)); + ret = weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_NAVIGATION_BAR)); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(ret), "JsWindow::OnSetSystemBarEnable failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set system bar enable end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* lastParam = nullptr; + if (info.argc > 0 && info.argv[0]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[0]; + } else if (info.argc > 1 && info.argv[1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetSystemBarEnable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowSystemBarEnable(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + std::map systemBarProperties; + if (info.argc < 1 || windowToken_ == nullptr || // 1: params num + !GetSystemBarStatus(systemBarProperties, engine, info, windowToken_)) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, systemBarProperties](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_STATUS_BAR))); + if (ret != WmErrorCode::WM_OK) { + task.Reject(engine, CreateJsError(engine, + static_cast(ret), "JsWindow::OnSetWindowSystemBarEnable failed")); + } + ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_NAVIGATION_BAR))); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(ret), "JsWindow::OnSetWindowSystemBarEnable failed")); + } + }; + NativeValue* lastParam = nullptr; + if (info.argc >= 1 && info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[0]; + } else if (info.argc >= 2 && // 2 arg count + info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) { + lastParam = info.argv[1]; + } + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowSystemBarEnable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetSystemBarProperties(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + std::map systemBarProperties; + if (errCode == WMError::WM_OK) { + NativeObject* nativeObj = ConvertNativeValueTo(info.argv[0]); + if (nativeObj == nullptr) { + WLOGFE("[NAPI]Failed to convert object to SystemBarProperties"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + if (!SetSystemBarPropertiesFromJs(engine, nativeObj, systemBarProperties, windowToken_)) { + WLOGFE("[NAPI]Failed to GetSystemBarProperties From Js Object"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + } + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, systemBarProperties, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + WMError ret = weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_STATUS_BAR)); + ret = weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_NAVIGATION_BAR)); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "JsWindow::OnSetSystemBarProperties failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set system bar properties end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetSystemBarProperties", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowSystemBarProperties(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 2: maximum params num + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + std::map systemBarProperties; + if (errCode == WmErrorCode::WM_OK) { + NativeObject* nativeObj = ConvertNativeValueTo(info.argv[0]); + if (nativeObj == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + if (!SetSystemBarPropertiesFromJs(engine, nativeObj, systemBarProperties, windowToken_)) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, systemBarProperties](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_STATUS_BAR))); + if (ret != WmErrorCode::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(ret))); + } + ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, + systemBarProperties.at(WindowType::WINDOW_TYPE_NAVIGATION_BAR))); + if (ret != WmErrorCode::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(ret))); + } + task.Resolve(engine, engine.CreateUndefined()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowSystemBarProperties", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnGetAvoidArea(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + AvoidAreaType avoidAreaType = AvoidAreaType::TYPE_SYSTEM; + if (errCode == WMError::WM_OK) { + NativeNumber* nativeMode = ConvertNativeValueTo(info.argv[0]); + if (nativeMode == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to AvoidAreaType"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + avoidAreaType = static_cast(static_cast(*nativeMode)); + errCode = ((avoidAreaType > AvoidAreaType::TYPE_KEYBOARD) || + (avoidAreaType < AvoidAreaType::TYPE_SYSTEM)) ? WMError::WM_ERROR_INVALID_PARAM : WMError::WM_OK; + } + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode, avoidAreaType](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + // getAvoidRect by avoidAreaType + AvoidArea avoidArea; + WMError ret = weakWindow->GetAvoidAreaByType(avoidAreaType, avoidArea); + if (ret != WMError::WM_OK) { + avoidArea.topRect_ = g_emptyRect; + avoidArea.leftRect_ = g_emptyRect; + avoidArea.rightRect_ = g_emptyRect; + avoidArea.bottomRect_ = g_emptyRect; + } + NativeValue* avoidAreaObj = ConvertAvoidAreaToJsValue(engine, avoidArea, avoidAreaType); + if (avoidAreaObj != nullptr) { + task.Resolve(engine, avoidAreaObj); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(WMError::WM_ERROR_NULLPTR), "JsWindow::OnGetAvoidArea failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] get avoid area end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnGetAvoidArea", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnGetWindowAvoidAreaSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + AvoidAreaType avoidAreaType = AvoidAreaType::TYPE_SYSTEM; + NativeNumber* nativeMode = ConvertNativeValueTo(info.argv[0]); + if (nativeMode == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + avoidAreaType = static_cast(static_cast(*nativeMode)); + errCode = ((avoidAreaType > AvoidAreaType::TYPE_KEYBOARD) || (avoidAreaType < AvoidAreaType::TYPE_SYSTEM)) ? + WmErrorCode::WM_ERROR_INVALID_PARAM : WmErrorCode::WM_OK; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + if (window == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + // getAvoidRect by avoidAreaType + AvoidArea avoidArea; + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(window->GetAvoidAreaByType(avoidAreaType, avoidArea)); + if (ret != WmErrorCode::WM_OK) { + avoidArea.topRect_ = g_emptyRect; + avoidArea.leftRect_ = g_emptyRect; + avoidArea.rightRect_ = g_emptyRect; + avoidArea.bottomRect_ = g_emptyRect; + } + NativeValue* avoidAreaObj = ConvertAvoidAreaToJsValue(engine, avoidArea, avoidAreaType); + if (avoidAreaObj != nullptr) { + return avoidAreaObj; + } else { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } +} + +NativeValue* JsWindow::OnIsShowing(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + bool state = weakWindow->GetWindowState() == WindowState::STATE_SHOWN; + task.Resolve(engine, CreateJsValue(engine, state)); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] get show state end, state = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), state); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnIsShowing", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnIsWindowShowingSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + if (window == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + bool state = (window->GetWindowState() == WindowState::STATE_SHOWN); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] get show state end, state = %{public}u", + window->GetWindowId(), window->GetWindowName().c_str(), state); + return CreateJsValue(engine, state); +} + +NativeValue* JsWindow::OnSetPreferredOrientation(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + Orientation requestedOrientation = Orientation::UNSPECIFIED; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + NativeNumber* nativeType = ConvertNativeValueTo(info.argv[0]); + if (nativeType == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + WLOGFE("[NAPI]Failed to convert parameter to Orientation"); + } else { + requestedOrientation = JS_TO_NATIVE_ORIENTATION_MAP.at( + static_cast(static_cast(*nativeType))); + if (requestedOrientation < Orientation::BEGIN || requestedOrientation > Orientation::END) { + WLOGFE("[NAPI]Orientation %{public}u invalid!", static_cast(requestedOrientation)); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + WLOGFE("[NAPI]get invalid param"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, requestedOrientation](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + task.Reject(engine, CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "OnSetPreferredOrientation failed")); + return; + } + weakWindow->SetRequestedOrientation(requestedOrientation); + task.Resolve(engine, engine.CreateUndefined()); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnSetPreferredOrientation end, orientation = %{public}u", + weakWindow->GetWindowId(), + weakWindow->GetWindowName().c_str(), + static_cast(requestedOrientation)); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetPreferredOrientation", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnIsSupportWideGamut(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + bool flag = weakWindow->IsSupportWideGamut(); + task.Resolve(engine, CreateJsValue(engine, flag)); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnIsSupportWideGamut end, ret = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), flag); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnIsSupportWideGamut", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnIsWindowSupportWideGamut(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr or get invalid param"); + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + bool flag = weakWindow->IsSupportWideGamut(); + task.Resolve(engine, CreateJsValue(engine, flag)); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnIsWindowSupportWideGamut end, ret = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), flag); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + ((info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnIsWindowSupportWideGamut", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetBackgroundColor(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + std::string color; + if (errCode == WMError::WM_OK && !ConvertFromJsValue(engine, info.argv[0], color)) { + WLOGFE("[NAPI]Failed to convert parameter to background color"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, color, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetBackgroundColor(color); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), + "Window set background color failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set background color end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetBackgroundColor", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowBackgroundColorSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + std::string color; + if (errCode == WmErrorCode::WM_OK && !ConvertFromJsValue(engine, info.argv[0], color)) { + WLOGFE("[NAPI]Failed to convert parameter to background color"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + if (window == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(window->SetBackgroundColor(color)); + if (ret == WmErrorCode::WM_OK) { + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set background color end", + window->GetWindowId(), window->GetWindowName().c_str()); + return engine.CreateUndefined(); + } else { + engine.Throw(CreateJsError(engine, static_cast(ret))); + return engine.CreateUndefined(); + } +} + +NativeValue* JsWindow::OnSetBrightness(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + float brightness = UNDEFINED_BRIGHTNESS; + if (errCode == WMError::WM_OK) { + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to brightness"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + brightness = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, brightness, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetBrightness(brightness); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set brightness failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set brightness end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetBrightness", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowBrightness(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + float brightness = UNDEFINED_BRIGHTNESS; + if (errCode == WmErrorCode::WM_OK) { + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to brightness"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + brightness = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, brightness](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Invalidate params.")); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->SetBrightness(brightness)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set brightness failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set brightness end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowBrightness", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetDimBehind(NativeEngine& engine, NativeCallbackInfo& info) +{ + AsyncTask::CompleteCallback complete = + [](NativeEngine& engine, AsyncTask& task, int32_t status) { + task.Reject(engine, CreateJsError(engine, static_cast(WMError::WM_ERROR_DEVICE_NOT_SUPPORT))); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetDimBehind", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetFocusable(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool focusable = true; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to focusable"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + focusable = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, focusable, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetFocusable(focusable); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set focusable failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set focusable end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetFocusable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowFocusable(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool focusable = true; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to focusable"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + focusable = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, focusable](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Invalidate params.")); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->SetFocusable(focusable)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set focusable failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set focusable end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowFocusable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetKeepScreenOn(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool keepScreenOn = true; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to keepScreenOn"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + keepScreenOn = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, keepScreenOn, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetKeepScreenOn(keepScreenOn); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), + "Window set keep screen on failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set keep screen on end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetKeepScreenOn", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowKeepScreenOn(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool keepScreenOn = true; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to keepScreenOn"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + keepScreenOn = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, keepScreenOn](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Invalidate params.")); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->SetKeepScreenOn(keepScreenOn)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), + "Window set keep screen on failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set keep screen on end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowKeepScreenOn", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWakeUpScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set wake up screen permission denied!"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1 || windowToken_ == nullptr) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + bool wakeUp = false; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to keepScreenOn"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } else { + wakeUp = static_cast(*nativeVal); + } + } + + windowToken_->SetTurnScreenOn(wakeUp); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set wake up screen %{public}d end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), wakeUp); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnSetOutsideTouchable(NativeEngine& engine, NativeCallbackInfo& info) +{ + AsyncTask::CompleteCallback complete = + [](NativeEngine& engine, AsyncTask& task, int32_t status) { + task.Reject(engine, CreateJsError(engine, static_cast(WMError::WM_ERROR_DEVICE_NOT_SUPPORT))); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetOutsideTouchable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetPrivacyMode(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool isPrivacyMode = false; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isPrivacyMode"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + isPrivacyMode = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isPrivacyMode, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params")); + return; + } + weakWindow->SetPrivacyMode(isPrivacyMode); + task.Resolve(engine, engine.CreateUndefined()); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set privacy mode end, mode = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), isPrivacyMode); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetPrivacyMode", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowPrivacyMode(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool isPrivacyMode = false; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isPrivacyMode"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + isPrivacyMode = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isPrivacyMode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Invalidate params")); + return; + } + weakWindow->SetPrivacyMode(isPrivacyMode); + task.Resolve(engine, engine.CreateUndefined()); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set privacy mode end, mode = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), isPrivacyMode); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowPrivacyMode", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetTouchable(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool touchable = true; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to touchable"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + touchable = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, touchable, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetTouchable(touchable); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set touchable failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set touchable end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetTouchable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowTouchable(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool touchable = true; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to touchable"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + touchable = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, touchable](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Invalidate params.")); + return; + } + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(weakWindow->SetTouchable(touchable)); + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set touchable failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set touchable end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowTouchable", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetTransparent(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + bool isTransparent = true; + if (errCode == WMError::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to isTransparent"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + isTransparent = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isTransparent, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetTransparent(isTransparent); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window set transparent failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set transparent end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetTransparent", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetCallingWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + uint32_t callingWindow = INVALID_WINDOW_ID; + if (errCode == WMError::WM_OK) { + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to touchable"); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + callingWindow = static_cast(*nativeVal); + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, callingWindow, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "Invalidate params.")); + return; + } + WMError ret = weakWindow->SetCallingWindow(callingWindow); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), + "Window set calling window failed")); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] set calling window end", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str()); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetCallingWindow", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnDisableWindowDecor(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (windowToken_ == nullptr) { + return engine.CreateUndefined(); + } + windowToken_->DisableAppWindowDecor(); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] disable app window decor end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str()); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnSetColorSpace(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + ColorSpace colorSpace = ColorSpace::COLOR_SPACE_DEFAULT; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + NativeNumber* nativeType = ConvertNativeValueTo(info.argv[0]); + if (nativeType == nullptr) { + errCode = WMError::WM_ERROR_INVALID_PARAM; + WLOGFE("[NAPI]Failed to convert parameter to ColorSpace"); + } else { + colorSpace = static_cast(static_cast(*nativeType)); + if (colorSpace > ColorSpace::COLOR_SPACE_WIDE_GAMUT) { + WLOGFE("[NAPI]ColorSpace %{public}u invalid!", static_cast(colorSpace)); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + } + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, colorSpace, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode), "OnSetColorSpace failed")); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + weakWindow->SetColorSpace(colorSpace); + task.Resolve(engine, engine.CreateUndefined()); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnSetColorSpace end, colorSpace = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), static_cast(colorSpace)); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetColorSpace", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetWindowColorSpace(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + ColorSpace colorSpace = ColorSpace::COLOR_SPACE_DEFAULT; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + NativeNumber* nativeType = ConvertNativeValueTo(info.argv[0]); + if (nativeType == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + WLOGFE("[NAPI]Failed to convert parameter to ColorSpace"); + } else { + colorSpace = static_cast(static_cast(*nativeType)); + if (colorSpace > ColorSpace::COLOR_SPACE_WIDE_GAMUT) { + WLOGFE("[NAPI]ColorSpace %{public}u invalid!", static_cast(colorSpace)); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, colorSpace](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "OnSetWindowColorSpace failed")); + return; + } + weakWindow->SetColorSpace(colorSpace); + task.Resolve(engine, engine.CreateUndefined()); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnSetWindowColorSpace end, colorSpace = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), static_cast(colorSpace)); + }; + + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetWindowColorSpace", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnGetColorSpace(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc > 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, errCode](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr || errCode != WMError::WM_OK) { + task.Reject(engine, CreateJsError(engine, static_cast(errCode))); + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return; + } + ColorSpace colorSpace = weakWindow->GetColorSpace(); + task.Resolve(engine, CreateJsValue(engine, static_cast(colorSpace))); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnGetColorSpace end, colorSpace = %{public}u", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), static_cast(colorSpace)); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnGetColorSpace", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnGetWindowColorSpaceSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + if (window == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + ColorSpace colorSpace = window->GetColorSpace(); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnGetColorSpace end, colorSpace = %{public}u", + window->GetWindowId(), window->GetWindowName().c_str(), static_cast(colorSpace)); + + return CreateJsValue(engine, static_cast(colorSpace)); +} + +NativeValue* JsWindow::OnDump(NativeEngine& engine, NativeCallbackInfo& info) +{ + WLOGFD("[NAPI]dump window start"); + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + return nullptr; + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]window is nullptr or get invalid param"); + return nullptr; + } + std::vector params; + if (!ConvertNativeValueToVector(engine, info.argv[0], params)) { + WLOGFE("[NAPI]ConvertNativeValueToVector fail"); + return nullptr; + } + std::vector dumpInfo; + windowToken_->DumpInfo(params, dumpInfo); + NativeValue* dumpInfoValue = CreateNativeArray(engine, dumpInfo); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] dump end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str()); + return dumpInfoValue; +} + +NativeValue* JsWindow::Snapshot(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Snapshot"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSnapshot(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::OnSetForbidSplitMove(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool isForbidSplitMove = false; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + isForbidSplitMove = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, isForbidSplitMove](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), "Invalidate params.")); + return; + } + WmErrorCode ret; + if (isForbidSplitMove) { + ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->AddWindowFlag(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE)); + } else { + ret = WM_JS_TO_ERROR_CODE_MAP.at( + weakWindow->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE)); + } + if (ret == WmErrorCode::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(ret), "Window OnSetForbidSplitMove failed.")); + } + }; + NativeValue* lastParam = (info.argc <= 1) ? nullptr : + ((info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSetForbidSplitMove", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSnapshot(NativeEngine& engine, NativeCallbackInfo& info) +{ + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + WLOGFE("[NAPI]window is nullptr"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + + std::shared_ptr pixelMap = weakWindow->Snapshot(); + if (pixelMap == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + WLOGFE("[NAPI]window snapshot get pixelmap is null"); + return; + } + + auto nativePixelMap = reinterpret_cast( + Media::PixelMapNapi::CreatePixelMap(reinterpret_cast(&engine), pixelMap)); + if (nativePixelMap == nullptr) { + WLOGFE("[NAPI]window snapshot get nativePixelMap is null"); + } + task.Resolve(engine, nativePixelMap); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] OnSnapshot, WxH=%{public}dx%{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), + pixelMap->GetWidth(), pixelMap->GetHeight()); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + ((info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnSnapshot", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnSetSnapshotSkip(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: params num + WLOGFE("[NAPI] inbalid param"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + bool isSkip = false; + if (errCode == WmErrorCode::WM_OK) { + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } else { + isSkip = static_cast(*nativeVal); + } + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + if (window == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + + window->SetSnapshotSkip(isSkip); + WLOGFD("NAPI [%{public}u, %{public}s] set snapshotSkip end", + window->GetWindowId(), window->GetWindowName().c_str()); + + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnOpacity(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]Opacity is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to alpha"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (MathHelper::LessNotEqual(*nativeVal, 0.0) || MathHelper::GreatNotEqual(*nativeVal, 1.0)) { + WLOGFE("[NAPI]alpha should greater than 0 or smaller than 1.0"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + float alpha = static_cast(*nativeVal); + windowToken_->SetAlpha(alpha); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] Opacity end, alpha = %{public}f", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), alpha); + return engine.CreateUndefined(); +} + +static bool IsPivotValid(double data) +{ + if (MathHelper::LessNotEqual(data, 0.0) || (MathHelper::GreatNotEqual(data, 1.0))) { + return false; + } + return true; +} + +static bool IsScaleValid(double data) +{ + if (!MathHelper::GreatNotEqual(data, 0.0)) { + return false; + } + return true; +} + +bool JsWindow::ParseScaleOption(NativeEngine& engine, NativeObject* jsObject, Transform& trans) +{ + double data = 0.0f; + if (ParseJsValue(jsObject, engine, "pivotX", data)) { + if (!IsPivotValid(data)) { + return false; + } + trans.pivotX_ = data; + } + if (ParseJsValue(jsObject, engine, "pivotY", data)) { + if (!IsPivotValid(data)) { + return false; + } + trans.pivotY_ = data; + } + if (ParseJsValue(jsObject, engine, "x", data)) { + if (!IsScaleValid(data)) { + return false; + } + trans.scaleX_ = data; + } + if (ParseJsValue(jsObject, engine, "y", data)) { + if (!IsScaleValid(data)) { + return false; + } + trans.scaleY_ = data; + } + return true; +} + +NativeValue* JsWindow::OnScale(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]Scale is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeObject* nativeObj = ConvertNativeValueTo(info.argv[0]); + if (nativeObj == nullptr) { + WLOGFE("[NAPI]Failed to convert object to ScaleOptions"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + auto trans = windowToken_->GetTransform(); + if (!ParseScaleOption(engine, nativeObj, trans)) { + WLOGFE("[NAPI] PivotX or PivotY should between 0.0 ~ 1.0, scale should greater than 0.0"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + windowToken_->SetTransform(trans); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] Scale end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str()); + WLOGFD("[NAPI]scaleX = %{public}f, scaleY = %{public}f, pivotX = %{public}f pivotY = %{public}f", + trans.scaleX_, trans.scaleY_, trans.pivotX_, trans.pivotY_); + return engine.CreateUndefined(); +} + +bool JsWindow::ParseRotateOption(NativeEngine& engine, NativeObject* jsObject, Transform& trans) +{ + double data = 0.0f; + if (ParseJsValue(jsObject, engine, "pivotX", data)) { + if (!IsPivotValid(data)) { + return false; + } + trans.pivotX_ = data; + } + if (ParseJsValue(jsObject, engine, "pivotY", data)) { + if (!IsPivotValid(data)) { + return false; + } + trans.pivotY_ = data; + } + if (ParseJsValue(jsObject, engine, "x", data)) { + trans.rotationX_ = data; + } + if (ParseJsValue(jsObject, engine, "y", data)) { + trans.rotationY_ = data; + } + if (ParseJsValue(jsObject, engine, "z", data)) { + trans.rotationZ_ = data; + } + return true; +} + +NativeValue* JsWindow::OnRotate(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]Rotate is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeObject* nativeObj = ConvertNativeValueTo(info.argv[0]); + if (nativeObj == nullptr) { + WLOGFE("[NAPI]Failed to convert object to RotateOptions"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + // cannot use sync task since next transform base on current transform + auto trans = windowToken_->GetTransform(); + if (!ParseRotateOption(engine, nativeObj, trans)) { + WLOGFE("[NAPI] PivotX or PivotY should between 0.0 ~ 1.0"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + windowToken_->SetTransform(trans); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] Rotate end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str()); + WLOGFD("[NAPI]rotateX = %{public}f, rotateY = %{public}f," \ + "rotateZ = %{public}f pivotX = %{public}f pivotY = %{public}f", + trans.rotationX_, trans.rotationY_, trans.rotationZ_, trans.pivotX_, trans.pivotY_); + return engine.CreateUndefined(); +} + +bool JsWindow::ParseTranslateOption(NativeEngine& engine, NativeObject* jsObject, Transform& trans) +{ + double data = 0.0f; + if (ParseJsValue(jsObject, engine, "x", data)) { + trans.translateX_ = data; + } + if (ParseJsValue(jsObject, engine, "y", data)) { + trans.translateY_ = data; + } + if (ParseJsValue(jsObject, engine, "z", data)) { + trans.translateZ_ = data; + } + return true; +} + +NativeValue* JsWindow::OnTranslate(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]Translate is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeObject* nativeObj = ConvertNativeValueTo(info.argv[0]); + if (nativeObj == nullptr) { + WLOGFE("[NAPI]Failed to convert object to TranslateOptions"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + auto trans = windowToken_->GetTransform(); + if (!ParseTranslateOption(engine, nativeObj, trans)) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + windowToken_->SetTransform(trans); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] Translate end," \ + "translateX = %{public}f, translateY = %{public}f, translateZ = %{public}f", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), + trans.translateX_, trans.translateY_, trans.translateZ_); + return engine.CreateUndefined(); +} + +void JsWindow::CreateTransitionController(NativeEngine& engine) +{ + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]windowToken_ is nullptr not match"); + return; + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]CreateTransitionController is not allowed since window is not system window"); + return; + } + NativeValue* objValue = engine.CreateObject(); + auto name = GetWindowName(); + std::shared_ptr jsWindowObj = FindJsWindowObject(name); + if (jsWindowObj == nullptr || jsWindowObj->Get() == nullptr) { + return; + } + sptr nativeController = new JsTransitionController( + engine, jsWindowObj, windowToken_); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to convert to TransitionController Object"); + return; + } + object->SetNativePointer(new wptr(nativeController), + [](NativeEngine*, void* data, void*) { + WLOGFE("Finalizer for wptr form native Transition Controller is called"); + delete static_cast*>(data); + }, nullptr); + windowToken_->RegisterAnimationTransitionController(nativeController); + jsTransControllerObj_.reset(engine.CreateReference(objValue, 1)); + nativeController->SetJsController(jsTransControllerObj_); + WLOGFD("[NAPI]Window [%{public}u, %{public}s] CreateTransitionController end", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str()); +} + +NativeValue* JsWindow::OnGetTransitionController(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]OnGetTransitionController is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + if (jsTransControllerObj_ == nullptr || jsTransControllerObj_->Get() == nullptr) { + CreateTransitionController(engine); + } + return jsTransControllerObj_ == nullptr ? nullptr : jsTransControllerObj_->Get(); +} + +NativeValue* JsWindow::OnSetCornerRadius(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set corner radius permission denied!"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]SetCornerRadius is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr || MathHelper::LessNotEqual(static_cast(*nativeVal), 0.0)) { + WLOGFE("[NAPI]SetCornerRadius invalid radius"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + float radius = static_cast(*nativeVal); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->SetCornerRadius(radius)); + if (ret != WmErrorCode::WM_OK) { + WLOGFE("[NAPI]Window SetCornerRadius failed"); + engine.Throw(CreateJsError(engine, static_cast(ret))); + return engine.CreateUndefined(); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] SetCornerRadius end, radius = %{public}f", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), radius); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnSetShadow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode ret = WmErrorCode::WM_OK; + if (info.argc < 1) { // 1: min param num + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + + { // parse the 1st param: radius + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr || MathHelper::LessNotEqual(static_cast(*nativeVal), 0.0)) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->SetShadowRadius(static_cast(*nativeVal))); + } + + if ((ret == WmErrorCode::WM_OK) && (info.argc >= 2)) { // parse the 2nd param: color + std::string color; + if (!ConvertFromJsValue(engine, info.argv[1], color)) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->SetShadowColor(color)); + } + + if (ret != WmErrorCode::WM_OK) { + engine.Throw(CreateJsError(engine, static_cast(ret))); + return engine.CreateUndefined(); + } + + if (info.argc >= 3) { // parse the 3rd param: offsetX + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[2]); // 2: the 3rd param + if (nativeVal == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + windowToken_->SetShadowOffsetX(static_cast(*nativeVal)); + } + + if (info.argc >= 4) { // parse the 4th param: offsetY + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[3]); // 3: the 4th param + if (nativeVal == nullptr) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + windowToken_->SetShadowOffsetY(static_cast(*nativeVal)); + } + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnSetBlur(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]SetBlur is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr || MathHelper::LessNotEqual(static_cast(*nativeVal), 0.0)) { + WLOGFE("[NAPI]SetBlur invalid radius"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + float radius = static_cast(*nativeVal); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->SetBlur(radius)); + if (ret != WmErrorCode::WM_OK) { + WLOGFE("[NAPI]Window SetBlur failed"); + engine.Throw(CreateJsError(engine, static_cast(ret))); + return engine.CreateUndefined(); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] SetBlur end, radius = %{public}f", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), radius); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnSetBackdropBlur(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]SetBackdropBlur is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr || MathHelper::LessNotEqual(static_cast(*nativeVal), 0.0)) { + WLOGFE("[NAPI]SetBackdropBlur invalid radius"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + float radius = static_cast(*nativeVal); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->SetBackdropBlur(radius)); + if (ret != WmErrorCode::WM_OK) { + WLOGFE("[NAPI]Window SetBackdropBlur failed"); + engine.Throw(CreateJsError(engine, static_cast(ret))); + return engine.CreateUndefined(); + } + WLOGFD("[NAPI]Window [%{public}u, %{public}s] SetBackdropBlur end, radius = %{public}f", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), radius); + return engine.CreateUndefined(); +} + +NativeValue* JsWindow::OnSetBackdropBlurStyle(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (windowToken_ == nullptr) { + WLOGFE("[NAPI]WindowToken_ is nullptr"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (!WindowHelper::IsSystemWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]SetBackdropBlurStyle is not allowed since window is not system window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + + NativeNumber* nativeMode = ConvertNativeValueTo(info.argv[0]); + if (nativeMode == nullptr || + static_cast(*nativeMode) > static_cast(WindowBlurStyle::WINDOW_BLUR_THICK)) { + WLOGFE("[NAPI]SetBackdropBlurStyle Invalid window blur style"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + WindowBlurStyle style = static_cast(static_cast(*nativeMode)); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(windowToken_->SetBackdropBlurStyle(style)); + if (ret != WmErrorCode::WM_OK) { + WLOGFE("[NAPI]Window SetBackdropBlurStyle failed"); + engine.Throw(CreateJsError(engine, static_cast(ret))); + return engine.CreateUndefined(); + } + + WLOGFD("[NAPI]Window [%{public}u, %{public}s] SetBackdropBlurStyle end, style = %{public}u", + windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), style); + return engine.CreateUndefined(); +} + +std::shared_ptr FindJsWindowObject(std::string windowName) +{ + WLOGFD("[NAPI]Try to find window %{public}s in g_jsWindowMap", windowName.c_str()); + std::lock_guard lock(g_mutex); + if (g_jsWindowMap.find(windowName) == g_jsWindowMap.end()) { + WLOGFD("[NAPI]Can not find window %{public}s in g_jsWindowMap", windowName.c_str()); + return nullptr; + } + return g_jsWindowMap[windowName]; +} + +NativeValue* CreateJsWindowObject(NativeEngine& engine, sptr& window) +{ + std::string windowName = window->GetWindowName(); + // avoid repeatedly create js window when getWindow + std::shared_ptr jsWindowObj = FindJsWindowObject(windowName); + if (jsWindowObj != nullptr && jsWindowObj->Get() != nullptr) { + WLOGFD("[NAPI]FindJsWindowObject %{public}s", windowName.c_str()); + return jsWindowObj->Get(); + } + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + + WLOGFD("[NAPI]CreateJsWindow %{public}s", windowName.c_str()); + std::unique_ptr jsWindow = std::make_unique(window); + object->SetNativePointer(jsWindow.release(), JsWindow::Finalizer, nullptr); + + BindFunctions(engine, object, "JsWindow"); + + std::shared_ptr jsWindowRef; + jsWindowRef.reset(engine.CreateReference(objValue, 1)); + std::lock_guard lock(g_mutex); + g_jsWindowMap[windowName] = jsWindowRef; + return objValue; +} + +void BindFunctions(NativeEngine& engine, NativeObject* object, const char *moduleName) +{ + BindNativeFunction(engine, *object, "show", moduleName, JsWindow::Show); + BindNativeFunction(engine, *object, "showWindow", moduleName, JsWindow::ShowWindow); + BindNativeFunction(engine, *object, "showWithAnimation", moduleName, JsWindow::ShowWithAnimation); + BindNativeFunction(engine, *object, "destroy", moduleName, JsWindow::Destroy); + BindNativeFunction(engine, *object, "destroyWindow", moduleName, JsWindow::DestroyWindow); + BindNativeFunction(engine, *object, "hide", moduleName, JsWindow::Hide); + BindNativeFunction(engine, *object, "hideWithAnimation", moduleName, JsWindow::HideWithAnimation); + BindNativeFunction(engine, *object, "moveTo", moduleName, JsWindow::MoveTo); + BindNativeFunction(engine, *object, "moveWindowTo", moduleName, JsWindow::MoveWindowTo); + BindNativeFunction(engine, *object, "resetSize", moduleName, JsWindow::Resize); + BindNativeFunction(engine, *object, "resize", moduleName, JsWindow::ResizeWindow); + BindNativeFunction(engine, *object, "setWindowType", moduleName, JsWindow::SetWindowType); + BindNativeFunction(engine, *object, "setWindowMode", moduleName, JsWindow::SetWindowMode); + BindNativeFunction(engine, *object, "getProperties", moduleName, JsWindow::GetProperties); + BindNativeFunction(engine, *object, "getWindowProperties", moduleName, JsWindow::GetWindowPropertiesSync); + BindNativeFunction(engine, *object, "on", moduleName, JsWindow::RegisterWindowCallback); + BindNativeFunction(engine, *object, "off", moduleName, JsWindow::UnregisterWindowCallback); + BindNativeFunction(engine, *object, "bindDialogTarget", moduleName, JsWindow::BindDialogTarget); + BindNativeFunction(engine, *object, "loadContent", moduleName, JsWindow::LoadContent); + BindNativeFunction(engine, *object, "setUIContent", moduleName, JsWindow::SetUIContent); + BindNativeFunction(engine, *object, "setFullScreen", moduleName, JsWindow::SetFullScreen); + BindNativeFunction(engine, *object, "setLayoutFullScreen", moduleName, JsWindow::SetLayoutFullScreen); + BindNativeFunction(engine, *object, "setWindowLayoutFullScreen", moduleName, JsWindow::SetWindowLayoutFullScreen); + BindNativeFunction(engine, *object, "setSystemBarEnable", moduleName, JsWindow::SetSystemBarEnable); + BindNativeFunction(engine, *object, "setWindowSystemBarEnable", moduleName, JsWindow::SetWindowSystemBarEnable); + BindNativeFunction(engine, *object, "setSystemBarProperties", moduleName, JsWindow::SetSystemBarProperties); + BindNativeFunction(engine, *object, "setWindowSystemBarProperties", + moduleName, JsWindow::SetWindowSystemBarProperties); + BindNativeFunction(engine, *object, "getAvoidArea", moduleName, JsWindow::GetAvoidArea); + BindNativeFunction(engine, *object, "getWindowAvoidArea", moduleName, JsWindow::GetWindowAvoidAreaSync); + BindNativeFunction(engine, *object, "isShowing", moduleName, JsWindow::IsShowing); + BindNativeFunction(engine, *object, "isWindowShowing", moduleName, JsWindow::IsWindowShowingSync); + BindNativeFunction(engine, *object, "isSupportWideGamut", moduleName, JsWindow::IsSupportWideGamut); + BindNativeFunction(engine, *object, "isWindowSupportWideGamut", moduleName, JsWindow::IsWindowSupportWideGamut); + BindNativeFunction(engine, *object, "setColorSpace", moduleName, JsWindow::SetColorSpace); + BindNativeFunction(engine, *object, "setWindowColorSpace", moduleName, JsWindow::SetWindowColorSpace); + BindNativeFunction(engine, *object, "getColorSpace", moduleName, JsWindow::GetColorSpace); + BindNativeFunction(engine, *object, "getWindowColorSpace", moduleName, JsWindow::GetWindowColorSpaceSync); + BindNativeFunction(engine, *object, "setBackgroundColor", moduleName, JsWindow::SetBackgroundColor); + BindNativeFunction(engine, *object, "setWindowBackgroundColor", moduleName, JsWindow::SetWindowBackgroundColorSync); + BindNativeFunction(engine, *object, "setBrightness", moduleName, JsWindow::SetBrightness); + BindNativeFunction(engine, *object, "setWindowBrightness", moduleName, JsWindow::SetWindowBrightness); + BindNativeFunction(engine, *object, "setDimBehind", moduleName, JsWindow::SetDimBehind); + BindNativeFunction(engine, *object, "setFocusable", moduleName, JsWindow::SetFocusable); + BindNativeFunction(engine, *object, "setWindowFocusable", moduleName, JsWindow::SetWindowFocusable); + BindNativeFunction(engine, *object, "setKeepScreenOn", moduleName, JsWindow::SetKeepScreenOn); + BindNativeFunction(engine, *object, "setWindowKeepScreenOn", moduleName, JsWindow::SetWindowKeepScreenOn); + BindNativeFunction(engine, *object, "setWakeUpScreen", moduleName, JsWindow::SetWakeUpScreen); + BindNativeFunction(engine, *object, "setOutsideTouchable", moduleName, JsWindow::SetOutsideTouchable); + BindNativeFunction(engine, *object, "setPrivacyMode", moduleName, JsWindow::SetPrivacyMode); + BindNativeFunction(engine, *object, "setWindowPrivacyMode", moduleName, JsWindow::SetWindowPrivacyMode); + BindNativeFunction(engine, *object, "setTouchable", moduleName, JsWindow::SetTouchable); + BindNativeFunction(engine, *object, "setWindowTouchable", moduleName, JsWindow::SetWindowTouchable); + BindNativeFunction(engine, *object, "setTransparent", moduleName, JsWindow::SetTransparent); + BindNativeFunction(engine, *object, "setCallingWindow", moduleName, JsWindow::SetCallingWindow); + BindNativeFunction(engine, *object, "setSnapshotSkip", moduleName, JsWindow::SetSnapshotSkip); + BindNativeFunction(engine, *object, "disableWindowDecor", moduleName, JsWindow::DisableWindowDecor); + BindNativeFunction(engine, *object, "dump", moduleName, JsWindow::Dump); + BindNativeFunction(engine, *object, "setForbidSplitMove", moduleName, JsWindow::SetForbidSplitMove); + BindNativeFunction(engine, *object, "setPreferredOrientation", moduleName, JsWindow::SetPreferredOrientation); + BindNativeFunction(engine, *object, "opacity", moduleName, JsWindow::Opacity); + BindNativeFunction(engine, *object, "scale", moduleName, JsWindow::Scale); + BindNativeFunction(engine, *object, "rotate", moduleName, JsWindow::Rotate); + BindNativeFunction(engine, *object, "translate", moduleName, JsWindow::Translate); + BindNativeFunction(engine, *object, "getTransitionController", moduleName, JsWindow::GetTransitionController); + BindNativeFunction(engine, *object, "snapshot", moduleName, JsWindow::Snapshot); + BindNativeFunction(engine, *object, "setCornerRadius", moduleName, JsWindow::SetCornerRadius); + BindNativeFunction(engine, *object, "setShadow", moduleName, JsWindow::SetShadow); + BindNativeFunction(engine, *object, "setBlur", moduleName, JsWindow::SetBlur); + BindNativeFunction(engine, *object, "setBackdropBlur", moduleName, JsWindow::SetBackdropBlur); + BindNativeFunction(engine, *object, "setBackdropBlurStyle", moduleName, JsWindow::SetBackdropBlurStyle); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.h b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.h new file mode 100644 index 0000000..93be56b --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021-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_WINDOW_H +#define OHOS_JS_WINDOW_H + +#include "js_runtime_utils.h" + +#ifndef WINDOW_PREVIEW +#include "js_window_register_manager.h" +#else +#include "mock/js_window_register_manager.h" +#endif + +#include "js_window_utils.h" +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +NativeValue* CreateJsWindowObject(NativeEngine& engine, sptr& window); +std::shared_ptr FindJsWindowObject(std::string windowName); +void BindFunctions(NativeEngine& engine, NativeObject* object, const char *moduleName); +class JsWindow final { +public: + explicit JsWindow(const sptr& window); + ~JsWindow(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* Show(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* ShowWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* ShowWithAnimation(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Destroy(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* DestroyWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Hide(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* HideWithAnimation(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* MoveTo(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* MoveWindowTo(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Resize(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* ResizeWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowType(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowMode(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetProperties(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetWindowPropertiesSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* RegisterWindowCallback(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* UnregisterWindowCallback(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* BindDialogTarget(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* LoadContent(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetUIContent(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetFullScreen(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetLayoutFullScreen(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowLayoutFullScreen(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetSystemBarEnable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowSystemBarEnable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetSystemBarProperties(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowSystemBarProperties(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetAvoidArea(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetWindowAvoidAreaSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* IsShowing(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* IsWindowShowingSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetBackgroundColor(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowBackgroundColorSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetBrightness(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowBrightness(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetDimBehind(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetFocusable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowFocusable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetKeepScreenOn(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowKeepScreenOn(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWakeUpScreen(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetOutsideTouchable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetPrivacyMode(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowPrivacyMode(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetTouchable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowTouchable(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetTransparent(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetCallingWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetPreferredOrientation(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* DisableWindowDecor(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetSnapshotSkip(NativeEngine* engine, NativeCallbackInfo* info); + // colorspace, gamut + static NativeValue* IsSupportWideGamut(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* IsWindowSupportWideGamut(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetColorSpace(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetWindowColorSpace(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetColorSpace(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetWindowColorSpaceSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Dump(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetForbidSplitMove(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Snapshot(NativeEngine* engine, NativeCallbackInfo* info); + + // animation config + static NativeValue* Opacity(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Scale(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Rotate(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Translate(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetTransitionController(NativeEngine* engine, NativeCallbackInfo* info); + + // window effect + static NativeValue* SetCornerRadius(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetShadow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetBlur(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetBackdropBlur(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetBackdropBlurStyle(NativeEngine* engine, NativeCallbackInfo* info); +private: + std::string GetWindowName(); + static bool ParseScaleOption(NativeEngine& engine, NativeObject* jsObject, Transform& trans); + static bool ParseRotateOption(NativeEngine& engine, NativeObject* jsObject, Transform& trans); + static bool ParseTranslateOption(NativeEngine& engine, NativeObject* jsObject, Transform& trans); + NativeValue* LoadContentScheduleOld(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* LoadContentScheduleNew(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnShow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnShowWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnShowWithAnimation(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnDestroy(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnDestroyWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnHide(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnHideWithAnimation(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnMoveTo(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnMoveWindowTo(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnResize(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnResizeWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowType(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowMode(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetProperties(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetWindowPropertiesSync(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnRegisterWindowCallback(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnUnregisterWindowCallback(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnBindDialogTarget(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetFullScreen(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetLayoutFullScreen(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowLayoutFullScreen(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetSystemBarEnable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowSystemBarEnable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetSystemBarProperties(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowSystemBarProperties(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnLoadContent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetUIContent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetAvoidArea(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetWindowAvoidAreaSync(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnIsShowing(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnIsWindowShowingSync(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetPreferredOrientation(NativeEngine& engine, NativeCallbackInfo& info); + + // colorspace, gamut + NativeValue* OnIsSupportWideGamut(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnIsWindowSupportWideGamut(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetColorSpace(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowColorSpace(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetColorSpace(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetWindowColorSpaceSync(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetBackgroundColor(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowBackgroundColorSync(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetBrightness(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowBrightness(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetDimBehind(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetFocusable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowFocusable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetKeepScreenOn(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowKeepScreenOn(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWakeUpScreen(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetOutsideTouchable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetPrivacyMode(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowPrivacyMode(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetTouchable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetWindowTouchable(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetTransparent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetCallingWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnDisableWindowDecor(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnDump(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetForbidSplitMove(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSnapshot(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetSnapshotSkip(NativeEngine& engine, NativeCallbackInfo& info); + + // animation Config + NativeValue* OnOpacity(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnScale(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnRotate(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnTranslate(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetTransitionController(NativeEngine& engine, NativeCallbackInfo& info); + void CreateTransitionController(NativeEngine& engine); + + // window effect + NativeValue* OnSetCornerRadius(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetShadow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetBlur(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetBackdropBlur(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetBackdropBlurStyle(NativeEngine& engine, NativeCallbackInfo& info); + + sptr windowToken_ = nullptr; + std::unique_ptr registerManager_ = nullptr; + std::shared_ptr jsTransControllerObj_ = nullptr; +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp new file mode 100644 index 0000000..1abadaa --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2021-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_window_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, HILOG_DOMAIN_WINDOW, "JsWindowListener"}; +} + +JsWindowListener::~JsWindowListener() +{ + WLOGFI("[NAPI]~JsWindowListener"); +} + +void JsWindowListener::CallJsMethod(const char* methodName, NativeValue* const* argv, size_t argc) +{ + WLOGFI("[NAPI]CallJsMethod methodName = %{public}s", methodName); + if (engine_ == nullptr || jsCallBack_ == nullptr) { + WLOGFE("[NAPI]engine_ nullptr or jsCallBack_ is nullptr"); + return; + } + NativeValue* method = jsCallBack_->Get(); + if (method == nullptr) { + WLOGFE("[NAPI]Failed to get method callback from object"); + return; + } + engine_->CallFunction(engine_->CreateUndefined(), method, argv, argc); +} + +void JsWindowListener::OnSizeChange(Rect rect, WindowSizeChangeReason reason) +{ + WLOGFI("[NAPI]OnSizeChange, wh[%{public}u, %{public}u], reason = %{public}u", rect.width_, rect.height_, reason); + // js callback should run in js thread + std::unique_ptr complete = std::make_unique ( + [self = weakRef_, rect, eng = engine_] (NativeEngine &engine, + AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr || eng == nullptr) { + WLOGFE("[NAPI]this listener or engine is nullptr"); + return; + } + NativeValue* sizeValue = eng->CreateObject(); + NativeObject* object = ConvertNativeValueTo(sizeValue); + if (object == nullptr) { + WLOGFE("Failed to convert rect to jsObject"); + return; + } + object->SetProperty("width", CreateJsValue(*eng, rect.width_)); + object->SetProperty("height", CreateJsValue(*eng, rect.height_)); + NativeValue* argv[] = {sizeValue}; + thisListener->CallJsMethod(WINDOW_SIZE_CHANGE_CB.c_str(), argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnSizeChange", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnModeChange(WindowMode mode) +{ + WLOGFI("[NAPI]OnModeChange %{public}u", mode); +} + +void JsWindowListener::OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) +{ + WLOGFI("[NAPI]OnSystemBarPropertyChange"); + // js callback should run in js thread + std::unique_ptr complete = std::make_unique ( + [self = weakRef_, displayId, tints, eng = engine_] (NativeEngine &engine, + AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr || eng == nullptr) { + WLOGFE("[NAPI]this listener or engine is nullptr"); + return; + } + NativeValue* propertyValue = eng->CreateObject(); + NativeObject* object = ConvertNativeValueTo(propertyValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to convert prop to jsObject"); + return; + } + object->SetProperty("displayId", CreateJsValue(*eng, static_cast(displayId))); + object->SetProperty("regionTint", CreateJsSystemBarRegionTintArrayObject(*eng, tints)); + NativeValue* argv[] = {propertyValue}; + thisListener->CallJsMethod(SYSTEM_BAR_TINT_CHANGE_CB.c_str(), argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnSystemBarPropertyChange", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type) +{ + WLOGFI("[NAPI]OnAvoidAreaChanged"); + // js callback should run in js thread + std::unique_ptr complete = std::make_unique ( + [self = weakRef_, avoidArea, type, eng = engine_] (NativeEngine &engine, + AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr || eng == nullptr) { + WLOGFE("[NAPI]this listener or engine is nullptr"); + return; + } + NativeValue* avoidAreaValue = ConvertAvoidAreaToJsValue(engine, avoidArea, type); + if (avoidAreaValue == nullptr) { + return; + } + if (thisListener->isDeprecatedInterface_) { + NativeValue* argv[] = { avoidAreaValue }; + thisListener->CallJsMethod(SYSTEM_AVOID_AREA_CHANGE_CB.c_str(), argv, ArraySize(argv)); + } else { + NativeValue *objValue = engine.CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("Failed to get object"); + return; + } + object->SetProperty("type", CreateJsValue(engine, static_cast(type))); + object->SetProperty("area", avoidAreaValue); + NativeValue* argv[] = { objValue }; + thisListener->CallJsMethod(AVOID_AREA_CHANGE_CB.c_str(), argv, ArraySize(argv)); + } + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnAvoidAreaChanged", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::LifeCycleCallBack(LifeCycleEventType eventType) +{ + WLOGFI("[NAPI]LifeCycleCallBack, envent type: %{public}u", eventType); + std::unique_ptr complete = std::make_unique( + [self = weakRef_, eventType, eng = engine_] (NativeEngine &engine, + AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr || eng == nullptr) { + WLOGFE("[NAPI]this listener or engine is nullptr"); + return; + } + NativeValue* argv[] = {CreateJsValue(*eng, static_cast(eventType))}; + thisListener->CallJsMethod(LIFECYCLE_EVENT_CB.c_str(), argv, ArraySize(argv)); + } + ); + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::LifeCycleCallBack", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::AfterForeground() +{ + LifeCycleCallBack(LifeCycleEventType::FOREGROUND); +} + +void JsWindowListener::AfterBackground() +{ + LifeCycleCallBack(LifeCycleEventType::BACKGROUND); +} + +void JsWindowListener::AfterFocused() +{ + LifeCycleCallBack(LifeCycleEventType::ACTIVE); +} + +void JsWindowListener::AfterUnfocused() +{ + LifeCycleCallBack(LifeCycleEventType::INACTIVE); +} + +void JsWindowListener::OnSizeChange(const sptr& info) +{ + WLOGFI("[NAPI]OccupiedAreaChangeInfo, type: %{public}u, " \ + "input rect: [%{public}d, %{public}d, %{public}u, %{public}u]", static_cast(info->type_), + info->rect_.posX_, info->rect_.posY_, info->rect_.width_, info->rect_.height_); + // js callback should run in js thread + std::unique_ptr complete = std::make_unique ( + [self = weakRef_, info, eng = engine_] (NativeEngine &engine, + AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr || eng == nullptr) { + WLOGFE("[NAPI]this listener or engine is nullptr"); + return; + } + NativeValue* argv[] = {CreateJsValue(*eng, info->rect_.height_)}; + thisListener->CallJsMethod(KEYBOARD_HEIGHT_CHANGE_CB.c_str(), argv, ArraySize(argv)); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnSizeChange", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnTouchOutside() const +{ + WLOGFI("CALLED"); + std::unique_ptr complete = std::make_unique ( + [self = weakRef_] (NativeEngine &engine, AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr) { + WLOGFE("[NAPI]this listener is nullptr"); + return; + } + thisListener->CallJsMethod(TOUCH_OUTSIDE_CB.c_str(), nullptr, 0); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnOutsidePressed", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnScreenshot() +{ + WLOGFI("CALLED"); + std::unique_ptr complete = std::make_unique ( + [self = wptr(this)] (NativeEngine &engine, AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr) { + WLOGFE("[NAPI]this listener is nullptr"); + return; + } + thisListener->CallJsMethod(SCREENSHOT_EVENT_CB.c_str(), nullptr, 0); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnScreenshot", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnDialogTargetTouch() const +{ + std::unique_ptr complete = std::make_unique ( + [self = weakRef_] (NativeEngine &engine, AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr) { + WLOGFE("[NAPI]this listener is nullptr"); + return; + } + thisListener->CallJsMethod(DIALOG_TARGET_TOUCH_CB.c_str(), nullptr, 0); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnDialogTargetTouch", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} + +void JsWindowListener::OnDialogDeathRecipient() const +{ + std::unique_ptr complete = std::make_unique ( + [self = weakRef_] (NativeEngine &engine, AsyncTask &task, int32_t status) { + auto thisListener = self.promote(); + if (thisListener == nullptr) { + WLOGFE("[NAPI]this listener is nullptr"); + return; + } + thisListener->CallJsMethod(DIALOG_DEATH_RECIPIENT_CB.c_str(), nullptr, 0); + } + ); + + NativeReference* callback = nullptr; + std::unique_ptr execute = nullptr; + AsyncTask::Schedule("JsWindowListener::OnDialogDeathRecipient", + *engine_, std::make_unique(callback, std::move(execute), std::move(complete))); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h new file mode 100644 index 0000000..bbc9789 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_listener.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021-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_WINDOW_LISTENER_H +#define OHOS_JS_WINDOW_LISTENER_H + +#include +#include + +#include "class_var_definition.h" +#include "js_window_utils.h" +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "refbase.h" +#include "window.h" +#include "window_manager.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +const std::string WINDOW_SIZE_CHANGE_CB = "windowSizeChange"; +const std::string SYSTEM_BAR_TINT_CHANGE_CB = "systemBarTintChange"; +const std::string SYSTEM_AVOID_AREA_CHANGE_CB = "systemAvoidAreaChange"; +const std::string AVOID_AREA_CHANGE_CB = "avoidAreaChange"; +const std::string LIFECYCLE_EVENT_CB = "lifeCycleEvent"; +const std::string WINDOW_STAGE_EVENT_CB = "windowStageEvent"; +const std::string KEYBOARD_HEIGHT_CHANGE_CB = "keyboardHeightChange"; +const std::string TOUCH_OUTSIDE_CB = "touchOutside"; +const std::string SCREENSHOT_EVENT_CB = "screenshot"; +const std::string DIALOG_TARGET_TOUCH_CB = "dialogTargetTouch"; +const std::string DIALOG_DEATH_RECIPIENT_CB = "dialogDeathRecipient"; + +class JsWindowListener : public IWindowChangeListener, + public ISystemBarChangedListener, + public IAvoidAreaChangedListener, + public IWindowLifeCycle, + public IOccupiedAreaChangeListener, + public ITouchOutsideListener, + public IScreenshotListener, + public IDialogTargetTouchListener, + public IDialogDeathRecipientListener { +public: + JsWindowListener(NativeEngine* engine, std::shared_ptr callback) + : engine_(engine), jsCallBack_(callback), weakRef_(wptr (this)) {} + ~JsWindowListener(); + void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override; + void OnSizeChange(Rect rect, WindowSizeChangeReason reason) override; + void OnModeChange(WindowMode mode) override; + void OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type) override; + void AfterForeground() override; + void AfterBackground() override; + void AfterFocused() override; + void AfterUnfocused() override; + void OnSizeChange(const sptr& info) override; + void OnTouchOutside() const override; + void OnScreenshot() override; + void OnDialogTargetTouch() const override; + void OnDialogDeathRecipient() const override; + void CallJsMethod(const char* methodName, NativeValue* const* argv = nullptr, size_t argc = 0); +private: + void LifeCycleCallBack(LifeCycleEventType eventType); + NativeEngine* engine_ = nullptr; + std::shared_ptr jsCallBack_ = nullptr; + wptr weakRef_ = nullptr; + DEFINE_VAR_DEFAULT_FUNC_SET(bool, IsDeprecatedInterface, isDeprecatedInterface, false) +}; +} // namespace Rosen +} // namespace OHOS +#endif /* OHOS_JS_WINDOW_LISTENER_H */ diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp new file mode 100644 index 0000000..5b016fd --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.cpp @@ -0,0 +1,303 @@ +/* + * 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_window_register_manager.h" +#include "singleton_container.h" +#include "window_manager.h" +#include "window_manager_hilog.h" +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowRegisterManager"}; +} + +JsWindowRegisterManager::JsWindowRegisterManager() +{ + // white register list for window manager + listenerProcess_[CaseType::CASE_WINDOW_MANAGER] = { + {SYSTEM_BAR_TINT_CHANGE_CB, &JsWindowRegisterManager::ProcessSystemBarChangeRegister } + }; + // white register list for window + listenerProcess_[CaseType::CASE_WINDOW] = { + { WINDOW_SIZE_CHANGE_CB, &JsWindowRegisterManager::ProcessWindowChangeRegister }, + { SYSTEM_AVOID_AREA_CHANGE_CB, &JsWindowRegisterManager::ProcessSystemAvoidAreaChangeRegister }, + { AVOID_AREA_CHANGE_CB, &JsWindowRegisterManager::ProcessAvoidAreaChangeRegister }, + { LIFECYCLE_EVENT_CB, &JsWindowRegisterManager::ProcessLifeCycleEventRegister }, + { KEYBOARD_HEIGHT_CHANGE_CB, &JsWindowRegisterManager::ProcessOccupiedAreaChangeRegister }, + { TOUCH_OUTSIDE_CB, &JsWindowRegisterManager::ProcessTouchOutsideRegister }, + { SCREENSHOT_EVENT_CB, &JsWindowRegisterManager::ProcessScreenshotRegister }, + { DIALOG_TARGET_TOUCH_CB, &JsWindowRegisterManager::ProcessDialogTargetTouchRegister }, + { DIALOG_DEATH_RECIPIENT_CB, &JsWindowRegisterManager::ProcessDialogDeathRecipientRegister }, + }; + // white register list for window stage + listenerProcess_[CaseType::CASE_STAGE] = { + {WINDOW_STAGE_EVENT_CB, &JsWindowRegisterManager::ProcessLifeCycleEventRegister } + }; +} + +JsWindowRegisterManager::~JsWindowRegisterManager() +{ +} + +bool JsWindowRegisterManager::ProcessWindowChangeRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterWindowChangeListener(thisListener); + } else { + window->UnregisterWindowChangeListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessSystemAvoidAreaChangeRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + return false; + } + if (listener == nullptr) { + WLOGFE("[NAPI]listener is nullptr"); + return false; + } + listener->SetIsDeprecatedInterface(true); + sptr thisListener(listener); + if (isRegister) { + window->RegisterAvoidAreaChangeListener(thisListener); + } else { + window->UnregisterAvoidAreaChangeListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessAvoidAreaChangeRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterAvoidAreaChangeListener(thisListener); + } else { + window->UnregisterAvoidAreaChangeListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessLifeCycleEventRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterLifeCycleListener(thisListener); + } else { + window->UnregisterLifeCycleListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessOccupiedAreaChangeRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + WLOGFE("[NAPI]Window is nullptr"); + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterOccupiedAreaChangeListener(thisListener); + } else { + window->UnregisterOccupiedAreaChangeListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessSystemBarChangeRegister(sptr listener, + sptr window, bool isRegister) +{ + sptr thisListener(listener); + if (isRegister) { + SingletonContainer::Get().RegisterSystemBarChangedListener(thisListener); + } else { + SingletonContainer::Get().UnregisterSystemBarChangedListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessTouchOutsideRegister(sptr listener, + sptr window, bool isRegister) +{ + WLOGFI("called"); + if (window == nullptr) { + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterTouchOutsideListener(thisListener); + } else { + window->UnregisterTouchOutsideListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessScreenshotRegister(sptr listener, + sptr window, bool isRegister) +{ + WLOGFI("called"); + if (window == nullptr) { + WLOGFE("%{public}sregister screenshot listener failed. window is null", isRegister? "" : "un"); + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterScreenshotListener(thisListener); + } else { + window->UnregisterScreenshotListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessDialogTargetTouchRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterDialogTargetTouchListener(thisListener); + } else { + window->UnregisterDialogTargetTouchListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::ProcessDialogDeathRecipientRegister(sptr listener, + sptr window, bool isRegister) +{ + if (window == nullptr) { + return false; + } + sptr thisListener(listener); + if (isRegister) { + window->RegisterDialogDeathRecipientListener(thisListener); + } else { + window->UnregisterDialogDeathRecipientListener(thisListener); + } + return true; +} + +bool JsWindowRegisterManager::IsCallbackRegistered(std::string type, NativeValue* jsListenerObject) +{ + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFI("[NAPI]Method %{public}s has not been registerted", type.c_str()); + return false; + } + + for (auto iter = jsCbMap_[type].begin(); iter != jsCbMap_[type].end(); ++iter) { + if (jsListenerObject->StrictEquals(iter->first->Get())) { + WLOGFE("[NAPI]Method %{public}s has already been registered", type.c_str()); + return true; + } + } + return false; +} + +void JsWindowRegisterManager::RegisterListener(sptr window, std::string type, + CaseType caseType, NativeEngine& engine, NativeValue* value) +{ + std::lock_guard lock(mtx_); + if (IsCallbackRegistered(type, value)) { + return; + } + if (listenerProcess_[caseType].count(type) == 0) { + WLOGFE("[NAPI]Type %{public}s is not supported", type.c_str()); + return; + } + std::shared_ptr callbackRef; + callbackRef.reset(engine.CreateReference(value, 1)); + sptr windowManagerListener = new(std::nothrow) JsWindowListener(&engine, callbackRef); + if (windowManagerListener == nullptr) { + WLOGFE("[NAPI]New JsWindowListener failed"); + return; + } + if (!((this->*listenerProcess_[caseType][type])(windowManagerListener, window, true))) { + WLOGFE("[NAPI]Register type %{public}s failed", type.c_str()); + return; + } + jsCbMap_[type][callbackRef] = windowManagerListener; + WLOGFI("[NAPI]Register type %{public}s success! callback map size: %{public}zu", + type.c_str(), jsCbMap_[type].size()); +} + +void JsWindowRegisterManager::UnregisterListener(sptr window, std::string type, + CaseType caseType, NativeValue* value) +{ + std::lock_guard lock(mtx_); + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + WLOGFE("[NAPI]Type %{public}s was not registerted", type.c_str()); + return; + } + if (listenerProcess_[caseType].count(type) == 0) { + WLOGFE("[NAPI]Type %{public}s is not supported", type.c_str()); + return; + } + if (value == nullptr) { + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end();) { + if (!((this->*listenerProcess_[caseType][type])(it->second, window, false))) { + WLOGFE("[NAPI]Unregister type %{public}s failed, no value", type.c_str()); + return; + } + jsCbMap_[type].erase(it++); + } + } else { + bool findFlag = false; + for (auto it = jsCbMap_[type].begin(); it != jsCbMap_[type].end(); ++it) { + if (!value->StrictEquals(it->first->Get())) { + continue; + } + findFlag = true; + if (!(this->*listenerProcess_[caseType][type])(it->second, window, false)) { + WLOGFE("[NAPI]Unregister type %{public}s failed", type.c_str()); + return; + } + jsCbMap_[type].erase(it); + break; + } + if (!findFlag) { + WLOGFE("[NAPI]Unregister type %{public}s failed because not found callback!", type.c_str()); + return; + } + } + WLOGFI("[NAPI]Unregister type %{public}s success! callback map size: %{public}zu", + type.c_str(), jsCbMap_[type].size()); + // erase type when there is no callback in one type + if (jsCbMap_[type].empty()) { + jsCbMap_.erase(type); + } +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h new file mode 100644 index 0000000..66fb641 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_register_manager.h @@ -0,0 +1,60 @@ +/* + * 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_WINDOW_REGISTER_MANAGER_H +#define OHOS_JS_WINDOW_REGISTER_MANAGER_H +#include +#include +#include "js_window_listener.h" +#include "native_engine/native_engine.h" +#include "native_engine/native_reference.h" +#include "native_engine/native_value.h" +#include "refbase.h" +#include "window.h" +namespace OHOS { +namespace Rosen { +enum class CaseType { + CASE_WINDOW_MANAGER = 0, + CASE_WINDOW, + CASE_STAGE +}; +class JsWindowRegisterManager { +public: + JsWindowRegisterManager(); + ~JsWindowRegisterManager(); + void RegisterListener(sptr window, std::string type, + CaseType caseType, NativeEngine& engine, NativeValue* value); + void UnregisterListener(sptr window, std::string type, + CaseType caseType, NativeValue* value); +private: + bool IsCallbackRegistered(std::string type, NativeValue* jsListenerObject); + bool ProcessWindowChangeRegister(sptr listener, sptr window, bool isRegister); + bool ProcessSystemAvoidAreaChangeRegister(sptr listener, sptr window, bool isRegister); + bool ProcessAvoidAreaChangeRegister(sptr listener, sptr window, bool isRegister); + bool ProcessLifeCycleEventRegister(sptr listener, sptr window, bool isRegister); + bool ProcessOccupiedAreaChangeRegister(sptr listener, sptr window, bool isRegister); + bool ProcessSystemBarChangeRegister(sptr listener, sptr window, bool isRegister); + bool ProcessTouchOutsideRegister(sptr listener, sptr window, bool isRegister); + bool ProcessScreenshotRegister(sptr listener, sptr window, bool isRegister); + bool ProcessDialogTargetTouchRegister(sptr listener, sptr window, bool isRegister); + bool ProcessDialogDeathRecipientRegister(sptr listener, sptr window, bool isRegister); + using Func_t = bool(JsWindowRegisterManager::*)(sptr, sptr window, bool); + std::map, sptr>> jsCbMap_; + std::mutex mtx_; + std::map> listenerProcess_; +}; +} // namespace Rosen +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp new file mode 100644 index 0000000..c5ebbd4 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp @@ -0,0 +1,647 @@ +/* + * Copyright (c) 2021-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_window_utils.h" +#include +#include +#include +#include "accesstoken_kit.h" +#include "bundle_constants.h" +#include "ipc_skeleton.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowUtils"}; +} + +NativeValue* WindowTypeInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]WindowTypeInit"); + + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("TYPE_APP", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_APP))); + object->SetProperty("TYPE_SYSTEM_ALERT", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_SYSTEM_ALERT))); + object->SetProperty("TYPE_INPUT_METHOD", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_INPUT_METHOD))); + object->SetProperty("TYPE_STATUS_BAR", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_STATUS_BAR))); + object->SetProperty("TYPE_PANEL", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_PANEL))); + object->SetProperty("TYPE_KEYGUARD", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_KEYGUARD))); + object->SetProperty("TYPE_VOLUME_OVERLAY", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_VOLUME_OVERLAY))); + object->SetProperty("TYPE_NAVIGATION_BAR", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_NAVIGATION_BAR))); + object->SetProperty("TYPE_FLOAT", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_FLOAT))); + object->SetProperty("TYPE_FLOAT_CAMERA", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_FLOAT_CAMERA))); + object->SetProperty("TYPE_WALLPAPER", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_WALLPAPER))); + object->SetProperty("TYPE_DESKTOP", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_DESKTOP))); + object->SetProperty("TYPE_LAUNCHER_RECENT", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_LAUNCHER_RECENT))); + object->SetProperty("TYPE_LAUNCHER_DOCK", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_LAUNCHER_DOCK))); + object->SetProperty("TYPE_VOICE_INTERACTION", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_VOICE_INTERACTION))); + object->SetProperty("TYPE_DIALOG", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_DIALOG))); + object->SetProperty("TYPE_POINTER", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_POINTER))); + object->SetProperty("TYPE_SCREENSHOT", CreateJsValue(*engine, + static_cast(ApiWindowType::TYPE_SCREENSHOT))); + + return objValue; +} + +NativeValue* AvoidAreaTypeInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]AvoidAreaTypeInit"); + + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("TYPE_SYSTEM", CreateJsValue(*engine, + static_cast(AvoidAreaType::TYPE_SYSTEM))); + object->SetProperty("TYPE_CUTOUT", CreateJsValue(*engine, + static_cast(AvoidAreaType::TYPE_CUTOUT))); + object->SetProperty("TYPE_SYSTEM_GESTURE", CreateJsValue(*engine, + static_cast(AvoidAreaType::TYPE_SYSTEM_GESTURE))); + object->SetProperty("TYPE_KEYBOARD", CreateJsValue(*engine, static_cast(AvoidAreaType::TYPE_KEYBOARD))); + return objValue; +} + +NativeValue* WindowModeInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]WindowModeInit"); + + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("UNDEFINED", CreateJsValue(*engine, + static_cast(ApiWindowMode::UNDEFINED))); + object->SetProperty("FULLSCREEN", CreateJsValue(*engine, + static_cast(ApiWindowMode::FULLSCREEN))); + object->SetProperty("PRIMARY", CreateJsValue(*engine, + static_cast(ApiWindowMode::PRIMARY))); + object->SetProperty("SECONDARY", CreateJsValue(*engine, + static_cast(ApiWindowMode::SECONDARY))); + object->SetProperty("FLOATING", CreateJsValue(*engine, + static_cast(ApiWindowMode::FLOATING))); + return objValue; +} + +NativeValue* ColorSpaceInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]ColorSpaceInit"); + + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("DEFAULT", CreateJsValue(*engine, + static_cast(ColorSpace::COLOR_SPACE_DEFAULT))); + object->SetProperty("WIDE_GAMUT", CreateJsValue(*engine, + static_cast(ColorSpace::COLOR_SPACE_WIDE_GAMUT))); + return objValue; +} + +NativeValue* OrientationInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]OrientationInit"); + + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("UNSPECIFIED", CreateJsValue(*engine, + static_cast(Orientation::UNSPECIFIED))); + object->SetProperty("PORTRAIT", CreateJsValue(*engine, + static_cast(Orientation::VERTICAL))); + object->SetProperty("LANDSCAPE", CreateJsValue(*engine, + static_cast(Orientation::HORIZONTAL))); + object->SetProperty("PORTRAIT_INVERTED", CreateJsValue(*engine, + static_cast(Orientation::REVERSE_VERTICAL))); + object->SetProperty("LANDSCAPE_INVERTED", CreateJsValue(*engine, + static_cast(Orientation::REVERSE_HORIZONTAL))); + object->SetProperty("AUTO_ROTATION", CreateJsValue(*engine, + static_cast(Orientation::SENSOR))); + object->SetProperty("AUTO_ROTATION_PORTRAIT", CreateJsValue(*engine, + static_cast(Orientation::SENSOR_VERTICAL))); + object->SetProperty("AUTO_ROTATION_LANDSCAPE", CreateJsValue(*engine, + static_cast(Orientation::SENSOR_HORIZONTAL))); + object->SetProperty("AUTO_ROTATION_RESTRICTED", CreateJsValue(*engine, + static_cast(Orientation::AUTO_ROTATION_RESTRICTED))); + object->SetProperty("AUTO_ROTATION_PORTRAIT_RESTRICTED", CreateJsValue(*engine, + static_cast(Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED))); + object->SetProperty("AUTO_ROTATION_LANDSCAPE_RESTRICTED", CreateJsValue(*engine, + static_cast(Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED))); + object->SetProperty("LOCKED", CreateJsValue(*engine, + static_cast(Orientation::LOCKED))); + return objValue; +} + +NativeValue* WindowStageEventTypeInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]WindowStageEventTypeInit"); + + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("SHOWN", CreateJsValue(*engine, + static_cast(LifeCycleEventType::FOREGROUND))); + object->SetProperty("ACTIVE", CreateJsValue(*engine, + static_cast(LifeCycleEventType::ACTIVE))); + object->SetProperty("INACTIVE", CreateJsValue(*engine, + static_cast(LifeCycleEventType::INACTIVE))); + object->SetProperty("HIDDEN", CreateJsValue(*engine, + static_cast(LifeCycleEventType::BACKGROUND))); + return objValue; +} + +NativeValue* WindowLayoutModeInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]WindowLayoutModeInit"); + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("WINDOW_LAYOUT_MODE_CASCADE", CreateJsValue(*engine, + static_cast(WindowLayoutMode::CASCADE))); + object->SetProperty("WINDOW_LAYOUT_MODE_TILE", CreateJsValue(*engine, + static_cast(WindowLayoutMode::TILE))); + return objValue; +} + +NativeValue* BlurStyleInit(NativeEngine* engine) +{ + WLOGFI("[NAPI]BlurStyleInit"); + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("OFF", CreateJsValue(*engine, + static_cast(WindowBlurStyle::WINDOW_BLUR_OFF))); + object->SetProperty("THIN", CreateJsValue(*engine, + static_cast(WindowBlurStyle::WINDOW_BLUR_THIN))); + object->SetProperty("REGULAR", CreateJsValue(*engine, + static_cast(WindowBlurStyle::WINDOW_BLUR_REGULAR))); + object->SetProperty("THICK", CreateJsValue(*engine, + static_cast(WindowBlurStyle::WINDOW_BLUR_THICK))); + return objValue; +} + +NativeValue* WindowErrorInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]WindowErrorInit"); + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + + object->SetProperty("WM_DO_NOTHING", CreateJsValue(*engine, + static_cast(WMError::WM_DO_NOTHING))); + object->SetProperty("WM_ERROR_NO_MEM", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_NO_MEM))); + object->SetProperty("WM_ERROR_DESTROYED_OBJECT", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_DESTROYED_OBJECT))); + object->SetProperty("WM_ERROR_INVALID_WINDOW", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_INVALID_WINDOW))); + object->SetProperty("WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE))); + object->SetProperty("WM_ERROR_INVALID_OPERATION", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_INVALID_OPERATION))); + object->SetProperty("WM_ERROR_INVALID_PERMISSION", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_INVALID_PERMISSION))); + object->SetProperty("WM_ERROR_NO_REMOTE_ANIMATION", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_NO_REMOTE_ANIMATION))); + object->SetProperty("WM_ERROR_DEVICE_NOT_SUPPORT", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_DEVICE_NOT_SUPPORT))); + object->SetProperty("WM_ERROR_NULLPTR", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_NULLPTR))); + object->SetProperty("WM_ERROR_INVALID_TYPE", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_INVALID_TYPE))); + object->SetProperty("WM_ERROR_INVALID_PARAM", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_INVALID_PARAM))); + object->SetProperty("WM_ERROR_SAMGR", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_SAMGR))); + object->SetProperty("WM_ERROR_IPC_FAILED", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_IPC_FAILED))); + object->SetProperty("WM_ERROR_START_ABILITY_FAILED", CreateJsValue(*engine, + static_cast(WMError::WM_ERROR_START_ABILITY_FAILED))); + return objValue; +} + +NativeValue* WindowErrorCodeInit(NativeEngine* engine) +{ + WLOGFD("[NAPI]WindowErrorCodeInit"); + if (engine == nullptr) { + WLOGFE("[NAPI]Engine is nullptr"); + return nullptr; + } + + NativeValue *objValue = engine->CreateObject(); + NativeObject *object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to get object"); + return nullptr; + } + object->SetProperty("WM_ERROR_NO_PERMISSION", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_NO_PERMISSION))); + object->SetProperty("WM_ERROR_INVALID_PARAM", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + object->SetProperty("WM_ERROR_DEVICE_NOT_SUPPORT", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_DEVICE_NOT_SUPPORT))); + object->SetProperty("WM_ERROR_REPEAT_OPERATION", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_REPEAT_OPERATION))); + object->SetProperty("WM_ERROR_STATE_ABNORMALLY", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + object->SetProperty("WM_ERROR_SYSTEM_ABNORMALLY", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY))); + object->SetProperty("WM_ERROR_INVALID_CALLING", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + object->SetProperty("WM_ERROR_STAGE_ABNORMALLY", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY))); + object->SetProperty("WM_ERROR_CONTEXT_ABNORMALLY", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_CONTEXT_ABNORMALLY))); + object->SetProperty("WM_ERROR_START_ABILITY_FAILED", CreateJsValue(*engine, + static_cast(WmErrorCode::WM_ERROR_START_ABILITY_FAILED))); + return objValue; +} + +NativeValue* GetRectAndConvertToJsValue(NativeEngine& engine, const Rect& rect) +{ + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to convert rect to jsObject"); + return nullptr; + } + object->SetProperty("left", CreateJsValue(engine, rect.posX_)); + object->SetProperty("top", CreateJsValue(engine, rect.posY_)); + object->SetProperty("width", CreateJsValue(engine, rect.width_)); + object->SetProperty("height", CreateJsValue(engine, rect.height_)); + return objValue; +} + +NativeValue* CreateJsWindowPropertiesObject(NativeEngine& engine, sptr& window) +{ + WLOGFI("[NAPI]CreateJsWindowPropertiesObject"); + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to convert windowProperties to jsObject"); + return nullptr; + } + + Rect rect = window->GetRect(); + NativeValue* rectObj = GetRectAndConvertToJsValue(engine, rect); + if (rectObj == nullptr) { + WLOGFE("[NAPI]GetRect failed!"); + } + object->SetProperty("windowRect", rectObj); + WindowType type = window->GetType(); + if (NATIVE_JS_TO_WINDOW_TYPE_MAP.count(type) != 0) { + object->SetProperty("type", CreateJsValue(engine, NATIVE_JS_TO_WINDOW_TYPE_MAP.at(type))); + } else { + object->SetProperty("type", CreateJsValue(engine, type)); + } + object->SetProperty("isLayoutFullScreen", CreateJsValue(engine, window->IsLayoutFullScreen())); + object->SetProperty("isFullScreen", CreateJsValue(engine, window->IsFullScreen())); + object->SetProperty("touchable", CreateJsValue(engine, window->GetTouchable())); + object->SetProperty("focusable", CreateJsValue(engine, window->GetFocusable())); + object->SetProperty("name", CreateJsValue(engine, window->GetWindowName())); + object->SetProperty("isPrivacyMode", CreateJsValue(engine, window->IsPrivacyMode())); + object->SetProperty("isKeepScreenOn", CreateJsValue(engine, window->IsKeepScreenOn())); + object->SetProperty("brightness", CreateJsValue(engine, window->GetBrightness())); + object->SetProperty("isTransparent", CreateJsValue(engine, window->IsTransparent())); + object->SetProperty("isRoundCorner", CreateJsValue(engine, false)); // empty method + object->SetProperty("dimBehindValue", CreateJsValue(engine, 0)); + object->SetProperty("id", CreateJsValue(engine, window->GetWindowId())); + return objValue; +} +static std::string GetHexColor(uint32_t color) +{ + std::stringstream ioss; + std::string temp; + ioss << std::setiosflags(std::ios::uppercase) << std::hex << color; + ioss >> temp; + int count = RGBA_LENGTH - static_cast(temp.length()); + std::string tmpColor(count, '0'); + tmpColor += temp; + std::string finalColor("#"); + finalColor += tmpColor; + return finalColor; +} + +static NativeValue* CreateJsSystemBarRegionTintObject(NativeEngine& engine, const SystemBarRegionTint& tint) +{ + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to convert SystemBarProperty to jsObject"); + return nullptr; + } + if (NATIVE_JS_TO_WINDOW_TYPE_MAP.count(tint.type_) != 0) { + object->SetProperty("type", CreateJsValue(engine, NATIVE_JS_TO_WINDOW_TYPE_MAP.at(tint.type_))); + } else { + object->SetProperty("type", CreateJsValue(engine, tint.type_)); + } + object->SetProperty("isEnable", CreateJsValue(engine, tint.prop_.enable_)); + std::string bkgColor = GetHexColor(tint.prop_.backgroundColor_); + object->SetProperty("backgroundColor", CreateJsValue(engine, bkgColor)); + std::string contentColor = GetHexColor(tint.prop_.contentColor_); + object->SetProperty("contentColor", CreateJsValue(engine, contentColor)); + Rect rect = tint.region_; + object->SetProperty("region", GetRectAndConvertToJsValue(engine, rect)); + + WLOGFI("[NAPI]Type %{public}u [%{public}u %{public}s %{public}s]", + tint.type_, tint.prop_.enable_, bkgColor.c_str(), contentColor.c_str()); + WLOGFI("[NAPI]Region [%{public}d %{public}d %{public}u %{public}u]", + rect.posX_, rect.posY_, rect.width_, rect.height_); + return objValue; +} + +NativeValue* CreateJsSystemBarRegionTintArrayObject(NativeEngine& engine, const SystemBarRegionTints& tints) +{ + if (tints.empty()) { + WLOGFE("[NAPI]Empty tints"); + return nullptr; + } + NativeValue* objValue = engine.CreateArray(tints.size()); + NativeArray* array = ConvertNativeValueTo(objValue); + if (array == nullptr) { + WLOGFE("[NAPI]Failed to convert SystemBarPropertys to jsArrayObject"); + return nullptr; + } + uint32_t index = 0; + for (size_t i = 0; i < tints.size(); i++) { + array->SetElement(index++, CreateJsSystemBarRegionTintObject(engine, tints[i])); + } + return objValue; +} + +bool GetSystemBarStatus(std::map& systemBarProperties, + NativeEngine& engine, NativeCallbackInfo& info, sptr& window) +{ + NativeArray* nativeArray = nullptr; + uint32_t size = 0; + if (info.argc > 0 && info.argv[0]->TypeOf() != NATIVE_FUNCTION) { + nativeArray = ConvertNativeValueTo(info.argv[0]); + if (nativeArray == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to SystemBarArray"); + return false; + } + size = nativeArray->GetLength(); + } + auto statusProperty = window->GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR); + auto navProperty = window->GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + statusProperty.enable_ = false; + navProperty.enable_ = false; + systemBarProperties[WindowType::WINDOW_TYPE_STATUS_BAR] = statusProperty; + systemBarProperties[WindowType::WINDOW_TYPE_NAVIGATION_BAR] = navProperty; + for (uint32_t i = 0; i < size; i++) { + std::string name; + if (!ConvertFromJsValue(engine, nativeArray->GetElement(i), name)) { + WLOGFE("[NAPI]Failed to convert parameter to SystemBarName"); + return false; + } + if (name.compare("status") == 0) { + systemBarProperties[WindowType::WINDOW_TYPE_STATUS_BAR].enable_ = true; + } else if (name.compare("navigation") == 0) { + systemBarProperties[WindowType::WINDOW_TYPE_NAVIGATION_BAR].enable_ = true; + } + } + return true; +} + +static uint32_t GetColorFromJs(NativeEngine& engine, NativeObject* jsObject, + const char* name, uint32_t defaultColor) +{ + NativeValue* jsColor = jsObject->GetProperty(name); + if (jsColor->TypeOf() != NATIVE_UNDEFINED) { + std::string colorStr; + if (!ConvertFromJsValue(engine, jsColor, colorStr)) { + WLOGFE("[NAPI]Failed to convert parameter to color"); + return defaultColor; + } + std::regex pattern("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$"); + if (!std::regex_match(colorStr, pattern)) { + WLOGFE("[NAPI]Invalid color input"); + return defaultColor; + } + std::string color = colorStr.substr(1); + if (color.length() == RGB_LENGTH) { + color = "FF" + color; // ARGB + } + std::stringstream ss; + uint32_t hexColor; + ss << std::hex << color; + ss >> hexColor; + WLOGFI("[NAPI]Origin %{public}s, process %{public}s, final %{public}x", + colorStr.c_str(), color.c_str(), hexColor); + return hexColor; + } + return defaultColor; +} + +bool SetSystemBarPropertiesFromJs(NativeEngine& engine, NativeObject* jsObject, + std::map& properties, sptr& window) +{ + auto statusProperty = window->GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR); + auto navProperty = window->GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + properties[WindowType::WINDOW_TYPE_STATUS_BAR] = statusProperty; + properties[WindowType::WINDOW_TYPE_NAVIGATION_BAR] = navProperty; + properties[WindowType::WINDOW_TYPE_STATUS_BAR].backgroundColor_ = GetColorFromJs(engine, + jsObject, "statusBarColor", statusProperty.backgroundColor_); + properties[WindowType::WINDOW_TYPE_NAVIGATION_BAR].backgroundColor_ = GetColorFromJs(engine, + jsObject, "navigationBarColor", navProperty.backgroundColor_); + NativeValue* jsStatusContentColor = jsObject->GetProperty("statusBarContentColor"); + NativeValue* jsStatusIcon = jsObject->GetProperty("isStatusBarLightIcon"); + if (jsStatusContentColor->TypeOf() != NATIVE_UNDEFINED) { + properties[WindowType::WINDOW_TYPE_STATUS_BAR].contentColor_ = GetColorFromJs(engine, + jsObject, "statusBarContentColor", statusProperty.contentColor_); + } else if (jsStatusIcon->TypeOf() != NATIVE_UNDEFINED) { + bool isStatusBarLightIcon; + if (!ConvertFromJsValue(engine, jsStatusIcon, isStatusBarLightIcon)) { + WLOGFE("[NAPI]Failed to convert parameter to isStatusBarLightIcon"); + return false; + } + if (isStatusBarLightIcon) { + properties[WindowType::WINDOW_TYPE_STATUS_BAR].contentColor_ = SYSTEM_COLOR_WHITE; + } else { + properties[WindowType::WINDOW_TYPE_STATUS_BAR].contentColor_ = SYSTEM_COLOR_BLACK; + } + } + NativeValue* jsNavigationContentColor = jsObject->GetProperty("navigationBarContentColor"); + NativeValue* jsNavigationIcon = jsObject->GetProperty("isNavigationBarLightIcon"); + if (jsNavigationContentColor->TypeOf() != NATIVE_UNDEFINED) { + properties[WindowType::WINDOW_TYPE_NAVIGATION_BAR].contentColor_ = GetColorFromJs(engine, + jsObject, "navigationBarContentColor", navProperty.contentColor_); + } else if (jsNavigationIcon->TypeOf() != NATIVE_UNDEFINED) { + bool isNavigationBarLightIcon; + if (!ConvertFromJsValue(engine, jsNavigationIcon, isNavigationBarLightIcon)) { + WLOGFE("[NAPI]Failed to convert parameter to isNavigationBarLightIcon"); + return false; + } + if (isNavigationBarLightIcon) { + properties[WindowType::WINDOW_TYPE_NAVIGATION_BAR].contentColor_ = SYSTEM_COLOR_WHITE; + } else { + properties[WindowType::WINDOW_TYPE_NAVIGATION_BAR].contentColor_ = SYSTEM_COLOR_BLACK; + } + } + return true; +} + +NativeValue* ConvertAvoidAreaToJsValue(NativeEngine& engine, const AvoidArea& avoidArea, AvoidAreaType type) +{ + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + if (object == nullptr) { + WLOGFE("[NAPI]Failed to convert avoidArea to jsObject"); + return nullptr; + } + object->SetProperty("visible", CreateJsValue(engine, type == AvoidAreaType::TYPE_CUTOUT ? false : true)); + object->SetProperty("leftRect", GetRectAndConvertToJsValue(engine, avoidArea.leftRect_)); + object->SetProperty("topRect", GetRectAndConvertToJsValue(engine, avoidArea.topRect_)); + object->SetProperty("rightRect", GetRectAndConvertToJsValue(engine, avoidArea.rightRect_)); + object->SetProperty("bottomRect", GetRectAndConvertToJsValue(engine, avoidArea.bottomRect_)); + return objValue; +} + +bool CheckCallingPermission(std::string permission) +{ + WLOGFI("[NAPI]Permission: %{public}s", permission.c_str()); + if (!permission.empty() && + Security::AccessToken::AccessTokenKit::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission) + != AppExecFwk::Constants::PERMISSION_GRANTED) { + WLOGFE("[NAPI]Permission %{public}s is not granted", permission.c_str()); + return false; + } + return true; +} + +bool GetAPI7Ability(NativeEngine& engine, AppExecFwk::Ability* &ability) +{ + napi_value global; + auto env = reinterpret_cast(&engine); + if (napi_get_global(env, &global) != napi_ok) { + WLOGFI("[NAPI]Get global failed"); + return false; + } + napi_value jsAbility; + napi_status status = napi_get_named_property(env, global, "ability", &jsAbility); + if (status != napi_ok || jsAbility == nullptr) { + WLOGFI("[NAPI]Get ability property failed"); + return false; + } + + if (napi_get_value_external(env, jsAbility, reinterpret_cast(&ability)) != napi_ok) { + WLOGFI("[NAPI]Get ability external failed"); + return false; + } + if (ability == nullptr) { + return false; + } else { + WLOGFI("[NAPI]Get ability"); + } + return true; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h new file mode 100644 index 0000000..2540f70 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_napi/js_window_utils.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2021-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_WINDOW_UTILS_H +#define OHOS_JS_WINDOW_UTILS_H +#include +#include "js_runtime_utils.h" +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "window.h" + +#ifndef WINDOW_PREVIEW +#include "window_manager.h" +#else +#include "mock/window_manager.h" +#endif + +#include "window_option.h" +#include "wm_common.h" +namespace OHOS { +namespace Rosen { +constexpr int32_t RGB_LENGTH = 6; +constexpr int32_t RGBA_LENGTH = 8; +enum class ApiWindowType : uint32_t { + TYPE_BASE, + TYPE_APP = TYPE_BASE, + TYPE_SYSTEM_ALERT, + TYPE_INPUT_METHOD, + TYPE_STATUS_BAR, + TYPE_PANEL, + TYPE_KEYGUARD, + TYPE_VOLUME_OVERLAY, + TYPE_NAVIGATION_BAR, + TYPE_FLOAT, + TYPE_WALLPAPER, + TYPE_DESKTOP, + TYPE_LAUNCHER_RECENT, + TYPE_LAUNCHER_DOCK, + TYPE_VOICE_INTERACTION, + TYPE_POINTER, + TYPE_FLOAT_CAMERA, + TYPE_DIALOG, + TYPE_SCREENSHOT, + TYPE_END +}; + +enum class LifeCycleEventType : uint32_t { + FOREGROUND = 1, + ACTIVE, + INACTIVE, + BACKGROUND, +}; + +const std::map NATIVE_JS_TO_WINDOW_TYPE_MAP { + { WindowType::WINDOW_TYPE_APP_SUB_WINDOW, ApiWindowType::TYPE_APP }, + { WindowType::WINDOW_TYPE_DIALOG, ApiWindowType::TYPE_DIALOG }, + { WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW, ApiWindowType::TYPE_SYSTEM_ALERT }, + { WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, ApiWindowType::TYPE_INPUT_METHOD }, + { WindowType::WINDOW_TYPE_STATUS_BAR, ApiWindowType::TYPE_STATUS_BAR }, + { WindowType::WINDOW_TYPE_PANEL, ApiWindowType::TYPE_PANEL }, + { WindowType::WINDOW_TYPE_KEYGUARD, ApiWindowType::TYPE_KEYGUARD }, + { WindowType::WINDOW_TYPE_VOLUME_OVERLAY, ApiWindowType::TYPE_VOLUME_OVERLAY }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, ApiWindowType::TYPE_NAVIGATION_BAR }, + { WindowType::WINDOW_TYPE_FLOAT, ApiWindowType::TYPE_FLOAT }, + { WindowType::WINDOW_TYPE_FLOAT_CAMERA, ApiWindowType::TYPE_FLOAT_CAMERA }, + { WindowType::WINDOW_TYPE_WALLPAPER, ApiWindowType::TYPE_WALLPAPER }, + { WindowType::WINDOW_TYPE_DESKTOP, ApiWindowType::TYPE_DESKTOP }, + { WindowType::WINDOW_TYPE_LAUNCHER_RECENT, ApiWindowType::TYPE_LAUNCHER_RECENT }, + { WindowType::WINDOW_TYPE_LAUNCHER_DOCK, ApiWindowType::TYPE_LAUNCHER_DOCK }, + { WindowType::WINDOW_TYPE_VOICE_INTERACTION, ApiWindowType::TYPE_VOICE_INTERACTION }, + { WindowType::WINDOW_TYPE_POINTER, ApiWindowType::TYPE_POINTER }, + { WindowType::WINDOW_TYPE_SCREENSHOT, ApiWindowType::TYPE_SCREENSHOT }, +}; + +const std::map JS_TO_NATIVE_WINDOW_TYPE_MAP { + { ApiWindowType::TYPE_APP, WindowType::WINDOW_TYPE_APP_SUB_WINDOW }, + { ApiWindowType::TYPE_DIALOG, WindowType::WINDOW_TYPE_DIALOG }, + { ApiWindowType::TYPE_SYSTEM_ALERT, WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW }, + { ApiWindowType::TYPE_INPUT_METHOD, WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT }, + { ApiWindowType::TYPE_STATUS_BAR, WindowType::WINDOW_TYPE_STATUS_BAR }, + { ApiWindowType::TYPE_PANEL, WindowType::WINDOW_TYPE_PANEL }, + { ApiWindowType::TYPE_KEYGUARD, WindowType::WINDOW_TYPE_KEYGUARD }, + { ApiWindowType::TYPE_VOLUME_OVERLAY, WindowType::WINDOW_TYPE_VOLUME_OVERLAY }, + { ApiWindowType::TYPE_NAVIGATION_BAR, WindowType::WINDOW_TYPE_NAVIGATION_BAR }, + { ApiWindowType::TYPE_FLOAT, WindowType::WINDOW_TYPE_FLOAT }, + { ApiWindowType::TYPE_FLOAT_CAMERA, WindowType::WINDOW_TYPE_FLOAT_CAMERA }, + { ApiWindowType::TYPE_WALLPAPER, WindowType::WINDOW_TYPE_WALLPAPER }, + { ApiWindowType::TYPE_DESKTOP, WindowType::WINDOW_TYPE_DESKTOP }, + { ApiWindowType::TYPE_LAUNCHER_RECENT, WindowType::WINDOW_TYPE_LAUNCHER_RECENT }, + { ApiWindowType::TYPE_LAUNCHER_DOCK, WindowType::WINDOW_TYPE_LAUNCHER_DOCK }, + { ApiWindowType::TYPE_VOICE_INTERACTION, WindowType::WINDOW_TYPE_VOICE_INTERACTION }, + { ApiWindowType::TYPE_POINTER, WindowType::WINDOW_TYPE_POINTER }, + { ApiWindowType::TYPE_SCREENSHOT, WindowType::WINDOW_TYPE_SCREENSHOT }, +}; + +enum class ApiWindowMode : uint32_t { + UNDEFINED = 1, + FULLSCREEN, + PRIMARY, + SECONDARY, + FLOATING, + MODE_END = FLOATING +}; + +const std::map NATIVE_TO_JS_WINDOW_MODE_MAP { + { WindowMode::WINDOW_MODE_UNDEFINED, ApiWindowMode::UNDEFINED }, + { WindowMode::WINDOW_MODE_FULLSCREEN, ApiWindowMode::FULLSCREEN }, + { WindowMode::WINDOW_MODE_SPLIT_PRIMARY, ApiWindowMode::PRIMARY }, + { WindowMode::WINDOW_MODE_SPLIT_SECONDARY, ApiWindowMode::SECONDARY }, + { WindowMode::WINDOW_MODE_FLOATING, ApiWindowMode::FLOATING }, +}; + +const std::map JS_TO_NATIVE_WINDOW_MODE_MAP { + {ApiWindowMode::UNDEFINED, WindowMode::WINDOW_MODE_UNDEFINED }, + {ApiWindowMode::FULLSCREEN, WindowMode::WINDOW_MODE_FULLSCREEN }, + {ApiWindowMode::PRIMARY, WindowMode::WINDOW_MODE_SPLIT_PRIMARY }, + {ApiWindowMode::SECONDARY, WindowMode::WINDOW_MODE_SPLIT_SECONDARY }, + {ApiWindowMode::FLOATING, WindowMode::WINDOW_MODE_FLOATING }, +}; + +enum class ApiOrientation : uint32_t { + UNSPECIFIED = 0, + PORTRAIT = 1, + LANDSCAPE = 2, + PORTRAIT_INVERTED = 3, + LANDSCAPE_INVERTED = 4, + AUTO_ROTATION = 5, + AUTO_ROTATION_PORTRAIT = 6, + AUTO_ROTATION_LANDSCAPE = 7, + AUTO_ROTATION_RESTRICTED = 8, + AUTO_ROTATION_PORTRAIT_RESTRICTED = 9, + AUTO_ROTATION_LANDSCAPE_RESTRICTED = 10, + LOCKED = 11, +}; + +const std::map JS_TO_NATIVE_ORIENTATION_MAP { + {ApiOrientation::UNSPECIFIED, Orientation::UNSPECIFIED }, + {ApiOrientation::PORTRAIT, Orientation::VERTICAL }, + {ApiOrientation::LANDSCAPE, Orientation::HORIZONTAL }, + {ApiOrientation::PORTRAIT_INVERTED, Orientation::REVERSE_VERTICAL }, + {ApiOrientation::LANDSCAPE_INVERTED, Orientation::REVERSE_HORIZONTAL }, + {ApiOrientation::AUTO_ROTATION, Orientation::SENSOR }, + {ApiOrientation::AUTO_ROTATION_PORTRAIT, Orientation::SENSOR_VERTICAL }, + {ApiOrientation::AUTO_ROTATION_LANDSCAPE, Orientation::SENSOR_HORIZONTAL }, + {ApiOrientation::AUTO_ROTATION_RESTRICTED, Orientation::AUTO_ROTATION_RESTRICTED }, + {ApiOrientation::AUTO_ROTATION_PORTRAIT_RESTRICTED, Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED }, + {ApiOrientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED, Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED }, + {ApiOrientation::LOCKED, Orientation::LOCKED }, +}; + + NativeValue* GetRectAndConvertToJsValue(NativeEngine& engine, const Rect& rect); + NativeValue* CreateJsWindowPropertiesObject(NativeEngine& engine, sptr& window); + bool SetSystemBarPropertiesFromJs(NativeEngine& engine, NativeObject* jsObject, + std::map& properties, sptr& window); + bool GetSystemBarStatus(std::map& systemBarProperties, + NativeEngine& engine, NativeCallbackInfo& info, sptr& window); + NativeValue* CreateJsSystemBarRegionTintArrayObject(NativeEngine& engine, + const SystemBarRegionTints& tints); + NativeValue* ConvertAvoidAreaToJsValue(NativeEngine& engine, const AvoidArea& avoidArea, AvoidAreaType type); + bool CheckCallingPermission(std::string permission); + NativeValue* WindowTypeInit(NativeEngine* engine); + NativeValue* AvoidAreaTypeInit(NativeEngine* engine); + NativeValue* WindowModeInit(NativeEngine* engine); + NativeValue* ColorSpaceInit(NativeEngine* engine); + NativeValue* OrientationInit(NativeEngine* engine); + NativeValue* WindowStageEventTypeInit(NativeEngine* engine); + NativeValue* WindowLayoutModeInit(NativeEngine* engine); + NativeValue* BlurStyleInit(NativeEngine* engine); + NativeValue* WindowErrorCodeInit(NativeEngine* engine); + NativeValue* WindowErrorInit(NativeEngine* engine); + bool GetAPI7Ability(NativeEngine& engine, AppExecFwk::Ability* &ability); + template + bool ParseJsValue(NativeObject* jsObject, NativeEngine& engine, const std::string& name, T& data) + { + NativeValue* value = jsObject->GetProperty(name.c_str()); + if (value->TypeOf() != NATIVE_UNDEFINED) { + if (!AbilityRuntime::ConvertFromJsValue(engine, value, data)) { + return false; + } + } else { + return false; + } + return true; + } + template + inline bool ConvertNativeValueToVector(NativeEngine& engine, NativeValue* nativeValue, std::vector& out) + { + NativeArray* nativeArray = AbilityRuntime::ConvertNativeValueTo(nativeValue); + if (nativeArray == nullptr) { + return false; + } + T value; + for (uint32_t i = 0; i < nativeArray->GetLength(); i++) { + if (!AbilityRuntime::ConvertFromJsValue(engine, nativeArray->GetElement(i), value)) { + return false; + } + out.emplace_back(value); + } + return true; + } +} +} +#endif \ No newline at end of file diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/BUILD.gn b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/BUILD.gn new file mode 100644 index 0000000..63a59d2 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/BUILD.gn @@ -0,0 +1,55 @@ +# Copyright (c) 2021-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. + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/ohos.gni") + +es2abc_gen_abc("gen_window_stage_abc") { + src_js = rebase_path("window_stage.js") + dst_file = rebase_path(target_out_dir + "/window_stage.abc") + in_puts = [ "window_stage.js" ] + out_puts = [ target_out_dir + "/window_stage.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("window_stage_js") { + input = "window_stage.js" + output = target_out_dir + "/window_stage.o" +} + +gen_js_obj("window_stage_abc") { + input = get_label_info(":gen_window_stage_abc", "target_out_dir") + + "/window_stage.abc" + output = target_out_dir + "/window_stage_abc.o" + dep = ":gen_window_stage_abc" +} + +ohos_shared_library("windowstage") { + sources = [ "window_stage_module.cpp" ] + + configs = [ + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + ":window_stage_abc", + ":window_stage_js", + ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/application" + + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp new file mode 100644 index 0000000..f03fb21 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2021-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_window_stage.h" +#include +#include "js_runtime_utils.h" +#include "js_window.h" +#include "js_window_register_manager.h" +#include "js_window_utils.h" +#include "window_manager_hilog.h" +#include "permission.h" + +namespace OHOS { +namespace Rosen { +using namespace AbilityRuntime; +namespace { +const int CONTENT_STORAGE_ARG = 2; +constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowStage"}; +} // namespace + +std::unique_ptr g_listenerManager = std::make_unique(); +JsWindowStage::JsWindowStage(const std::shared_ptr& windowScene) + : windowScene_(windowScene) +{ +} + +JsWindowStage::~JsWindowStage() +{ +} + +void JsWindowStage::Finalizer(NativeEngine* engine, void* data, void* hint) +{ + WLOGFI("[NAPI]Finalizer"); + std::unique_ptr(static_cast(data)); +} + +NativeValue* JsWindowStage::SetUIContent(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetUIContent"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetUIContent(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::GetMainWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetMainWindow"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetMainWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::GetMainWindowSync(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetMainWindowSync"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetMainWindowSync(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::On(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]On"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnEvent(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::Off(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]Off"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OffEvent(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::LoadContent(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]LoadContent"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnLoadContent(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::GetWindowMode(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetWindowMode"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetWindowMode(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::CreateSubWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]CreateSubWindow"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnCreateSubWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::GetSubWindow(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]GetSubWindow"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnGetSubWindow(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::SetShowOnLockScreen(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]SetShowOnLockScreen"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetShowOnLockScreen(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::DisableWindowDecor(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGFD("[NAPI]DisableWindowDecor"); + JsWindowStage* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnDisableWindowDecor(*engine, *info) : nullptr; +} + +NativeValue* JsWindowStage::OnSetUIContent(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc < 2) { // 2: minimum param num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + return engine.CreateUndefined(); + } + auto weakScene = windowScene_.lock(); + if (weakScene == nullptr || weakScene->GetMainWindow() == nullptr) { + WLOGFE("[NAPI]WindowScene is null or window is null"); + return engine.CreateUndefined(); + } + + // Parse info->argv[0] as abilitycontext + auto objContext = ConvertNativeValueTo(info.argv[0]); + if (objContext == nullptr) { + WLOGFE("[NAPI]Context is nullptr"); + return engine.CreateUndefined(); + } + + // Parse info->argv[1] as url + std::string contextUrl; + if (!ConvertFromJsValue(engine, info.argv[1], contextUrl)) { + WLOGFE("[NAPI]Failed to convert parameter to url"); + return engine.CreateUndefined(); + } + weakScene->GetMainWindow()->SetUIContent(contextUrl, &engine, info.argv[CONTENT_STORAGE_ARG]); + return engine.CreateUndefined(); +} + +NativeValue* JsWindowStage::OnGetMainWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + AsyncTask::CompleteCallback complete = + [weak = windowScene_](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakScene = weak.lock(); + if (weakScene == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY))); + WLOGFE("[NAPI]WindowScene_ is nullptr!"); + return; + } + auto window = weakScene->GetMainWindow(); + if (window != nullptr) { + task.Resolve(engine, OHOS::Rosen::CreateJsWindowObject(engine, window)); + WLOGFI("[NAPI]Get main window [%{public}u, %{public}s]", + window->GetWindowId(), window->GetWindowName().c_str()); + } else { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "Get main window failed.")); + } + }; + NativeValue* callback = (info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowStage::OnGetMainWindow", + engine, CreateAsyncTaskWithLastParam(engine, callback, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowStage::OnGetMainWindowSync(NativeEngine& engine, NativeCallbackInfo& info) +{ + auto weakScene = windowScene_.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]WindowScene is null"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY))); + return engine.CreateUndefined(); + } + auto window = weakScene->GetMainWindow(); + if (window == nullptr) { + WLOGFE("[NAPI]window is null"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + + return OHOS::Rosen::CreateJsWindowObject(engine, window); +} + + +NativeValue* JsWindowStage::OnEvent(NativeEngine& engine, NativeCallbackInfo& info) +{ + auto weakScene = windowScene_.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]Window scene is null"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + if (info.argc < 2) { // 2: minimum param nums + WLOGFE("[NAPI]argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + // Parse info->argv[0] as string + std::string eventString; + if (!ConvertFromJsValue(engine, info.argv[0], eventString)) { + WLOGFE("[NAPI]Failed to convert parameter to string"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + NativeValue* value = info.argv[1]; + if (!value->IsCallable()) { + WLOGFE("[NAPI]Callback(info->argv[1]) is not callable"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + auto window = weakScene->GetMainWindow(); + if (window == nullptr) { + WLOGFE("[NAPI]Get window failed"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + g_listenerManager->RegisterListener(window, eventString, CaseType::CASE_STAGE, engine, value); + WLOGFI("[NAPI]Window [%{public}u, %{public}s] register event %{public}s, callback %{public}p", + window->GetWindowId(), window->GetWindowName().c_str(), eventString.c_str(), value); + + return engine.CreateUndefined(); +} + +NativeValue* JsWindowStage::OffEvent(NativeEngine& engine, NativeCallbackInfo& info) +{ + auto weakScene = windowScene_.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]Window scene is null"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + + // Parse info->argv[0] as string + std::string eventString; + if (!ConvertFromJsValue(engine, info.argv[0], eventString)) { + WLOGFE("[NAPI]Failed to convert parameter to string"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + if (eventString.compare("windowStageEvent") != 0) { + WLOGFE("[NAPI]Envent %{public}s is invalid", eventString.c_str()); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + auto window = weakScene->GetMainWindow(); + if (window == nullptr) { + WLOGFE("[NAPI]Get window failed"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return engine.CreateUndefined(); + } + NativeValue* value = nullptr; + if (info.argv[1] == nullptr || info.argv[1]->TypeOf() != NATIVE_FUNCTION) { + g_listenerManager->UnregisterListener(window, eventString, CaseType::CASE_STAGE, nullptr); + } else { + g_listenerManager->UnregisterListener(window, eventString, CaseType::CASE_STAGE, info.argv[1]); + } + + if (info.argc == 1) { + g_listenerManager->UnregisterListener(window, eventString, CaseType::CASE_STAGE, nullptr); + } else { + value = info.argv[1]; + if (value != nullptr && value->TypeOf() == NATIVE_FUNCTION) { + g_listenerManager->UnregisterListener(window, eventString, CaseType::CASE_STAGE, value); + } else { + g_listenerManager->UnregisterListener(window, eventString, CaseType::CASE_STAGE, nullptr); + } + } + WLOGFI("[NAPI]Window [%{public}u, %{public}s] unregister event %{public}s, callback %{public}p", + window->GetWindowId(), window->GetWindowName().c_str(), eventString.c_str(), value); + + return engine.CreateUndefined(); +} + +static void LoadContentTask(std::shared_ptr contentStorage, std::string contextUrl, + sptr weakWindow, NativeEngine& engine, AsyncTask& task) +{ + NativeValue* nativeStorage = (contentStorage == nullptr) ? nullptr : contentStorage->Get(); + WMError ret = weakWindow->SetUIContent(contextUrl, &engine, nativeStorage, false); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "Window load content failed")); + } + WLOGFI("[NAPI]Window [%{public}u, %{public}s] load content end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + return; +} + +NativeValue* JsWindowStage::OnLoadContent(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + std::string contextUrl; + if (!ConvertFromJsValue(engine, info.argv[0], contextUrl)) { + WLOGFE("[NAPI]Failed to convert parameter to context url"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + NativeValue* storage = nullptr; + NativeValue* callBack = nullptr; + NativeValue* value1 = info.argv[1]; + NativeValue* value2 = info.argv[2]; // 2: param index + if (value1->TypeOf() == NATIVE_FUNCTION) { + callBack = value1; + } else if (value1->TypeOf() == NATIVE_OBJECT) { + storage = value1; + } + if (value2->TypeOf() == NATIVE_FUNCTION) { + callBack = value2; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + WLOGFE("[NAPI]Window scene is null or get invalid param"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + std::shared_ptr contentStorage = (storage == nullptr) ? nullptr : + std::shared_ptr(engine.CreateReference(storage, 1)); + AsyncTask::CompleteCallback complete = + [weak = windowScene_, contentStorage, contextUrl, errCode]( + NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakScene = weak.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]Window scene is null"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY))); + return; + } + auto win = weakScene->GetMainWindow(); + if (win == nullptr) { + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + WLOGFE("[NAPI]Get window failed"); + return; + } + LoadContentTask(contentStorage, contextUrl, win, engine, task); + }; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowStage::OnLoadContent", + engine, CreateAsyncTaskWithLastParam(engine, callBack, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowStage::OnGetWindowMode(NativeEngine& engine, NativeCallbackInfo& info) +{ + AsyncTask::CompleteCallback complete = + [weak = windowScene_](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakScene = weak.lock(); + if (weakScene == nullptr) { + task.Reject(engine, CreateJsError(engine, static_cast(WMError::WM_ERROR_NULLPTR))); + WLOGFE("[NAPI]windowScene_ is nullptr"); + return; + } + auto window = weakScene->GetMainWindow(); + if (window == nullptr) { + task.Reject(engine, CreateJsError(engine, static_cast(Rosen::WMError::WM_ERROR_NULLPTR), + "Get window failed")); + WLOGFE("[NAPI]Get window failed"); + return; + } + Rosen::WindowMode mode = window->GetMode(); + if (NATIVE_TO_JS_WINDOW_MODE_MAP.count(mode) != 0) { + task.Resolve(engine, CreateJsValue(engine, NATIVE_TO_JS_WINDOW_MODE_MAP.at(mode))); + WLOGFI("[NAPI]Window [%{public}u, %{public}s] get mode %{public}u, api mode %{public}u", + window->GetWindowId(), window->GetWindowName().c_str(), + mode, NATIVE_TO_JS_WINDOW_MODE_MAP.at(mode)); + } else { + task.Resolve(engine, CreateJsValue(engine, mode)); + WLOGFE("[NAPI]Get mode %{public}u, but not in apimode", mode); + } + }; + NativeValue* callback = (info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? info.argv[0] : nullptr; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowStage::OnGetWindowMode", + engine, CreateAsyncTaskWithLastParam(engine, callback, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowStage::OnCreateSubWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + WmErrorCode errCode = WmErrorCode::WM_OK; + std::string windowName; + if (!ConvertFromJsValue(engine, info.argv[0], windowName)) { + WLOGFE("[NAPI]Failed to convert parameter to windowName"); + errCode = WmErrorCode::WM_ERROR_INVALID_PARAM; + } + if (errCode == WmErrorCode::WM_ERROR_INVALID_PARAM) { + WLOGFE("[NAPI]get invalid param"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + AsyncTask::CompleteCallback complete = + [weak = windowScene_, windowName](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakScene = weak.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]Window scene is null"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + sptr windowOption = new Rosen::WindowOption(); + windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + auto window = weakScene->CreateWindow(windowName, windowOption); + if (window == nullptr) { + WLOGFE("[NAPI]Get window failed"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), "Get window failed")); + return; + } + task.Resolve(engine, CreateJsWindowObject(engine, window)); + WLOGFI("[NAPI]Create sub widdow %{public}s end", windowName.c_str()); + }; + NativeValue* callback = (info.argv[1] != nullptr && info.argv[1]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[1] : nullptr; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowStage::OnCreateSubWindow", + engine, CreateAsyncTaskWithLastParam(engine, callback, nullptr, std::move(complete), &result)); + return result; +} + +static NativeValue* CreateJsSubWindowArrayObject(NativeEngine& engine, + std::vector> subWinVec) +{ + NativeValue* objValue = engine.CreateArray(subWinVec.size()); + NativeArray* array = ConvertNativeValueTo(objValue); + if (array == nullptr) { + WLOGFE("[NAPI]Failed to convert subWinVec to jsArrayObject"); + return nullptr; + } + uint32_t index = 0; + for (size_t i = 0; i < subWinVec.size(); i++) { + array->SetElement(index++, CreateJsWindowObject(engine, subWinVec[i])); + } + return objValue; +} + +NativeValue* JsWindowStage::OnGetSubWindow(NativeEngine& engine, NativeCallbackInfo& info) +{ + AsyncTask::CompleteCallback complete = + [weak = windowScene_](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakScene = weak.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]Window scene is nullptr"); + task.Reject(engine, CreateJsError(engine, + static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return; + } + std::vector> subWindowVec = weakScene->GetSubWindow(); + task.Resolve(engine, CreateJsSubWindowArrayObject(engine, subWindowVec)); + WLOGFI("[NAPI]Get sub windows, size = %{public}zu", subWindowVec.size()); + }; + NativeValue* callback = (info.argv[0] != nullptr && info.argv[0]->TypeOf() == NATIVE_FUNCTION) ? + info.argv[0] : nullptr; + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindowStage::OnGetSubWindow", + engine, CreateAsyncTaskWithLastParam(engine, callback, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindowStage::OnSetShowOnLockScreen(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set show on lock screen permission denied!"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return CreateJsValue(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING)); + } + if (info.argc < 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return CreateJsValue(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM)); + } + auto weakScene = windowScene_.lock(); + if (weakScene == nullptr || weakScene->GetMainWindow() == nullptr) { + WLOGFE("[NAPI]WindowScene is null or window is null"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); + return CreateJsValue(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY)); + } + + bool showOnLockScreen = false; + NativeBoolean* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + WLOGFE("[NAPI]Failed to convert parameter to boolean"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return CreateJsValue(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM)); + } else { + showOnLockScreen = static_cast(*nativeVal); + } + + auto window = weakScene->GetMainWindow(); + WmErrorCode ret; + if (showOnLockScreen) { + ret = WM_JS_TO_ERROR_CODE_MAP.at( + window->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + } else { + ret = WM_JS_TO_ERROR_CODE_MAP.at( + window->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + } + WLOGFI("[NAPI]Window [%{public}u, %{public}s] SetShowOnLockScreen %{public}u, ret = %{public}u", + window->GetWindowId(), window->GetWindowName().c_str(), showOnLockScreen, ret); + + return CreateJsValue(engine, static_cast(ret)); +} + +NativeValue* JsWindowStage::OnDisableWindowDecor(NativeEngine& engine, NativeCallbackInfo& info) +{ + auto weakScene = windowScene_.lock(); + if (weakScene == nullptr) { + WLOGFE("[NAPI]WindowScene is null"); + return CreateJsValue(engine, static_cast(WmErrorCode::WM_ERROR_STAGE_ABNORMALLY)); + } + + auto window = weakScene->GetMainWindow(); + if (window == nullptr) { + WLOGFE("[NAPI]Window is null"); + return CreateJsValue(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY)); + } + window->DisableAppWindowDecor(); + WLOGFI("[NAPI]Window [%{public}u, %{public}s] disable app window decor end", + window->GetWindowId(), window->GetWindowName().c_str()); + return engine.CreateUndefined(); +} + +NativeValue* CreateJsWindowStage(NativeEngine& engine, + std::shared_ptr windowScene) +{ + WLOGFD("[NAPI]CreateJsWindowStage"); + NativeValue* objValue = engine.CreateObject(); + NativeObject* object = ConvertNativeValueTo(objValue); + + std::unique_ptr jsWindowStage = std::make_unique(windowScene); + object->SetNativePointer(jsWindowStage.release(), JsWindowStage::Finalizer, nullptr); + + const char *moduleName = "JsWindowStage"; + BindNativeFunction(engine, + *object, "setUIContent", moduleName, JsWindowStage::SetUIContent); + BindNativeFunction(engine, + *object, "loadContent", moduleName, JsWindowStage::LoadContent); + BindNativeFunction(engine, + *object, "getMainWindow", moduleName, JsWindowStage::GetMainWindow); + BindNativeFunction(engine, + *object, "getMainWindowSync", moduleName, JsWindowStage::GetMainWindowSync); + BindNativeFunction(engine, + *object, "getWindowMode", moduleName, JsWindowStage::GetWindowMode); + BindNativeFunction(engine, + *object, "createSubWindow", moduleName, JsWindowStage::CreateSubWindow); + BindNativeFunction(engine, + *object, "getSubWindow", moduleName, JsWindowStage::GetSubWindow); + BindNativeFunction(engine, *object, "on", moduleName, JsWindowStage::On); + BindNativeFunction(engine, *object, "off", moduleName, JsWindowStage::Off); + BindNativeFunction(engine, + *object, "setShowOnLockScreen", moduleName, JsWindowStage::SetShowOnLockScreen); + BindNativeFunction(engine, + *object, "disableWindowDecor", moduleName, JsWindowStage::DisableWindowDecor); + + return objValue; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h new file mode 100644 index 0000000..b7fc775 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021-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_WINDOW_STAGE_H +#define OHOS_JS_WINDOW_STAGE_H +#include +#include +#include "native_engine/native_engine.h" +#include "native_engine/native_reference.h" +#include "native_engine/native_value.h" +#include "window_scene.h" +namespace OHOS { +namespace Rosen { +NativeValue* CreateJsWindowStage(NativeEngine& engine, std::shared_ptr windowScene); +class JsWindowStage { +public: + explicit JsWindowStage(const std::shared_ptr& windowScene); + ~JsWindowStage(); + static void Finalizer(NativeEngine* engine, void* data, void* hint); + static NativeValue* SetUIContent(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetMainWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetMainWindowSync(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* On(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* Off(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* LoadContent(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetWindowMode(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* CreateSubWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* GetSubWindow(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetShowOnLockScreen(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* DisableWindowDecor(NativeEngine* engine, NativeCallbackInfo* info); + +private: + NativeValue* OnSetUIContent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetMainWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetMainWindowSync(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnEvent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OffEvent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnLoadContent(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetWindowMode(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnCreateSubWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnGetSubWindow(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetShowOnLockScreen(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnDisableWindowDecor(NativeEngine& engine, NativeCallbackInfo& info); + + std::weak_ptr windowScene_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_JS_WINDOW_STAGE_H diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage.js b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage.js new file mode 100644 index 0000000..dadc4b7 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage.js @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021-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. + */ + +class WindowStage { + constructor(obj) { + this.__window_stage__ = obj + } + + setUIContent(context, url, storage) { + return this.__window_stage__.setUIContent(context, url, storage) + } + + loadContent (url, storage, asyncCallback) { + return this.__window_stage__.loadContent(url, storage, asyncCallback) + } + + getWindowMode(asyncCallback) { + return this.__window_stage__.getWindowMode(asyncCallback) + } + + getMainWindow(asyncCallback) { + return this.__window_stage__.getMainWindow(asyncCallback) + } + + getMainWindowSync() { + return this.__window_stage__.getMainWindowSync() + } + + createSubWindow(windowName, asyncCallback) { + return this.__window_stage__.createSubWindow(windowName, asyncCallback) + } + + getSubWindow(asyncCallback) { + return this.__window_stage__.getSubWindow(asyncCallback) + } + + on(type, callback) { + return this.__window_stage__.on(type, callback) + } + + off(type, callback) { + return this.__window_stage__.off(type, callback) + } + + setShowOnLockScreen(showOnLockScreen) { + return this.__window_stage__.setShowOnLockScreen(showOnLockScreen) + } + + disableWindowDecor() { + return this.__window_stage__.disableWindowDecor() + } +} + +export default WindowStage diff --git a/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage_module.cpp b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage_module.cpp new file mode 100644 index 0000000..9a75d35 --- /dev/null +++ b/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/window_stage_module.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-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 "native_engine/native_engine.h" + +extern const char _binary_window_stage_js_start[]; +extern const char _binary_window_stage_js_end[]; +extern const char _binary_window_stage_abc_start[]; +extern const char _binary_window_stage_abc_end[]; + +extern "C" __attribute__((constructor)) void NAPI_application_WindowStage_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "application.WindowStage", + .fileName = "application/libwindowstage.so/window_stage.js", + }; + + moduleManager->Register(&newModuleInfo); +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_application_WindowStage_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_window_stage_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_window_stage_js_end - _binary_window_stage_js_start; + } +} + +// window_stage JS register +extern "C" __attribute__((visibility("default"))) +void NAPI_application_WindowStage_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_window_stage_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_window_stage_abc_end - _binary_window_stage_abc_start; + } +} + diff --git a/window_manager/previewer/BUILD.gn b/window_manager/previewer/BUILD.gn new file mode 100644 index 0000000..f028f4b --- /dev/null +++ b/window_manager/previewer/BUILD.gn @@ -0,0 +1,133 @@ +# 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. + +import("//build/ohos.gni") + +config("previewer_window_config") { + visibility = [ ":*" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/previewer/include", + ] +} + +ohos_shared_library("previewer_window") { + configs = [ ":previewer_window_config" ] + + libs = [] + + sources = [ + "../../../../commonlibrary/c_utils/base/src/refbase.cpp", + "../utils/src/window_property.cpp", + "../utils/src/window_transition_info.cpp", + "../utils/src/wm_math.cpp", + "../wm/src/input_transfer_station.cpp", + "../wm/src/vsync_station.cpp", + "../wm/src/window.cpp", + "../wm/src/window_frame_trace_impl.cpp", + "../wm/src/window_input_channel.cpp", + "../wm/src/window_option.cpp", + "mock/parcel.cpp", + "src/window_impl.cpp", + "src/window_scene.cpp", + ] + + include_dirs = [ + "include", + "mock", + "../interfaces/innerkits/wm", + "../interfaces/innerkits/dm", + "../wm/include", + "../utils/include", + "../../../../commonlibrary/c_utils/base/include", + ] + + deps = [ + "//foundation/arkui/napi:ace_napi", + "//foundation/arkui/napi:ace_napi_ark", + ] + + cflags = [ "-std=c++11" ] + part_name = "window_manager" + subsystem_name = "window" +} + +config("previewer_window_napi_config") { + visibility = [ ":*" ] + + include_dirs = [ "//foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_napi" ] +} + +ohos_shared_library("previewer_window_napi") { + public_configs = [ ":previewer_window_napi_config" ] + + libs = [] + + sources = [ + "../../../ability/ability_runtime/frameworks/native/runtime/js_runtime_utils.cpp", + "../interfaces/kits/napi/window_runtime/window_napi/js_window.cpp", + "../interfaces/kits/napi/window_runtime/window_napi/js_window_utils.cpp", + "../interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp", + + # mock + "mock/js_transition_controller.cpp", + "mock/js_window_register_manager.cpp", + "mock/permission.cpp", + "mock/pixel_map_napi.cpp", + "mock/ui/rs_node.cpp", + ] + + include_dirs = [ + ".", # 避免冲突的mock目录 + "include", + "mock", + "mock/ui", + "mock/transaction", + "../wm/include", + "../utils/include", + "../interfaces/innerkits/wm", + "../interfaces/innerkits/dm", + "../interfaces/kits/napi/window_runtime/window_stage_napi", + "../../../ability/ability_runtime/interfaces/inner_api/runtime/include", + "../../../../commonlibrary/c_utils/base/include", + ] + + deps = [ + ":previewer_window", + "//foundation/arkui/napi:ace_napi", + "//foundation/arkui/napi:ace_napi_ark", + ] + + cflags_cc = [ "-DWINDOW_PREVIEW" ] + cflags = [ "-std=c++11" ] + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_copy("copy_previewer_library") { + if (host_os == "mac") { + suffix = ".dylib" + } else { + suffix = ".dll" + } + shared_library_path = + get_label_info(":previewer_window_napi", "root_out_dir") + + "/window/window_manager/libpreviewer_window_napi" + suffix + deps = [ ":previewer_window_napi" ] + sources = [ shared_library_path ] + outputs = + [ target_out_dir + "/previewer/common/bin/libpreviewer_window" + suffix ] + module_source_dir = target_out_dir + "/previewer/common/bin/" + module_install_name = "" +} diff --git a/window_manager/previewer/include/window_impl.h b/window_manager/previewer/include/window_impl.h new file mode 100644 index 0000000..45f5ab8 --- /dev/null +++ b/window_manager/previewer/include/window_impl.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_IMPL_H +#define OHOS_ROSEN_WINDOW_IMPL_H + +#include + +#include + +#include "window.h" +#include "window_property.h" + +namespace OHOS::AbilityRuntime { + class Context; +} + +namespace OHOS { +namespace Rosen { +union ColorParam { +#if BIG_ENDIANNESS + struct { + uint8_t alpha; + uint8_t red; + uint8_t green; + uint8_t blue; + } argb; +#else + struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + } argb; +#endif + uint32_t value; +}; + +class WindowImpl : public Window { +public: + explicit WindowImpl(const sptr& option); + ~WindowImpl(); + static sptr Find(const std::string& id); + static sptr GetTopWindowWithContext(const std::shared_ptr& context = nullptr); + static sptr GetTopWindowWithId(uint32_t mainWinId); + static std::vector> GetSubWindow(uint32_t parantId); + static void UpdateConfigurationForAll(const std::shared_ptr& configuration); + virtual std::shared_ptr GetSurfaceNode() const override; + virtual Rect GetRect() const override; + virtual Rect GetRequestRect() const override; + virtual WindowType GetType() const override; + virtual WindowMode GetMode() const override; + virtual float GetAlpha() const override; + virtual WindowState GetWindowState() const override; + virtual WMError SetFocusable(bool isFocusable) override; + virtual bool GetFocusable() const override; + virtual WMError SetTouchable(bool isTouchable) override; + virtual bool GetTouchable() const override; + virtual const std::string& GetWindowName() const override; + virtual uint32_t GetWindowId() const override; + virtual uint32_t GetWindowFlags() const override; + uint32_t GetRequestModeSupportInfo() const override; + bool IsMainHandlerAvailable() const override; + virtual SystemBarProperty GetSystemBarPropertyByType(WindowType type) const override; + virtual bool IsFullScreen() const override; + virtual bool IsLayoutFullScreen() const override; + virtual WMError SetWindowType(WindowType type) override; + virtual WMError SetWindowMode(WindowMode mode) override; + virtual void SetAlpha(float alpha) override; + virtual void SetTransform(const Transform& trans) override; + virtual WMError AddWindowFlag(WindowFlag flag) override; + virtual WMError RemoveWindowFlag(WindowFlag flag) override; + virtual WMError SetWindowFlags(uint32_t flags) override; + virtual WMError SetSystemBarProperty(WindowType type, const SystemBarProperty& property) override; + virtual WMError SetLayoutFullScreen(bool status) override; + virtual WMError SetFullScreen(bool status) override; + virtual const Transform& GetTransform() const override; + virtual WMError UpdateSurfaceNodeAfterCustomAnimation(bool isAdd) override; + virtual WMError GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea) override; + + WMError Create(uint32_t parentId, + const std::shared_ptr& context = nullptr); + virtual WMError Destroy() override; + virtual WMError Show(uint32_t reason = 0, bool withAnimation = false) override; + virtual WMError Hide(uint32_t reason = 0, bool withAnimation = false) override; + virtual WMError MoveTo(int32_t x, int32_t y) override; + virtual WMError Resize(uint32_t width, uint32_t height) override; + virtual WMError SetKeepScreenOn(bool keepScreenOn) override; + virtual bool IsKeepScreenOn() const override; + virtual WMError SetTurnScreenOn(bool turnScreenOn) override; + virtual bool IsTurnScreenOn() const override; + virtual WMError SetBackgroundColor(const std::string& color) override; + virtual WMError SetTransparent(bool isTransparent) override; + virtual bool IsTransparent() const override; + virtual WMError SetBrightness(float brightness) override; + virtual float GetBrightness() const override; + virtual WMError SetCallingWindow(uint32_t windowId) override; + virtual void SetPrivacyMode(bool isPrivacyMode) override; + virtual bool IsPrivacyMode() const override; + virtual void SetSystemPrivacyMode(bool isSystemPrivacyMode) override; + virtual void DisableAppWindowDecor() override; + virtual WMError BindDialogTarget(sptr targetToken) override; + virtual void SetSnapshotSkip(bool isSkip) override; + + // window effect + virtual WMError SetCornerRadius(float cornerRadius) override; + virtual WMError SetShadowRadius(float radius) override; + virtual WMError SetShadowColor(std::string color) override; + virtual void SetShadowOffsetX(float offsetX) override; + virtual void SetShadowOffsetY(float offsetY) override; + virtual WMError SetBlur(float radius) override; + virtual WMError SetBackdropBlur(float radius) override; + virtual WMError SetBackdropBlurStyle(WindowBlurStyle blurStyle) override; + + virtual bool IsDecorEnable() const override; + virtual WMError Maximize() override; + virtual WMError Minimize() override; + virtual WMError Recover() override; + virtual WMError Close() override; + virtual void StartMove() override; + + virtual WMError RequestFocus() const override; + virtual bool IsFocused() const override; + virtual void SetInputEventConsumer(const std::shared_ptr& inputEventConsumer) override; + + virtual bool RegisterLifeCycleListener(const sptr& listener) override; + virtual bool RegisterWindowChangeListener(const sptr& listener) override; + virtual bool UnregisterLifeCycleListener(const sptr& listener) override; + virtual bool UnregisterWindowChangeListener(const sptr& listener) override; + virtual bool RegisterAvoidAreaChangeListener(sptr& listener) override; + virtual bool UnregisterAvoidAreaChangeListener(sptr& listener) override; + virtual bool RegisterDragListener(const sptr& listener) override; + virtual bool UnregisterDragListener(const sptr& listener) override; + virtual bool RegisterDisplayMoveListener(sptr& listener) override; + virtual bool UnregisterDisplayMoveListener(sptr& listener) override; + virtual void RegisterWindowDestroyedListener(const NotifyNativeWinDestroyFunc& func) override; + virtual bool RegisterOccupiedAreaChangeListener(const sptr& listener) override; + virtual bool UnregisterOccupiedAreaChangeListener(const sptr& listener) override; + virtual bool RegisterTouchOutsideListener(const sptr& listener) override; + virtual bool UnregisterTouchOutsideListener(const sptr& listener) override; + virtual bool RegisterAnimationTransitionController(const sptr& listener) override; + virtual bool RegisterScreenshotListener(const sptr& listener) override; + virtual bool UnregisterScreenshotListener(const sptr& listener) override; + virtual bool RegisterDialogTargetTouchListener(const sptr& listener) override; + virtual bool UnregisterDialogTargetTouchListener(const sptr& listener) override; + virtual void RegisterDialogDeathRecipientListener(const sptr& listener) override; + virtual void UnregisterDialogDeathRecipientListener(const sptr& listener) override; + virtual void SetAceAbilityHandler(const sptr& handler) override; + virtual void SetRequestModeSupportInfo(uint32_t modeSupportInfo) override; + virtual void ConsumeKeyEvent(std::shared_ptr& inputEvent) override; + virtual void ConsumePointerEvent(const std::shared_ptr& inputEvent) override; + virtual void RequestVsync(const std::shared_ptr& vsyncCallback) override; + virtual void UpdateConfiguration(const std::shared_ptr& configuration) override; + void NotifyTouchDialogTarget() override; + + virtual WMError SetUIContent(const std::string& contentInfo, NativeEngine* engine, + NativeValue* storage, bool isdistributed, AppExecFwk::Ability* ability) override; + virtual std::string GetContentInfo() override; + virtual const std::shared_ptr GetContext() const override; + virtual Ace::UIContent* GetUIContent() const override; + virtual void OnNewWant(const AAFwk::Want& want) override; + virtual void SetRequestedOrientation(Orientation) override; + virtual Orientation GetRequestedOrientation() override; + virtual void SetNeedRemoveWindowInputChannel(bool needRemoveWindowInputChannel) override; + virtual WMError SetTouchHotAreas(const std::vector& rects) override; + virtual void GetRequestedTouchHotAreas(std::vector& rects) const override; + virtual WMError SetAPPWindowLabel(const std::string& label) override; + virtual WMError SetAPPWindowIcon(const std::shared_ptr& icon) override; + + // colorspace, gamut + virtual bool IsSupportWideGamut() override; + virtual void SetColorSpace(ColorSpace colorSpace) override; + virtual ColorSpace GetColorSpace() override; + + virtual void DumpInfo(const std::vector& params, std::vector& info) override; + virtual std::shared_ptr Snapshot() override; + virtual WMError NotifyMemoryLevel(int32_t level) const override; + virtual bool IsAllowHaveSystemSubWindow() override; + +private: + static std::map>> windowMap_; + static std::map>> subWindowMap_; + sptr property_; + WindowState state_ { WindowState::STATE_INITIAL }; + std::string name_; + std::unique_ptr uiContent_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_IMPL_H diff --git a/window_manager/previewer/include/window_scene.h b/window_manager/previewer/include/window_scene.h new file mode 100644 index 0000000..cf8eefc --- /dev/null +++ b/window_manager/previewer/include/window_scene.h @@ -0,0 +1,57 @@ +/* + * 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 INTERFACES_INNERKITS_WINDOW_SCENE_H +#define INTERFACES_INNERKITS_WINDOW_SCENE_H + +#include +#include + +#include "window.h" +#include "window_option.h" + +namespace OHOS::AppExecFwk { + class Configuration; +} + +namespace OHOS { +namespace Rosen { +#ifdef CreateWindow +#undef CreateWindow +#endif +class WindowScene : public RefBase { +public: + WindowScene() = default; + ~WindowScene(); + WMError Init(DisplayId displayId, const std::shared_ptr& context, + sptr& listener, sptr option = nullptr); + sptr CreateWindow(const std::string& windowName, sptr& option) const; + const sptr& GetMainWindow() const; + std::vector> GetSubWindow(); + WMError GoDestroy(); + void UpdateConfiguration(const std::shared_ptr& configuration); + +private: + std::string GenerateMainWindowName(const std::shared_ptr& context) const; + + sptr mainWindow_ = nullptr; + static inline std::atomic count { 0 }; + static const std::string MAIN_WINDOW_ID; + static const DisplayId DEFAULT_DISPLAY_ID = 0; + DisplayId displayId_ = DEFAULT_DISPLAY_ID; +}; +} // namespace Rosen +} // namespace OHOS +#endif // INTERFACES_INNERKITS_WINDOW_SCENE_H diff --git a/window_manager/previewer/mock/ability_info.h b/window_manager/previewer/mock/ability_info.h new file mode 100644 index 0000000..5d0bd08 --- /dev/null +++ b/window_manager/previewer/mock/ability_info.h @@ -0,0 +1,28 @@ +/* + * 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 FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_BASE_INCLUDE_ABILITY_INFO_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_BASE_INCLUDE_ABILITY_INFO_H + +namespace OHOS { +namespace AppExecFwk { +enum class SupportWindowMode { + FULLSCREEN = 0, + SPLIT, + FLOATING, +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_BASE_INCLUDE_ABILITY_INFO_H diff --git a/window_manager/previewer/mock/accesstoken_kit.h b/window_manager/previewer/mock/accesstoken_kit.h new file mode 100644 index 0000000..ec09282 --- /dev/null +++ b/window_manager/previewer/mock/accesstoken_kit.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 INTERFACES_INNER_KITS_ACCESSTOKEN_KIT_H +#define INTERFACES_INNER_KITS_ACCESSTOKEN_KIT_H + +#include + +namespace OHOS { +namespace Security { +namespace AccessToken { +class AccessTokenKit { +public: + static int VerifyAccessToken(unsigned int tokenID, const std::string& permissionName) + { + return 0; + } + static int VerifyAccessToken( + unsigned int callerTokenID, unsigned int firstTokenID, const std::string& permissionName) + { + return 0; + } +}; +} // namespace AccessToken +} // namespace Security +} // namespace OHOS +#endif // INTERFACES_INNER_KITS_ACCESSTOKEN_KIT_H diff --git a/window_manager/previewer/mock/axis_event.h b/window_manager/previewer/mock/axis_event.h new file mode 100644 index 0000000..b4b3fd7 --- /dev/null +++ b/window_manager/previewer/mock/axis_event.h @@ -0,0 +1,27 @@ +/* + * 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 AXIS_EVENT_H +#define AXIS_EVENT_H + +#include "input_event.h" + +namespace OHOS { +namespace MMI { +class AxisEvent : public InputEvent { +}; +} // namespace MMI +} // namespace OHOS +#endif // AXIS_EVENT_H \ No newline at end of file diff --git a/window_manager/previewer/mock/bundle_constants.h b/window_manager/previewer/mock/bundle_constants.h new file mode 100644 index 0000000..3dc75d2 --- /dev/null +++ b/window_manager/previewer/mock/bundle_constants.h @@ -0,0 +1,30 @@ +/* + * 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 FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_CONSTANTS_H +#define FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_CONSTANTS_H + +#include +#include +#include + +namespace OHOS { +namespace AppExecFwk { +namespace Constants { + constexpr int PERMISSION_GRANTED = 0; +} // namespace Constants +} // namespace AppExecFwk +} // namespace OHOS +#endif // FOUNDATION_APPEXECFWK_INTERFACES_INNERKITS_APPEXECFWK_BASE_INCLUDE_BUNDLE_CONSTANTS_H \ No newline at end of file diff --git a/window_manager/previewer/mock/configuration.h b/window_manager/previewer/mock/configuration.h new file mode 100644 index 0000000..917788c --- /dev/null +++ b/window_manager/previewer/mock/configuration.h @@ -0,0 +1,33 @@ +/* + * 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_ABILITY_BASE_CONFIGURATION_H +#define OHOS_ABILITY_BASE_CONFIGURATION_H + +#include +#include +#include + +namespace OHOS { +namespace AppExecFwk { +class Configuration { +public: + Configuration(); + + ~Configuration(); +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_BASE_CONFIGURATION_H diff --git a/window_manager/previewer/mock/context.h b/window_manager/previewer/mock/context.h new file mode 100644 index 0000000..b1dbd3f --- /dev/null +++ b/window_manager/previewer/mock/context.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_ABILITY_RUNTIME_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_CONTEXT_H + +#include + +namespace OHOS { +namespace AbilityRuntime { +class Context { +public: + Context() = default; + virtual ~Context() = default; + virtual std::string GetBundleName() const = 0; +}; +} // namespace AbilityRuntime +namespace AppExecFwk { +class Context { +public: + Context() = default; + virtual ~Context() = default; +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_CONTEXT_H diff --git a/window_manager/previewer/mock/context_container.h b/window_manager/previewer/mock/context_container.h new file mode 100644 index 0000000..e345293 --- /dev/null +++ b/window_manager/previewer/mock/context_container.h @@ -0,0 +1,26 @@ +/* + * 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_ABILITY_RUNTIME_CONTEXT_CONTAINER_H +#define OHOS_ABILITY_RUNTIME_CONTEXT_CONTAINER_H + +#include "context.h" + +namespace OHOS { +namespace AppExecFwk { +class ContextContainer : public Context { +}; +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_CONTEXT_CONTAINER_H diff --git a/window_manager/previewer/mock/event_handler.h b/window_manager/previewer/mock/event_handler.h new file mode 100644 index 0000000..50c1fcc --- /dev/null +++ b/window_manager/previewer/mock/event_handler.h @@ -0,0 +1,55 @@ +/* + * 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_EVENTHANDLER_H +#define OHOS_EVENTHANDLER_H + +#include +#include + +#include "event_queue.h" +#include "event_runner.h" + +namespace OHOS { +namespace AppExecFwk { +class EventHandler { +public: + using Callback = std::function; + using Priority = EventQueue::Priority; + + EventHandler() {}; + explicit EventHandler(const std::shared_ptr &runner = nullptr) {}; + virtual ~EventHandler() {}; + + static std::shared_ptr Current() + { + return nullptr; + } + + void RemoveTask(const std::string &name) + { + return; + } + + inline bool PostTask(const Callback &callback, const std::string &name = std::string(), int64_t delayTime = 0, + Priority priority = Priority::LOW) + { + return true; + } +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // OHOS_EVENTHANDLER_H diff --git a/window_manager/previewer/mock/event_queue.h b/window_manager/previewer/mock/event_queue.h new file mode 100644 index 0000000..18b9202 --- /dev/null +++ b/window_manager/previewer/mock/event_queue.h @@ -0,0 +1,36 @@ +/* + * 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 BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H +#define BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H + +#include +#include + +namespace OHOS { +namespace AppExecFwk { +class EventQueue final { +public: + enum class Priority : uint32_t { + IMMEDIATE = 0, + HIGH, + LOW, + IDLE, + }; +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H diff --git a/window_manager/previewer/mock/event_runner.h b/window_manager/previewer/mock/event_runner.h new file mode 100644 index 0000000..4293c49 --- /dev/null +++ b/window_manager/previewer/mock/event_runner.h @@ -0,0 +1,57 @@ +/* + * 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 BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_RUNNER_H +#define BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_RUNNER_H + +#include "event_queue.h" + +namespace OHOS { +namespace AppExecFwk { +class EventRunner final { +public: + EventRunner() {}; + virtual ~EventRunner() {}; + static std::shared_ptr Create(bool inNewThread = true) + { + return nullptr; + } + static std::shared_ptr Create(const std::string &threadName) + { + return nullptr; + } + static inline std::shared_ptr Create(const char *threadName) + { + return nullptr; + } + + static std::shared_ptr GetMainEventRunner() + { + return nullptr; + } + + uint64_t GetThreadId() + { + return 0; + } + + explicit EventRunner(bool deposit); + + friend class EventHandler; +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_RUNNER_H diff --git a/window_manager/previewer/mock/hilog_wrapper.h b/window_manager/previewer/mock/hilog_wrapper.h new file mode 100644 index 0000000..d39b9eb --- /dev/null +++ b/window_manager/previewer/mock/hilog_wrapper.h @@ -0,0 +1,25 @@ +/* + * 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 HILOG_WRAPPER_H +#define HILOG_WRAPPER_H + +#define HILOG_FATAL(...) +#define HILOG_ERROR(...) +#define HILOG_WARN(...) +#define HILOG_INFO(...) +#define HILOG_DEBUG(...) + +#endif // HILOG_WRAPPER_H \ No newline at end of file diff --git a/window_manager/previewer/mock/i_input_event_consumer.h b/window_manager/previewer/mock/i_input_event_consumer.h new file mode 100644 index 0000000..36c1b7e --- /dev/null +++ b/window_manager/previewer/mock/i_input_event_consumer.h @@ -0,0 +1,35 @@ +/* + * 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 I_INPUT_EVENT_CONSUMER_H +#define I_INPUT_EVENT_CONSUMER_H + +#include "axis_event.h" +#include "key_event.h" +#include "pointer_event.h" + +namespace OHOS { +namespace MMI { +struct IInputEventConsumer { +public: + IInputEventConsumer() = default; + virtual ~IInputEventConsumer() = default; + + virtual void OnInputEvent(std::shared_ptr keyEvent) const; + virtual void OnInputEvent(std::shared_ptr pointerEvent) const; + virtual void OnInputEvent(std::shared_ptr axisEvent) const; +}; +} // namespace MMI +} // namespace OHOS +#endif // I_INPUT_EVENT_CONSUMER_H \ No newline at end of file diff --git a/window_manager/previewer/mock/input_event.h b/window_manager/previewer/mock/input_event.h new file mode 100644 index 0000000..c99430b --- /dev/null +++ b/window_manager/previewer/mock/input_event.h @@ -0,0 +1,41 @@ +/* + * 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 INPUT_EVENT_H +#define INPUT_EVENT_H + +#include "parcel.h" + +namespace OHOS { +namespace MMI { +class InputEvent { +public: + int32_t GetTargetWindowId() const + { + return 0; + } + int32_t GetAgentWindowId() const + { + return 0; + } + + void MarkProcessed() + { + return; + } +}; +} // namespace MMI +} // namespace OHOS +#endif // INPUT_EVENT_H \ No newline at end of file diff --git a/window_manager/previewer/mock/input_manager.h b/window_manager/previewer/mock/input_manager.h new file mode 100644 index 0000000..7cc370c --- /dev/null +++ b/window_manager/previewer/mock/input_manager.h @@ -0,0 +1,43 @@ +/* + * 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 INPUT_MANAGER_H +#define INPUT_MANAGER_H + +#include "i_input_event_consumer.h" +#include "event_handler.h" + +namespace OHOS { +namespace MMI { +class InputManager : public AppExecFwk::EventHandler { +public: + void SetWindowInputEventConsumer(std::shared_ptr inputEventConsumer) + { + return; + } + void SetWindowInputEventConsumer(std::shared_ptr inputEventConsumer, + std::shared_ptr eventHandler) + { + return; + } + + static InputManager *GetInstance() + { + return nullptr; + } +}; +} // namespace MMI +} // namespace OHOS +#endif // INPUT_MANAGER_H \ No newline at end of file diff --git a/window_manager/previewer/mock/input_method_controller.h b/window_manager/previewer/mock/input_method_controller.h new file mode 100644 index 0000000..9f9ee49 --- /dev/null +++ b/window_manager/previewer/mock/input_method_controller.h @@ -0,0 +1,36 @@ +/* + * 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 FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H +#define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H + +#include + +namespace OHOS { +namespace MiscServices { + class InputMethodController : public RefBase { + public: + static sptr GetInstance() + { + return nullptr; + } + bool dispatchKeyEvent(std::shared_ptr keyEvent) + { + return true; + } + }; +} // namespace MiscServices +} // namespace OHOS +#endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_CONTROLLER_H diff --git a/window_manager/previewer/mock/ipc_skeleton.h b/window_manager/previewer/mock/ipc_skeleton.h new file mode 100644 index 0000000..4bba6e8 --- /dev/null +++ b/window_manager/previewer/mock/ipc_skeleton.h @@ -0,0 +1,33 @@ +/* + * 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_IPC_IPC_SKELETON_H +#define OHOS_IPC_IPC_SKELETON_H + +#include "refbase.h" + +namespace OHOS { +class IPCSkeleton { +public: + IPCSkeleton() = default; + ~IPCSkeleton() = default; + + static uint32_t GetCallingTokenID() + { + return 0; + } +}; +} +#endif // OHOS_IPC_IPC_SKELETON_H \ No newline at end of file diff --git a/window_manager/previewer/mock/iremote_object.h b/window_manager/previewer/mock/iremote_object.h new file mode 100644 index 0000000..427994f --- /dev/null +++ b/window_manager/previewer/mock/iremote_object.h @@ -0,0 +1,26 @@ +/* + * 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_IPC_IREMOTE_OBJECT_H +#define OHOS_IPC_IREMOTE_OBJECT_H + +#include "parcel.h" +#include "refbase.h" + +namespace OHOS { +class IRemoteObject : public virtual Parcelable, public virtual RefBase { +}; +} // namespace OHOS +#endif // OHOS_IPC_IREMOTE_OBJECT_H diff --git a/window_manager/previewer/mock/js_transition_controller.cpp b/window_manager/previewer/mock/js_transition_controller.cpp new file mode 100644 index 0000000..33ee6bd --- /dev/null +++ b/window_manager/previewer/mock/js_transition_controller.cpp @@ -0,0 +1,36 @@ +/* + * 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_transition_controller.h" +namespace OHOS { +namespace Rosen { +JsTransitionController::JsTransitionController(NativeEngine& engine, std::shared_ptr jsWin, + sptr window) +{ +} +JsTransitionController::~JsTransitionController() +{ +} +void JsTransitionController::SetJsController(std::shared_ptr jsVal) +{ +} +void JsTransitionController::AnimationForShown() +{ +} +void JsTransitionController::AnimationForHidden() +{ +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/previewer/mock/js_transition_controller.h b/window_manager/previewer/mock/js_transition_controller.h new file mode 100644 index 0000000..c5bc5c9 --- /dev/null +++ b/window_manager/previewer/mock/js_transition_controller.h @@ -0,0 +1,35 @@ +/* + * 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_TRANSITION_CONTROLLER_H +#define OHOS_JS_TRANSITION_CONTROLLER_H + +#include "native_engine/native_engine.h" +#include "native_engine/native_value.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +class JsTransitionController : public IAnimationTransitionController { +public: + JsTransitionController(NativeEngine& engine, std::shared_ptr jsWin, sptr window); + ~JsTransitionController(); + void AnimationForShown() override; + void AnimationForHidden() override; + void SetJsController(std::shared_ptr jsVal); +}; +} +} +#endif // OHOS_JS_TRANSITION_CONTROLLER_H \ No newline at end of file diff --git a/window_manager/previewer/mock/js_window_register_manager.cpp b/window_manager/previewer/mock/js_window_register_manager.cpp new file mode 100644 index 0000000..6f44db4 --- /dev/null +++ b/window_manager/previewer/mock/js_window_register_manager.cpp @@ -0,0 +1,36 @@ +/* + * 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_window_register_manager.h" +namespace OHOS { +namespace Rosen { +JsWindowRegisterManager::JsWindowRegisterManager() +{ +} + +JsWindowRegisterManager::~JsWindowRegisterManager() +{ +} + +void JsWindowRegisterManager::RegisterListener(sptr window, std::string type, + CaseType caseType, NativeEngine& engine, NativeValue* value) +{ +} + +void JsWindowRegisterManager::UnregisterListener(sptr window, std::string type, + CaseType caseType, NativeValue* value) +{ +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/previewer/mock/js_window_register_manager.h b/window_manager/previewer/mock/js_window_register_manager.h new file mode 100644 index 0000000..4bf456f --- /dev/null +++ b/window_manager/previewer/mock/js_window_register_manager.h @@ -0,0 +1,42 @@ +/* + * 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_WINDOW_REGISTER_MANAGER_H +#define OHOS_JS_WINDOW_REGISTER_MANAGER_H +#include +#include +#include "native_engine/native_engine.h" +#include "native_engine/native_reference.h" +#include "native_engine/native_value.h" +#include "refbase.h" +#include "window.h" +namespace OHOS { +namespace Rosen { +enum class CaseType { + CASE_WINDOW_MANAGER = 0, + CASE_WINDOW, + CASE_STAGE +}; +class JsWindowRegisterManager { +public: + JsWindowRegisterManager(); + ~JsWindowRegisterManager(); + void RegisterListener(sptr window, std::string type, + CaseType caseType, NativeEngine& engine, NativeValue* value); + void UnregisterListener(sptr window, std::string type, + CaseType caseType, NativeValue* value); +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_JS_WINDOW_REGISTER_MANAGER_H \ No newline at end of file diff --git a/window_manager/previewer/mock/key_event.h b/window_manager/previewer/mock/key_event.h new file mode 100644 index 0000000..7a5d2fd --- /dev/null +++ b/window_manager/previewer/mock/key_event.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 KEY_EVENT_H +#define KEY_EVENT_H + +#include "input_event.h" + +namespace OHOS { +namespace MMI { +class KeyEvent : public InputEvent { +public: + static const int32_t KEYCODE_FN = 0; + static const int32_t KEYCODE_NUMPAD_RIGHT_PAREN = 1; + static const int32_t KEYCODE_0 = 2; + static const int32_t KEYCODE_BACK = 3; + + int32_t GetKeyCode() const + { + return 0; + } +}; +} // namespace MMI +} // namespace OHOS +#endif // KEY_EVENT_H \ No newline at end of file diff --git a/window_manager/previewer/mock/napi_remote_object.h b/window_manager/previewer/mock/napi_remote_object.h new file mode 100644 index 0000000..e56ecbf --- /dev/null +++ b/window_manager/previewer/mock/napi_remote_object.h @@ -0,0 +1,30 @@ +/* + * 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 NAPI_IPC_OHOS_REMOTE_OBJECT_H +#define NAPI_IPC_OHOS_REMOTE_OBJECT_H + +#include "iremote_object.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "refbase.h" + +namespace OHOS { + sptr NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object) + { + return nullptr; + } +} // namespace OHOS +#endif // NAPI_IPC_OHOS_REMOTE_OBJECT_H diff --git a/window_manager/previewer/mock/parcel.cpp b/window_manager/previewer/mock/parcel.cpp new file mode 100644 index 0000000..99ffbd5 --- /dev/null +++ b/window_manager/previewer/mock/parcel.cpp @@ -0,0 +1,99 @@ +/* + * 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 "parcel.h" +namespace OHOS { +Parcelable::Parcelable() +{ +} + +Parcel::Parcel() +{ +} + +Parcel::~Parcel() +{ +} + +bool Parcel::WriteInt32(int32_t value) +{ + return true; +} + +bool Parcel::ReadInt32(int32_t &value) +{ + return true; +} + +int32_t Parcel::ReadInt32() +{ + return 0; +} + +bool Parcel::WriteUint32(uint32_t value) +{ + return true; +} + +bool Parcel::ReadUint32(uint32_t &value) +{ + return true; +} + +uint32_t Parcel::ReadUint32() +{ + return 0; +} + +bool Parcel::WriteUint64(uint64_t value) +{ + return true; +} + +uint64_t Parcel::ReadUint64() +{ + return 0; +} + +bool Parcel::WriteFloat(float value) +{ + return true; +} + +float Parcel::ReadFloat() +{ + return 0; +} + +bool Parcel::WriteString(const std::string &value) +{ + return true; +} + +const std::string Parcel::ReadString() +{ + return ""; +} + +bool Parcel::WriteBool(bool value) +{ + return true; +} + +bool Parcel::ReadBool() +{ + return true; +} +} // namespace OHOS diff --git a/window_manager/previewer/mock/parcel.h b/window_manager/previewer/mock/parcel.h new file mode 100644 index 0000000..2a7f225 --- /dev/null +++ b/window_manager/previewer/mock/parcel.h @@ -0,0 +1,82 @@ +/* + * 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_UTILS_PARCEL_H +#define OHOS_UTILS_PARCEL_H + +#include +#include +#include "refbase.h" + +namespace OHOS { +class Parcel; + +class Parcelable : public virtual RefBase { +public: + virtual ~Parcelable() = default; + + Parcelable(); + + virtual bool Marshalling(Parcel &parcel) const = 0; +}; + +class Parcel { +public: + Parcel(); + + virtual ~Parcel(); + + bool WriteInt32(int32_t value); + + bool ReadInt32(int32_t &value); + + int32_t ReadInt32(); + + bool WriteUint32(uint32_t value); + + bool ReadUint32(uint32_t &value); + + uint32_t ReadUint32(); + + bool WriteUint64(uint64_t value); + + uint64_t ReadUint64(); + + bool WriteFloat(float value); + + float ReadFloat(); + + bool WriteString(const std::string &value); + + const std::string ReadString(); + + bool WriteBool(bool value); + + bool ReadBool(); + + template + bool WriteObject(const sptr &object) + { + return true; + } + + template + sptr ReadObject() + { + return nullptr; + } +}; +} // namespace OHOS +#endif // OHOS_UTILS_PARCEL_H diff --git a/window_manager/previewer/mock/permission.cpp b/window_manager/previewer/mock/permission.cpp new file mode 100644 index 0000000..df91699 --- /dev/null +++ b/window_manager/previewer/mock/permission.cpp @@ -0,0 +1,41 @@ +/* + * 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 "permission.h" + +namespace OHOS { +namespace Rosen { + +bool Permission::IsSystemServiceCalling(bool needPrintLog) +{ + return true; +} + +bool Permission::IsSystemCalling() +{ + return true; +} + +bool Permission::CheckCallingPermission(const std::string& permission) +{ + return true; +} + +bool Permission::IsStartByHdcd() +{ + return true; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/previewer/mock/permission.h b/window_manager/previewer/mock/permission.h new file mode 100644 index 0000000..60e96be --- /dev/null +++ b/window_manager/previewer/mock/permission.h @@ -0,0 +1,32 @@ +/* + * 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 WM_PERMISSION_H +#define WM_PERMISSION_H + +#include + +namespace OHOS { +namespace Rosen { +class Permission { +public: + static bool IsSystemServiceCalling(bool needPrintLog = true); + static bool IsSystemCalling(); + static bool CheckCallingPermission(const std::string& permission); + static bool IsStartByHdcd(); +}; +} // Rosen +} // OHOS +#endif // WM_PERMISSION_H \ No newline at end of file diff --git a/window_manager/previewer/mock/pixel_map.h b/window_manager/previewer/mock/pixel_map.h new file mode 100644 index 0000000..01f79ac --- /dev/null +++ b/window_manager/previewer/mock/pixel_map.h @@ -0,0 +1,27 @@ +/* + * 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 INTERFACES_INNERKITS_INCLUDE_PIXEL_MAP_H_ +#define INTERFACES_INNERKITS_INCLUDE_PIXEL_MAP_H_ + +#include "parcel.h" + +namespace OHOS { +namespace Media { +class PixelMap : public Parcelable { +}; +} +} +#endif // INTERFACES_INNERKITS_INCLUDE_PIXEL_MAP_H_ \ No newline at end of file diff --git a/window_manager/previewer/mock/pixel_map_napi.cpp b/window_manager/previewer/mock/pixel_map_napi.cpp new file mode 100644 index 0000000..7b645e9 --- /dev/null +++ b/window_manager/previewer/mock/pixel_map_napi.cpp @@ -0,0 +1,44 @@ +/* + * 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 "pixel_map_napi.h" + +namespace OHOS { +namespace Media { +PixelMapNapi::PixelMapNapi() + :env_(nullptr), wrapper_(nullptr) +{ +} + +PixelMapNapi::~PixelMapNapi() +{ +} + +napi_env PixelMapNapi::getEnv() +{ + return env_; +} + +napi_ref PixelMapNapi::getWrapper() +{ + return wrapper_; +} + +napi_value PixelMapNapi::CreatePixelMap(napi_env env, std::shared_ptr pixelmap) +{ + return nullptr; +} +} // namespace Media +} // namespace OHOS diff --git a/window_manager/previewer/mock/pixel_map_napi.h b/window_manager/previewer/mock/pixel_map_napi.h new file mode 100644 index 0000000..dc31928 --- /dev/null +++ b/window_manager/previewer/mock/pixel_map_napi.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 INTERFACES_KITS_JS_COMMON_INCLUDE_PIXEL_MAP_NAPI_H_ +#define INTERFACES_KITS_JS_COMMON_INCLUDE_PIXEL_MAP_NAPI_H_ + +#include "pixel_map.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace Media { +class PixelMapNapi { +public: + PixelMapNapi(); + ~PixelMapNapi(); + + static napi_value CreatePixelMap(napi_env env, std::shared_ptr pixelmap); + napi_env getEnv(); + napi_ref getWrapper(); +private: + napi_env env_ = nullptr; + napi_ref wrapper_ = nullptr; +}; +} // namespace Media +} // namespace OHOS +#endif // INTERFACES_KITS_JS_COMMON_INCLUDE_PIXEL_MAP_NAPI_H_ diff --git a/window_manager/previewer/mock/pointer_event.h b/window_manager/previewer/mock/pointer_event.h new file mode 100644 index 0000000..9e3e04c --- /dev/null +++ b/window_manager/previewer/mock/pointer_event.h @@ -0,0 +1,103 @@ +/* + * 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 POINTER_EVENT_H +#define POINTER_EVENT_H + +#include +#include +#include +#include +#include +#include + +#include "input_event.h" + +namespace OHOS { +namespace MMI { +class PointerEvent : public InputEvent { +public: + static constexpr int32_t POINTER_ACTION_UNKNOWN = 0; + static constexpr int32_t POINTER_ACTION_CANCEL = 1; + static constexpr int32_t POINTER_ACTION_DOWN = 2; + static constexpr int32_t POINTER_ACTION_MOVE = 3; + static constexpr int32_t POINTER_ACTION_UP = 4; + static constexpr int32_t POINTER_ACTION_AXIS_BEGIN = 5; + static constexpr int32_t POINTER_ACTION_AXIS_UPDATE = 6; + static constexpr int32_t POINTER_ACTION_AXIS_END = 7; + static constexpr int32_t POINTER_ACTION_BUTTON_DOWN = 8; + static constexpr int32_t POINTER_ACTION_BUTTON_UP = 9; + static constexpr int32_t POINTER_ACTION_ENTER_WINDOW = 10; + static constexpr int32_t POINTER_ACTION_LEAVE_WINDOW = 11; + + int32_t GetPointerAction() const + { + return 0; + } + + class PointerItem { + public: + int32_t pointerId_ {}; + int32_t GetDisplayX() const + { + return 0; + } + + int32_t GetDisplayY() const + { + return 0; + } + + void SetDisplayY(int32_t y) + { + pointerId_ = y; + } + + void SetDisplayX(int32_t x) + { + pointerId_ = x; + } + + void SetWindowY(int32_t y) + { + pointerId_ = y; + } + + void SetWindowX(int32_t x) + { + pointerId_ = x; + } + }; + + bool GetPointerItem(int32_t pointerId, PointerItem &pointerItem) + { + pointerItem = PointerItem(); + pointerItem.pointerId_ = pointerId; + return true; + } + + void UpdatePointerItem(int32_t pointerId, PointerItem &pointerItem) + { + pointerItem.pointerId_ = pointerId; + } + + int32_t GetPointerId() const + { + return 0; + } +}; +} // namespace MMI +} // namespace OHOS +#endif // POINTER_EVENT_H \ No newline at end of file diff --git a/window_manager/previewer/mock/request_info.h b/window_manager/previewer/mock/request_info.h new file mode 100644 index 0000000..0b408f7 --- /dev/null +++ b/window_manager/previewer/mock/request_info.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_REQUEST_INFO_H +#define OHOS_ABILITY_RUNTIME_REQUEST_INFO_H + +namespace OHOS { +namespace AbilityRuntime { +class RequestInfo { +public: + static NativeValue* WrapRequestInfo(NativeEngine &engine, RequestInfo *request) { + return nullptr; + }; + static std::shared_ptr UnwrapRequestInfo(NativeEngine &engine, NativeValue *jsParam) { + return nullptr; + }; + + sptr GetToken() { + return callerToken_; + }; +private: + sptr callerToken_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_REQUEST_INFO_H diff --git a/window_manager/previewer/mock/transaction/rs_interfaces.h b/window_manager/previewer/mock/transaction/rs_interfaces.h new file mode 100644 index 0000000..e30f2f3 --- /dev/null +++ b/window_manager/previewer/mock/transaction/rs_interfaces.h @@ -0,0 +1,46 @@ +/* + * 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 RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H +#define RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H + +#include +#include +#include + +namespace OHOS { +namespace Rosen { +class RSInterfaces { +public: + static RSInterfaces &GetInstance() + { + static RSInterfaces instance; + return instance; + }; + + std::shared_ptr CreateVSyncReceiver( + const std::string& name, const std::shared_ptr &looper = nullptr) + { + return nullptr; + } + +private: + RSInterfaces() = default; + ~RSInterfaces() noexcept {}; +}; +} // namespace Rosen +} // namespace OHOS + +#endif // RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H diff --git a/window_manager/previewer/mock/ui/rs_node.cpp b/window_manager/previewer/mock/ui/rs_node.cpp new file mode 100644 index 0000000..b4e8d20 --- /dev/null +++ b/window_manager/previewer/mock/ui/rs_node.cpp @@ -0,0 +1,64 @@ +/* + * 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 "rs_node.h" + +namespace OHOS { +namespace Rosen { +void RSNode::SetPivotX(float pivotX) +{ +} + +void RSNode::SetPivotY(float pivotY) +{ +} + +void RSNode::SetScaleX(float scaleX) +{ +} + +void RSNode::SetScaleY(float scaleY) +{ +} + +void RSNode::SetRotation(float degree) +{ +} + +void RSNode::SetRotation(const Quaternion& quaternion) +{ +} + +void RSNode::SetRotationX(float degree) +{ +} + +void RSNode::SetRotationY(float degree) +{ +} + +void RSNode::SetTranslateX(float translate) +{ +} + +void RSNode::SetTranslateY(float translate) +{ +} + +void RSNode::SetTranslateZ(float translate) +{ +} +} +} \ No newline at end of file diff --git a/window_manager/previewer/mock/ui/rs_node.h b/window_manager/previewer/mock/ui/rs_node.h new file mode 100644 index 0000000..1aac10f --- /dev/null +++ b/window_manager/previewer/mock/ui/rs_node.h @@ -0,0 +1,41 @@ +/* + * 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 RENDER_SERVICE_CLIENT_CORE_UI_RS_NODE_H +#define RENDER_SERVICE_CLIENT_CORE_UI_RS_NODE_H + +#include "ui/rs_vector4.h" + +namespace OHOS { +namespace Rosen { +class RSNode { +public: + void SetPivotX(float pivotX); + void SetPivotY(float pivotY); + + void SetScaleX(float scaleX); + void SetScaleY(float scaleY); + + void SetRotation(float degree); + void SetRotation(const Quaternion& quaternion); + void SetRotationX(float degree); + void SetRotationY(float degree); + + void SetTranslateX(float translate); + void SetTranslateY(float translate); + void SetTranslateZ(float translate); +}; +} // Rosen +} // OHOS +#endif // RENDER_SERVICE_CLIENT_CORE_UI_RS_NODE_H \ No newline at end of file diff --git a/window_manager/previewer/mock/ui/rs_surface_node.h b/window_manager/previewer/mock/ui/rs_surface_node.h new file mode 100644 index 0000000..2085398 --- /dev/null +++ b/window_manager/previewer/mock/ui/rs_surface_node.h @@ -0,0 +1,26 @@ +/* + * 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 RENDER_SERVICE_CLIENT_CORE_UI_RS_SURFACE_NODE_H +#define RENDER_SERVICE_CLIENT_CORE_UI_RS_SURFACE_NODE_H + +#include "ui/rs_node.h" + +namespace OHOS { +namespace Rosen { +class RSSurfaceNode : public RSNode { +}; +} // namespace Rosen +} // namespace OHOS +#endif // RENDER_SERVICE_CLIENT_CORE_UI_RS_SURFACE_NODE_H diff --git a/window_manager/previewer/mock/ui/rs_vector4.h b/window_manager/previewer/mock/ui/rs_vector4.h new file mode 100644 index 0000000..8162e01 --- /dev/null +++ b/window_manager/previewer/mock/ui/rs_vector4.h @@ -0,0 +1,38 @@ +/* + * 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 RENDER_SERVICE_CLIENT_CORE_COMMON_RS_VECTOR4_H +#define RENDER_SERVICE_CLIENT_CORE_COMMON_RS_VECTOR4_H + +namespace OHOS { +namespace Rosen { +class Vector4 { +}; +class Quaternion { +public: + Quaternion(float x, float y, float z, float w) : myx(x), myy(y), myz(z), myw(w) {} + int useXYZW() + { + return myx + myy + myz + myw; + }; +private: + float myx; + float myy; + float myz; + float myw; +}; +} // namespace Rosen +} // namespace OHOS +#endif // RENDER_SERVICE_CLIENT_CORE_COMMON_RS_VECTOR4_H \ No newline at end of file diff --git a/window_manager/previewer/mock/ui_content.h b/window_manager/previewer/mock/ui_content.h new file mode 100644 index 0000000..431173c --- /dev/null +++ b/window_manager/previewer/mock/ui_content.h @@ -0,0 +1,123 @@ +/* + * 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 FOUNDATION_ACE_INTERFACE_INNERKITS_ACE_UI_CONTENT_H +#define FOUNDATION_ACE_INTERFACE_INNERKITS_ACE_UI_CONTENT_H + +#include +#include + +namespace OHOS { +namespace AbilityRuntime { +class Context; +} + +namespace AppExecFwk { +class Configuration; +class Ability; +} + +namespace Rosen { +class Window; +enum class WindowMode : uint32_t; +class RSSurfaceNode; +} + +namespace AAFwk { +class Want; +} + +namespace MMI { +class PointerEvent; +class KeyEvent; +class AxisEvent; +} // namespace MMI + +namespace Media { + class PixelMap; +} +} // namespace OHOS + +class NativeEngine; +class NativeValue; + +namespace OHOS::Ace { +#define ACE_EXPORT __attribute__((visibility("default"))) +class ACE_EXPORT UIContent { +public: + static std::unique_ptr Create(OHOS::AbilityRuntime::Context* context, NativeEngine* runtime); + static std::unique_ptr Create(OHOS::AppExecFwk::Ability* ability); + static void ShowDumpHelp(std::vector& info); + + virtual ~UIContent() = default; + + // UI content life-cycles + virtual void Initialize(OHOS::Rosen::Window* window, const std::string& url, NativeValue* storage) = 0; + virtual void Foreground() = 0; + virtual void Background() = 0; + virtual void Focus() = 0; + virtual void UnFocus() = 0; + virtual void Destroy() = 0; + virtual void OnNewWant(const OHOS::AAFwk::Want& want) = 0; + + // distribute + virtual void Restore(OHOS::Rosen::Window* window, const std::string& contentInfo, NativeValue* storage) = 0; + virtual std::string GetContentInfo() const = 0; + virtual void DestroyUIDirector() = 0; + + // UI content event process + virtual bool ProcessBackPressed() = 0; + virtual bool ProcessPointerEvent(const std::shared_ptr& pointerEvent) = 0; + virtual bool ProcessKeyEvent(const std::shared_ptr& keyEvent) = 0; + virtual bool ProcessAxisEvent(const std::shared_ptr& axisEvent) = 0; + virtual bool ProcessVsyncEvent(uint64_t timeStampNanos) = 0; + virtual void UpdateConfiguration(const std::shared_ptr& config) = 0; + virtual void UpdateWindowMode(OHOS::Rosen::WindowMode mode) = 0; + virtual void HideWindowTitleButton(bool hideSplit, bool hideMaximize, bool hideMinimize) = 0; + + // Window color + virtual uint32_t GetBackgroundColor() = 0; + virtual void SetBackgroundColor(uint32_t color) = 0; + + virtual void DumpInfo(const std::vector& params, std::vector& info) = 0; + + // Set UIContent callback for custom window animation + virtual void SetNextFrameLayoutCallback(std::function&& callback) = 0; + + // Receive memory level notification + virtual void NotifyMemoryLevel(int32_t level) = 0; + + // receive label and icon + virtual void SetAppWindowTitle(const std::string& title) = 0; + virtual void SetAppWindowIcon(const std::shared_ptr& pixelMap) = 0; + + // ArkTS Form + virtual std::shared_ptr GetFormRootNode() = 0; + + virtual void UpdateFormData(const std::string& data) = 0; + + virtual void SetFormWidth(const float width) = 0; + virtual void SetFormHeight(const float height) = 0; + virtual float GetFormWidth() = 0; + virtual float GetFormHeight() = 0; + + virtual void SetActionEventHandler( + std::function&& actionCallback) = 0; + virtual void SetErrorEventHandler( + std::function&& errorCallback) = 0; +}; +} // namespace OHOS::Ace + +#endif // FOUNDATION_ACE_INTERFACE_INNERKITS_ACE_UI_CONTENT_H diff --git a/window_manager/previewer/mock/vsync_receiver.h b/window_manager/previewer/mock/vsync_receiver.h new file mode 100644 index 0000000..55a72a7 --- /dev/null +++ b/window_manager/previewer/mock/vsync_receiver.h @@ -0,0 +1,53 @@ +/* + * 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 VSYNC_VSYNC_RECEIVER_H +#define VSYNC_VSYNC_RECEIVER_H + +#include +#include + +namespace OHOS { +namespace Rosen { +enum VsyncError { + GSERROR_OK = 0, +}; + +class VSyncCallBackListener { +public: + using VSyncCallback = std::function; + struct FrameCallback { + void *userData_; + VSyncCallback callback_; + }; +}; + +class VSyncReceiver : public RefBase { +public: + using FrameCallback = VSyncCallBackListener::FrameCallback; + + VsyncError Init() + { + return GSERROR_OK; + } + VsyncError RequestNextVSync(FrameCallback callback) + { + return GSERROR_OK; + } +}; +} // namespace Rosen +} // namespace OHOS + +#endif diff --git a/window_manager/previewer/mock/window_info.h b/window_manager/previewer/mock/window_info.h new file mode 100644 index 0000000..bff07b3 --- /dev/null +++ b/window_manager/previewer/mock/window_info.h @@ -0,0 +1,64 @@ +/* + * 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_ABILITY_RUNTIME_WINDOW_INFO_H +#define OHOS_ABILITY_RUNTIME_WINDOW_INFO_H + +#include "parcel.h" + +namespace OHOS { +namespace AAFwk { +enum class TransitionReason : uint32_t { + MINIMIZE = 0, + CLOSE, + ABILITY_TRANSITION, + BACK_TRANSITION, +}; +struct AbilityTransitionInfo : public Parcelable { + std::string bundleName_; + std::string abilityName_; + uint32_t mode_ = 0; + std::vector windowModes_; + sptr abilityToken_ = nullptr; + uint64_t displayId_ = 0; + bool isShowWhenLocked_ = false; + bool isRecent_ = false; + double maxWindowRatio_; + double minWindowRatio_; + uint32_t maxWindowWidth_; + uint32_t minWindowWidth_; + uint32_t maxWindowHeight_; + uint32_t minWindowHeight_; + TransitionReason reason_ = TransitionReason::ABILITY_TRANSITION; + int32_t missionId_ = -1; + + virtual bool Marshalling(Parcel& parcel) const override + { + return true; + } + + bool WriteWindowInfo(Parcel& parcel) const + { + return true; + } + + static AbilityTransitionInfo* Unmarshalling(Parcel& parcel) + { + return nullptr; + } +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_WINDOW_INFO_H diff --git a/window_manager/previewer/mock/window_manager.h b/window_manager/previewer/mock/window_manager.h new file mode 100644 index 0000000..1e0e07b --- /dev/null +++ b/window_manager/previewer/mock/window_manager.h @@ -0,0 +1,41 @@ +/* + * 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_ROSEN_WINDOW_MANAGER_H +#define OHOS_ROSEN_WINDOW_MANAGER_H + +#include +#include +#include +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +struct SystemBarRegionTint { + WindowType type_; + SystemBarProperty prop_; + Rect region_; + SystemBarRegionTint() : prop_(SystemBarProperty()) {} + SystemBarRegionTint(WindowType type, SystemBarProperty prop, Rect region) + : type_(type), prop_(prop), region_(region) {} +}; +using SystemBarRegionTints = std::vector; + +class WindowManager { +}; +} // namespace Rosen +} // namespace OHOS + +#endif // OHOS_ROSEN_WINDOW_MANAGER_H diff --git a/window_manager/previewer/mock/window_manager_hilog.h b/window_manager/previewer/mock/window_manager_hilog.h new file mode 100644 index 0000000..4c20a16 --- /dev/null +++ b/window_manager/previewer/mock/window_manager_hilog.h @@ -0,0 +1,46 @@ +/* + * 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_WM_INCLUDE_WINDOW_MANAGER_HILOG_H +#define OHOS_WM_INCLUDE_WINDOW_MANAGER_HILOG_H + +#include "window_input_channel.h" +namespace OHOS { +namespace Rosen { +typedef enum { + LOG_TYPE_MIN = 0, + LOG_APP = 0, + LOG_INIT = 1, + LOG_CORE = 3, + LOG_KMSG = 4, + LOG_TYPE_MAX +} LogType; + +namespace HiviewDFX { +using HiLogLabel = struct { + LogType type; + unsigned int domain; + const char *tag; +}; +} // namespace HiviewDFX + +static constexpr unsigned int HILOG_DOMAIN_WINDOW = 0xD004200; +#define WLOGFD(...) +#define WLOGFI(...) +#define WLOGFW(...) +#define WLOGFE(...) +} // namespace Rosen +} // namespace OHOS +#endif // FRAMEWORKS_WM_INCLUDE_WINDOW_MANAGER_HILOG_H diff --git a/window_manager/previewer/src/window_impl.cpp b/window_manager/previewer/src/window_impl.cpp new file mode 100644 index 0000000..0bb72ab --- /dev/null +++ b/window_manager/previewer/src/window_impl.cpp @@ -0,0 +1,762 @@ +/* + * 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 "window_impl.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +std::map>> WindowImpl::windowMap_; +std::map>> WindowImpl::subWindowMap_; +static int constructorCnt = 0; +static int deConstructorCnt = 0; +WindowImpl::WindowImpl(const sptr& option) +{ + property_ = new (std::nothrow) WindowProperty(); + property_->SetWindowName(option->GetWindowName()); + property_->SetRequestRect(option->GetWindowRect()); + property_->SetWindowType(option->GetWindowType()); + property_->SetWindowMode(option->GetWindowMode()); + property_->SetFullScreen(option->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN); + property_->SetFocusable(option->GetFocusable()); + property_->SetTouchable(option->GetTouchable()); + property_->SetDisplayId(option->GetDisplayId()); + property_->SetCallingWindow(option->GetCallingWindow()); + property_->SetWindowFlags(option->GetWindowFlags()); + property_->SetHitOffset(option->GetHitOffset()); + property_->SetRequestedOrientation(option->GetRequestedOrientation()); + property_->SetTurnScreenOn(option->IsTurnScreenOn()); + property_->SetKeepScreenOn(option->IsKeepScreenOn()); + property_->SetBrightness(option->GetBrightness()); + auto& sysBarPropMap = option->GetSystemBarProperty(); + for (auto it : sysBarPropMap) { + property_->SetSystemBarProperty(it.first, it.second); + } + name_ = option->GetWindowName(); + + WLOGFI("WindowImpl constructorCnt: %{public}d name: %{public}s", + ++constructorCnt, property_->GetWindowName().c_str()); +} + +WindowImpl::~WindowImpl() +{ + WLOGFI("windowName: %{public}s, windowId: %{public}d, deConstructorCnt: %{public}d", + GetWindowName().c_str(), GetWindowId(), ++deConstructorCnt); + Destroy(); +} + +sptr WindowImpl::Find(const std::string& name) +{ + auto iter = windowMap_.find(name); + if (iter == windowMap_.end()) { + return nullptr; + } + return iter->second.second; +} + +const std::shared_ptr WindowImpl::GetContext() const +{ + return nullptr; +} + +sptr WindowImpl::GetTopWindowWithId(uint32_t mainWinId) +{ + if (windowMap_.empty()) { + WLOGFE("Please create mainWindow First!"); + return nullptr; + } + for (auto iter = windowMap_.begin(); iter != windowMap_.end(); iter++) { + if (mainWinId == iter->second.first) { + WLOGFI("FindTopWindow id: %{public}u", mainWinId); + return iter->second.second; + } + } + WLOGFE("Cannot find topWindow!"); +} + +sptr WindowImpl::GetTopWindowWithContext(const std::shared_ptr& context) +{ + if (windowMap_.empty()) { + WLOGFE("Please create mainWindow First!"); + return nullptr; + } + uint32_t mainWinId = INVALID_WINDOW_ID; + WLOGFI("GetTopWindowfinal MainWinId:%{public}u!", mainWinId); + if (mainWinId == INVALID_WINDOW_ID) { + WLOGFE("Cannot find topWindow!"); + return nullptr; + } + return GetTopWindowWithId(mainWinId); +} + +std::vector> WindowImpl::GetSubWindow(uint32_t parentId) +{ + if (subWindowMap_.find(parentId) == subWindowMap_.end()) { + WLOGFE("Cannot parentWindow with id: %{public}u!", parentId); + return std::vector>(); + } + return std::vector>(subWindowMap_[parentId].begin(), subWindowMap_[parentId].end()); +} + +void WindowImpl::UpdateConfigurationForAll(const std::shared_ptr& configuration) +{ + for (const auto& winPair : windowMap_) { + auto window = winPair.second.second; + window->UpdateConfiguration(configuration); + } +} + +std::shared_ptr WindowImpl::GetSurfaceNode() const +{ + return nullptr; +} + +Rect WindowImpl::GetRect() const +{ + return property_->GetWindowRect(); +} + +Rect WindowImpl::GetRequestRect() const +{ + return property_->GetRequestRect(); +} + +WindowType WindowImpl::GetType() const +{ + return property_->GetWindowType(); +} + +WindowMode WindowImpl::GetMode() const +{ + return property_->GetWindowMode(); +} + +float WindowImpl::GetAlpha() const +{ + return property_->GetAlpha(); +} + +WindowState WindowImpl::GetWindowState() const +{ + return state_; +} + +WMError WindowImpl::SetFocusable(bool isFocusable) +{ + return WMError::WM_OK; +} + +bool WindowImpl::GetFocusable() const +{ + return property_->GetFocusable(); +} + +WMError WindowImpl::SetTouchable(bool isTouchable) +{ + return WMError::WM_OK; +} + +bool WindowImpl::GetTouchable() const +{ + return property_->GetTouchable(); +} + +const std::string& WindowImpl::GetWindowName() const +{ + return name_; +} + +uint32_t WindowImpl::GetWindowId() const +{ + return property_->GetWindowId(); +} + +uint32_t WindowImpl::GetWindowFlags() const +{ + return property_->GetWindowFlags(); +} + +uint32_t WindowImpl::GetRequestModeSupportInfo() const +{ + return property_->GetRequestModeSupportInfo(); +} + +bool WindowImpl::IsMainHandlerAvailable() const +{ + return true; +} + +SystemBarProperty WindowImpl::GetSystemBarPropertyByType(WindowType type) const +{ + auto curProperties = property_->GetSystemBarProperty(); + return curProperties[type]; +} + +WMError WindowImpl::GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetWindowType(WindowType type) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetWindowMode(WindowMode mode) +{ + return WMError::WM_OK; +} + +void WindowImpl::SetAlpha(float alpha) +{ + return; +} + +void WindowImpl::SetTransform(const Transform& trans) +{ + return; +} + +const Transform& WindowImpl::GetTransform() const +{ + return property_->GetTransform(); +} + +WMError WindowImpl::AddWindowFlag(WindowFlag flag) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::RemoveWindowFlag(WindowFlag flag) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetWindowFlags(uint32_t flags) +{ + return WMError::WM_OK; +} + +void WindowImpl::OnNewWant(const AAFwk::Want& want) +{ + return; +} + +WMError WindowImpl::SetUIContent(const std::string& contentInfo, + NativeEngine* engine, NativeValue* storage, bool isdistributed, AppExecFwk::Ability* ability) +{ + return WMError::WM_OK; +} + +Ace::UIContent* WindowImpl::GetUIContent() const +{ + return uiContent_.get(); +} + +std::string WindowImpl::GetContentInfo() +{ + return ""; +} + +bool WindowImpl::IsSupportWideGamut() +{ + return true; +} + +void WindowImpl::SetColorSpace(ColorSpace colorSpace) +{ + return; +} + +ColorSpace WindowImpl::GetColorSpace() +{ + return ColorSpace::COLOR_SPACE_DEFAULT; +} + +std::shared_ptr WindowImpl::Snapshot() +{ + return nullptr; +} + +void WindowImpl::DumpInfo(const std::vector& params, std::vector& info) +{ + return; +} + +WMError WindowImpl::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetLayoutFullScreen(bool status) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetFullScreen(bool status) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Create(uint32_t parentId, const std::shared_ptr& context) +{ + WLOGFI("[Client] Window [name:%{public}s] Create", name_.c_str()); + // check window name, same window names are forbidden + if (windowMap_.find(name_) != windowMap_.end()) { + WLOGFE("WindowName(%{public}s) already exists.", name_.c_str()); + return WMError::WM_ERROR_INVALID_PARAM; + } + // check parent id, if create sub window and there is not exist parent Window, then return + if (parentId != INVALID_WINDOW_ID) { + for (const auto& winPair : windowMap_) { + if (winPair.second.first == parentId) { + property_->SetParentId(parentId); + break; + } + } + if (property_->GetParentId() != parentId) { + WLOGFE("ParentId is empty or valid. ParentId is %{public}u", parentId); + return WMError::WM_ERROR_INVALID_PARAM; + } + } + + static std::atomic tempWindowId = 0; + uint32_t windowId = tempWindowId++; + property_->SetWindowId(windowId); + windowMap_.insert(std::make_pair(name_, std::pair>(windowId, this))); + + state_ = WindowState::STATE_CREATED; + + return WMError::WM_OK; +} + +WMError WindowImpl::BindDialogTarget(sptr targetToken) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Destroy() +{ + return WMError::WM_OK; +} + +WMError WindowImpl::UpdateSurfaceNodeAfterCustomAnimation(bool isAdd) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Show(uint32_t reason, bool withAnimation) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Hide(uint32_t reason, bool withAnimation) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::MoveTo(int32_t x, int32_t y) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Resize(uint32_t width, uint32_t height) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetKeepScreenOn(bool keepScreenOn) +{ + return WMError::WM_OK; +} + +bool WindowImpl::IsKeepScreenOn() const +{ + return property_->IsKeepScreenOn(); +} + +WMError WindowImpl::SetTurnScreenOn(bool turnScreenOn) +{ + return WMError::WM_OK; +} + +bool WindowImpl::IsTurnScreenOn() const +{ + return property_->IsTurnScreenOn(); +} + +WMError WindowImpl::SetBackgroundColor(const std::string& color) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetTransparent(bool isTransparent) +{ + return WMError::WM_OK; +} + +bool WindowImpl::IsTransparent() const +{ + return true; +} + +WMError WindowImpl::SetBrightness(float brightness) +{ + return WMError::WM_OK; +} + +float WindowImpl::GetBrightness() const +{ + return property_->GetBrightness(); +} + +WMError WindowImpl::SetCallingWindow(uint32_t windowId) +{ + return WMError::WM_OK; +} + +void WindowImpl::SetPrivacyMode(bool isPrivacyMode) +{ + return; +} + +bool WindowImpl::IsPrivacyMode() const +{ + return property_->GetPrivacyMode(); +} + +void WindowImpl::SetSystemPrivacyMode(bool isSystemPrivacyMode) +{ + return; +} + +void WindowImpl::SetSnapshotSkip(bool isSkip) +{ + return; +} + +void WindowImpl::DisableAppWindowDecor() +{ + return; +} + +bool WindowImpl::IsDecorEnable() const +{ + return property_->GetDecorEnable(); +} + +WMError WindowImpl::Maximize() +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Minimize() +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Recover() +{ + return WMError::WM_OK; +} + +WMError WindowImpl::Close() +{ + return WMError::WM_OK; +} + +void WindowImpl::StartMove() +{ + return; +} + +WMError WindowImpl::RequestFocus() const +{ + return WMError::WM_OK; +} + +bool WindowImpl::IsFocused() const +{ + return true; +} + +void WindowImpl::SetInputEventConsumer(const std::shared_ptr& inputEventConsumer) +{ + return; +} + +bool WindowImpl::RegisterLifeCycleListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterWindowChangeListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterLifeCycleListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterWindowChangeListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterAvoidAreaChangeListener(sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterAvoidAreaChangeListener(sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterDragListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterDragListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterDisplayMoveListener(sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterDisplayMoveListener(sptr& listener) +{ + return true; +} + +void WindowImpl::RegisterWindowDestroyedListener(const NotifyNativeWinDestroyFunc& func) +{ + return; +} + +bool WindowImpl::RegisterOccupiedAreaChangeListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterOccupiedAreaChangeListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterTouchOutsideListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterTouchOutsideListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterAnimationTransitionController(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterScreenshotListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterScreenshotListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::RegisterDialogTargetTouchListener(const sptr& listener) +{ + return true; +} + +bool WindowImpl::UnregisterDialogTargetTouchListener(const sptr& listener) +{ + return true; +} + +void WindowImpl::RegisterDialogDeathRecipientListener(const sptr& listener) +{ + return; +} + +void WindowImpl::UnregisterDialogDeathRecipientListener(const sptr& listener) +{ + return; +} + +void WindowImpl::SetAceAbilityHandler(const sptr& handler) +{ + return; +} + +void WindowImpl::SetRequestModeSupportInfo(uint32_t modeSupportInfo) +{ + return; +} + +void WindowImpl::ConsumeKeyEvent(std::shared_ptr& keyEvent) +{ + return; +} + +void WindowImpl::ConsumePointerEvent(const std::shared_ptr& pointerEvent) +{ + return; +} + +void WindowImpl::RequestVsync(const std::shared_ptr& vsyncCallback) +{ + return; +} + +void WindowImpl::UpdateConfiguration(const std::shared_ptr& configuration) +{ + if (uiContent_ != nullptr) { + WLOGFD("notify ace winId:%{public}u", GetWindowId()); + uiContent_->UpdateConfiguration(configuration); + } + if (subWindowMap_.count(GetWindowId()) == 0) { + return; + } + for (auto& subWindow : subWindowMap_.at(GetWindowId())) { + subWindow->UpdateConfiguration(configuration); + } +} + +void WindowImpl::NotifyTouchDialogTarget() +{ + return; +} + +void WindowImpl::SetNeedRemoveWindowInputChannel(bool needRemoveWindowInputChannel) +{ + return; +} + +bool WindowImpl::IsLayoutFullScreen() const +{ + return true; +} + +bool WindowImpl::IsFullScreen() const +{ + return true; +} + +void WindowImpl::SetRequestedOrientation(Orientation orientation) +{ + return; +} + +Orientation WindowImpl::GetRequestedOrientation() +{ + return property_->GetRequestedOrientation(); +} + +WMError WindowImpl::SetTouchHotAreas(const std::vector& rects) +{ + return WMError::WM_OK; +} +void WindowImpl::GetRequestedTouchHotAreas(std::vector& rects) const +{ + property_->GetTouchHotAreas(rects); +} + +WMError WindowImpl::SetAPPWindowLabel(const std::string& label) +{ + if (uiContent_ == nullptr) { + WLOGFE("uicontent is empty"); + return WMError::WM_ERROR_NULLPTR; + } + uiContent_->SetAppWindowTitle(label); + return WMError::WM_OK; +} + +WMError WindowImpl::SetAPPWindowIcon(const std::shared_ptr& icon) +{ + if (icon == nullptr) { + WLOGFE("window icon is empty"); + return WMError::WM_ERROR_NULLPTR; + } + if (uiContent_ == nullptr) { + WLOGFE("uicontent is empty"); + return WMError::WM_ERROR_NULLPTR; + } + uiContent_->SetAppWindowIcon(icon); + return WMError::WM_OK; +} + +WMError WindowImpl::SetCornerRadius(float cornerRadius) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetShadowRadius(float radius) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetShadowColor(std::string color) +{ + return WMError::WM_OK; +} + +void WindowImpl::SetShadowOffsetX(float offsetX) +{ + return; +} + +void WindowImpl::SetShadowOffsetY(float offsetY) +{ + return; +} + +WMError WindowImpl::SetBlur(float radius) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetBackdropBlur(float radius) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::SetBackdropBlurStyle(WindowBlurStyle blurStyle) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::NotifyMemoryLevel(int32_t level) const +{ + return WMError::WM_OK; +} + +bool WindowImpl::IsAllowHaveSystemSubWindow() +{ + return true; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/previewer/src/window_scene.cpp b/window_manager/previewer/src/window_scene.cpp new file mode 100644 index 0000000..80bb6cb --- /dev/null +++ b/window_manager/previewer/src/window_scene.cpp @@ -0,0 +1,115 @@ +/* + * 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 "window_impl.h" +#include "window_manager_hilog.h" +#include "window_scene.h" + +namespace OHOS { +namespace Rosen { +const std::string WindowScene::MAIN_WINDOW_ID = "main window"; + +WindowScene::~WindowScene() +{ +} + +WMError WindowScene::Init(DisplayId displayId, const std::shared_ptr& context, + sptr& listener, sptr option) +{ + displayId_ = displayId; + if (option == nullptr) { + option = new(std::nothrow) WindowOption(); + if (option == nullptr) { + WLOGFW("alloc WindowOption failed"); + return WMError::WM_ERROR_NULLPTR; + } + } + option->SetDisplayId(displayId); + option->SetWindowTag(WindowTag::MAIN_WINDOW); + + mainWindow_ = Window::Create(GenerateMainWindowName(context), option, context); + if (mainWindow_ == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + mainWindow_->RegisterLifeCycleListener(listener); + + return WMError::WM_OK; +} + +std::string WindowScene::GenerateMainWindowName(const std::shared_ptr& context) const +{ + if (context == nullptr) { + return MAIN_WINDOW_ID + std::to_string(count++); + } else { + std::string windowName = "MainWinodw" + std::to_string(count++); + std::size_t pos = windowName.find_last_of('.'); + return (pos == std::string::npos) ? windowName : windowName.substr(pos + 1); // skip '.' + } +} + +sptr WindowScene::CreateWindow(const std::string& windowName, sptr& option) const +{ + if (windowName.empty() || mainWindow_ == nullptr || option == nullptr) { + WLOGFE("WindowScene Name: %{public}s", windowName.c_str()); + return nullptr; + } + option->SetParentId(mainWindow_->GetWindowId()); + option->SetWindowTag(WindowTag::SUB_WINDOW); + return Window::Create(windowName, option, mainWindow_->GetContext()); +} + +const sptr& WindowScene::GetMainWindow() const +{ + return mainWindow_; +} + +std::vector> WindowScene::GetSubWindow() +{ + if (mainWindow_ == nullptr) { + WLOGFE("Get sub window failed, because main window is null"); + return std::vector>(); + } + uint32_t parentId = mainWindow_->GetWindowId(); + return Window::GetSubWindow(parentId); +} + +WMError WindowScene::GoDestroy() +{ + if (mainWindow_ == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + + WMError ret = mainWindow_->Destroy(); + if (ret != WMError::WM_OK) { + WLOGFE("WindowScene go destroy failed name: %{public}s", mainWindow_->GetWindowName().c_str()); + return ret; + } + mainWindow_ = nullptr; + return WMError::WM_OK; +} + +void WindowScene::UpdateConfiguration(const std::shared_ptr& configuration) +{ + if (mainWindow_ == nullptr) { + WLOGFE("Update configuration failed, because main window is null"); + return; + } + WLOGFI("notify mainWindow winId:%{public}u", mainWindow_->GetWindowId()); + mainWindow_->UpdateConfiguration(configuration); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/resources/BUILD.gn b/window_manager/resources/BUILD.gn new file mode 100644 index 0000000..7e48ca5 --- /dev/null +++ b/window_manager/resources/BUILD.gn @@ -0,0 +1,19 @@ +# 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. + +group("window_resources") { + deps = [ + "config:window_config", + "media:window_resources_media", + ] +} diff --git a/window_manager/resources/config/BUILD.gn b/window_manager/resources/config/BUILD.gn new file mode 100644 index 0000000..c1ffc9b --- /dev/null +++ b/window_manager/resources/config/BUILD.gn @@ -0,0 +1,46 @@ +# 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. +import("//build/ohos.gni") + +ohos_prebuilt_etc("window_manager_config") { + if (device_name == "rk3568") { + source = "//foundation/window/window_manager/resources/config/rk3568/window_manager_config.xml" + install_enable = true + } else { + source = "//foundation/window/window_manager/resources/config/other/window_manager_config.xml" + install_enable = false + } + part_name = "window_manager" + subsystem_name = "window" + relative_install_dir = "window/resources" +} + +ohos_prebuilt_etc("display_manager_config") { + if (device_name == "rk3568") { + source = "//foundation/window/window_manager/resources/config/rk3568/display_manager_config.xml" + install_enable = true + } else { + source = "//foundation/window/window_manager/resources/config/other/display_manager_config.xml" + install_enable = false + } + part_name = "window_manager" + subsystem_name = "window" + relative_install_dir = "window/resources" +} + +group("window_config") { + deps = [ + ":display_manager_config", + ":window_manager_config", + ] +} diff --git a/window_manager/resources/config/build/BUILD.gn b/window_manager/resources/config/build/BUILD.gn new file mode 100644 index 0000000..2afd5ce --- /dev/null +++ b/window_manager/resources/config/build/BUILD.gn @@ -0,0 +1,33 @@ +# 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. + +declare_args() { + window_manager_feature_coverage = false +} + +config("coverage_flags") { + if (window_manager_feature_coverage) { + cflags = [ "--coverage" ] + ldflags = [ "--coverage" ] + } +} + +config("testcase_flags") { + cflags = [ + "-Wall", + "-Werror", + "-g3", + "-Dprivate=public", + "-Dprotected=public", + ] +} diff --git a/window_manager/resources/config/other/display_manager_config.xml b/window_manager/resources/config/other/display_manager_config.xml new file mode 100644 index 0000000..ea91687 --- /dev/null +++ b/window_manager/resources/config/other/display_manager_config.xml @@ -0,0 +1,19 @@ + + + + + 0 + \ No newline at end of file diff --git a/window_manager/resources/config/other/window_manager_config.xml b/window_manager/resources/config/other/window_manager_config.xml new file mode 100644 index 0000000..0d28fcc --- /dev/null +++ b/window_manager/resources/config/other/window_manager_config.xml @@ -0,0 +1,38 @@ + + + + + + + 1 + + + + 0.1 0.9 + + 0.5 0.33 0.67 + + + 0.7 0.7 + + + + 500 + 300 + 0.2 0.0 0.2 1.0 + + + diff --git a/window_manager/resources/config/rk3568/display_manager_config.xml b/window_manager/resources/config/rk3568/display_manager_config.xml new file mode 100644 index 0000000..024dce9 --- /dev/null +++ b/window_manager/resources/config/rk3568/display_manager_config.xml @@ -0,0 +1,57 @@ + + + + + 240 + + + 0 + + + + + + + + + + 0 0 0 0 + + + + + + + + + + + + + + + + + + + 0 + + + + + + 0 + diff --git a/window_manager/resources/config/rk3568/window_manager_config.xml b/window_manager/resources/config/rk3568/window_manager_config.xml new file mode 100644 index 0000000..f8331d7 --- /dev/null +++ b/window_manager/resources/config/rk3568/window_manager_config.xml @@ -0,0 +1,95 @@ + + + + + + + 100 + + 100 + + + + 50 50 50 + + + + 0.1 0.9 + + 0.5 0.33 0.67 + + 1 + + + + + 350 + + + + + 0.7 0.7 + + 0 0 1 0 + + 0 0 + + 0 + + + + + + 150 + + 150 + + 0.2 0.0 0.2 1.0 + + + + + + + + + + + off + off + off + + + + 0 + #000000 + 0 + 0 + 0 + + + 0 + #000000 + 0 + 0 + 0 + + + + + diff --git a/window_manager/resources/media/BUILD.gn b/window_manager/resources/media/BUILD.gn new file mode 100644 index 0000000..b3d5d6d --- /dev/null +++ b/window_manager/resources/media/BUILD.gn @@ -0,0 +1,26 @@ +# 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. +import("//build/ohos.gni") + +ohos_prebuilt_etc("window_place_holder_image") { + source = "//foundation/window/window_manager/resources/media/img/bg_place_holder.png" + part_name = "window_manager" + subsystem_name = "window" + relative_install_dir = "window/resources" +} + +group("window_resources_media") { + deps = [ + ":window_place_holder_image", + ] +} diff --git a/window_manager/resources/media/img/bg_place_holder.png b/window_manager/resources/media/img/bg_place_holder.png new file mode 100644 index 0000000000000000000000000000000000000000..9936aee1a38039dba2ddfacaf56ce9d8c94a1f59 GIT binary patch literal 3500 zcmeH~k55xa9Ker?ii(mfnUINK+>EJHV2sg*m0zM$>I71M01padt|~SyqSykZ1%JUd z9cXA+#-L1H!Htyq>$O0kW$U2P1}ma1Qr;{0<~sH))v~tK(ss{3V+qOKeJ|hp=DwHv z-re_e-{fTNS-bkZ)c}CCnR|CJ03Z=v5(rsAh<_`eydlJ@lY8?|0}%86+Zt3UP2~~B zMVY(O4_3C>ko`>?b9d@yPXGE)cpH&WcWj|g+#+4OvR_d{Qh#`|yq-`*TZGCvo{AquG0d|HOioJ+%QLFrXv0z$A9a={ zNeot>f|FqvE@;D|!9udLJW^?#tf59`d3~ay7M9SIuD??Vmqa{>3uWcE@KQRWk*TS| z&&MmK6r6-*0EFer;3tsMC#u~h4aKNMP1r<3$pp%qiVKy>aL9OOV^`^9F_XzGEG|xM zw|Z`I%z5m00eF?>M7?pLW}3mvG1r$wD9R&E{N-t6>AhI>!u6Vf&uyznN>=yv^-X<(oIE9{9WtB<4-eORYEWWvG)d>|{r;W?#)C)R zCY=-2(+onUNht{dy?j{AI3YX2=4g6wHJtd;?R^Xh@UxuO&Y7B&=!e$%8?1bnRQzUq zxYn$QH_W@99qX_)>9DdJ08~=Bxi6bk$lOUk9{UmOb{tj?U8R3R+a)c}0?sDRZ85 zXJ{21=iJAEuJKauKizVX^ZD?l;fv8Ag$5gOR=&R`qMlKdj|T4Nh}v9o`P@KnZv+>y z>TWtd1%1_^6y$YiO z!Xf(XW&lz|8Eg(>;~ikz3hCvs00c)6#_Jli_bm2oj2Z(UzDt1T)n4D1fys-)<1!9G zb2YRmIbVg0QXBPmwiAG#LV}Ht1*sMUm8909#KW2gQ~3nMD;>AgDq5V*UJTVFNAM6<|tlM_vzLuVn$0NwjhU%TZc~p zK>G?7$H(d&cC*3>;eKn%f)Vs4k6{E`-pC_?y0G5}k58ZmrSNZNP!63eHC8XOMuGt? zxJ}s#52*ycqUIg@BW(#Qrz)s;WFc668ED3|j$uqw)Tpz?zB+d0T$>pN5F< P7s%Y5wX0|67w7&1Q$p_} literal 0 HcmV?d00001 diff --git a/window_manager/sa_profile/4606.xml b/window_manager/sa_profile/4606.xml new file mode 100644 index 0000000..3af2972 --- /dev/null +++ b/window_manager/sa_profile/4606.xml @@ -0,0 +1,27 @@ + + + + foundation + + 4606 + libwms.z.so + + + true + false + 1 + CoreStartPhase + + diff --git a/window_manager/sa_profile/4607.xml b/window_manager/sa_profile/4607.xml new file mode 100644 index 0000000..b3af415 --- /dev/null +++ b/window_manager/sa_profile/4607.xml @@ -0,0 +1,27 @@ + + + + foundation + + 4607 + libwms.z.so + + + true + false + 1 + CoreStartPhase + + \ No newline at end of file diff --git a/window_manager/sa_profile/BUILD.gn b/window_manager/sa_profile/BUILD.gn new file mode 100644 index 0000000..f8dc9ba --- /dev/null +++ b/window_manager/sa_profile/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2021-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. + +import("//build/ohos/sa_profile/sa_profile.gni") + +ohos_sa_profile("wms_sa_profile") { + sources = [ + "4606.xml", + "4607.xml", + ] + part_name = "window_manager" +} diff --git a/window_manager/snapshot/BUILD.gn b/window_manager/snapshot/BUILD.gn new file mode 100644 index 0000000..31fb37d --- /dev/null +++ b/window_manager/snapshot/BUILD.gn @@ -0,0 +1,73 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") + +## Build snapshot {{{ +config("snapshot_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +ohos_executable("snapshot_display") { + install_enable = true + sources = [ "src/snapshot_display.cpp" ] + + configs = [ + ":snapshot_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + ":libsnapshot_util", + "../dm:libdm", + ] + + external_deps = [ + "c_utils:utils", + "multimedia_image_framework:image_native", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_shared_library("libsnapshot_util") { + sources = [ "src/snapshot_utils.cpp" ] + + configs = [ + ":snapshot_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "//foundation/window/window_manager/dm:libdm", + "//third_party/libjpeg-turbo:turbojpeg_static", + ] + + external_deps = [ + "c_utils:utils", + "hitrace_native:hitrace_meter", + "multimedia_image_framework:image_native", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +## Build snapshot }}} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/snapshot/include/snapshot_utils.h b/window_manager/snapshot/include/snapshot_utils.h new file mode 100644 index 0000000..adc0afa --- /dev/null +++ b/window_manager/snapshot/include/snapshot_utils.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021-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 SNAPSHOT_UTILS_H +#define SNAPSHOT_UTILS_H + +#include +#include +#include + +#include "display_manager.h" +#include "dm_common.h" + +namespace OHOS { + +struct WriteToJpegParam { + uint32_t width; + uint32_t height; + uint32_t stride; + Media::PixelFormat format; + const uint8_t *data; +}; + +struct CmdArgments { + bool isDisplayIdSet = false; + Rosen::DisplayId displayId = Rosen::DISPLAY_ID_INVALID; + std::string fileName; + bool isWidthSet = false; + int32_t width = -1; + bool isHeightSet = false; + int32_t height = -1; +}; + +class SnapShotUtils { +public: + SnapShotUtils() = default; + ~SnapShotUtils() = default; + + static void PrintUsage(const std::string &cmdLine); + static bool CheckFileNameValid(const std::string &fileName); + static std::string GenerateFileName(int offset = 0); + static bool CheckWidthAndHeightValid(int32_t w, int32_t h); + static bool RGBA8888ToRGB888(const uint8_t* rgba8888Buf, uint8_t *rgb888Buf, int32_t size); + static bool RGB565ToRGB888(const uint8_t* rgb565Buf, uint8_t *rgb888Buf, int32_t size); + static bool WriteRgb888ToJpeg(FILE* file, uint32_t width, uint32_t height, const uint8_t* data); + static bool WriteToJpeg(const std::string &fileName, const WriteToJpegParam ¶m); + static bool WriteToJpeg(int fd, const WriteToJpegParam ¶m); + static bool WriteToJpegWithPixelMap(const std::string &fileName, Media::PixelMap &pixelMap); + static bool WriteToJpegWithPixelMap(int fd, Media::PixelMap &pixelMap); + static bool ProcessArgs(int argc, char * const argv[], CmdArgments& cmdArgments); + static bool CheckWHValid(int32_t param); + static bool CheckParamValid(const WriteToJpegParam ¶m); +private: + static bool ProcessDisplayId(Rosen::DisplayId &displayId, bool isDisplayIdSet); +}; +} + +#endif // SNAPSHOT_UTILS_H diff --git a/window_manager/snapshot/src/snapshot_display.cpp b/window_manager/snapshot/src/snapshot_display.cpp new file mode 100644 index 0000000..9eed83b --- /dev/null +++ b/window_manager/snapshot/src/snapshot_display.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021-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 +#include +#include +#include + +#include "display_manager.h" +#include "snapshot_utils.h" + +using namespace OHOS; +using namespace OHOS::Media; +using namespace OHOS::Rosen; + +int main(int argc, char *argv[]) +{ + CmdArgments cmdArgments; + cmdArgments.fileName = ""; + + if (!SnapShotUtils::ProcessArgs(argc, argv, cmdArgments)) { + return 0; + } + + auto display = DisplayManager::GetInstance().GetDisplayById(cmdArgments.displayId); + if (display == nullptr) { + std::cout << "error: GetDisplayById " << cmdArgments.displayId << " error!" << std::endl; + return -1; + } + + std::cout << "process: display " << cmdArgments.displayId << + ": width " << display->GetWidth() << ", height " << display->GetHeight() << std::endl; + + // get PixelMap from DisplayManager API + std::shared_ptr pixelMap = nullptr; + if (!cmdArgments.isWidthSet && !cmdArgments.isHeightSet) { + pixelMap = DisplayManager::GetInstance().GetScreenshot(cmdArgments.displayId); // default width & height + } else { + if (!cmdArgments.isWidthSet) { + cmdArgments.width = display->GetWidth(); + std::cout << "process: reset to display's width " << cmdArgments.width << std::endl; + } + if (!cmdArgments.isHeightSet) { + cmdArgments.height = display->GetHeight(); + std::cout << "process: reset to display's height " << cmdArgments.height << std::endl; + } + if (!SnapShotUtils::CheckWidthAndHeightValid(cmdArgments.width, cmdArgments.height)) { + std::cout << "error: width " << cmdArgments.width << " height " << + cmdArgments.height << " invalid!" << std::endl; + return -1; + } + const Media::Rect rect = {0, 0, display->GetWidth(), display->GetHeight()}; + const Media::Size size = {cmdArgments.width, cmdArgments.height}; + constexpr int rotation = 0; + pixelMap = DisplayManager::GetInstance().GetScreenshot(cmdArgments.displayId, rect, size, rotation); + } + + bool ret = false; + if (pixelMap != nullptr) { + ret = SnapShotUtils::WriteToJpegWithPixelMap(cmdArgments.fileName, *pixelMap); + } + if (!ret) { + std::cout << "\nerror: snapshot display " << cmdArgments.displayId << + ", write to " << cmdArgments.fileName.c_str() << " as jpeg failed!" << std::endl; + return -1; + } + + std::cout << "\nsuccess: snapshot display " << cmdArgments.displayId << " , write to " << + cmdArgments.fileName.c_str() << " as jpeg, width " << pixelMap->GetWidth() << + ", height " << pixelMap->GetHeight() << std::endl; + return 0; +} \ No newline at end of file diff --git a/window_manager/snapshot/src/snapshot_utils.cpp b/window_manager/snapshot/src/snapshot_utils.cpp new file mode 100644 index 0000000..8714575 --- /dev/null +++ b/window_manager/snapshot/src/snapshot_utils.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2021-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 "snapshot_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jpeglib.h" +#include +#include +#include + +using namespace OHOS::Rosen; + +namespace OHOS { +constexpr int MAX_TIME_STR_LEN = 40; +constexpr int YEAR_SINCE = 1900; +constexpr int32_t RGB565_PIXEL_BYTES = 2; +constexpr int32_t RGB888_PIXEL_BYTES = 3; +constexpr int32_t RGBA8888_PIXEL_BYTES = 4; +constexpr uint8_t B_INDEX = 0; +constexpr uint8_t G_INDEX = 1; +constexpr uint8_t R_INDEX = 2; +constexpr uint8_t SHIFT_2_BIT = 2; +constexpr uint8_t SHITF_3_BIT = 3; +constexpr uint8_t SHIFT_5_BIT = 5; +constexpr uint8_t SHIFT_8_BIT = 8; +constexpr uint8_t SHIFT_11_BIT = 11; +constexpr uint8_t SHIFT_16_BIT = 16; + +constexpr uint16_t RGB565_MASK_BLUE = 0xF800; +constexpr uint16_t RGB565_MASK_GREEN = 0x07E0; +constexpr uint16_t RGB565_MASK_RED = 0x001F; +constexpr uint32_t RGBA8888_MASK_BLUE = 0x000000FF; +constexpr uint32_t RGBA8888_MASK_GREEN = 0x0000FF00; +constexpr uint32_t RGBA8888_MASK_RED = 0x00FF0000; + +struct MissionErrorMgr : public jpeg_error_mgr { + jmp_buf environment; +}; + +void mission_error_exit(j_common_ptr cinfo) +{ + if (cinfo == nullptr || cinfo->err == nullptr) { + std::cout << __func__ << ": param is invalid." << std::endl; + return; + } + auto err = (MissionErrorMgr*)cinfo->err; + longjmp(err->environment, 1); +} + +const char *VALID_SNAPSHOT_PATH = "/data"; +const char *DEFAULT_SNAPSHOT_PREFIX = "/snapshot"; +const char *VALID_SNAPSHOT_SUFFIX = ".jpeg"; + +void SnapShotUtils::PrintUsage(const std::string &cmdLine) +{ + std::cout << "usage: " << cmdLine.c_str() << + " [-i displayId] [-f output_file] [-w width] [-h height] [-m]" << std::endl; +} + +std::string SnapShotUtils::GenerateFileName(int offset) +{ + timeval tv; + std::string fileName = VALID_SNAPSHOT_PATH; + + fileName += DEFAULT_SNAPSHOT_PREFIX; + if (gettimeofday(&tv, nullptr) == 0) { + tv.tv_sec += offset; // add offset second + struct tm *tmVal = localtime(&tv.tv_sec); + if (tmVal != nullptr) { + char timeStr[MAX_TIME_STR_LEN] = { 0 }; + snprintf_s(timeStr, sizeof(timeStr), sizeof(timeStr) - 1, + "_%04d-%02d-%02d_%02d-%02d-%02d", + tmVal->tm_year + YEAR_SINCE, tmVal->tm_mon + 1, tmVal->tm_mday, + tmVal->tm_hour, tmVal->tm_min, tmVal->tm_sec); + fileName += timeStr; + } + } + fileName += VALID_SNAPSHOT_SUFFIX; + return fileName; +} + +bool SnapShotUtils::CheckFileNameValid(const std::string &fileName) +{ + if (fileName.length() <= strlen(VALID_SNAPSHOT_SUFFIX)) { + std::cout << "error: fileName " << fileName.c_str() << " invalid, file length too short!" << std::endl; + return false; + } + // check file path + std::string fileDir = fileName; + auto pos = fileDir.find_last_of("/"); + if (pos != std::string::npos) { + fileDir.erase(pos + 1); + } else { + fileDir = "."; // current work dir + } + char resolvedPath[PATH_MAX] = { 0 }; + char *realPath = realpath(fileDir.c_str(), resolvedPath); + if (realPath == nullptr) { + std::cout << "error: fileName " << fileName.c_str() << " invalid, realpath nullptr!" << std::endl; + return false; + } + if (strncmp(realPath, VALID_SNAPSHOT_PATH, strlen(VALID_SNAPSHOT_PATH)) != 0) { + std::cout << "error: fileName " << fileName.c_str() << " invalid, realpath " + << realPath << " must dump at dir: " << VALID_SNAPSHOT_PATH << std::endl; + return false; + } + + // check file suffix + const char *fileNameSuffix = fileName.c_str() + (fileName.length() - strlen(VALID_SNAPSHOT_SUFFIX)); + if (strncmp(fileNameSuffix, VALID_SNAPSHOT_SUFFIX, strlen(VALID_SNAPSHOT_SUFFIX)) == 0) { + return true; // valid suffix + } + + std::cout << "error: fileName " << fileName.c_str() << + " invalid, suffix must be " << VALID_SNAPSHOT_SUFFIX << std::endl; + return false; +} + +bool SnapShotUtils::CheckWHValid(int32_t param) +{ + return (param > 0) && (param <= DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT); +} + +bool SnapShotUtils::CheckWidthAndHeightValid(int32_t w, int32_t h) +{ + return CheckWHValid(w) && CheckWHValid(h); +} + +bool SnapShotUtils::CheckParamValid(const WriteToJpegParam ¶m) +{ + switch (param.format) { + case Media::PixelFormat::RGBA_8888: + if (param.stride != param.width * RGBA8888_PIXEL_BYTES) { + return false; + } + break; + case Media::PixelFormat::RGB_565: + if (param.stride != param.width * RGB565_PIXEL_BYTES) { + return false; + } + break; + case Media::PixelFormat::RGB_888: + if (param.stride != param.width * RGB888_PIXEL_BYTES) { + return false; + } + break; + default: + std::cout << __func__ << ": unsupported pixel format: " << + static_cast(param.format) << std::endl; + return false; + } + if (!CheckWidthAndHeightValid(param.width, param.height)) { + return false; + } + if (param.data == nullptr) { + return false; + } + return true; +} + +bool SnapShotUtils::RGBA8888ToRGB888(const uint8_t* rgba8888Buf, uint8_t *rgb888Buf, int32_t size) +{ + if (rgba8888Buf == nullptr || rgb888Buf == nullptr || size <= 0) { + std::cout << __func__ << ": params are invalid." << std::endl; + return false; + } + const uint32_t* rgba8888 = reinterpret_cast(rgba8888Buf); + for (int32_t i = 0; i < size; i++) { + rgb888Buf[i * RGB888_PIXEL_BYTES + R_INDEX] = (rgba8888[i] & RGBA8888_MASK_RED) >> SHIFT_16_BIT; + rgb888Buf[i * RGB888_PIXEL_BYTES + G_INDEX] = (rgba8888[i] & RGBA8888_MASK_GREEN) >> SHIFT_8_BIT; + rgb888Buf[i * RGB888_PIXEL_BYTES + B_INDEX] = rgba8888[i] & RGBA8888_MASK_BLUE; + } + return true; +} + +bool SnapShotUtils::RGB565ToRGB888(const uint8_t* rgb565Buf, uint8_t *rgb888Buf, int32_t size) +{ + if (rgb565Buf == nullptr || rgb888Buf == nullptr || size <= 0) { + std::cout << __func__ << ": params are invalid." << std::endl; + return false; + } + const uint16_t* rgb565 = reinterpret_cast(rgb565Buf); + for (int32_t i = 0; i < size; i++) { + rgb888Buf[i * RGB888_PIXEL_BYTES + R_INDEX] = (rgb565[i] & RGB565_MASK_RED); + rgb888Buf[i * RGB888_PIXEL_BYTES + G_INDEX] = (rgb565[i] & RGB565_MASK_GREEN) >> SHIFT_5_BIT; + rgb888Buf[i * RGB888_PIXEL_BYTES + B_INDEX] = (rgb565[i] & RGB565_MASK_BLUE) >> SHIFT_11_BIT; + rgb888Buf[i * RGB888_PIXEL_BYTES + R_INDEX] <<= SHITF_3_BIT; + rgb888Buf[i * RGB888_PIXEL_BYTES + G_INDEX] <<= SHIFT_2_BIT; + rgb888Buf[i * RGB888_PIXEL_BYTES + B_INDEX] <<= SHITF_3_BIT; + } + return true; +} + +// The method will NOT release file. +bool SnapShotUtils::WriteRgb888ToJpeg(FILE* file, uint32_t width, uint32_t height, const uint8_t* data) +{ + if (data == nullptr) { + std::cout << "error: data error, nullptr!" << std::endl; + return false; + } + + if (file == nullptr) { + std::cout << "error: file is null" << std::endl; + return false; + } + + struct jpeg_compress_struct jpeg; + struct MissionErrorMgr jerr; + jpeg.err = jpeg_std_error(&jerr); + jerr.error_exit = mission_error_exit; + if (setjmp(jerr.environment)) { + jpeg_destroy_compress(&jpeg); + std::cout << "error: lib jpeg exit with error!" << std::endl; + return false; + } + + jpeg_create_compress(&jpeg); + jpeg.image_width = width; + jpeg.image_height = height; + jpeg.input_components = RGB888_PIXEL_BYTES; + jpeg.in_color_space = JCS_RGB; + jpeg_set_defaults(&jpeg); + + constexpr int32_t quality = 75; + jpeg_set_quality(&jpeg, quality, TRUE); + + jpeg_stdio_dest(&jpeg, file); + jpeg_start_compress(&jpeg, TRUE); + JSAMPROW rowPointer[1]; + for (uint32_t i = 0; i < jpeg.image_height; i++) { + rowPointer[0] = const_cast(data + i * jpeg.image_width * RGB888_PIXEL_BYTES); + (void)jpeg_write_scanlines(&jpeg, rowPointer, 1); + } + + jpeg_finish_compress(&jpeg); + jpeg_destroy_compress(&jpeg); + return true; +} + +bool SnapShotUtils::WriteToJpeg(const std::string &fileName, const WriteToJpegParam ¶m) +{ + bool ret = false; + if (!CheckFileNameValid(fileName)) { + return ret; + } + if (!CheckParamValid(param)) { + std::cout << "error: invalid param." << std::endl; + return ret; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "snapshot:WriteToJpeg(%s)", fileName.c_str()); + + FILE *file = fopen(fileName.c_str(), "wb"); + if (file == nullptr) { + std::cout << "error: open file [" << fileName.c_str() << "] error, " << errno << "!" << std::endl; + return ret; + } + std::cout << "snapshot: pixel format is: " << static_cast(param.format) << std::endl; + if (param.format == Media::PixelFormat::RGBA_8888) { + int32_t rgb888Size = param.stride * param.height * RGB888_PIXEL_BYTES / RGBA8888_PIXEL_BYTES; + uint8_t *rgb888 = new uint8_t[rgb888Size]; + ret = RGBA8888ToRGB888(param.data, rgb888, rgb888Size / RGB888_PIXEL_BYTES); + if (ret) { + std::cout << "snapshot: convert rgba8888 to rgb888 successfully." << std::endl; + ret = WriteRgb888ToJpeg(file, param.width, param.height, rgb888); + } + delete[] rgb888; + } else if (param.format == Media::PixelFormat::RGB_565) { + int32_t rgb888Size = param.stride * param.height * RGB888_PIXEL_BYTES / RGB565_PIXEL_BYTES; + uint8_t *rgb888 = new uint8_t[rgb888Size]; + ret = RGB565ToRGB888(param.data, rgb888, rgb888Size / RGB888_PIXEL_BYTES); + if (ret) { + std::cout << "snapshot: convert rgb565 to rgb888 successfully." << std::endl; + ret = WriteRgb888ToJpeg(file, param.width, param.height, rgb888); + } + delete[] rgb888; + } else if (param.format == Media::PixelFormat::RGB_888) { + ret = WriteRgb888ToJpeg(file, param.width, param.height, param.data); + } else { + std::cout << "snapshot: invalid pixel format." << std::endl; + } + if (fclose(file) != 0) { + std::cout << "error: close file failed!" << std::endl; + ret = false; + } + return ret; +} + +bool SnapShotUtils::WriteToJpeg(int fd, const WriteToJpegParam ¶m) +{ + bool ret = false; + if (!CheckParamValid(param)) { + std::cout << "error: invalid param." << std::endl; + return ret; + } + + FILE *file = fdopen(fd, "wb"); + if (file == nullptr) { + return ret; + } + std::cout << "snapshot: pixel format is: " << static_cast(param.format) << std::endl; + if (param.format == Media::PixelFormat::RGBA_8888) { + int32_t rgb888Size = param.stride * param.height * RGB888_PIXEL_BYTES / RGBA8888_PIXEL_BYTES; + uint8_t *rgb888 = new uint8_t[rgb888Size]; + ret = RGBA8888ToRGB888(param.data, rgb888, rgb888Size / RGB888_PIXEL_BYTES); + if (ret) { + std::cout << "snapshot: convert rgba8888 to rgb888 successfully." << std::endl; + ret = WriteRgb888ToJpeg(file, param.width, param.height, rgb888); + } + delete[] rgb888; + } else if (param.format == Media::PixelFormat::RGB_565) { + int32_t rgb888Size = param.stride * param.height * RGB888_PIXEL_BYTES / RGB565_PIXEL_BYTES; + uint8_t *rgb888 = new uint8_t[rgb888Size]; + ret = RGB565ToRGB888(param.data, rgb888, rgb888Size / RGB888_PIXEL_BYTES); + if (ret) { + std::cout << "snapshot: convert rgb565 to rgb888 successfully." << std::endl; + ret = WriteRgb888ToJpeg(file, param.width, param.height, rgb888); + } + delete[] rgb888; + } else if (param.format == Media::PixelFormat::RGB_888) { + ret = WriteRgb888ToJpeg(file, param.width, param.height, param.data); + } else { + std::cout << "snapshot: invalid pixel format." << std::endl; + } + if (fclose(file) != 0) { + std::cout << "error: close file failed!" << std::endl; + ret = false; + } + return ret; +} + +bool SnapShotUtils::WriteToJpegWithPixelMap(const std::string &fileName, Media::PixelMap &pixelMap) +{ + WriteToJpegParam param; + param.width = static_cast(pixelMap.GetWidth()); + param.height = static_cast(pixelMap.GetHeight()); + param.data = pixelMap.GetPixels(); + param.stride = static_cast(pixelMap.GetRowBytes()); + param.format = pixelMap.GetPixelFormat(); + return SnapShotUtils::WriteToJpeg(fileName, param); +} + +bool SnapShotUtils::WriteToJpegWithPixelMap(int fd, Media::PixelMap &pixelMap) +{ + WriteToJpegParam param; + param.width = static_cast(pixelMap.GetWidth()); + param.height = static_cast(pixelMap.GetHeight()); + param.data = pixelMap.GetPixels(); + param.stride = static_cast(pixelMap.GetRowBytes()); + param.format = pixelMap.GetPixelFormat(); + return SnapShotUtils::WriteToJpeg(fd, param); +} + +bool SnapShotUtils::ProcessDisplayId(Rosen::DisplayId &displayId, bool isDisplayIdSet) +{ + if (!isDisplayIdSet) { + displayId = DisplayManager::GetInstance().GetDefaultDisplayId(); + } else { + bool validFlag = false; + auto displayIds = DisplayManager::GetInstance().GetAllDisplayIds(); + for (auto id: displayIds) { + if (displayId == id) { + validFlag = true; + break; + } + } + if (!validFlag) { + std::cout << "error: displayId " << static_cast(displayId) << " invalid!" << std::endl; + std::cout << "tips: supported displayIds:" << std::endl; + for (auto dispId: displayIds) { + std::cout << "\t" << dispId << std::endl; + } + return false; + } + } + return true; +} + +bool SnapShotUtils::ProcessArgs(int argc, char * const argv[], CmdArgments &cmdArgments) +{ + int opt = 0; + const struct option longOption[] = { + { "id", required_argument, nullptr, 'i' }, + { "width", required_argument, nullptr, 'w' }, + { "height", required_argument, nullptr, 'h' }, + { "file", required_argument, nullptr, 'f' }, + { "help", required_argument, nullptr, 'm' }, + { nullptr, 0, nullptr, 0 } + }; + while ((opt = getopt_long(argc, argv, "i:w:h:f:m", longOption, nullptr)) != -1) { + switch (opt) { + case 'i': // display id + cmdArgments.displayId = static_cast(atoll(optarg)); + cmdArgments.isDisplayIdSet = true; + break; + case 'w': // output width + cmdArgments.width = atoi(optarg); + cmdArgments.isWidthSet = true; + break; + case 'h': // output height + cmdArgments.height = atoi(optarg); + cmdArgments.isHeightSet = true; + break; + case 'f': // output file name + cmdArgments.fileName = optarg; + break; + case 'm': // help + default: + SnapShotUtils::PrintUsage(argv[0]); + return false; + } + } + + if (!ProcessDisplayId(cmdArgments.displayId, cmdArgments.isDisplayIdSet)) { + return false; + } + + if (cmdArgments.fileName == "") { + cmdArgments.fileName = GenerateFileName(); + std::cout << "process: set filename to " << cmdArgments.fileName.c_str() << std::endl; + } + + // check fileName + if (!SnapShotUtils::CheckFileNameValid(cmdArgments.fileName)) { + std::cout << "error: filename " << cmdArgments.fileName.c_str() << " invalid!" << std::endl; + return false; + } + return true; +} +} \ No newline at end of file diff --git a/window_manager/snapshot/test/BUILD.gn b/window_manager/snapshot/test/BUILD.gn new file mode 100644 index 0000000..a29ddb1 --- /dev/null +++ b/window_manager/snapshot/test/BUILD.gn @@ -0,0 +1,17 @@ +# 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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/snapshot/test/unittest/BUILD.gn b/window_manager/snapshot/test/unittest/BUILD.gn new file mode 100644 index 0000000..4b0fd98 --- /dev/null +++ b/window_manager/snapshot/test/unittest/BUILD.gn @@ -0,0 +1,90 @@ +# 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. + +import("//build/test.gni") + +module_out_path = "window_manager/snapshot" + +group("unittest") { + testonly = true + + deps = [ + ":snapshot_display_test", + ":snapshot_utils_test", + ] +} + +ohos_unittest("snapshot_utils_test") { + module_out_path = module_out_path + + sources = [ "snapshot_utils_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("snapshot_display_test") { + module_out_path = module_out_path + + sources = [ "snapshot_display_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +## Build utils_unittest_common.a {{{ +config("utils_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/snapshot/include", + "//foundation/window/window_manager/test/common/utils/include", + "//foundation/window/window_manager/utils/include", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_base/include", + ] +} + +ohos_static_library("utils_unittest_common") { + visibility = [ ":*" ] + testonly = true + + public_configs = [ + ":utils_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//commonlibrary/c_utils/base:utils", + "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_base:librender_service_base", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/snapshot:libsnapshot_util", + "//foundation/window/window_manager/test/common/utils:libtestutil", + "//foundation/window/window_manager/utils:libwmutil", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "hilog_native:libhilog", + "ipc:ipc_core", + ] + + subsystem_name = "window" + part_name = "window_manager" +} +## Build utils_unittest_common.a }}} diff --git a/window_manager/snapshot/test/unittest/snapshot_display_test.cpp b/window_manager/snapshot/test/unittest/snapshot_display_test.cpp new file mode 100644 index 0000000..fe266bd --- /dev/null +++ b/window_manager/snapshot/test/unittest/snapshot_display_test.cpp @@ -0,0 +1,235 @@ +/* + * 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 "pixel_map.h" + +#include "snapshot_utils.h" +#include "common_test_utils.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SnapshotDisplayTest"}; +} + +class SnapshotDisplayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static DisplayId defaultId_; + DisplayId invalidId_ = DISPLAY_ID_INVALID; + const std::string defaultCmd_ = "/system/bin/snapshot_display"; + const int testTimeCount_ = 2; +}; + +DisplayId SnapshotDisplayTest::defaultId_ = DISPLAY_ID_INVALID; + +void SnapshotDisplayTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + if (display == nullptr) { + WLOGFE("GetDefaultDisplay: failed!\n"); + return; + } + WLOGFI("GetDefaultDisplay: id %" PRIu64", w %d, h %d, fps %u\n", display->GetId(), display->GetWidth(), + display->GetHeight(), display->GetRefreshRate()); + + defaultId_ = display->GetId(); + + CommonTestUtils::InjectTokenInfoByHapName(0, "com.ohos.systemui", 0); +} + +void SnapshotDisplayTest::TearDownTestCase() +{ +} + +void SnapshotDisplayTest::SetUp() +{ +} + +void SnapshotDisplayTest::TearDown() +{ +} + +bool CheckFileExist(const std::string& fPath) +{ + if (!fPath.empty()) { + FILE* fp = fopen(fPath.c_str(), "r"); + if (fp != nullptr) { + fclose(fp); + return true; + } + } + return false; +} + +bool TakeScreenshotBySpecifiedParam(std::string exec, std::string imgPath, std::string extraParam) +{ + if (CheckFileExist(imgPath)) { + remove(imgPath.c_str()); + } + const std::string cmd = exec + " -f " + imgPath + " " + extraParam; + (void)system(cmd.c_str()); + bool isExist = CheckFileExist(imgPath); + if (isExist) { + remove(imgPath.c_str()); + } + return isExist; +} + +namespace { +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot default cmd and check if it saves image in default path + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid01, Function | MediumTest | Level2) +{ + std::string imgPath[testTimeCount_]; + int i; + + for (i = 0; i < testTimeCount_; i++) { + imgPath[i] = SnapShotUtils::GenerateFileName(i); + if (CheckFileExist(imgPath[i])) { + remove(imgPath[i].c_str()); + } + } + + (void)system(defaultCmd_.c_str()); + + for (i = 0; i < testTimeCount_; i++) { + if (CheckFileExist(imgPath[i])) { // ok + remove(imgPath[i].c_str()); + ASSERT_TRUE(true); + return; + } + } + ADD_FAILURE(); // fail, can't find snapshot file +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with default displayID and default path + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid02, Function | MediumTest | Level2) +{ + std::string imgPath[testTimeCount_]; + int i; + + for (i = 0; i < testTimeCount_; i++) { + imgPath[i] = SnapShotUtils::GenerateFileName(i); + if (CheckFileExist(imgPath[i])) { + remove(imgPath[i].c_str()); + } + } + + const std::string cmd = defaultCmd_ + " -i " + std::to_string(defaultId_); + (void)system(cmd.c_str()); + + for (i = 0; i < testTimeCount_; i++) { + if (CheckFileExist(imgPath[i])) { // ok + remove(imgPath[i].c_str()); + ASSERT_TRUE(true); + return; + } + } + ADD_FAILURE(); // fail, can't find snapshot file +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with default displayID and custom path + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid03, Function | MediumTest | Level2) +{ + const std::string imgPath = "/data/snapshot_display_test.jpeg"; + std::string extraParam = "-i " + std::to_string(defaultId_); + ASSERT_EQ(true, TakeScreenshotBySpecifiedParam(defaultCmd_, imgPath, extraParam)); +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with valid width/height + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid04, Function | MediumTest | Level2) +{ + const std::string imgPath = "/data/snapshot_display_test.jpeg"; + std::string extraParam = "-i " + std::to_string(defaultId_) + " -w 100 -h 100"; + ASSERT_EQ(true, TakeScreenshotBySpecifiedParam(defaultCmd_, imgPath, extraParam)); +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with valid width + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid05, Function | MediumTest | Level2) +{ + const std::string imgPath = "/data/snapshot_display_test.jpeg"; + std::string extraParam = "-i " + std::to_string(defaultId_) + " -w 100"; + ASSERT_EQ(true, TakeScreenshotBySpecifiedParam(defaultCmd_, imgPath, extraParam)); +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with valid height + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid06, Function | MediumTest | Level2) +{ + const std::string imgPath = "/data/snapshot_display_test.jpeg"; + std::string extraParam = "-i " + std::to_string(defaultId_) + " -h 100"; + ASSERT_EQ(true, TakeScreenshotBySpecifiedParam(defaultCmd_, imgPath, extraParam)); +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with invalid width/height + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid07, Function | MediumTest | Level2) +{ + const std::string imgPath = "/data/snapshot_display_test.jpeg"; + std::string extraParam = "-i " + std::to_string(defaultId_) + " -w 10000 -h 10000"; + ASSERT_EQ(false, TakeScreenshotBySpecifiedParam(defaultCmd_, imgPath, extraParam)); +} + +/** + * @tc.name: ScreenShotCmdValid + * @tc.desc: Call screenshot with -m + * @tc.type: FUNC + */ +HWTEST_F(SnapshotDisplayTest, ScreenShotCmdValid08, Function | MediumTest | Level2) +{ + const std::string imgPath = "/data/snapshot_display_test.jpeg"; + std::string extraParam = "-i " + std::to_string(defaultId_) + " -m"; + ASSERT_EQ(false, TakeScreenshotBySpecifiedParam(defaultCmd_, imgPath, extraParam)); +} +} // namespace +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/snapshot/test/unittest/snapshot_utils_test.cpp b/window_manager/snapshot/test/unittest/snapshot_utils_test.cpp new file mode 100644 index 0000000..3846389 --- /dev/null +++ b/window_manager/snapshot/test/unittest/snapshot_utils_test.cpp @@ -0,0 +1,325 @@ +/* + * 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 "display.h" +#include "display_manager.h" +#include "snapshot_utils.h" +#include "common_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr int BPP = 4; +} +class SnapshotUtilsTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + const std::string defaultFile_ = "/data/snapshot_display_1.jpeg"; + const int defaultBitDepth_ = 8; +}; + +void SnapshotUtilsTest::SetUpTestCase() +{ + CommonTestUtils::InjectTokenInfoByHapName(0, "com.ohos.systemui", 0); +} + +void SnapshotUtilsTest::TearDownTestCase() +{ +} + +void SnapshotUtilsTest::SetUp() +{ +} + +void SnapshotUtilsTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Check01 + * @tc.desc: Check if default jpeg is valid file names + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Check01, Function | SmallTest | Level3) +{ + ASSERT_EQ(true, SnapShotUtils::CheckFileNameValid(defaultFile_)); +} + +/** + * @tc.name: Check02 + * @tc.desc: Check custom jpeg is valid file names + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Check02, Function | SmallTest | Level3) +{ + std::string fileName = "/data/test.jpeg"; + ASSERT_EQ(true, SnapShotUtils::CheckFileNameValid(fileName)); +} + +/** + * @tc.name: Check03 + * @tc.desc: Check random path is invalid file names + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Check03, Function | SmallTest | Level3) +{ + std::string fileName1 = "/path/to/test/1.jpeg"; + ASSERT_EQ(false, SnapShotUtils::CheckFileNameValid(fileName1)); + std::string fileName2 = ""; + ASSERT_EQ(false, SnapShotUtils::CheckFileNameValid(fileName2)); + std::string fileName3 = "/data/test.png"; + ASSERT_EQ(false, SnapShotUtils::CheckFileNameValid(fileName3)); +} + +/** + * @tc.name: RGBA8888ToRGB88801 + * @tc.desc: RGBA8888 to RGB888 using invalid params + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, RGBA8888ToRGB88801, Function | SmallTest | Level3) +{ + ASSERT_FALSE(SnapShotUtils::RGBA8888ToRGB888(nullptr, nullptr, -1)); +} + +/** + * @tc.name: WriteRgb888ToJpeg01 + * @tc.desc: write rgb888 to jpeg using invalid data + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, WriteRgb888ToJpeg01, Function | SmallTest | Level3) +{ + uint8_t *data = nullptr; + FILE *file = fopen(defaultFile_.c_str(), "wb"); + ASSERT_FALSE(SnapShotUtils::WriteRgb888ToJpeg(file, 100, 100, data)); +} + +/** + * @tc.name: WriteRgb888ToJpeg02 + * @tc.desc: write rgb888 to jpeg using invalid file + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, WriteRgb888ToJpeg02, Function | SmallTest | Level3) +{ + uint8_t *data = new uint8_t; + FILE *file = nullptr; + ASSERT_FALSE(SnapShotUtils::WriteRgb888ToJpeg(file, 100, 100, data)); +} + +/** + * @tc.name: Write01 + * @tc.desc: Write default jpeg using valid file names and valid PixelMap + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write01, Function | MediumTest | Level3) +{ + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + std::shared_ptr pixelMap = DisplayManager::GetInstance().GetScreenshot(id); + ASSERT_NE(nullptr, pixelMap); + ASSERT_EQ(true, SnapShotUtils::WriteToJpegWithPixelMap(defaultFile_, *pixelMap)); +} + +/** + * @tc.name: Write02 + * @tc.desc: Write default jpeg using valid file names and valid WriteToJpegParam + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write02, Function | MediumTest | Level3) +{ + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + std::shared_ptr pixelMap = DisplayManager::GetInstance().GetScreenshot(id); + ASSERT_NE(nullptr, pixelMap); + WriteToJpegParam param = { + .width = pixelMap->GetWidth(), + .height = pixelMap->GetHeight(), + .stride = pixelMap->GetRowBytes(), + .format = pixelMap->GetPixelFormat(), + .data = pixelMap->GetPixels() + }; + ASSERT_EQ(true, SnapShotUtils::WriteToJpeg(defaultFile_, param)); +} + +/** + * @tc.name: Write03 + * @tc.desc: Write custom jpeg using valid file names and valid WriteToJpegParam + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write03, Function | MediumTest | Level3) +{ + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + std::shared_ptr pixelMap = DisplayManager::GetInstance().GetScreenshot(id); + ASSERT_NE(nullptr, pixelMap); + WriteToJpegParam param = { + .width = (pixelMap->GetWidth() / 2), + .height = (pixelMap->GetWidth() / 2), + .stride = pixelMap->GetRowBytes(), + .format = pixelMap->GetPixelFormat(), + .data = pixelMap->GetPixels() + }; + ASSERT_EQ(false, SnapShotUtils::WriteToJpeg(defaultFile_, param)); +} + +/** + * @tc.name: Write04 + * @tc.desc: Write pixel map with jpeg, using fd + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write04, Function | MediumTest | Level3) +{ + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + std::shared_ptr pixelMap = DisplayManager::GetInstance().GetScreenshot(id); + ASSERT_EQ(true, SnapShotUtils::WriteToJpegWithPixelMap(0, *pixelMap)); +} + +/** + * @tc.name: Write05 + * @tc.desc: Write custom jpeg using invalid file names and valid WriteToJpegParam + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write05, Function | MediumTest | Level3) +{ + WriteToJpegParam param = { + .width = 256, + .height = 256, + .stride = 256 * BPP, + .format = Media::PixelFormat::UNKNOWN, + .data = new uint8_t + }; + ASSERT_FALSE(SnapShotUtils::WriteToJpeg("", param)); +} + +/** + * @tc.name: Write06 + * @tc.desc: Write custom jpeg using valid file names and invalid WriteToJpegParam + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write06, Function | MediumTest | Level3) +{ + WriteToJpegParam param = { + .width = 256, + .height = 256, + .stride = 256 * BPP, + .format = Media::PixelFormat::UNKNOWN, + .data = nullptr + }; + ASSERT_FALSE(SnapShotUtils::WriteToJpeg(defaultFile_, param)); +} + +/** + * @tc.name: Write07 + * @tc.desc: Write custom jpeg using valid fd and invalid WriteToJpegParam + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, Write07, Function | MediumTest | Level3) +{ + WriteToJpegParam param = { + .width = 256, + .height = 256, + .stride = 256 * BPP, + .format = Media::PixelFormat::UNKNOWN, + .data = nullptr + }; + ASSERT_FALSE(SnapShotUtils::WriteToJpeg(1, param)); +} + +/** + * @tc.name: CheckWHValid + * @tc.desc: Check width and height whether valid + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, CheckWHValid, Function | SmallTest | Level3) +{ + ASSERT_EQ(false, SnapShotUtils::CheckWHValid(0)); + ASSERT_EQ(true, SnapShotUtils::CheckWHValid(DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT)); + ASSERT_EQ(false, SnapShotUtils::CheckWHValid(DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT + 1)); +} + +/** + * @tc.name: CheckParamValid01 + * @tc.desc: Check jpeg param whether valid width + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, CheckParamValid01, Function | SmallTest | Level3) +{ + WriteToJpegParam paramInvalidWidth = { + .width = DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT + 1, + .height = 0, + .stride = 0, + .format = Media::PixelFormat::UNKNOWN, + .data = nullptr + }; + ASSERT_EQ(false, SnapShotUtils::CheckParamValid(paramInvalidWidth)); +} + +/** + * @tc.name: CheckParamValid02 + * @tc.desc: Check jpeg param whether valid height + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, CheckParamValid02, Function | SmallTest | Level3) +{ + WriteToJpegParam paramInvalidHeight = { + .width = DisplayManager::MAX_RESOLUTION_SIZE_SCREENSHOT, + .height = 0, + .stride = 0, + .format = Media::PixelFormat::UNKNOWN, + .data = nullptr + }; + ASSERT_EQ(false, SnapShotUtils::CheckParamValid(paramInvalidHeight)); +} + +/** + * @tc.name: CheckParamValid03 + * @tc.desc: Check jpeg param whether valid stride + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, CheckParamValid03, Function | SmallTest | Level3) +{ + WriteToJpegParam paramInvalidStride = { + .width = 256, + .height = 256, + .stride = 1, + .format = Media::PixelFormat::UNKNOWN, + .data = nullptr + }; + ASSERT_EQ(false, SnapShotUtils::CheckParamValid(paramInvalidStride)); +} + +/** + * @tc.name: CheckParamValid04 + * @tc.desc: Check jpeg param whether valid data + * @tc.type: FUNC + */ +HWTEST_F(SnapshotUtilsTest, CheckParamValid04, Function | SmallTest | Level3) +{ + WriteToJpegParam paramInvalidData = { + .width = 256, + .height = 256, + .stride = 256 * BPP, + .format = Media::PixelFormat::UNKNOWN, + .data = nullptr + }; + ASSERT_EQ(false, SnapShotUtils::CheckParamValid(paramInvalidData)); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/BUILD.gn b/window_manager/test/BUILD.gn new file mode 100644 index 0000000..4123513 --- /dev/null +++ b/window_manager/test/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +group("test") { + testonly = true + deps = [ + "demo:demo", + "fuzztest:fuzztest", + "systemtest:systemtest", + ] +} diff --git a/window_manager/test/common/mock/iremote_object_mocker.h b/window_manager/test/common/mock/iremote_object_mocker.h new file mode 100644 index 0000000..8baafb8 --- /dev/null +++ b/window_manager/test/common/mock/iremote_object_mocker.h @@ -0,0 +1,129 @@ +/* + * 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_ROSEN_TEST_COMMON_MOCK_IREMOTE_OBJECT_MOCKER +#define OHOS_ROSEN_TEST_COMMON_MOCK_IREMOTE_OBJECT_MOCKER + +#include + +namespace OHOS { +namespace Rosen { +class IRemoteObjectMocker : public IRemoteObject { +public: + IRemoteObjectMocker() : IRemoteObject {u"IRemoteObjectMocker"} + { + } + + ~IRemoteObjectMocker() + { + } + + int32_t GetObjectRefCount() + { + return 0; + } + + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + + bool IsProxyObject() const + { + return true; + } + + bool CheckObjectLegality() const + { + return true; + } + + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + + sptr AsInterface() + { + return nullptr; + } + + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; +class MockIRemoteObject : public IRemoteObject { +public: + MockIRemoteObject() : IRemoteObject {u"MockIRemoteObject"} + { + } + + ~MockIRemoteObject() + { + } + + int32_t GetObjectRefCount() + { + return 0; + } + + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return sendRequestResult_; + } + + bool IsProxyObject() const + { + return true; + } + + bool CheckObjectLegality() const + { + return true; + } + + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + + sptr AsInterface() + { + return nullptr; + } + + int Dump(int fd, const std::vector &args) + { + return 0; + } + + int sendRequestResult_ = 0; + int count_ = 0; +}; +} +} + +#endif \ No newline at end of file diff --git a/window_manager/test/common/mock/mock_IWindow.h b/window_manager/test/common/mock/mock_IWindow.h new file mode 100644 index 0000000..5075441 --- /dev/null +++ b/window_manager/test/common/mock/mock_IWindow.h @@ -0,0 +1,56 @@ +/* + * 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 "iremote_broker.h" +#include "window.h" +#include "window_property.h" +#include "wm_common.h" +#include "wm_common_inner.h" +#include + +namespace OHOS { +namespace Rosen { +class IWindowMocker : public IWindow { +public: + IWindowMocker() {}; + ~IWindowMocker() {}; + MOCK_METHOD3(UpdateWindowRect, WMError(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason)); + MOCK_METHOD1(UpdateWindowMode, WMError(WindowMode mode)); + MOCK_METHOD1(UpdateWindowModeSupportInfo, WMError(uint32_t modeSupportInfo)); + MOCK_METHOD1(UpdateFocusStatus, WMError(bool focused)); + MOCK_METHOD2(UpdateAvoidArea, WMError(const sptr& avoidArea, AvoidAreaType type)); + MOCK_METHOD1(UpdateWindowState, WMError(WindowState state)); + MOCK_METHOD2(UpdateWindowDragInfo, WMError(const PointInfo& point, DragEvent event)); + MOCK_METHOD2(UpdateDisplayId, WMError(DisplayId from, DisplayId to)); + MOCK_METHOD1(UpdateOccupiedAreaChangeInfo, WMError(const sptr& info)); + MOCK_METHOD1(UpdateActiveStatus, WMError(bool isActive)); + MOCK_METHOD0(GetWindowProperty, sptr()); + MOCK_METHOD0(NotifyTouchOutside, WMError()); + MOCK_METHOD0(NotifyScreenshot, WMError()); + MOCK_METHOD1(DumpInfo, WMError(const std::vector& params)); + MOCK_METHOD0(NotifyDestroy, WMError(void)); + MOCK_METHOD0(NotifyForeground, WMError(void)); + MOCK_METHOD0(NotifyBackground, WMError(void)); + MOCK_METHOD1(NotifyWindowClientPointUp, WMError(const std::shared_ptr& pointerEvent)); + MOCK_METHOD2(UpdateZoomTransform, WMError(const Transform& trans, bool isDisplayZoomOn)); + MOCK_METHOD1(RestoreSplitWindowMode, WMError(uint32_t mode)); + sptr AsObject() override + { + return nullptr; + }; +}; +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/common/mock/mock_RSIWindowAnimationController.h b/window_manager/test/common/mock/mock_RSIWindowAnimationController.h new file mode 100644 index 0000000..8ae19bf --- /dev/null +++ b/window_manager/test/common/mock/mock_RSIWindowAnimationController.h @@ -0,0 +1,102 @@ +/* + * 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 FRAMEWORKS_WM_TEST_UT_MOCK_RSIWINDOWANIMATIONCONTROLLER_H +#define FRAMEWORKS_WM_TEST_UT_MOCK_RSIWINDOWANIMATIONCONTROLLER_H + +#include +#include +#include + +#include "rs_iwindow_animation_controller.h" +#include "iremote_object_mocker.h" + +namespace OHOS { +namespace Rosen { +class RSIWindowAnimationControllerMocker : public RSIWindowAnimationController { +public: + RSIWindowAnimationControllerMocker() + { + remoteObject_ = new IRemoteObjectMocker(); + } + + ~RSIWindowAnimationControllerMocker() {}; + void OnWindowAnimationTargetsUpdate(const sptr& fullScreenWindowTarget, + const std::vector>& floatingWindowTargets) override + { + animationTarget_ = fullScreenWindowTarget; + floatingWindowTargets_ = floatingWindowTargets; + return; + } + + void OnWallpaperUpdate(const sptr& wallpaperTarget) override + { + animationTarget_ = wallpaperTarget; + return; + } + + void OnStartApp(StartingAppType type, const sptr& startingWindowTarget, + const sptr& finishedCallback) override + { + finishedCallback_ = finishedCallback; + } + + void OnAppTransition(const sptr& from, const sptr& to, + const sptr& finishedCallback) + { + finishedCallback_ = finishedCallback; + } + + void OnAppBackTransition(const sptr& from, const sptr& to, + const sptr& finishedCallback) + { + finishedCallback_ = finishedCallback; + } + + void OnMinimizeWindow(const sptr& minimizingWindow, + const sptr& finishedCallback) + { + finishedCallback_ = finishedCallback; + } + + void OnMinimizeAllWindow(std::vector> minimizingWindows, + const sptr& finishedCallback) + { + finishedCallback_ = finishedCallback; + } + + void OnCloseWindow(const sptr& closingWindow, + const sptr& finishedCallback) + { + finishedCallback_ = finishedCallback; + } + + void OnScreenUnlock(const sptr& finishedCallback) + { + finishedCallback_ = finishedCallback; + } + + sptr AsObject() override + { + return remoteObject_; + }; + + sptr finishedCallback_ = nullptr; + sptr remoteObject_ = nullptr; + sptr animationTarget_ = nullptr; + std::vector> floatingWindowTargets_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // FRAMEWORKS_WM_TEST_UT_MOCK_RSIWINDOWANIMATIONCONTROLLER_H \ No newline at end of file diff --git a/window_manager/test/common/mock/mock_display_manager_adapter.h b/window_manager/test/common/mock/mock_display_manager_adapter.h new file mode 100644 index 0000000..a81358c --- /dev/null +++ b/window_manager/test/common/mock/mock_display_manager_adapter.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021-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 FRAMEWORKS_WM_TEST_UT_MOCK_DISPLAY_MANAGER_ADAPTER_H +#define FRAMEWORKS_WM_TEST_UT_MOCK_DISPLAY_MANAGER_ADAPTER_H +#include + +#include "display_manager_adapter.h" + +namespace OHOS { +namespace Rosen { +class MockDisplayManagerAdapter : public DisplayManagerAdapter { +public: + MOCK_METHOD0(Clear, void()); + MOCK_METHOD2(RegisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, + DisplayManagerAgentType type)); + MOCK_METHOD2(UnregisterDisplayManagerAgent, bool(const sptr& displayManagerAgent, + DisplayManagerAgentType type)); + MOCK_METHOD0(GetDefaultDisplayInfo, sptr()); + MOCK_METHOD1(GetDisplayInfoByScreenId, sptr(ScreenId screenId)); + 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_METHOD1(SetDisplayState, bool(DisplayState state)); + MOCK_METHOD1(GetDisplayState, DisplayState(DisplayId displayId)); + MOCK_METHOD1(NotifyDisplayEvent, void(DisplayEvent event)); + MOCK_METHOD1(GetDisplayInfo, sptr(DisplayId displayId)); + MOCK_METHOD1(GetCutoutInfo, sptr(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_METHOD2(CreateVirtualScreen, ScreenId(VirtualScreenOption option, + const sptr& displayManagerAgent)); + MOCK_METHOD1(DestroyVirtualScreen, DMError(ScreenId screenId)); + MOCK_METHOD2(SetVirtualScreenSurface, DMError(ScreenId screenId, sptr surface)); + MOCK_METHOD1(GetScreenGroupInfoById, sptr(ScreenId screenId)); + MOCK_METHOD0(GetAllScreenInfos, std::vector>()); + 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(GetScreenInfo, sptr(ScreenId screenId)); + MOCK_METHOD2(SetScreenPowerForAll, bool(ScreenPowerState state, PowerStateChangeReason reason)); + MOCK_METHOD1(GetScreenPower, ScreenPowerState(ScreenId dmsScreenId)); + + 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)); + MOCK_METHOD2(GetScreenGamutMap, DMError(ScreenId screenId, ScreenGamutMap& gamutMap)); + MOCK_METHOD2(SetScreenGamutMap, DMError(ScreenId screenId, ScreenGamutMap gamutMap)); + MOCK_METHOD1(SetScreenColorTransform, DMError(ScreenId screenId)); + + MOCK_METHOD1(RemoveVirtualScreenFromGroup, void(std::vector screens)); + MOCK_METHOD1(SetScreenRotationLocked, void(bool isLocked)); + MOCK_METHOD0(IsScreenRotationLocked, bool()); +}; +} +} // namespace OHOS + +#endif // FRAMEWORKS_WM_TEST_UT_MOCK_DISPLAY_MANAGER_ADAPTER_H \ No newline at end of file diff --git a/window_manager/test/common/mock/mock_rs_iwindow_animation_controller.h b/window_manager/test/common/mock/mock_rs_iwindow_animation_controller.h new file mode 100644 index 0000000..5ae0180 --- /dev/null +++ b/window_manager/test/common/mock/mock_rs_iwindow_animation_controller.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-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 FRAMEWORKS_WM_TEST_UT_MOCK_RS_IWINDOW_ANIMATION_CONTROLLER_H +#define FRAMEWORKS_WM_TEST_UT_MOCK_RS_IWINDOW_ANIMATION_CONTROLLER_H +#include + +#include +#include +#include + +namespace OHOS { +namespace Rosen { +class MockRSIWindowAnimationController : public RSIWindowAnimationController { +public: + MockRSIWindowAnimationController() {}; + MOCK_METHOD3(OnStartApp, void(StartingAppType type, const sptr& startingWindowTarget, + const sptr& finishedCallback)); + MOCK_METHOD3(OnAppTransition, void(const sptr& from, + const sptr& to, const sptr& finishedCallback)); + MOCK_METHOD3(OnAppBackTransition, void(const sptr& from, + const sptr& to, const sptr& finishedCallback)); + + MOCK_METHOD2(OnMinimizeWindow, void(const sptr& minimizingWindow, + const sptr& finishedCallback)); + MOCK_METHOD2(OnMinimizeAllWindow, void(std::vector> minimizingWindows, + const sptr& finishedCallback)); + MOCK_METHOD2(OnCloseWindow, void(const sptr& closingWindow, + const sptr& finishedCallback)); + + MOCK_METHOD1(OnScreenUnlock, void(const sptr& finishedCallback)); + MOCK_METHOD2(OnWindowAnimationTargetsUpdate, void(const sptr& fullScreenWindowTarget, + const std::vector>& floatingWindowTargets)); + MOCK_METHOD1(OnWallpaperUpdate, void(const sptr& wallpaperTarget)); + MOCK_METHOD0(AsObject, sptr()); +}; +} +} // namespace OHOS + +#endif // FRAMEWORKS_WM_TEST_UT_MOCK_RS_IWINDOW_ANIMATION_CONTROLLER_H diff --git a/window_manager/test/common/mock/mock_static_call.h b/window_manager/test/common/mock/mock_static_call.h new file mode 100644 index 0000000..1769402 --- /dev/null +++ b/window_manager/test/common/mock/mock_static_call.h @@ -0,0 +1,34 @@ +/* + * 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 FRAMEWORKS_WM_TEST_UT_MOCK_STATIC_CALL_H +#define FRAMEWORKS_WM_TEST_UT_MOCK_STATIC_CALL_H +#include + +#include "ability_context_impl.h" +#include "foundation/ability/ability_runtime/interfaces/kits/native/appkit/ability_runtime/context/context.h" +#include "static_call.h" + +namespace OHOS { +namespace Rosen { +class MockStaticCall : public StaticCall { +public: + MOCK_METHOD3(CreateWindow, sptr(const std::string& windowName, + sptr& option, std::shared_ptr abilityContext)); +}; +} // namepsace Rosen +} // namespace OHOS + +#endif // FRAMEWORKS_WM_TEST_UT_MOCK_STATIC_CALL_H+ diff --git a/window_manager/test/common/mock/mock_uicontent.h b/window_manager/test/common/mock/mock_uicontent.h new file mode 100644 index 0000000..4e23a0a --- /dev/null +++ b/window_manager/test/common/mock/mock_uicontent.h @@ -0,0 +1,82 @@ +/* + * 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_ROSEN_TEST_COMMON_MOCK_IREMOTE_OBJECT_MOCKER +#define OHOS_ROSEN_TEST_COMMON_MOCK_IREMOTE_OBJECT_MOCKER + +#include "ui_content.h" +#include "native_engine/native_value.h" +#include "native_engine/native_engine.h" +#include +namespace OHOS { +namespace AppExecFwk { + class Ability; + class Configuration; +} // namespace AppExecFwk +namespace AAFwk { + class Want; +} // namespace AAFwk +namespace MMI { + class PointerEvent; + class AxisEvent; +} // namespace MMI +namespace Media { + class PixelMap; +} // namespace Media +} // namespace OHOS +namespace OHOS { +namespace Ace { +class UIContentMocker : public UIContent { +public: + MOCK_METHOD3(Initialize, void(OHOS::Rosen::Window* window, const std::string& url, NativeValue* storage)); + MOCK_METHOD0(Foreground, void()); + MOCK_METHOD0(Background, void()); + MOCK_METHOD0(Focus, void()); + MOCK_METHOD0(UnFocus, void()); + MOCK_METHOD0(Destroy, void()); + MOCK_METHOD1(OnNewWant, void(const OHOS::AAFwk::Want& want)); + MOCK_METHOD3(Restore, void(OHOS::Rosen::Window* window, const std::string& contentInfo, NativeValue* storage)); + MOCK_CONST_METHOD0(GetContentInfo, std::string()); + MOCK_METHOD0(DestroyUIDirector, void()); + MOCK_METHOD0(ProcessBackPressed, bool()); + MOCK_METHOD1(ProcessPointerEvent, bool(const std::shared_ptr& pointerEvent)); + MOCK_METHOD1(ProcessKeyEvent, bool(const std::shared_ptr& keyEvent)); + MOCK_METHOD1(ProcessAxisEvent, bool(const std::shared_ptr& axisEvent)); + MOCK_METHOD1(ProcessVsyncEvent, bool(uint64_t timeStampNanos)); + MOCK_METHOD1(UpdateConfiguration, void(const std::shared_ptr& config)); + MOCK_METHOD2(UpdateViewportConfig, void(const ViewportConfig& config, OHOS::Rosen::WindowSizeChangeReason reason)); + MOCK_METHOD1(UpdateWindowMode, void(OHOS::Rosen::WindowMode mode)); + MOCK_METHOD3(HideWindowTitleButton, void(bool hideSplit, bool hideMaximize, bool hideMinimize)); + MOCK_METHOD0(GetBackgroundColor, uint32_t()); + MOCK_METHOD1(SetBackgroundColor, void(uint32_t color)); + MOCK_METHOD2(DumpInfo, void(const std::vector& params, std::vector& info)); + MOCK_METHOD1(SetNextFrameLayoutCallback, void(std::function&& callback)); + MOCK_METHOD1(NotifyMemoryLevel, void(int32_t level)); + MOCK_METHOD1(SetAppWindowTitle, void(const std::string& title)); + MOCK_METHOD1(SetAppWindowIcon, void(const std::shared_ptr& pixelMap)); + MOCK_METHOD0(GetFormRootNode, std::shared_ptr()); + MOCK_METHOD1(UpdateFormData, void(const std::string& data)); + MOCK_METHOD1(SetFormWidth, void(const float width)); + MOCK_METHOD1(SetFormHeight, void(const float height)); + MOCK_METHOD0(GetFormWidth, float()); + MOCK_METHOD0(GetFormHeight, float()); + MOCK_METHOD1(SetActionEventHandler, void(std::function&& actionCallback)); + MOCK_METHOD1(SetErrorEventHandler, + void(std::function&& actionCallback)); +}; +} // namespace Ace +} // namespace OHOS + +#endif diff --git a/window_manager/test/common/mock/mock_window_adapter.h b/window_manager/test/common/mock/mock_window_adapter.h new file mode 100644 index 0000000..1f3e52b --- /dev/null +++ b/window_manager/test/common/mock/mock_window_adapter.h @@ -0,0 +1,56 @@ +/* + * 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 FRAMEWORKS_WM_TEST_UT_MOCK_WINDOW_ADAPTER_H +#define FRAMEWORKS_WM_TEST_UT_MOCK_WINDOW_ADAPTER_H +#include + +#include "window_adapter.h" + +namespace OHOS { +namespace Rosen { +class MockWindowAdapter : public WindowAdapter { +public: + MOCK_METHOD5(CreateWindow, WMError(sptr& window, sptr& windowProperty, + std::shared_ptr surfaceNode, uint32_t& windowId, const sptr& token)); + MOCK_METHOD1(AddWindow, WMError(sptr& windowProperty)); + MOCK_METHOD1(RemoveWindow, WMError(uint32_t windowId)); + MOCK_METHOD0(ClearWindowAdapter, void()); + MOCK_METHOD1(DestroyWindow, WMError(uint32_t windowId)); + MOCK_METHOD2(UpdateProperty, WMError(sptr& windowProperty, PropertyChangeAction action)); + MOCK_METHOD2(GetTopWindowId, WMError(uint32_t mainWinId, uint32_t& topWinId)); + MOCK_METHOD3(GetAvoidAreaByType, WMError(uint32_t windowId, AvoidAreaType type, AvoidArea& avoidArea)); + MOCK_METHOD2(BindDialogTarget, WMError(uint32_t& windowId, sptr targetToken)); + MOCK_METHOD2(UpdateRsTree, WMError(uint32_t windowId, bool isAdd)); + MOCK_METHOD1(MinimizeAllAppWindows, void(DisplayId displayId)); + MOCK_METHOD0(ToggleShownStateForAllAppWindows, WMError()); + MOCK_METHOD2(ProcessPointDown, void(uint32_t windowId, bool isPointDown)); + MOCK_METHOD1(ProcessPointUp, void(uint32_t windowId)); + MOCK_METHOD1(RequestFocus, WMError(uint32_t windowId)); + MOCK_METHOD2(NotifyWindowTransition, WMError(sptr from, sptr to)); + MOCK_METHOD2(GetModeChangeHotZones, WMError(DisplayId displayId, ModeChangeHotZones& hotZones)); + MOCK_METHOD3(NotifyServerReadyToMoveOrDrag, void(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty)); + MOCK_METHOD2(RegisterWindowManagerAgent, bool(WindowManagerAgentType type, + const sptr& windowManagerAgent)); + MOCK_METHOD2(UnregisterWindowManagerAgent, bool(WindowManagerAgentType type, + const sptr& windowManagerAgent)); + MOCK_METHOD1(GetVisibilityWindowInfo, WMError(std::vector>& infos)); + MOCK_METHOD1(GetAccessibilityWindowInfo, WMError(std::vector>& infos)); +}; +} +} // namespace OHOS + +#endif // FRAMEWORKS_WM_TEST_UT_MOCK_WINDOW_ADAPTER_H \ No newline at end of file diff --git a/window_manager/test/common/mock/singleton_mocker.h b/window_manager/test/common/mock/singleton_mocker.h new file mode 100644 index 0000000..e87b91f --- /dev/null +++ b/window_manager/test/common/mock/singleton_mocker.h @@ -0,0 +1,46 @@ +/* + * 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 FRAMEWORKS_WM_TEST_UT_SINGLETON_MOCKER_H +#define FRAMEWORKS_WM_TEST_UT_SINGLETON_MOCKER_H + +#include "singleton_container.h" +namespace OHOS { +namespace Rosen { +template +class SingletonMocker { +public: + SingletonMocker() + { + SingletonContainer::Set(mock); + } + + ~SingletonMocker() + { + SingletonContainer::Set(T::GetInstance()); + } + + MockT& Mock() + { + return mock; + } + +private: + MockT mock; +}; +} // namespace Rosen +} // namespace OHOS + +#endif // FRAMEWORKS_WM_TEST_UT_SINGLETON_MOCKER_H diff --git a/window_manager/test/common/utils/BUILD.gn b/window_manager/test/common/utils/BUILD.gn new file mode 100644 index 0000000..4922fc6 --- /dev/null +++ b/window_manager/test/common/utils/BUILD.gn @@ -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. + +import("//build/ohos.gni") +config("libtestutil_private_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +## Build libtestutil.a +ohos_static_library("libtestutil") { + sources = [ + "src/common_test_utils.cpp", + "src/screen_manager_utils.cpp", + ] + + include_dirs = [ "//foundation/window/window_manager/utils/include" ] + + configs = [ ":libtestutil_private_config" ] + + public_configs = [ + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "graphic_standard:surface", + "hilog_native:libhilog", + "multimedia_image_framework:image_native", + ] + + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/test/common/utils/include/common_test_utils.h b/window_manager/test/common/utils/include/common_test_utils.h new file mode 100644 index 0000000..b53801c --- /dev/null +++ b/window_manager/test/common/utils/include/common_test_utils.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 TEST_UTILS_H +#define TEST_UTILS_H + +#include +#include "pixel_map.h" + +namespace OHOS::Rosen { +class CommonTestUtils { +public: + static void InjectTokenInfoByHapName(int userID, const std::string& bundleName, int instIndex); + static std::shared_ptr CreatePixelMap(); + static constexpr int32_t TEST_IMAGE_HEIGHT = 1080; + static constexpr int32_t TEST_IMAGE_WIDTH = 1920; + static void SetAceessTokenPermission(const std::string processName); + static void SetAceessTokenPermission(const std::string processName, + const char** perms, const int permCount); +}; +} // namespace OHOS::Rosen +#endif // TEST_UTILS_H \ No newline at end of file diff --git a/window_manager/test/common/utils/include/screen_manager_utils.h b/window_manager/test/common/utils/include/screen_manager_utils.h new file mode 100644 index 0000000..81ef94e --- /dev/null +++ b/window_manager/test/common/utils/include/screen_manager_utils.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021-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 FRAMEWORKS_DM_TEST_UT_SCREEN_MANAGER_UTILS_H +#define FRAMEWORKS_DM_TEST_UT_SCREEN_MANAGER_UTILS_H + +#include +#include +#include +#include + +namespace OHOS::Rosen { +class ScreenManagerUtils { +public: + bool CreateSurface(); + + sptr csurface_ = nullptr; // cosumer surface + sptr psurface_ = nullptr; // producer surface +}; +} // namespace OHOS::Rosen + +#endif // FRAMEWORKS_DM_TEST_UT_SCREEN_MANAGER_UTILS_H \ No newline at end of file diff --git a/window_manager/test/common/utils/include/screenshot_listener_future.h b/window_manager/test/common/utils/include/screenshot_listener_future.h new file mode 100644 index 0000000..4f325ca --- /dev/null +++ b/window_manager/test/common/utils/include/screenshot_listener_future.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 SCREENSHOT_LISTENER_FUTURE_H +#define SCREENSHOT_LISTENER_FUTURE_H + +#include "display_manager.h" +#include "future.h" + +namespace OHOS { +namespace Rosen { +class ScreenshotListenerFuture : public DisplayManager::IScreenshotListener { +public: + virtual void OnScreenshot(const ScreenshotInfo info) override + { + future_.SetValue(info); + } + RunnableFuture future_; +}; +} // Rosen +} // OHOS +#endif // SCREENSHOT_LISTENER_FUTURE_H \ No newline at end of file diff --git a/window_manager/test/common/utils/include/virtual_screen_group_change_listener_future.h b/window_manager/test/common/utils/include/virtual_screen_group_change_listener_future.h new file mode 100644 index 0000000..6a1e98c --- /dev/null +++ b/window_manager/test/common/utils/include/virtual_screen_group_change_listener_future.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 VIRTUAL_SCREEN_GROUP_CHANGE_LISTENER_FUTURE_H +#define VIRTUAL_SCREEN_GROUP_CHANGE_LISTENER_FUTURE_H + +#include "future.h" +#include "screen_manager.h" + +namespace OHOS { +namespace Rosen { +class VirtualScreenGroupChangeListenerFuture : public ScreenManager::IVirtualScreenGroupListener { +public: + virtual void OnMirrorChange(const ChangeInfo& info) override + { + mirrorChangeFuture_.SetValue(info); + } + RunnableFuture mirrorChangeFuture_; +}; +} // Rosen +} // OHOS +#endif // VIRTUAL_SCREEN_GROUP_CHANGE_LISTENER_FUTURE_H \ No newline at end of file diff --git a/window_manager/test/common/utils/src/common_test_utils.cpp b/window_manager/test/common/utils/src/common_test_utils.cpp new file mode 100644 index 0000000..46edf25 --- /dev/null +++ b/window_manager/test/common/utils/src/common_test_utils.cpp @@ -0,0 +1,108 @@ +/* + * 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 "common_test_utils.h" + +#include +#include +#include +#include +#include + +namespace OHOS::Rosen { +void CommonTestUtils::InjectTokenInfoByHapName(int userID, const std::string& bundleName, int instIndex) +{ + Security::AccessToken::AccessTokenID tokenId = + Security::AccessToken::AccessTokenKit::GetHapTokenID(userID, bundleName, instIndex); + SetSelfTokenID(tokenId); +} + +std::shared_ptr CommonTestUtils::CreatePixelMap() +{ + // pixel_map testing code + Media::InitializationOptions opt; + opt.size.width = TEST_IMAGE_WIDTH; + opt.size.height = TEST_IMAGE_HEIGHT; + opt.pixelFormat = Media::PixelFormat::RGBA_8888; + opt.alphaType = Media::AlphaType::IMAGE_ALPHA_TYPE_OPAQUE; + opt.scaleMode = Media::ScaleMode::FIT_TARGET_SIZE; + opt.editable = false; + opt.useSourceIfMatch = false; + + const int bitmapDepth = 8; // color depth + const int bpp = 4; // bytes per pixel + const int pixelValue = 125; + + const int voulumeSize = opt.size.width * opt.size.height * bpp; + auto data = (uint32_t *)malloc(voulumeSize); + if (data == nullptr) { + return nullptr; + } + + uint8_t *pic = (uint8_t *)data; + if (memset_s(pic, voulumeSize, pixelValue, voulumeSize) != EOK) { + free(data); + return nullptr; + } + + uint32_t colorLen = voulumeSize * bitmapDepth; + auto pixelMap = Media::PixelMap::Create(data, colorLen, opt); + free(data); + if (pixelMap == nullptr) { + return nullptr; + } + std::shared_ptr pixelMap_(pixelMap.release()); + return pixelMap_; +} + +void CommonTestUtils::SetAceessTokenPermission(const std::string processName) +{ + uint64_t tokenId; + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 0, + .aclsNum = 0, + .dcaps = nullptr, + .perms = nullptr, + .acls = nullptr, + .processName = processName.c_str(), + .aplStr = "system_basic", + }; + tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); +} + +void CommonTestUtils::SetAceessTokenPermission(const std::string processName, + const char** perms, const int permCount) +{ + if (perms == nullptr || permCount == 0) { + return; + } + uint64_t tokenId; + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = permCount, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = processName.c_str(), + .aplStr = "system_basic", + }; + tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/test/common/utils/src/screen_manager_utils.cpp b/window_manager/test/common/utils/src/screen_manager_utils.cpp new file mode 100644 index 0000000..e9664eb --- /dev/null +++ b/window_manager/test/common/utils/src/screen_manager_utils.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-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 "screen_manager_utils.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenManagerUtils"}; +} + +bool ScreenManagerUtils::CreateSurface() +{ + csurface_ = Surface::CreateSurfaceAsConsumer(); + if (csurface_ == nullptr) { + WLOGFE("csurface create failed"); + return false; + } + + auto producer = csurface_->GetProducer(); + psurface_ = Surface::CreateSurfaceAsProducer(producer); + if (psurface_ == nullptr) { + WLOGFE("csurface create failed"); + return false; + } + return true; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/test/demo/BUILD.gn b/window_manager/test/demo/BUILD.gn new file mode 100644 index 0000000..04a3a32 --- /dev/null +++ b/window_manager/test/demo/BUILD.gn @@ -0,0 +1,118 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") + +group("demo") { + testonly = true + + deps = [ + ":demo_freeze_display", + ":demo_mirror_screen_listener", + ":demo_screenshot_listener", + ":demo_snapshot_virtual_screen", + ":demo_system_sub_window", + ] +} + +ohos_executable("demo_mirror_screen_listener") { + sources = [ "demo_mirror_screen_listener.cpp" ] + + include_dirs = + [ "//foundation/window/window_manager/test/common/utils/include" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_base:librender_service_base", + "//foundation/window/window_manager/dm:libdm", + ] + + external_deps = [ "c_utils:utils" ] + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_executable("demo_screenshot_listener") { + sources = [ "demo_screenshot_listener.cpp" ] + + include_dirs = + [ "//foundation/window/window_manager/test/common/utils/include" ] + + deps = [ + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + ] + + external_deps = [ + "c_utils:utils", + "hilog_native:libhilog", + "multimedia_image_framework:image_native", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_executable("demo_snapshot_virtual_screen") { + sources = [ "demo_snapshot_virtual_screen.cpp" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/snapshot/include", + "//foundation/window/window_manager/utils/include", + ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/snapshot:libsnapshot_util", + "//foundation/window/window_manager/utils:libwmutil", + ] + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_executable("demo_system_sub_window") { + sources = [ "demo_system_sub_window.cpp" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/test/common/utils/include", + ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_base:librender_service_base", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ "c_utils:utils" ] + + part_name = "window_manager" + subsystem_name = "window" +} + +ohos_executable("demo_freeze_display") { + sources = [ "demo_freeze_display.cpp" ] + + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/dm", + + # pixel_map.h + "//foundation/multimedia/image_framework/interfaces/innerkits/include", + ] + deps = [ "//foundation/window/window_manager/dm:libdm" ] + external_deps = [ "multimedia_image_framework:image_native" ] + part_name = "window_manager" + subsystem_name = "window" +} diff --git a/window_manager/test/demo/demo_freeze_display.cpp b/window_manager/test/demo/demo_freeze_display.cpp new file mode 100644 index 0000000..72d3e75 --- /dev/null +++ b/window_manager/test/demo/demo_freeze_display.cpp @@ -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. + */ + +#include +#include "display_manager.h" + +using namespace OHOS; +using namespace OHOS::Rosen; + +int main(int argc, char *argv[]) +{ + auto displayId = DisplayManager::GetInstance().GetDefaultDisplayId(); + std::vector ids; + ids.push_back(displayId); + if (argc < 2) { // 2 is arg number + std::cout << "Invalid operation." << std::endl; + return 0; + } + if (atoi(argv[1]) == 1) { + if (DisplayManager::GetInstance().Freeze(ids)) { + std::cout << "Freeze display success." << std::endl; + return 0; + } + } else if (atoi(argv[1]) == 0) { + if (DisplayManager::GetInstance().Unfreeze(ids)) { + std::cout << "Unfreeze display success." << std::endl; + return 0; + } + } else { + std::cout << "Invalid cmd." << std::endl; + return 0; + } + std::cout << "Freeze/Unfreeze failed." << std::endl; + return 0; +} \ No newline at end of file diff --git a/window_manager/test/demo/demo_mirror_screen_listener.cpp b/window_manager/test/demo/demo_mirror_screen_listener.cpp new file mode 100644 index 0000000..6c70a30 --- /dev/null +++ b/window_manager/test/demo/demo_mirror_screen_listener.cpp @@ -0,0 +1,45 @@ +/* + * 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 "virtual_screen_group_change_listener_future.h" + +using namespace OHOS; +using namespace OHOS::Rosen; + +int main(int argc, char *argv[]) +{ + std::cout << "===========================Start===========================" << std::endl; + std::cout << "Please do screen mirror in 20s..." << std::endl; + + sptr listener = new VirtualScreenGroupChangeListenerFuture(); + auto& sm = ScreenManager::GetInstance(); + sm.RegisterVirtualScreenGroupListener(listener); + auto info = listener->mirrorChangeFuture_.GetResult(20000); + + std::cout << "mirror event=" << std::to_string(static_cast(info.event)) + << ", trigger=" << info.trigger << std::endl; + std::cout << "ids.size=" << std::to_string(info.ids.size()) << ", "; + for (size_t i = 0; i < info.ids.size(); i++) { + std::cout << "ids[" << std::to_string(i) << "]=" << std::to_string(info.ids[i]); + } + std::cout << std::endl; + + sm.UnregisterVirtualScreenGroupListener(listener); + + std::cout << "============================End============================" << std::endl; + return 0; +} \ No newline at end of file diff --git a/window_manager/test/demo/demo_screenshot_listener.cpp b/window_manager/test/demo/demo_screenshot_listener.cpp new file mode 100644 index 0000000..8a90f50 --- /dev/null +++ b/window_manager/test/demo/demo_screenshot_listener.cpp @@ -0,0 +1,40 @@ +/* + * 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 "screenshot_listener_future.h" + +using namespace OHOS; +using namespace OHOS::Rosen; + +int main(int argc, char *argv[]) +{ + std::cout << "===========================Start===========================" << std::endl; + std::cout << "Please do screenshot in 20s..." << std::endl; + sptr listener = new ScreenshotListenerFuture(); + + auto& dm = DisplayManager::GetInstance(); + dm.RegisterScreenshotListener(listener); + + auto info = listener->future_.GetResult(20000); + std::cout << "screenshot trigger=" << info.GetTrigger() + << ", display=" << std::to_string(info.GetDisplayId()) << std::endl; + + dm.UnregisterScreenshotListener(listener); + + std::cout << "============================End============================" << std::endl; + return 0; +} \ No newline at end of file diff --git a/window_manager/test/demo/demo_snapshot_virtual_screen.cpp b/window_manager/test/demo/demo_snapshot_virtual_screen.cpp new file mode 100644 index 0000000..3c59767 --- /dev/null +++ b/window_manager/test/demo/demo_snapshot_virtual_screen.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021-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 "screen_manager.h" +#include "snapshot_utils.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()) { + std::cout << "surfaceReader init failed!" << std::endl; + 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); + if (startTime < 0) { + std::cout << "startTime error!" << std::endl; + return 0; + } + while (time(nullptr) - startTime < MAX_SNAPSHOT_COUNT) { + int waitCount = 0; + while (!surfaceReaderHandler->IsImageOk()) { + waitCount++; + if (waitCount >= MAX_WAIT_COUNT) { + std::cout << "wait image overtime" << std::endl; + break; + } + usleep(SLEEP_US); + } + if (waitCount >= MAX_WAIT_COUNT) { + continue; + } + auto pixelMap = surfaceReaderHandler->GetPixelMap(); + bool ret = SnapShotUtils::WriteToJpegWithPixelMap(FILE_NAME + std::to_string(fileIndex) + ".jpeg", *pixelMap); + if (ret) { + std::cout << "snapshot "<< mainId << " write to " << + (FILE_NAME + std::to_string(fileIndex)).c_str() << " as jpeg" << std::endl; + } else { + std::cout << "snapshot "<< mainId << " write to " << + (FILE_NAME + std::to_string(fileIndex)).c_str() << " failed!" << std::endl; + } + surfaceReaderHandler->ResetFlag(); + fileIndex++; + } + ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId); + std::cout << "DestroyVirtualScreen " << virtualScreenId << std::endl; + return 0; +} diff --git a/window_manager/test/demo/demo_system_sub_window.cpp b/window_manager/test/demo/demo_system_sub_window.cpp new file mode 100644 index 0000000..c6075a9 --- /dev/null +++ b/window_manager/test/demo/demo_system_sub_window.cpp @@ -0,0 +1,111 @@ +/* + * 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 "window.h" +#include "wm_common.h" +#include "window_option.h" +#include "window_manager.h" + +#include "future.h" + +namespace OHOS { +namespace Rosen { +class SystemSubWindowFuture : public IVisibilityChangedListener { +using VisibleInfos = std::vector>; +public: + void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override + { + future_.SetValue(1); + }; + RunnableFuture future_; + static constexpr long WAIT_TIME = 20000; +}; +} +} + +using namespace OHOS; +using namespace OHOS::Rosen; + +void OutputWindowInfos(const std::vector>& infos) +{ + std::cout << "window tree infos length :" << infos.size() << std::endl; + std::cout << "windowId -- windowType -- displayId" << std::endl; + for (auto info: infos) { + std::cout << " " << info->wid_; + std::cout << " -- " << static_cast(info->type_); + std::cout << " -- " << std::to_string(info->displayId_); + std::cout << std::endl; + } +} + +int main(int argc, char *argv[]) +{ + std::cout << "===========================Start===========================" << std::endl; + std::cout << "Wait 20s, The Windows will close itself" << std::endl; + + std::vector> infos; + WindowManager::GetInstance().GetAccessibilityWindowInfo(infos); + std::cout << "before add window " << std::endl; + OutputWindowInfos(infos); + + Rect baseWindowRect = { 150, 150, 400, 600 }; + sptr baseOp = new WindowOption(); + baseOp->SetWindowType(WindowType::WINDOW_TYPE_FLOAT); + baseOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + baseOp->SetWindowRect(baseWindowRect); + + sptr window = Window::Create("Demo_SSW_BaseWindow", baseOp, nullptr); + window->Show(); + std::cout << "base window id = " << window->GetWindowId() << std::endl; + + Rect subWindowRect = { 200, 200, 150, 150 }; + sptr subWindowOp = new WindowOption(); + subWindowOp->SetWindowType(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW); + subWindowOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + subWindowOp->SetWindowRect(subWindowRect); + subWindowOp->SetParentId(window->GetWindowId()); + + sptr subWindow = Window::Create("Demo_SSW_SubWindow", subWindowOp, nullptr); + subWindow->Show(); + std::cout << "sub window id = " << subWindow->GetWindowId() << std::endl; + + infos.clear(); + WindowManager::GetInstance().GetAccessibilityWindowInfo(infos); + std::cout << "after add window:" << std::endl; + OutputWindowInfos(infos); + + std::cout << std::endl; + std::cout << "please check hidump to makesure the sub window node is on window tree" << std::endl; + sptr listener = new SystemSubWindowFuture(); + listener->future_.Reset(0); + listener->future_.GetResult(SystemSubWindowFuture::WAIT_TIME); + + subWindow->Hide(); + window->Hide(); + + subWindow->Destroy(); + window->Destroy(); + + infos.clear(); + WindowManager::GetInstance().GetAccessibilityWindowInfo(infos); + std::cout << "after destroy window:" << std::endl; + OutputWindowInfos(infos); + + std::cout << "============================End============================" << std::endl; + return 0; +} \ No newline at end of file diff --git a/window_manager/test/fuzztest/BUILD.gn b/window_manager/test/fuzztest/BUILD.gn new file mode 100644 index 0000000..b4beade --- /dev/null +++ b/window_manager/test/fuzztest/BUILD.gn @@ -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. + +config("configs_cc_ld") { + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] +} + +group("fuzztest") { + testonly = true + deps = [ + "dms:fuzztest", + "wms:fuzztest", + ] +} diff --git a/window_manager/test/fuzztest/dms/BUILD.gn b/window_manager/test/fuzztest/dms/BUILD.gn new file mode 100644 index 0000000..c6cb566 --- /dev/null +++ b/window_manager/test/fuzztest/dms/BUILD.gn @@ -0,0 +1,23 @@ +# 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. + +group("fuzztest") { + testonly = true + + deps = [ + "displaymanager_fuzzer:fuzztest", + "displaymanageripc_fuzzer:fuzztest", + "screen_fuzzer:fuzztest", + "screenmanager_fuzzer:fuzztest", + ] +} diff --git a/window_manager/test/fuzztest/dms/displaymanager_fuzzer/BUILD.gn b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/BUILD.gn new file mode 100644 index 0000000..9cf0531 --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/BUILD.gn @@ -0,0 +1,52 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/dms" + +##############################fuzztest########################################## +ohos_fuzztest("DisplayManagerFuzzTest") { + fuzz_config_file = "//foundation/window/window_manager/test/fuzztest/dms/displaymanager_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//commonlibrary/c_utils/base/include", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + sources = [ "displaymanager_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + ] + external_deps = [ "c_utils:utils" ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":DisplayManagerFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/dms/displaymanager_fuzzer/corpus/init b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.cpp b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.cpp new file mode 100644 index 0000000..543eed6 --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.cpp @@ -0,0 +1,188 @@ +/* + * 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 "displaymanager_fuzzer.h" + +#include +#include "display_manager.h" + +namespace OHOS ::Rosen { +class DisplayListener : public DisplayManager::IDisplayListener { +public: + virtual void OnCreate(DisplayId) override + { + } + virtual void OnDestroy(DisplayId) override + { + } + virtual void OnChange(DisplayId) override + { + } +}; + +class DisplayPowerEventListener : public IDisplayPowerEventListener { +public: + virtual void OnDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) override + { + } +}; + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +bool DisplayFuzzTest(const uint8_t* data, size_t size) +{ + DisplayId displayId; + ScreenId screenId; + if (data == nullptr || size < sizeof(displayId) + sizeof(screenId)) { + return false; + } + size_t startPos = 0; + DisplayManager& displayManager = DisplayManager::GetInstance(); + sptr displayListener = new DisplayListener(); + displayManager.GetAllDisplays(); + displayManager.GetAllDisplayIds(); + displayManager.GetDefaultDisplayId(); + displayManager.GetDefaultDisplay(); + + startPos += GetObject(displayId, data + startPos, size - startPos); + displayManager.GetDisplayById(displayId); + startPos += GetObject(screenId, data + startPos, size - startPos); + displayManager.GetDisplayByScreen(screenId); + displayManager.RegisterDisplayListener(displayListener); + displayManager.UnregisterDisplayListener(displayListener); + return true; +} + +bool GetScreenshotFuzzTest(const uint8_t* data, size_t size) +{ + DisplayId displayId; + Media::Rect rect; + Media::Size mediaSize; + int rotation; + if (data == nullptr || size < sizeof(displayId) + sizeof(rect) + sizeof(size) + sizeof(rotation)) { + return false; + } + size_t startPos = 0; + DisplayManager& displayManager = DisplayManager::GetInstance(); + startPos += GetObject(displayId, data + startPos, size - startPos); + displayManager.GetScreenshot(displayId); + startPos += GetObject(rect, data + startPos, size - startPos); + startPos += GetObject(mediaSize, data + startPos, size - startPos); + GetObject(rotation, data + startPos, size - startPos); + displayManager.GetScreenshot(displayId, rect, mediaSize, rotation); + return true; +} + +bool DisplayPowerFuzzTest(const uint8_t* data, size_t size) +{ + uint32_t reason; + DisplayId displayId; + uint32_t state; + if (data == nullptr || size < sizeof(reason) + sizeof(displayId) + sizeof(state)) { + return false; + } + size_t startPos = 0; + DisplayManager& displayManager = DisplayManager::GetInstance(); + sptr listener = new DisplayPowerEventListener(); + displayManager.RegisterDisplayPowerEventListener(listener); + + startPos += GetObject(reason, data + startPos, size - startPos); + displayManager.WakeUpBegin(static_cast(reason)); + displayManager.WakeUpEnd(); + displayManager.SuspendBegin(static_cast(reason)); + displayManager.SuspendEnd(); + + startPos += GetObject(state, data + startPos, size - startPos); + DisplayStateCallback callback = [](DisplayState state) { + }; + displayManager.SetDisplayState(static_cast(state), callback); + startPos += GetObject(displayId, data + startPos, size - startPos); + displayManager.GetDisplayState(displayId); + + displayManager.UnregisterDisplayPowerEventListener(listener); + return true; +} + +bool ScreenBrightnessFuzzTest(const uint8_t* data, size_t size) +{ + uint64_t screenId; + uint32_t level; + if (data == nullptr || size < sizeof(screenId) + sizeof(level)) { + return false; + } + size_t startPos = 0; + DisplayManager& displayManager = DisplayManager::GetInstance(); + + startPos += GetObject(screenId, data + startPos, size - startPos); + GetObject(level, data + startPos, size - startPos); + displayManager.SetScreenBrightness(screenId, level); + displayManager.GetScreenBrightness(screenId); + return true; +} + +bool FreezeFuzzTest(const uint8_t* data, size_t size) +{ + // 10 displays + if (data == nullptr || size < sizeof(DisplayId) * 10) { + return false; + } + size_t startPos = 0; + DisplayManager& displayManager = DisplayManager::GetInstance(); + // 10 displays + std::vector displays(10); + for (DisplayId& id : displays) { + startPos += GetObject(id, data + startPos, size - startPos); + } + displayManager.Freeze(displays); + displayManager.Unfreeze(displays); + return true; +} + +bool NotifyDisplayEventFuzzTest(const uint8_t* data, size_t size) +{ + // 10 displays + if (data == nullptr || size < sizeof(DisplayEvent)) { + return false; + } + size_t startPos = 0; + DisplayManager& displayManager = DisplayManager::GetInstance(); + uint32_t event; + GetObject(event, data + startPos, size - startPos); + displayManager.NotifyDisplayEvent(static_cast(event)); + return true; +} +} // namespace.OHOS::Rosen + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::Rosen::DisplayFuzzTest(data, size); + OHOS::Rosen::GetScreenshotFuzzTest(data, size); + OHOS::Rosen::DisplayPowerFuzzTest(data, size); + OHOS::Rosen::ScreenBrightnessFuzzTest(data, size); + OHOS::Rosen::FreezeFuzzTest(data, size); + OHOS::Rosen::NotifyDisplayEventFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.h b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.h new file mode 100644 index 0000000..35c8eed --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/displaymanager_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_DISPLAY_MANAGER_FUZZER_H +#define TEST_FUZZTEST_DISPLAY_MANAGER_FUZZER_H + +#define FUZZ_PROJECT_NAME "displaymanager_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/displaymanager_fuzzer/project.xml b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanager_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/BUILD.gn b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/BUILD.gn new file mode 100644 index 0000000..bbff643 --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/BUILD.gn @@ -0,0 +1,55 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/dms" + +##############################fuzztest########################################## +ohos_fuzztest("DisplayManagerIPCFuzzTest") { + fuzz_config_file = "//foundation/window/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/dm/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + sources = [ "displaymanageripc_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + ] + external_deps = [ + "ipc:ipc_core", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":DisplayManagerIPCFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/corpus/init b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.cpp b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.cpp new file mode 100644 index 0000000..dbce61d --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.cpp @@ -0,0 +1,230 @@ +/* + * 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 "displaymanageripc_fuzzer.h" + +#include +#include +#include +#include +#include + +#include "display_manager_interface.h" +#include "window_manager_hilog.h" + +namespace OHOS ::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerIPC_Fuzzer"}; +} +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +std::pair, sptr> GetProxy() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + WLOGFE("Failed to get system ability mgr."); + return { nullptr, nullptr }; + } + sptr remoteObject = systemAbilityManager->GetSystemAbility(DISPLAY_MANAGER_SERVICE_SA_ID); + if (!remoteObject) { + WLOGFE("Failed to get display manager service."); + return { nullptr, nullptr }; + } + sptr displayManagerServiceProxy = iface_cast(remoteObject); + if ((!displayManagerServiceProxy) || (!displayManagerServiceProxy->AsObject())) { + WLOGFE("Failed to get system display manager services"); + return { nullptr, nullptr }; + } + return { displayManagerServiceProxy, remoteObject }; +} + +bool IPCFuzzTest(const uint8_t* data, size_t size) +{ + std::set ignore = { + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_CREATE_VIRTUAL_SCREEN), + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE), + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_EXPAND), + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_MIRROR), + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_DISPLAY_SNAPSHOT) + }; + uint32_t code; + int flags, waitTime; + if (data == nullptr || size < sizeof(code) + sizeof(flags) + sizeof(waitTime)) { + return false; + } + auto proxy = GetProxy(); + if (proxy.first == nullptr || proxy.second == nullptr) { + return false; + } + size_t startPos = 0; + startPos += GetObject(code, data + startPos, size - startPos); + startPos += GetObject(flags, data + startPos, size - startPos); + startPos += GetObject(waitTime, data + startPos, size - startPos); + MessageParcel sendData; + MessageParcel reply; + MessageOption option(flags, waitTime); + if (ignore.find(code) != ignore.end()) { + return false; + } + uint32_t dataSize = (size - startPos) > 1024 * 1024 ? 1024 * 1024 : (size - startPos); + sendData.WriteBuffer(data + startPos, dataSize); + proxy.second->SendRequest(code, sendData, reply, option); + return true; +} + +void IPCSpecificInterfaceFuzzTest1(sptr proxy, MessageParcel& sendData, MessageParcel& reply, + MessageOption& option) +{ + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_DEFAULT_DISPLAY_INFO), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_DISPLAY_BY_ID), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_DISPLAY_BY_SCREEN), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_REGISTER_DISPLAY_MANAGER_AGENT), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_UNREGISTER_DISPLAY_MANAGER_AGENT), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_WAKE_UP_BEGIN), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_WAKE_UP_END), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SUSPEND_BEGIN), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SUSPEND_END), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_SCREEN_POWER_FOR_ALL), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_DISPLAY_STATE), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_DISPLAY_STATE), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_ALL_DISPLAYIDS), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_SCREEN_POWER), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_DISPLAY_STATE), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_DISPLAY_STATE), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_ALL_DISPLAYIDS), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_NOTIFY_DISPLAY_EVENT), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_NOTIFY_DISPLAY_EVENT), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_ALL_DISPLAYIDS), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_NOTIFY_DISPLAY_EVENT), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_FREEZE_EVENT), + sendData, reply, option); +} + +void IPCSpecificInterfaceFuzzTest2(sptr proxy, MessageParcel& sendData, MessageParcel& reply, + MessageOption& option, sptr manager) +{ + int flags = option.GetFlags(); + option.SetFlags(MessageOption::TF_SYNC); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_CREATE_VIRTUAL_SCREEN), + sendData, reply, option); + manager->DestroyVirtualScreen(static_cast(reply.ReadUint64())); + option.SetFlags(flags); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_DESTROY_VIRTUAL_SCREEN), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_SCREEN_SURFACE), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_SCREEN_INFO_BY_ID), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_SCREEN_GROUP_INFO_BY_ID), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_SCREEN_ACTIVE_MODE), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_GET_ALL_SCREEN_INFOS), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_ORIENTATION), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SET_VIRTUAL_PIXEL_RATIO), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_MIRROR), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_MAKE_EXPAND), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_REMOVE_VIRTUAL_SCREEN_FROM_SCREEN_GROUP), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_GET_SUPPORTED_COLOR_GAMUTS), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_GET_COLOR_GAMUT), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_SET_COLOR_GAMUT), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_GET_GAMUT_MAP), + sendData, reply, option); + proxy->SendRequest(static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_SET_GAMUT_MAP), + sendData, reply, option); + proxy->SendRequest( + static_cast(IDisplayManager::DisplayManagerMessage::TRANS_ID_SCREEN_SET_COLOR_TRANSFORM), + sendData, reply, option); +} + +bool IPCInterfaceFuzzTest(const uint8_t* data, size_t size) +{ + int flags, waitTime; + if (data == nullptr || size < sizeof(flags) + sizeof(waitTime)) { + return false; + } + auto proxy = GetProxy(); + if (proxy.first == nullptr || proxy.second == nullptr) { + return false; + } + size_t startPos = 0; + startPos += GetObject(flags, data + startPos, size - startPos); + startPos += GetObject(waitTime, data + startPos, size - startPos); + MessageParcel sendData; + MessageParcel reply; + MessageOption option(flags, waitTime); + sendData.WriteInterfaceToken(proxy.first->GetDescriptor()); + uint32_t dataSize = (size - startPos) > 1024 * 1024 ? 1024 * 1024 : (size - startPos); + sendData.WriteBuffer(data + startPos, dataSize); + IPCSpecificInterfaceFuzzTest1(proxy.second, sendData, reply, option); + IPCSpecificInterfaceFuzzTest2(proxy.second, sendData, reply, option, proxy.first); + return true; +} +} // namespace.OHOS::Rosen + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::Rosen::IPCFuzzTest(data, size); + OHOS::Rosen::IPCInterfaceFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.h b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.h new file mode 100644 index 0000000..57070d2 --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/displaymanageripc_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_DISPLAY_MANAGER_IPC_FUZZER_H +#define TEST_FUZZTEST_DISPLAY_MANAGER_IPC_FUZZER_H + +#define FUZZ_PROJECT_NAME "displaymanageripc_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/project.xml b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/dms/displaymanageripc_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/dms/screen_fuzzer/BUILD.gn b/window_manager/test/fuzztest/dms/screen_fuzzer/BUILD.gn new file mode 100644 index 0000000..e4cb388 --- /dev/null +++ b/window_manager/test/fuzztest/dms/screen_fuzzer/BUILD.gn @@ -0,0 +1,55 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/dms" + +##############################fuzztest########################################## +ohos_fuzztest("ScreenFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/dms/screen_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//commonlibrary/c_utils/base/include", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "screen_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + ] + external_deps = [ "c_utils:utils" ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":ScreenFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/dms/screen_fuzzer/corpus/init b/window_manager/test/fuzztest/dms/screen_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/dms/screen_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/screen_fuzzer/project.xml b/window_manager/test/fuzztest/dms/screen_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/dms/screen_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.cpp b/window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.cpp new file mode 100644 index 0000000..b1076f6 --- /dev/null +++ b/window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.cpp @@ -0,0 +1,186 @@ +/* + * 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 "screen_fuzzer.h" + +#include +#include + +#include "display_manager.h" +#include "display.h" +#include "dm_common.h" +#include "screen.h" +#include "screen_info.h" +#include "screen_manager.h" + +namespace OHOS::Rosen { + +namespace { + constexpr char END_CHAR = '\0'; + constexpr size_t LEN = 10; +} +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +sptr CreateScreenInfo(const uint8_t *data, size_t size) +{ + sptr info = new(std::nothrow) ScreenInfo(); + if (info == nullptr) { + return nullptr; + } + size_t startPos = 0; + char name[LEN + 1]; + name[LEN] = END_CHAR; + for (size_t i = 0; i < LEN; i++) { + startPos += GetObject(name[i], data + startPos, size - startPos); + } + std::string windowName(name); + info->name_ = windowName; + startPos += GetObject(info->id_, data + startPos, size - startPos); + startPos += GetObject(info->virtualWidth_, data + startPos, size - startPos); + startPos += GetObject(info->virtualHeight_, data + startPos, size - startPos); + startPos += GetObject(info->virtualPixelRatio_, data + startPos, size - startPos); + startPos += GetObject(info->lastParent_, data + startPos, size - startPos); + startPos += GetObject(info->parent_, data + startPos, size - startPos); + startPos += GetObject(info->isScreenGroup_, data + startPos, size - startPos); + startPos += GetObject(info->rotation_, data + startPos, size - startPos); + startPos += GetObject(info->orientation_, data + startPos, size - startPos); + startPos += GetObject(info->type_, data + startPos, size - startPos); + GetObject(info->modeId_, data + startPos, size - startPos); + return info; +} +bool ScreenFuzzTest(sptr screen, sptr display, const uint8_t *data, size_t size) +{ + if (screen == nullptr || display == nullptr) { + return false; + } + uint32_t modeId; + Orientation orientation; + size_t minSize = sizeof(modeId) + sizeof(orientation); + if (data == nullptr || size < minSize) { + return false; + } + size_t startPos = 0; + uint32_t originalDensityDpi = static_cast(display->GetVirtualPixelRatio() * DOT_PER_INCH); + uint32_t modifiedDensityDpi = static_cast( + originalDensityDpi + 80 >= 640 ? originalDensityDpi - 80 : originalDensityDpi + 80); + startPos += GetObject(modeId, data + startPos, size - startPos); + GetObject(orientation, data + startPos, size - startPos); + screen->SetScreenActiveMode(modeId); + screen->SetOrientation(orientation); + screen->SetDensityDpi(modifiedDensityDpi); + screen->SetScreenActiveMode(0); + screen->SetOrientation(Orientation::UNSPECIFIED); + screen->SetDensityDpi(originalDensityDpi); + return true; +} + +bool ScreenFuzzTestNoDisplay(sptr screen, const uint8_t *data, size_t size) +{ + if (screen == nullptr) { + return false; + } + uint32_t modeId; + Orientation orientation; + uint32_t originalDensityDpi = 0; + uint32_t modifiedDensityDpi = 0; + size_t minSize = sizeof(modeId) + sizeof(orientation) + sizeof(originalDensityDpi) + + sizeof(modifiedDensityDpi); + if (data == nullptr || size < minSize) { + return false; + } + size_t startPos = 0; + GetObject(originalDensityDpi, data + startPos, size - startPos); + GetObject(modifiedDensityDpi, data + startPos, size - startPos); + startPos += GetObject(modeId, data + startPos, size - startPos); + GetObject(orientation, data + startPos, size - startPos); + screen->SetScreenActiveMode(modeId); + screen->SetOrientation(orientation); + screen->SetDensityDpi(modifiedDensityDpi); + screen->SetScreenActiveMode(0); + screen->SetOrientation(Orientation::UNSPECIFIED); + screen->SetDensityDpi(originalDensityDpi); + return true; +} + +bool ColorGamutsFuzzTest(sptr screen, const uint8_t *data, size_t size) +{ + if (screen == nullptr) { + return false; + } + int32_t colorGamutIdx; + uint32_t gamutMap; + if (data == nullptr || size < sizeof(colorGamutIdx) + sizeof(gamutMap)) { + return false; + } + size_t startPos = 0; + startPos += GetObject(colorGamutIdx, data + startPos, size - startPos); + GetObject(gamutMap, data + startPos, size - startPos); + std::vector colorGamuts; + screen->GetScreenSupportedColorGamuts(colorGamuts); + size_t colorGamutsSize = colorGamuts.size(); + if (colorGamutsSize == 0) { + return false; + } + int32_t index = colorGamutIdx % colorGamutsSize; + screen->SetScreenColorGamut(index); + ScreenColorGamut colorGamut; + screen->GetScreenColorGamut(colorGamut); + // It is necessary to judge whether colorGamuts[index] and colorGamut are equal. + screen->SetScreenGamutMap(static_cast(gamutMap)); + ScreenGamutMap screenGamutMap; + screen->GetScreenGamutMap(screenGamutMap); + // It is necessary to judge whether gamutMap and screenGamutMap are equal. + return true; +} + +void DoMyFuzzTest(const uint8_t* data, size_t size) +{ + DisplayManager& displayManager = DisplayManager::GetInstance(); + sptr display = displayManager.GetDefaultDisplay(); + + sptr screen = nullptr; + if (display != nullptr) { + ScreenId screenId = display->GetScreenId(); + screen = ScreenManager::GetInstance().GetScreenById(screenId); + } else { + sptr info = CreateScreenInfo(data, size); + screen = new (std::nothrow) Screen(info); + } + if (display == nullptr) { + ScreenFuzzTestNoDisplay(screen, data, size); + } else { + ScreenFuzzTest(screen, display, data, size); + } + ColorGamutsFuzzTest(screen, data, size); +} + +} // namespace.OHOS::Rosen + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::Rosen::DoMyFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.h b/window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.h new file mode 100644 index 0000000..6a95d47 --- /dev/null +++ b/window_manager/test/fuzztest/dms/screen_fuzzer/screen_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_SCREEN_FUZZER_H +#define TEST_FUZZTEST_SCREEN_FUZZER_H + +#define FUZZ_PROJECT_NAME "screen_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/screenmanager_fuzzer/BUILD.gn b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/BUILD.gn new file mode 100644 index 0000000..e45c77c --- /dev/null +++ b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/BUILD.gn @@ -0,0 +1,52 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/dms" + +##############################fuzztest########################################## +ohos_fuzztest("ScreenManagerFuzzTest") { + fuzz_config_file = "//foundation/window/window_manager/test/fuzztest/dms/screenmanager_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//commonlibrary/c_utils/base/include", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + sources = [ "screenmanager_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + ] + external_deps = [ "c_utils:utils" ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":ScreenManagerFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/dms/screenmanager_fuzzer/corpus/init b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/dms/screenmanager_fuzzer/project.xml b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.cpp b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.cpp new file mode 100644 index 0000000..b583fee --- /dev/null +++ b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.cpp @@ -0,0 +1,300 @@ +/* + * 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 "screenmanager_fuzzer.h" + +#include +#include + +#include "dm_common.h" +#include "screen.h" +#include "screen_manager.h" + +namespace OHOS::Rosen { +class ScreenListener : public ScreenManager::IScreenListener { +public: + virtual void OnConnect(ScreenId screenId) override + { + }; + + virtual void OnDisconnect(ScreenId screenId) override + { + } + + virtual void OnChange(ScreenId screenId) override + { + } +}; + +class ScreenGroupListener : public ScreenManager::IScreenGroupListener { +public: + virtual void OnChange(const std::vector& screenIds, ScreenGroupChangeEvent event) override + { + } +}; + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +bool ScreenPowerFuzzTest(const uint8_t *data, size_t size) +{ + uint32_t screenPowerState; + uint32_t powerStateChangeReason; + if (data == nullptr || size < sizeof(screenPowerState) + sizeof(powerStateChangeReason)) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + sptr screenListener = new ScreenListener(); + screenManager.RegisterScreenListener(screenListener); + sptr screenGroupListener = new ScreenGroupListener(); + screenManager.RegisterScreenGroupListener(screenGroupListener); + + startPos += GetObject(screenPowerState, data + startPos, size - startPos); + startPos += GetObject(powerStateChangeReason, data + startPos, size - startPos); + screenManager.SetScreenPowerForAll(static_cast(screenPowerState), + static_cast(startPos)); + auto allScreen = screenManager.GetAllScreens(); + for (auto screen: allScreen) { + screenManager.GetScreenPower(screen->GetId()); + } + + screenManager.UnregisterScreenGroupListener(screenGroupListener); + screenManager.UnregisterScreenListener(screenListener); + return true; +} + +bool MakeMirrorWithVirtualScreenFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr || size < sizeof(VirtualScreenOption)) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + sptr screenListener = new ScreenListener(); + screenManager.RegisterScreenListener(screenListener); + sptr screenGroupListener = new ScreenGroupListener(); + screenManager.RegisterScreenGroupListener(screenGroupListener); + + std::string name = "screen"; + VirtualScreenOption option = { name }; + startPos += GetObject(option.width_, data + startPos, size - startPos); + startPos += GetObject(option.height_, data + startPos, size - startPos); + startPos += GetObject(option.density_, data + startPos, size - startPos); + startPos += GetObject(option.flags_, data + startPos, size - startPos); + GetObject(option.isForShot_, data + startPos, size - startPos); + ScreenId screenId = screenManager.CreateVirtualScreen(option); + if (screenId == SCREEN_ID_INVALID) { + return false; + } + screenManager.SetVirtualScreenSurface(screenId, nullptr); + + // make mirror + ScreenId groupId = screenManager.MakeMirror(0, { screenId }); + if (groupId == SCREEN_ID_INVALID) { + screenManager.DestroyVirtualScreen(screenId); + return false; + } + sptr group = screenManager.GetScreenGroup(groupId); + if (group == nullptr) { + screenManager.DestroyVirtualScreen(screenId); + return false; + } + std::vector ids = group->GetChildIds(); + screenManager.RemoveVirtualScreenFromGroup(ids); + screenManager.DestroyVirtualScreen(screenId); + screenManager.UnregisterScreenGroupListener(screenGroupListener); + screenManager.UnregisterScreenListener(screenListener); + return true; +} + +bool MakeExpandWithVirtualScreenFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr || size < sizeof(VirtualScreenOption)) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + sptr screenListener = new ScreenListener(); + screenManager.RegisterScreenListener(screenListener); + sptr screenGroupListener = new ScreenGroupListener(); + screenManager.RegisterScreenGroupListener(screenGroupListener); + + std::string name = "screen"; + VirtualScreenOption option = { name }; + startPos += GetObject(option.width_, data + startPos, size - startPos); + startPos += GetObject(option.height_, data + startPos, size - startPos); + startPos += GetObject(option.density_, data + startPos, size - startPos); + startPos += GetObject(option.flags_, data + startPos, size - startPos); + GetObject(option.isForShot_, data + startPos, size - startPos); + ScreenId screenId = screenManager.CreateVirtualScreen(option); + if (screenId == SCREEN_ID_INVALID) { + return false; + } + screenManager.SetVirtualScreenSurface(screenId, nullptr); + // make expand + std::vector options = {{0, 0, 0}, {screenId, 0, 0}}; + ScreenId groupId = screenManager.MakeExpand(options); + if (groupId == SCREEN_ID_INVALID) { + screenManager.DestroyVirtualScreen(screenId); + return false; + } + sptr group = screenManager.GetScreenGroup(groupId); + if (group == nullptr) { + screenManager.DestroyVirtualScreen(screenId); + return false; + } + std::vector ids = group->GetChildIds(); + screenManager.RemoveVirtualScreenFromGroup(ids); + screenManager.DestroyVirtualScreen(screenId); + screenManager.UnregisterScreenGroupListener(screenGroupListener); + screenManager.UnregisterScreenListener(screenListener); + return true; +} + +bool CreateAndDestroyVirtualScreenFuzzTest(const uint8_t *data, size_t size) +{ + if (data == nullptr || size < sizeof(VirtualScreenOption)) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + sptr screenListener = new ScreenListener(); + screenManager.RegisterScreenListener(screenListener); + sptr screenGroupListener = new ScreenGroupListener(); + screenManager.RegisterScreenGroupListener(screenGroupListener); + + std::string name = "screen"; + VirtualScreenOption option = { name }; + startPos += GetObject(option.width_, data + startPos, size - startPos); + startPos += GetObject(option.height_, data + startPos, size - startPos); + startPos += GetObject(option.density_, data + startPos, size - startPos); + startPos += GetObject(option.flags_, data + startPos, size - startPos); + startPos += GetObject(option.isForShot_, data + startPos, size - startPos); + ScreenId screenId = screenManager.CreateVirtualScreen(option); + if (screenId == SCREEN_ID_INVALID) { + return false; + } + screenManager.DestroyVirtualScreen(screenId); + GetObject(screenId, data + startPos, size - startPos); + screenManager.DestroyVirtualScreen(screenId); + screenManager.UnregisterScreenGroupListener(screenGroupListener); + screenManager.UnregisterScreenListener(screenListener); + return true; +} + +bool SetVirtualScreenSurfaceFuzzTest(const uint8_t *data, size_t size) +{ + ScreenId screenId; + if (data == nullptr || size < sizeof(screenId)) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + GetObject(screenId, data + startPos, size - startPos); + screenManager.SetVirtualScreenSurface(screenId, nullptr); + return true; +} + +bool RemoveVirtualScreenFromGroupFuzzTest(const uint8_t *data, size_t size) +{ + ScreenId screenId; + if (data == nullptr || size < sizeof(screenId)) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + GetObject(screenId, data + startPos, size - startPos); + std::vector screenIds = {screenId, screenId, screenId}; + screenManager.RemoveVirtualScreenFromGroup(screenIds); + return true; +} + +bool MakeMirrorFuzzTest(const uint8_t *data, size_t size) +{ + ScreenId screenId; + // 10 screens. + if (data == nullptr || size < sizeof(ScreenId) * 10) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + sptr screenListener = new ScreenListener(); + screenManager.RegisterScreenListener(screenListener); + sptr screenGroupListener = new ScreenGroupListener(); + screenManager.RegisterScreenGroupListener(screenGroupListener); + + std::vector screenIds; + // 10 screens + for (size_t i = 0; i < 10; i++) { + startPos += GetObject(screenId, data + startPos, size - startPos); + screenIds.emplace_back(screenId); + } + GetObject(screenId, data + startPos, size - startPos); + screenManager.MakeMirror(screenId, screenIds); + screenManager.UnregisterScreenGroupListener(screenGroupListener); + screenManager.UnregisterScreenListener(screenListener); + return true; +} + +bool MakeExpandFuzzTest(const uint8_t *data, size_t size) +{ + ScreenId screenId; + // 10 screens. + if (data == nullptr || size < sizeof(ScreenId) * 10) { + return false; + } + size_t startPos = 0; + ScreenManager &screenManager = ScreenManager::GetInstance(); + sptr screenListener = new ScreenListener(); + screenManager.RegisterScreenListener(screenListener); + sptr screenGroupListener = new ScreenGroupListener(); + screenManager.RegisterScreenGroupListener(screenGroupListener); + std::vector options; + // 10 screens + for (size_t i = 0; i < 10; i++) { + startPos += GetObject(screenId, data + startPos, size - startPos); + ExpandOption option = {screenId, 0, 0}; + options.emplace_back(option); + } + screenManager.MakeExpand(options); + screenManager.UnregisterScreenGroupListener(screenGroupListener); + screenManager.UnregisterScreenListener(screenListener); + return true; +} +} // namespace.OHOS::Rosen + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::Rosen::ScreenPowerFuzzTest(data, size); + OHOS::Rosen::MakeMirrorWithVirtualScreenFuzzTest(data, size); + OHOS::Rosen::MakeMirrorFuzzTest(data, size); + OHOS::Rosen::MakeExpandWithVirtualScreenFuzzTest(data, size); + OHOS::Rosen::MakeExpandFuzzTest(data, size); + OHOS::Rosen::CreateAndDestroyVirtualScreenFuzzTest(data, size); + OHOS::Rosen::SetVirtualScreenSurfaceFuzzTest(data, size); + OHOS::Rosen::RemoveVirtualScreenFromGroupFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.h b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.h new file mode 100644 index 0000000..19765f0 --- /dev/null +++ b/window_manager/test/fuzztest/dms/screenmanager_fuzzer/screenmanager_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_SCREEN_MANAGER_FUZZER_H +#define TEST_FUZZTEST_SCREEN_MANAGER_FUZZER_H + +#define FUZZ_PROJECT_NAME "screenmanager_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/BUILD.gn b/window_manager/test/fuzztest/wms/BUILD.gn new file mode 100644 index 0000000..64d4a63 --- /dev/null +++ b/window_manager/test/fuzztest/wms/BUILD.gn @@ -0,0 +1,28 @@ +# 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. + +group("fuzztest") { + testonly = true + + deps = [ + "window_fuzzer:fuzztest", + "windowagent_fuzzer:fuzztest", + "windowcontroller_fuzzer:fuzztest", + "windowipc_fuzzer:fuzztest", + "windowmanager_fuzzer:fuzztest", + "windowroot_fuzzer:fuzztest", + "windowpair_fuzzer:fuzztest", + "windowscene_fuzzer:fuzztest", + "windowutilmath_fuzzer:fuzztest", + ] +} diff --git a/window_manager/test/fuzztest/wms/window_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/window_fuzzer/BUILD.gn new file mode 100644 index 0000000..3dfe8c1 --- /dev/null +++ b/window_manager/test/fuzztest/wms/window_fuzzer/BUILD.gn @@ -0,0 +1,82 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/wms/window_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//commonlibrary/c_utils/base/include", + + # for abilityContext + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "//base/global/resource_management/interfaces/inner_api/include", + "//third_party/node/deps/icu-small/source/common", + "${ability_runtime_inner_api_path}/ability_manager/include", + + # abilityContext end + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "window_fuzzer.cpp" ] + deps = [ + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/wm:libwm", + ] + + public_deps = [ "//foundation/arkui/napi:ace_napi" ] + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ace_engine:ace_uicontent", + "c_utils:utils", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hilog_native:libhilog", + "input:libmmi-client", + "ipc:ipc_core", + "multimedia_image_framework:image_native", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/window_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/window_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/window_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/window_fuzzer/project.xml b/window_manager/test/fuzztest/wms/window_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/window_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.cpp b/window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.cpp new file mode 100644 index 0000000..92ffe4c --- /dev/null +++ b/window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.cpp @@ -0,0 +1,424 @@ +/* + * 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 "marshalling_helper.h" + +#include + +#include +#include "window.h" +#include "window_impl.h" +#include "window_manager.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; +} +class FocusChangedListener : public IFocusChangedListener { +public: + virtual void OnFocused(const sptr& focusChangeInfo) override + { + } + + virtual void OnUnfocused(const sptr& focusChangeInfo) override + { + } +}; + +class SystemBarChangedListener : public ISystemBarChangedListener { +public: + virtual void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override + { + } +}; + +class VisibilityChangedListener : public IVisibilityChangedListener { +public: + virtual void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override + { + } +}; + +class WindowUpdateListener : public IWindowUpdateListener { +public: + virtual void OnWindowUpdate(const std::vector>& infos, WindowUpdateType type) override + { + } +}; + +bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + std::string name = "WindowFuzzTest"; + sptr option = nullptr; + sptr window = Window::Create(name, option); + if (window == nullptr) { + return false; + } + window->Show(0); + Orientation orientation = static_cast(data[0]); + window->SetRequestedOrientation(static_cast(data[0])); + if (window->GetRequestedOrientation() != orientation) { + return false; + } + window->Hide(0); + window->Destroy(); + return true; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +void CheckWindowImplFunctionsPart1(sptr window, const uint8_t* data, size_t size) +{ + if (window == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + bool boolVal = false; + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetFocusable(boolVal); + window->IsFocused(); + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetTouchable(boolVal); + + WindowType windowType; + WindowMode windowMode; + startPos += GetObject(windowType, data + startPos, size - startPos); + startPos += GetObject(windowMode, data + startPos, size - startPos); + window->SetWindowType(windowType); + window->SetWindowMode(windowMode); + + float alpha; + startPos += GetObject(alpha, data + startPos, size - startPos); + window->SetAlpha(alpha); + + Transform transForm; + startPos += GetObject(transForm, data + startPos, size - startPos); + window->SetTransform(transForm); + + WindowFlag windowFlag; + startPos += GetObject(windowFlag, data + startPos, size - startPos); + window->AddWindowFlag(windowFlag); + startPos += GetObject(windowFlag, data + startPos, size - startPos); + window->RemoveWindowFlag(windowFlag); + + SystemBarProperty systemBarProperty; + startPos += GetObject(windowType, data + startPos, size - startPos); + startPos += GetObject(systemBarProperty, data + startPos, size - startPos); + window->SetSystemBarProperty(windowType, systemBarProperty); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetLayoutFullScreen(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetFullScreen(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->UpdateSurfaceNodeAfterCustomAnimation(boolVal); +} + +void CheckWindowImplFunctionsPart2(sptr window, const uint8_t* data, size_t size) +{ + if (window == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + int32_t posX; + int32_t posY; + startPos += GetObject(posX, data + startPos, size - startPos); + startPos += GetObject(posY, data + startPos, size - startPos); + window->MoveTo(posX, posY); + + uint32_t width; + uint32_t hight; + startPos += GetObject(width, data + startPos, size - startPos); + startPos += GetObject(hight, data + startPos, size - startPos); + window->Resize(width, hight); + + bool boolVal = false; + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetKeepScreenOn(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetTurnScreenOn(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetTransparent(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetBrightness(boolVal); + + int32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + window->SetCallingWindow(windowId); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetPrivacyMode(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetSystemPrivacyMode(boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetSnapshotSkip(boolVal); +} + +void CheckWindowImplFunctionsPart3(sptr window, const uint8_t* data, size_t size) +{ + if (window == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + float floatVal; + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->SetCornerRadius(floatVal); + + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->SetShadowRadius(floatVal); + + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->SetShadowOffsetX(floatVal); + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->SetShadowOffsetY(floatVal); + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->SetBlur(floatVal); + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->SetBackdropBlur(floatVal); + + WindowBlurStyle blurStyle; + startPos += GetObject(blurStyle, data + startPos, size - startPos); + window->SetBackdropBlurStyle(blurStyle); + + bool boolVal; + OHOS::Rosen::Rect rect; + WindowSizeChangeReason reason; + startPos += GetObject(boolVal, data + startPos, size - startPos); + startPos += GetObject(rect, data + startPos, size - startPos); + startPos += GetObject(reason, data + startPos, size - startPos); + window->UpdateRect(rect, boolVal, reason); + + WindowMode mode; + startPos += GetObject(mode, data + startPos, size - startPos); + window->UpdateMode(mode); + + uint32_t modeSupportInfo; + startPos += GetObject(modeSupportInfo, data + startPos, size - startPos); + window->UpdateModeSupportInfo(modeSupportInfo); + + WindowState windowState; + startPos += GetObject(windowState, data + startPos, size - startPos); + window->UpdateWindowState(windowState); + + PointInfo point; + DragEvent event; + startPos += GetObject(point, data + startPos, size - startPos); + startPos += GetObject(event, data + startPos, size - startPos); + window->UpdateDragEvent(point, event); + + DisplayId displayId[2]; + startPos += GetObject(displayId[0], data + startPos, size - startPos); + startPos += GetObject(displayId[1], data + startPos, size - startPos); + window->UpdateDisplayId(displayId[0], displayId[1]); +} + +void CheckWindowImplFunctionsPart4(sptr window, const uint8_t* data, size_t size) +{ + if (window == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + bool boolVal; + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->UpdateActiveStatus(boolVal); + + Transform trans; + startPos += GetObject(trans, data + startPos, size - startPos); + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->UpdateZoomTransform(trans, boolVal); + + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->SetNeedRemoveWindowInputChannel(boolVal); + + std::vector rectVector; + OHOS::Rosen::Rect rect; + startPos += GetObject(rect, data + startPos, size - startPos); + rectVector.emplace_back(rect); + window->SetTouchHotAreas(rectVector); + window->GetRequestedTouchHotAreas(rectVector); + rectVector.clear(); + + ColorSpace colorSpace; + startPos += GetObject(colorSpace, data + startPos, size - startPos); + window->SetColorSpace(colorSpace); + + int32_t level; + startPos += GetObject(level, data + startPos, size - startPos); + window->NotifyMemoryLevel(level); + + uint32_t mode; + startPos += GetObject(mode, data + startPos, size - startPos); + window->RestoreSplitWindowMode(mode); +} + +void CheckWindowImplFunctionsPart5(sptr window, const uint8_t* data, size_t size) +{ + if (window == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + OHOS::Rosen::Rect rect; + WindowSizeChangeReason reason; + startPos += GetObject(rect, data + startPos, size - startPos); + startPos += GetObject(reason, data + startPos, size - startPos); + window->NotifySizeChange(rect, reason); + + DisplayId displayId[2]; + startPos += GetObject(displayId[0], data + startPos, size - startPos); + startPos += GetObject(displayId[1], data + startPos, size - startPos); + window->NotifyDisplayMoveChange(displayId[0], displayId[1]); + + WindowMode mode; + startPos += GetObject(mode, data + startPos, size - startPos); + window->NotifyModeChange(mode); + + PointInfo point; + DragEvent dragEvent; + startPos += GetObject(point, data + startPos, size - startPos); + startPos += GetObject(dragEvent, data + startPos, size - startPos); + window->NotifyDragEvent(point, dragEvent); + + int32_t posX; + int32_t posY; + int32_t pointId; + int32_t sourceType; + startPos += GetObject(posX, data + startPos, size - startPos); + startPos += GetObject(posY, data + startPos, size - startPos); + startPos += GetObject(pointId, data + startPos, size - startPos); + startPos += GetObject(sourceType, data + startPos, size - startPos); + window->EndMoveOrDragWindow(posX, posY, pointId, sourceType); + window->IsPointInDragHotZone(posX, posY); + + bool boolVal; + startPos += GetObject(boolVal, data + startPos, size - startPos); + window->AdjustWindowAnimationFlag(boolVal); + + PropertyChangeAction action; + startPos += GetObject(action, data + startPos, size - startPos); + window->UpdateProperty(action); + + uint32_t uinte32Val; + startPos += GetObject(uinte32Val, data + startPos, size - startPos); + window->SetBackgroundColor(uinte32Val); + + LifeCycleEvent lifeCycleEvent; + OHOS::Rosen::WMError errCode; + startPos += GetObject(lifeCycleEvent, data + startPos, size - startPos); + startPos += GetObject(errCode, data + startPos, size - startPos); + window->RecordLifeCycleExceptionEvent(lifeCycleEvent, errCode); + window->TransferLifeCycleEventToString(lifeCycleEvent); + + startPos += GetObject(rect, data + startPos, size - startPos); + window->GetSystemAlarmWindowDefaultSize(rect); + window->HandleModeChangeHotZones(posX, posY); +} + + +void CheckWindowImplFunctionsPart6(sptr window, const uint8_t* data, size_t size) +{ + if (window == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + TransitionReason reason; + startPos += GetObject(reason, data + startPos, size - startPos); + window->NotifyWindowTransition(reason); + + WindowType type; + startPos += GetObject(type, data + startPos, size - startPos); + window->CheckCameraFloatingWindowMultiCreated(type); + + uint32_t uint32Val[2]; + startPos += GetObject(uint32Val[0], data + startPos, size - startPos); + startPos += GetObject(uint32Val[1], data + startPos, size - startPos); + window->SetModeSupportInfo(uint32Val[0]); + + float floatVal; + startPos += GetObject(floatVal, data + startPos, size - startPos); + window->CalculateStartRectExceptHotZone(floatVal); + + Transform transform; + startPos += GetObject(transform, data + startPos, size - startPos); + window->TransformSurfaceNode(transform); + + window->WindowCreateCheck(uint32Val[0]); + window->CalculatePointerDirection(uint32Val[0], uint32Val[1]); +} + +void WindowImplFuzzTest(const uint8_t* data, size_t size) +{ + std::string name = "WindowFuzzTest"; + sptr option = new OHOS::Rosen::WindowOption(); + sptr window = new(std::nothrow) OHOS::Rosen::WindowImpl(option); + if (window == nullptr) { + return; + } + OHOS::Rosen::WMError error = window->Create(option->GetParentId(), nullptr); + if (error != OHOS::Rosen::WMError::WM_OK) { + return; + } + + size_t startPos = 0; + uint32_t reason = 0; + bool withAnimation = false; + startPos += GetObject(reason, data + startPos, size - startPos); + startPos += GetObject(withAnimation, data + startPos, size - startPos); + window->Show(reason, withAnimation); + + OHOS::CheckWindowImplFunctionsPart1(window, data, size); + OHOS::CheckWindowImplFunctionsPart2(window, data, size); + OHOS::CheckWindowImplFunctionsPart3(window, data, size); + OHOS::CheckWindowImplFunctionsPart4(window, data, size); + OHOS::CheckWindowImplFunctionsPart5(window, data, size); + OHOS::CheckWindowImplFunctionsPart6(window, data, size); + + window->Hide(reason, withAnimation); + window->Destroy(); +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + OHOS::WindowImplFuzzTest(data, size); + return 0; +} \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.h b/window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.h new file mode 100644 index 0000000..d559d07 --- /dev/null +++ b/window_manager/test/fuzztest/wms/window_fuzzer/window_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_FUZZER_H +#define TEST_FUZZTEST_WINDOW_FUZZER_H + +#define FUZZ_PROJECT_NAME "window_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowagent_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowagent_fuzzer/BUILD.gn new file mode 100644 index 0000000..c4ca1c0 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowagent_fuzzer/BUILD.gn @@ -0,0 +1,82 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowAgentFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/wms/windowagent_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//commonlibrary/c_utils/base/include", + + # for abilityContext + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "//base/global/resource_management/interfaces/inner_api/include", + "//third_party/node/deps/icu-small/source/common", + "${ability_runtime_inner_api_path}/ability_manager/include", + + # abilityContext end + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "window_agent_fuzzer.cpp" ] + deps = [ + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/wm:libwm", + ] + + public_deps = [ "//foundation/arkui/napi:ace_napi" ] + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ace_engine:ace_uicontent", + "c_utils:utils", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hilog_native:libhilog", + "input:libmmi-client", + "ipc:ipc_core", + "multimedia_image_framework:image_native", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowAgentFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowagent_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowagent_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowagent_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowagent_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowagent_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowagent_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.cpp new file mode 100644 index 0000000..fed978e --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.cpp @@ -0,0 +1,157 @@ +/* + * 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 "marshalling_helper.h" +#include + +#include + +#include +#include "window.h" +#include "window_agent.h" +#include "window_impl.h" +#include "window_manager.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +void CheckWindowAgentFunctionsPart1(sptr agent, const uint8_t* data, size_t size) +{ + if (agent == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + OHOS::Rosen::Rect rect; + bool boolVal; + OHOS::Rosen::WindowSizeChangeReason reason; + startPos += GetObject(rect, data + startPos, size - startPos); + startPos += GetObject(boolVal, data + startPos, size - startPos); + startPos += GetObject(reason, data + startPos, size - startPos); + agent->UpdateWindowRect(rect, boolVal, reason); + + WindowMode mode; + startPos += GetObject(mode, data + startPos, size - startPos); + agent->UpdateWindowMode(mode); + + uint32_t modeSupportInfo; + startPos += GetObject(modeSupportInfo, data + startPos, size - startPos); + agent->UpdateWindowModeSupportInfo(modeSupportInfo); + agent->UpdateFocusStatus(boolVal); + + sptr avoidArea = new AvoidArea(); + startPos += GetObject(rect, data + startPos, size - startPos); + avoidArea->topRect_ = rect; + startPos += GetObject(rect, data + startPos, size - startPos); + avoidArea->leftRect_ = rect; + startPos += GetObject(rect, data + startPos, size - startPos); + avoidArea->rightRect_ = rect; + startPos += GetObject(rect, data + startPos, size - startPos); + avoidArea->bottomRect_ = rect; + AvoidAreaType type; + startPos += GetObject(type, data + startPos, size - startPos); + agent->UpdateAvoidArea(avoidArea, type); + + WindowState state; + GetObject(state, data + startPos, size - startPos); + agent->UpdateWindowState(state); +} + +void CheckWindowAgentFunctionsPart2(sptr agent, const uint8_t* data, size_t size) +{ + if (agent == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + PointInfo point; + DragEvent dragEvent; + startPos += GetObject(point, data + startPos, size - startPos); + startPos += GetObject(dragEvent, data + startPos, size - startPos); + agent->UpdateWindowDragInfo(point, dragEvent); + + DisplayId from; + DisplayId to; + startPos += GetObject(from, data + startPos, size - startPos); + startPos += GetObject(to, data + startPos, size - startPos); + agent->UpdateDisplayId(from, to); + + OHOS::Rosen::Rect rect; + OccupiedAreaType type; + startPos += GetObject(rect, data + startPos, size - startPos); + startPos += GetObject(type, data + startPos, size - startPos); + sptr info = new OccupiedAreaChangeInfo(type, rect); + if (info != nullptr) { + agent->UpdateOccupiedAreaChangeInfo(info); + } + + bool boolVal; + startPos += GetObject(boolVal, data + startPos, size - startPos); + agent->UpdateActiveStatus(boolVal); + agent->GetWindowProperty(); + agent->NotifyTouchOutside(); + agent->NotifyScreenshot(); + + Transform trans; + startPos += GetObject(trans, data + startPos, size - startPos); + agent->UpdateZoomTransform(trans, boolVal); + + uint32_t mode; + GetObject(mode, data + startPos, size - startPos); + agent->RestoreSplitWindowMode(mode); +} + +void WindowAgentFuzzTest(const uint8_t* data, size_t size) +{ + sptr option = new OHOS::Rosen::WindowOption(); + sptr window = new(std::nothrow) OHOS::Rosen::WindowImpl(option); + if (window == nullptr) { + return; + } + OHOS::Rosen::WMError error = window->Create(option->GetParentId(), nullptr); + if (error != OHOS::Rosen::WMError::WM_OK) { + return; + } + window->Show(); + + sptr windowAgent = new WindowAgent(window); + OHOS::CheckWindowAgentFunctionsPart1(windowAgent, data, size); + OHOS::CheckWindowAgentFunctionsPart2(windowAgent, data, size); + + window->Hide(); + window->Destroy(); +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::WindowAgentFuzzTest(data, size); + return 0; +} \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.h b/window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.h new file mode 100644 index 0000000..c66faa4 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowagent_fuzzer/window_agent_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_AGENT_FUZZER_H +#define TEST_FUZZTEST_WINDOW_AGENT_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowagent_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/BUILD.gn new file mode 100644 index 0000000..5abc0da --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/BUILD.gn @@ -0,0 +1,80 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowControllerFuzzTest") { + fuzz_config_file = "//foundation/window/window_manager/test/fuzztest/wms/windowcontroller_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/wmserver/include/window_snapshot", + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + "//commonlibrary/c_utils/base/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "windowcontroller_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//foundation/window/window_manager/wmserver:libwms", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", + "display_manager:displaymgr", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hicollie_native:libhicollie", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + "power_manager:powermgr_client", + "safwk:system_ability_fwk", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowControllerFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.cpp new file mode 100644 index 0000000..672614f --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.cpp @@ -0,0 +1,259 @@ +/* + * 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 "windowcontroller_fuzzer.h" + +#include +#include + +#include "window.h" +#include "window_controller.h" +#include "window_manager_service.h" +#include "window_transition_info.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; + constexpr char END_CHAR = '\0'; + constexpr size_t LEN = 10; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +sptr MakeWindowTransitionInfo(const uint8_t* data, size_t size) +{ + sptr info = new (std::nothrow)WindowTransitionInfo; + if (info == nullptr) { + return nullptr; + } + size_t startPos = 0; + char name1[LEN + 1]; + char name2[LEN + 1]; + name1[LEN] = END_CHAR; + name2[LEN] = END_CHAR; + for (size_t i = 0; i < LEN; i++) { + startPos += GetObject(name1[i], data + startPos, size - startPos); + startPos += GetObject(name2[i], data + startPos, size - startPos); + } + std::string bundleName(name1); + std::string abilityName(name2); + info->SetBundleName(bundleName); + info->SetAbilityName(abilityName); + + OHOS::Rosen::WindowMode mode; + startPos += GetObject(mode, data + startPos, size - startPos); + info->SetWindowMode(mode); + + OHOS::Rosen::Rect rect; + startPos += GetObject(rect, data + startPos, size - startPos); + info->SetWindowRect(rect); + + OHOS::Rosen::DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + info->SetDisplayId(displayId); + + OHOS::Rosen::WindowType windowType; + startPos += GetObject(windowType, data + startPos, size - startPos); + info->SetWindowType(windowType); + + bool boolVal; + startPos += GetObject(boolVal, data + startPos, size - startPos); + info->SetShowFlagWhenLocked(boolVal); + startPos += GetObject(boolVal, data + startPos, size - startPos); + info->SetIsRecent(boolVal); + + OHOS::Rosen::TransitionReason reson; + startPos += GetObject(reson, data + startPos, size - startPos); + info->SetTransitionReason(reson); + + startPos += GetObject(info->sizeLimits_, data + startPos, size - startPos); + + int32_t missionId; + GetObject(missionId, data + startPos, size - startPos); + info->SetMissionId(missionId); + return info; +} + +void WindowControllerFuzzTestPart1(sptr windowController, + const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + auto fromInfo = MakeWindowTransitionInfo(data, size); + auto toInfo = MakeWindowTransitionInfo(data, size); + windowController->NotifyWindowTransition(fromInfo, toInfo); + + uint32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + windowController->RequestFocus(windowId); + + AvoidAreaType avoidAreaType; + startPos += GetObject(avoidAreaType, data + startPos, size - startPos); + windowController->GetAvoidAreaByType(windowId, avoidAreaType); + + uint32_t mainWindowId; + startPos += GetObject(mainWindowId, data + startPos, size - startPos); + windowController->GetTopWindowId(mainWindowId, windowId); + + Parcel percel; + if (percel.WriteBuffer(data, size)) { + sptr moveDragProperty = nullptr; + moveDragProperty = MoveDragProperty::Unmarshalling(percel); + windowController->NotifyServerReadyToMoveOrDrag(mainWindowId, moveDragProperty); + } + + startPos += GetObject(mainWindowId, data + startPos, size - startPos); + windowController->ProcessPointUp(mainWindowId); + windowController->ProcessPointDown(mainWindowId, true); + + DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + windowController->MinimizeAllAppWindows(displayId); + + windowController->ToggleShownStateForAllAppWindows(); + + WindowLayoutMode mode; + GetObject(mode, data + startPos, size - startPos); + windowController->SetWindowLayoutMode(mode); +} + +void WindowControllerFuzzTestPart2(sptr windowController, + const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + uint32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + Parcel percel; + if (percel.WriteBuffer(data, size)) { + sptr moveDragProperty = MoveDragProperty::Unmarshalling(percel); + windowController->NotifyServerReadyToMoveOrDrag(windowId, moveDragProperty); + + sptr property = WindowProperty::Unmarshalling(percel); + PropertyChangeAction action; + startPos += GetObject(action, data + startPos, size - startPos); + windowController->UpdateProperty(property, action); + } + + windowController->NotifySystemBarTints(); + + DisplayId displayId; + ModeChangeHotZones hotZones; + ModeChangeHotZonesConfig config; + startPos += GetObject(displayId, data + startPos, size - startPos); + startPos += GetObject(hotZones, data + startPos, size - startPos); + startPos += GetObject(config, data + startPos, size - startPos); + windowController->GetModeChangeHotZones(displayId, hotZones, config); + + windowController->OnScreenshot(displayId); + + int32_t x; + int32_t y; + int32_t scale; + startPos += GetObject(x, data + startPos, size - startPos); + startPos += GetObject(y, data + startPos, size - startPos); + startPos += GetObject(scale, data + startPos, size - startPos); + windowController->SetAnchorAndScale(x, y, scale); + + windowController->SetAnchorOffset(x, y); + windowController->OffWindowZoom(); + + GetObject(windowId, data + startPos, size - startPos); + windowController->InterceptInputEventToServer(windowId); + windowController->RecoverInputEventToClient(windowId); + windowController->RecoverDefaultMouseStyle(windowId); +} + +void WindowControllerFuzzTestPart3(sptr windowController, + const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + uint32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + windowController->GenWindowId(); + windowController->RecordBootAnimationEvent(); + + OHOS::Rosen::WindowType type; + startPos += GetObject(type, data + startPos, size - startPos); + windowController->SetWindowType(windowId, type); + + uint32_t flags; + startPos += GetObject(flags, data + startPos, size - startPos); + windowController->SetWindowFlags(windowId, flags); + + OHOS::Rosen::SystemBarProperty property; + startPos += GetObject(property, data + startPos, size - startPos); + windowController->SetSystemBarProperty(windowId, type, property); + + OHOS::Rosen::Rect rect; + OHOS::Rosen::WindowSizeChangeReason reason; + startPos += GetObject(rect, data + startPos, size - startPos); + startPos += GetObject(reason, data + startPos, size - startPos); + windowController->ResizeRect(windowId, rect, reason); + windowController->ResizeRectAndFlush(windowId, rect, reason); + + OHOS::Rosen::WindowMode dstMode; + startPos += GetObject(dstMode, data + startPos, size - startPos); + windowController->SetWindowMode(windowId, dstMode); + windowController->RestoreCallingWindowSizeIfNeed(); + + GetObject(windowId, data + startPos, size - startPos); + windowController->UpdateTransform(windowId); + windowController->AsyncFlushInputInfo(windowId); +} + +bool DoWindowControllerFuzzTest(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + auto windowController = WindowManagerService::GetInstance().windowController_; + if (windowController == nullptr) { + return false; + } + OHOS::WindowControllerFuzzTestPart1(windowController, data, size); + OHOS::WindowControllerFuzzTestPart2(windowController, data, size); + OHOS::WindowControllerFuzzTestPart3(windowController, data, size); + + return true; +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoWindowControllerFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.h b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.h new file mode 100644 index 0000000..0b7db00 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowcontroller_fuzzer/windowcontroller_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_CONTROLLER_FUZZER_H +#define TEST_FUZZTEST_WINDOW_CONTROLLER_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowcontroller_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowipc_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowipc_fuzzer/BUILD.gn new file mode 100644 index 0000000..fb48d6a --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowipc_fuzzer/BUILD.gn @@ -0,0 +1,61 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowIPCFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/wms/windowipc_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/wm/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + sources = [ "windowipc_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/animation/window_animation:window_animation", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "input:libmmi-client", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowIPCFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowipc_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowipc_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowipc_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowipc_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowipc_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowipc_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.cpp new file mode 100644 index 0000000..6ed5984 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.cpp @@ -0,0 +1,184 @@ +/* + * 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 "windowipc_fuzzer.h" + +#include +#include +#include +#include + +#include "zidl/window_manager_proxy.h" +#include "window_manager_hilog.h" + +namespace OHOS ::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayManagerIPC_Fuzzer"}; +} +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +std::pair, sptr> GetProxy() +{ + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + WLOGFE("Failed to get system ability mgr."); + return { nullptr, nullptr }; + } + sptr remoteObject = systemAbilityManager->GetSystemAbility(WINDOW_MANAGER_SERVICE_ID); + if (!remoteObject) { + WLOGFE("Failed to get display manager service."); + return { nullptr, nullptr }; + } + sptr windowManagerServiceProxy = iface_cast(remoteObject); + if ((!windowManagerServiceProxy) || (!windowManagerServiceProxy->AsObject())) { + WLOGFE("Failed to get system display manager services"); + return { nullptr, nullptr }; + } + return { windowManagerServiceProxy, remoteObject }; +} + +bool IPCFuzzTest(const uint8_t* data, size_t size) +{ + uint32_t code; + int flags, waitTime; + if (data == nullptr || size < sizeof(code) + sizeof(flags) + sizeof(waitTime)) { + return false; + } + auto proxy = GetProxy(); + if (proxy.first == nullptr || proxy.second == nullptr) { + return false; + } + size_t startPos = 0; + startPos += GetObject(code, data + startPos, size - startPos); + startPos += GetObject(flags, data + startPos, size - startPos); + startPos += GetObject(waitTime, data + startPos, size - startPos); + MessageParcel sendData; + MessageParcel reply; + MessageOption option(flags, waitTime); + sendData.WriteBuffer(data + startPos, size - startPos); + proxy.second->SendRequest(code, sendData, reply, option); + return true; +} + +void IPCSpecificInterfaceFuzzTest1(sptr proxy, MessageParcel& sendData, MessageParcel& reply, + MessageOption& option) +{ + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_CREATE_WINDOW), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_ADD_WINDOW), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_REMOVE_WINDOW), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_DESTROY_WINDOW), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_REQUEST_FOCUS), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_REGISTER_FOCUS_CHANGED_LISTENER), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UNREGISTER_FOCUS_CHANGED_LISTENER), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_REGISTER_WINDOW_MANAGER_AGENT), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UNREGISTER_WINDOW_MANAGER_AGENT), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_AVOID_AREA), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_TOP_WINDOW_ID), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_NOTIFY_READY_MOVE_OR_DRAG), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_PROCESS_POINT_DOWN), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_PROCESS_POINT_UP), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_MINIMIZE_ALL_APP_WINDOWS), + sendData, reply, option); +} + +void IPCSpecificInterfaceFuzzTest2(sptr proxy, MessageParcel& sendData, MessageParcel& reply, + MessageOption& option) +{ + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_TOGGLE_SHOWN_STATE_FOR_ALL_APP_WINDOWS), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_SET_BACKGROUND_BLUR), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_SET_ALPHA), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UPDATE_LAYOUT_MODE), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UPDATE_PROPERTY), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_ACCESSIBILITY_WINDOW_INFO_ID), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_ANIMATION_SET_CONTROLLER), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_SYSTEM_CONFIG), + sendData, reply, option); + proxy->SendRequest(static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_NOTIFY_WINDOW_TRANSITION), + sendData, reply, option); + proxy->SendRequest( + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_FULLSCREEN_AND_SPLIT_HOT_ZONE), + sendData, reply, option); +} + +bool IPCInterfaceFuzzTest(const uint8_t* data, size_t size) +{ + int flags, waitTime; + if (data == nullptr || size < sizeof(flags) + sizeof(waitTime)) { + return false; + } + auto proxy = GetProxy(); + if (proxy.first == nullptr || proxy.second == nullptr) { + return false; + } + size_t startPos = 0; + startPos += GetObject(flags, data + startPos, size - startPos); + startPos += GetObject(waitTime, data + startPos, size - startPos); + MessageParcel sendData; + MessageParcel reply; + MessageOption option(flags, waitTime); + sendData.WriteInterfaceToken(proxy.first->GetDescriptor()); + sendData.WriteBuffer(data + startPos, size - startPos); + IPCSpecificInterfaceFuzzTest1(proxy.second, sendData, reply, option); + IPCSpecificInterfaceFuzzTest2(proxy.second, sendData, reply, option); + return true; +} +} // namespace.OHOS::Rosen + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::Rosen::IPCFuzzTest(data, size); + OHOS::Rosen::IPCInterfaceFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.h b/window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.h new file mode 100644 index 0000000..6ec2a79 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowipc_fuzzer/windowipc_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_IPC_FUZZER_H +#define TEST_FUZZTEST_WINDOW_IPC_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowipc_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowmanager_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/BUILD.gn new file mode 100644 index 0000000..6b21f60 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/BUILD.gn @@ -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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowManagerFuzzTest") { + fuzz_config_file = "//foundation/window/window_manager/test/fuzztest/wms/windowmanager_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//commonlibrary/c_utils/base/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "windowmanager_fuzzer.cpp" ] + deps = [ "//foundation/window/window_manager/wm:libwm" ] + + external_deps = [ + "c_utils:utils", + "ipc:ipc_core", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowManagerFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowmanager_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowmanager_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.cpp new file mode 100644 index 0000000..a81b6f4 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.cpp @@ -0,0 +1,184 @@ +/* + * 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 "marshalling_helper.h" +#include "window_manager.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +class FocusChangedListener : public IFocusChangedListener { +public: + virtual void OnFocused(const sptr& focusChangeInfo) override + { + } + + virtual void OnUnfocused(const sptr& focusChangeInfo) override + { + } +}; + +class SystemBarChangedListener : public ISystemBarChangedListener { +public: + virtual void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override + { + } +}; + +class VisibilityChangedListener : public IVisibilityChangedListener { +public: + virtual void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override + { + } +}; + +class WindowUpdateListener : public IWindowUpdateListener { +public: + virtual void OnWindowUpdate(const std::vector>& infos, WindowUpdateType type) override + { + } +}; + +class CameraFloatWindowChangedListener : public ICameraFloatWindowChangedListener { +public: + void OnCameraFloatWindowChange(uint32_t accessTokenId, bool isShowing) override + { + } +}; + + +bool DoSomethingForWindowManagerImpl(WindowManager& windowManager, const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + size_t startPos = 0; + uint32_t accessTokenId; + bool isShowing; + startPos += GetObject(accessTokenId, data + startPos, size - startPos); + startPos += GetObject(isShowing, data + startPos, size - startPos); + windowManager.UpdateCameraFloatWindowStatus(accessTokenId, isShowing); + + Parcel windowVisibilityInfosParcel; + if (windowVisibilityInfosParcel.WriteBuffer(data, size)) { + std::vector> infos; + if (MarshallingHelper::UnmarshallingVectorParcelableObj(windowVisibilityInfosParcel, + infos)) { + windowManager.GetVisibilityWindowInfo(infos); + windowManager.UpdateWindowVisibilityInfo(infos); + } + } + + DisplayId displayId; + SystemBarRegionTints tints; + startPos += GetObject(displayId, data + startPos, size - startPos); + GetObject(tints, data + startPos, size - startPos); + windowManager.UpdateSystemBarRegionTints(displayId, tints); + + return true; +} + +void CheckAccessibilityWindowInfo(WindowManager& windowManager, const uint8_t* data, size_t size) +{ + Parcel accessibilityWindowInfosParcel; + if (accessibilityWindowInfosParcel.WriteBuffer(data, size)) { + std::vector> infos; + if (MarshallingHelper::UnmarshallingVectorParcelableObj(accessibilityWindowInfosParcel, + infos)) { + windowManager.GetAccessibilityWindowInfo(infos); + WindowUpdateType type; + GetObject(type, data, size); + windowManager.NotifyAccessibilityWindowInfo(infos, type); + } + } +} + +bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + WindowManager& windowManager = WindowManager::GetInstance(); + CheckAccessibilityWindowInfo(windowManager, data, size); + + Parcel focusChangeInfoParcel; + if (focusChangeInfoParcel.WriteBuffer(data, size)) { + FocusChangeInfo::Unmarshalling(focusChangeInfoParcel); + } + Parcel parcel; + sptr focusChangeInfo = new FocusChangeInfo(); + focusChangeInfo->Marshalling(parcel); + + Parcel windowVisibilityInfoParcel; + if (windowVisibilityInfoParcel.WriteBuffer(data, size)) { + WindowVisibilityInfo::Unmarshalling(windowVisibilityInfoParcel); + } + sptr windowVisibilityInfo = new WindowVisibilityInfo(); + windowVisibilityInfo->Marshalling(parcel); + + Parcel accessibilityWindowInfoParcel; + if (accessibilityWindowInfoParcel.WriteBuffer(data, size)) { + AccessibilityWindowInfo::Unmarshalling(accessibilityWindowInfoParcel); + } + sptr accessibilityWindowInfo = new AccessibilityWindowInfo(); + accessibilityWindowInfo->Marshalling(parcel); + + windowManager.MinimizeAllAppWindows(static_cast(data[0])); + sptr focusChangedListener = new FocusChangedListener(); + windowManager.RegisterFocusChangedListener(focusChangedListener); + sptr systemBarChangedListener = new SystemBarChangedListener(); + windowManager.RegisterSystemBarChangedListener(systemBarChangedListener); + sptr visibilityChangedListener = new VisibilityChangedListener(); + windowManager.RegisterVisibilityChangedListener(visibilityChangedListener); + sptr windowUpdateListener = new WindowUpdateListener(); + windowManager.RegisterWindowUpdateListener(windowUpdateListener); + sptr cameraFloatWindowChanagedListener = new CameraFloatWindowChangedListener(); + windowManager.RegisterCameraFloatWindowChangedListener(cameraFloatWindowChanagedListener); + windowManager.SetWindowLayoutMode(static_cast(data[0])); + windowManager.UnregisterFocusChangedListener(focusChangedListener); + windowManager.UnregisterSystemBarChangedListener(systemBarChangedListener); + windowManager.UnregisterVisibilityChangedListener(visibilityChangedListener); + windowManager.UnregisterWindowUpdateListener(windowUpdateListener); + windowManager.UnregisterCameraFloatWindowChangedListener(cameraFloatWindowChanagedListener); + return true; +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.h b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.h new file mode 100644 index 0000000..ae6240c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowmanager_fuzzer/windowmanager_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_MANAGER_FUZZER_H +#define TEST_FUZZTEST_WINDOW_MANAGER_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowmanager_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowpair_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowpair_fuzzer/BUILD.gn new file mode 100644 index 0000000..1eabf0b --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowpair_fuzzer/BUILD.gn @@ -0,0 +1,85 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowPairFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/wms/windowpair_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "include", + "include/window_snapshot", + "//utils/system/safwk/native/include", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/dmserver/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "windowpair_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/etc:wms_etc", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//foundation/window/window_manager/wmserver:libwms", + "//third_party/libxml2:libxml2", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", + "display_manager:displaymgr", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hicollie_native:libhicollie", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + "power_manager:powermgr_client", + "safwk:system_ability_fwk", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowPairFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowpair_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowpair_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowpair_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowpair_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowpair_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowpair_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.cpp new file mode 100644 index 0000000..5eba667 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.cpp @@ -0,0 +1,135 @@ +/* + * 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 "windowpair_fuzzer.h" + +#include +#include "display_manager.h" +#include "common_event_manager.h" +#include "window_manager_hilog.h" +#include "window_helper.h" +#include "surface_draw.h" +#include "window_pair.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; + constexpr size_t LEN = 10; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +size_t InitWindowNode1(sptr &windowNode, const uint8_t *data, size_t size) +{ + size_t startPos = 0; + sptr property = new WindowProperty(); + Parcel parcel; + if (parcel.WriteBuffer(data + startPos, size - startPos)) { + property = OHOS::Rosen::WindowProperty::Unmarshalling(parcel); + } + windowNode = new OHOS::Rosen::WindowNode(property); + if (windowNode == nullptr) { + return startPos; + } + return startPos; +} + +bool DoSomethingInterestingWithMyAPI2(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + size_t startPos = 0; + DisplayId displayId = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplayId(); + sptr windowPair = new OHOS::Rosen::WindowPair(displayId); + sptr windowNode; + startPos += InitWindowNode1(windowNode, data + startPos, size -startPos); + std::vector vec; + int32_t num; + for(uint32_t i = 0; i < LEN; ++i) { + startPos += GetObject(num, data + startPos, size - startPos); + vec.emplace_back(num); + } + windowPair->IsDockSliceInExitSplitModeArea(vec); + windowPair->ExitSplitMode(); + windowPair->Clear(); + windowPair->IsSplitRelated(windowNode); + windowPair->GetOrderedPair(windowNode); + windowPair->GetPairedWindows(); + windowPair->UpdateIfSplitRelated(windowNode); + windowPair->UpdateWindowPairStatus(); + windowPair->SwitchPosition(); + windowPair->HandlePairedNodesChange(); + windowPair->UpdateWindowPairStatus(); + windowPair->Insert(windowNode); + windowPair->DumpPairInfo(); + windowPair->HandleRemoveWindow(windowNode); + OHOS::Rosen::Rect rect; + GetObject(rect, data + startPos, size - startPos); + windowPair->RotateDividerWindow(rect); + windowPair->SetDividerRect(rect); + windowPair->ClearPairSnapshot(); + return true; +} + +bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + OHOS::Rosen::DisplayId displayId = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplayId(); + sptr windowPair = new OHOS::Rosen::WindowPair(displayId); + size_t startPos = 0; + OHOS::Rosen::SplitEventMsgType msg; + startPos += GetObject(msg, data + startPos, size - startPos); + int32_t missionId; + startPos += GetObject(missionId, data + startPos, size - startPos); + sptr windowNode; + startPos += InitWindowNode1(windowNode, data + startPos, size -startPos); + bool isDestroy; + startPos += GetObject(isDestroy, data + startPos, size -startPos); + windowPair->NotifyCreateOrDestroyDivider(windowNode, isDestroy); + windowPair->Find(windowNode); + windowPair->IsPaired(); + float ratio; + GetObject(ratio, data + startPos, size - startPos); + windowPair->SetSplitRatio(ratio); + windowPair->GetSplitRatio(); + windowPair->GetPairStatus(); + windowPair->GetDividerWindow(); + windowPair->IsForbidDockSliceMove(); + return true; +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + OHOS::DoSomethingInterestingWithMyAPI2(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.h b/window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.h new file mode 100644 index 0000000..54bfa07 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowpair_fuzzer/windowpair_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_PAIR_FUZZER_H +#define TEST_FUZZTEST_WINDOW_PAIR_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowpair_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowroot_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowroot_fuzzer/BUILD.gn new file mode 100644 index 0000000..644210d --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowroot_fuzzer/BUILD.gn @@ -0,0 +1,89 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowRootFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/wms/windowroot_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/dm/include/zidl", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/wmserver/include/zidl", + "//foundation/window/window_manager/wmserver/include/window_snapshot", + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/snapshot/include", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + "//commonlibrary/c_utils/base/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + sources = [ "windowroot_fuzzer.cpp" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//foundation/window/window_manager/wmserver:libwms", + ] + + public_deps = [ "//foundation/arkui/napi:ace_napi" ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", + "display_manager:displaymgr", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hicollie_native:libhicollie", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + "power_manager:powermgr_client", + "safwk:system_ability_fwk", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowRootFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowroot_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowroot_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowroot_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowroot_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowroot_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowroot_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.cpp new file mode 100644 index 0000000..aa89bef --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.cpp @@ -0,0 +1,364 @@ +/* + * 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 "windowroot_fuzzer.h" + +#include "display_info.h" +#include "display_manager.h" +#include "marshalling_helper.h" +#include "window.h" +#include "window_node.h" +#include "window_root.h" +#include "window_manager.h" +#include "window_manager_service.h" +#include "window_scene.h" +#include "window_dumper.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; + constexpr size_t VECTOR_MAX_LEN = 4; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +sptr CreateWindowNode(const std::string& windowName, + const uint8_t *data, size_t size) +{ + sptr property = nullptr; + Parcel parcel; + if (parcel.WriteBuffer(data, size)) { + property = OHOS::Rosen::WindowProperty::Unmarshalling(parcel); + } + + sptr windowNode = new OHOS::Rosen::WindowNode(property); + if (windowNode == nullptr) { + return nullptr; + } + return windowNode; +} + +sptr CreateDisplayInfo(const uint8_t *data, size_t size) +{ + sptr displayInfo = nullptr; + Parcel parcel; + if (parcel.WriteBuffer(data, size)) { + displayInfo = OHOS::Rosen::DisplayInfo::Unmarshalling(parcel); + } + return displayInfo; +} + +void WindowRootFuzzPart1(sptr windowRoot, sptr windowNode, + const uint8_t *data, size_t size) +{ + if (windowRoot == nullptr || windowNode == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + OHOS::Rosen::DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + windowRoot->GetOrCreateWindowNodeContainer(displayId); + windowRoot->GetWindowNodeContainer(displayId); + + auto displayInfo = CreateDisplayInfo(data, size); + windowRoot->CreateWindowNodeContainer(displayInfo); + + uint32_t windowId; + startPos += GetObject(windowId, data + startPos, size - startPos); + windowRoot->GetWindowNode(windowId); + + std::vector> windowNodes; + OHOS::Rosen::ScreenId screenGroupId; + startPos += GetObject(screenGroupId, data + startPos, size - startPos); + windowRoot->GetBackgroundNodesByScreenId(screenGroupId, windowNodes); + + windowRoot->FindWindowNodeWithToken(windowNode->abilityToken_); + + bool fromStartingWin; + startPos += GetObject(fromStartingWin, data + startPos, size - startPos); + windowRoot->AddWindowNode(windowNode->GetParentId(), windowNode, fromStartingWin); + + OHOS::Rosen::WindowUpdateReason reason; + startPos += GetObject(reason, data + startPos, size - startPos); + windowRoot->UpdateWindowNode(windowNode->GetWindowId(), reason); + + uint64_t surfaceNodeId; + GetObject(surfaceNodeId, data + startPos, size - startPos); + windowRoot->AddSurfaceNodeIdWindowNodePair(surfaceNodeId, windowNode); + + windowRoot->IsVerticalDisplay(windowNode); + + windowRoot->RemoveWindowNode(windowNode->GetWindowId(), fromStartingWin); +} + +void WindowRootFuzzPart2(sptr windowRoot, sptr windowNode, + const uint8_t *data, size_t size) +{ + if (windowRoot == nullptr || windowNode == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + + windowRoot->IsForbidDockSliceMove(displayId); + windowRoot->IsDockSliceInExitSplitModeArea(displayId); + windowRoot->ExitSplitMode(displayId); + + windowRoot->RequestFocus(windowNode->GetWindowId()); + windowRoot->RequestActiveWindow(windowNode->GetWindowId()); + + windowRoot->MinimizeStructuredAppWindowsExceptSelf(windowNode); + + AvoidAreaType avoidAreaType; + startPos += GetObject(avoidAreaType, data + startPos, size - startPos); + windowRoot->GetAvoidAreaByType(windowNode->GetWindowId(), avoidAreaType); + + WindowMode dstMode; + startPos += GetObject(dstMode, data + startPos, size - startPos); + windowRoot->SetWindowMode(windowNode, dstMode); + + uint32_t mainWinId; + uint32_t topWinId; + startPos += GetObject(mainWinId, data + startPos, size - startPos); + startPos += GetObject(topWinId, data + startPos, size - startPos); + windowRoot->GetTopWindowId(mainWinId, topWinId); + + startPos += GetObject(displayId, data + startPos, size - startPos); + windowRoot->MinimizeAllAppWindows(displayId); + + windowRoot->ToggleShownStateForAllAppWindows(); + + WindowLayoutMode windowLayoutMode; + startPos += GetObject(windowLayoutMode, data + startPos, size - startPos); + windowRoot->SetWindowLayoutMode(displayId, windowLayoutMode); + + WindowState windowState; + WindowStateChangeReason windowStateChangeReason; + startPos += GetObject(windowState, data + startPos, size - startPos); + GetObject(windowStateChangeReason, data + startPos, size - startPos); + windowRoot->ProcessWindowStateChange(windowState, windowStateChangeReason); +} + +void WindowRootFuzzPart3(sptr windowRoot, sptr windowNode, + const uint8_t *data, size_t size) +{ + if (windowRoot == nullptr || windowNode == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + windowRoot->RaiseZOrderForAppWindow(windowNode); + + DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + windowRoot->GetVirtualPixelRatio(displayId); + windowRoot->GetDisplayGroupRect(displayId); + + WindowSizeChangeReason windowSizeChangeReason; + startPos += GetObject(windowSizeChangeReason, data + startPos, size - startPos); + windowRoot->UpdateSizeChangeReason(windowNode->GetWindowId(), windowSizeChangeReason); + + float brightNess; + startPos += GetObject(brightNess, data + startPos, size - startPos); + windowRoot->SetBrightness(windowNode->GetWindowId(), brightNess); + + windowRoot->UpdateFocusableProperty(windowNode->GetWindowId()); + bool requireLock; + startPos += GetObject(requireLock, data + startPos, size - startPos); + + windowRoot->HandleKeepScreenOn(windowNode->GetWindowId(), requireLock); + + uint32_t windowNum; + startPos += GetObject(windowNum, data + startPos, size - startPos); + windowRoot->SetMaxAppWindowNumber(windowNum); + + uint32_t uniAppWindowNum; + startPos += GetObject(uniAppWindowNum, data + startPos, size - startPos); + windowRoot->SetMaxUniRenderAppWindowNumber(uniAppWindowNum); + + ModeChangeHotZones hotZones; + ModeChangeHotZonesConfig config; + startPos += GetObject(hotZones, data + startPos, size - startPos); + startPos += GetObject(config, data + startPos, size - startPos); + windowRoot->GetModeChangeHotZones(displayId, hotZones, config); + + std::vector splitRatioNumbers; + for (size_t i = 0; i < VECTOR_MAX_LEN; i++) { + float value; + startPos += GetObject(value, data + startPos, size - startPos); + splitRatioNumbers.emplace_back(value); + } + windowRoot->SetSplitRatios(splitRatioNumbers); + windowRoot->SetExitSplitRatios(splitRatioNumbers); +} + +void WindowRootFuzzPart4(sptr windowRoot, sptr windowNode, + const uint8_t *data, size_t size) +{ + if (windowRoot == nullptr || windowNode == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + windowRoot->HasPrivateWindow(displayId); + windowRoot->GetDisplayRectWithoutSystemBarAreas(displayId); + windowRoot->GetSplitScreenWindowNodes(displayId); + windowRoot->GetAllDisplayIds(); + windowRoot->GetTotalWindowNum(); + + bool isUniRender; + startPos += GetObject(isUniRender, data + startPos, size - startPos); + windowRoot->OnRenderModeChanged(isUniRender); + + windowRoot->TakeWindowPairSnapshot(displayId); + windowRoot->ClearWindowPairSnapshot(displayId); + + std::vector> windowNodes; + windowNodes.emplace_back(windowNode); + windowRoot->GetAllAnimationPlayingNodes(windowNodes); + + std::vector> infos; + for (size_t i = 0; i < VECTOR_MAX_LEN; i++) { + sptr visibilityInfo = nullptr; + Parcel parcel; + if (parcel.WriteBuffer(data, size)) { + visibilityInfo = WindowVisibilityInfo::Unmarshalling(parcel); + } + if (visibilityInfo != nullptr) { + infos.emplace_back(visibilityInfo); + } + } + windowRoot->GetVisibilityWindowInfo(infos); + infos.clear(); + + int accountId; + GetObject(accountId, data + startPos, size - startPos); + windowRoot->RemoveSingleUserWindowNodes(accountId); + + windowRoot->NotifySystemBarTints(); + + windowRoot->FocusFaultDetection(); + windowRoot->GetMaxUniRenderAppWindowNumber(); + + windowRoot->GetWindowForDumpAceHelpInfo(); + windowRoot->DestroyLeakStartingWindow(); +} + +void WindowRootFuzzPart5(sptr windowRoot, sptr windowNode, + const uint8_t *data, size_t size) +{ + if (windowRoot == nullptr || windowNode == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + std::vector windowIds; + for (size_t i = 0; i < VECTOR_MAX_LEN; i++) { + uint32_t value; + startPos += GetObject(value, data + startPos, size - startPos); + windowIds.emplace_back(value); + } + windowRoot->MinimizeTargetWindows(windowIds); + windowRoot->UpdateRsTree(windowNode->GetWindowId(), false); + + windowRoot->SwitchRenderModeIfNeeded(); + windowRoot->IsUniRender(); + + bool afterAnimation; + GetObject(afterAnimation, data + startPos, size - startPos); + windowRoot->LayoutWhenAddWindowNode(windowNode, afterAnimation); +} + +void WindowRootFuzzPart6(sptr windowRoot, sptr windowNode, + const uint8_t *data, size_t size) +{ + if (windowRoot == nullptr || windowNode == nullptr || data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + windowRoot->GenAllWindowsLogInfo(); + DisplayId displayId; + bool isRecordedDisplay; + startPos += GetObject(displayId, data + startPos, size - startPos); + startPos += GetObject(isRecordedDisplay, data + startPos, size - startPos); + + windowRoot->GetScreenGroupId(displayId, isRecordedDisplay); + + std::vector infos; + for (size_t i = 0; i < VECTOR_MAX_LEN; i++) { + DisplayId disId; + startPos += GetObject(disId, data + startPos, size - startPos); + infos.emplace_back(disId); + } + windowRoot->GetAllDisplayInfos(infos); + + DisplayId defaultDisplayId; + startPos += GetObject(defaultDisplayId, data + startPos, size - startPos); + windowRoot->MoveNotShowingWindowToDefaultDisplay(defaultDisplayId, displayId); + + bool isToUnified; + GetObject(isToUnified, data + startPos, size - startPos); + windowRoot->ChangeRSRenderModeIfNeeded(isToUnified); + windowRoot->IsAppWindowExceed(); +} + +void DoFuzzTest(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + auto windowRoot = OHOS::Rosen::WindowManagerService::GetInstance().windowRoot_; + auto windowNode = CreateWindowNode("TestWindowNode", data, size); + if (windowNode == nullptr || windowRoot == nullptr) { + return; + } + windowRoot->SaveWindow(windowNode); + + OHOS::WindowRootFuzzPart1(windowRoot, windowNode, data, size); + OHOS::WindowRootFuzzPart2(windowRoot, windowNode, data, size); + OHOS::WindowRootFuzzPart3(windowRoot, windowNode, data, size); + OHOS::WindowRootFuzzPart4(windowRoot, windowNode, data, size); + OHOS::WindowRootFuzzPart5(windowRoot, windowNode, data, size); + OHOS::WindowRootFuzzPart6(windowRoot, windowNode, data, size); + + windowRoot->DestroyWindow(windowNode->GetWindowId(), false); + windowRoot->surfaceIdWindowNodeMap_.clear(); +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.h b/window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.h new file mode 100644 index 0000000..7036271 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowroot_fuzzer/windowroot_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_ROOT_FUZZER_H +#define TEST_FUZZTEST_WINDOW_ROOT_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowroot_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowscene_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowscene_fuzzer/BUILD.gn new file mode 100644 index 0000000..79e563a --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowscene_fuzzer/BUILD.gn @@ -0,0 +1,60 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowSceneFuzzTest") { + fuzz_config_file = + "//foundation/window/window_manager/test/fuzztest/wms/windowscene_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + "//commonlibrary/c_utils/base/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + sources = [ "windowscene_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "c_utils:utils", + "ipc:ipc_core", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowSceneFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowscene_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowscene_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowscene_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowscene_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowscene_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowscene_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.cpp new file mode 100644 index 0000000..8a170ac --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.cpp @@ -0,0 +1,192 @@ +/* + * 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 "windowscene_fuzzer.h" + +#include + +#include "display_manager.h" +#include "window.h" +#include "window_manager.h" +#include "window_scene.h" + +using namespace OHOS::Rosen; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; + constexpr char END_CHAR = '\0'; + constexpr size_t LEN = 10; +} +class WindowLifeCycle : public IWindowLifeCycle { +public: + virtual void AfterForeground() override + { + } + virtual void AfterBackground() override + { + } + virtual void AfterFocused() override + { + } + virtual void AfterUnfocused() override + { + } + virtual void AfterActive() override + { + } + virtual void AfterInactive() override + { + } +}; + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +size_t InitWindowOption1(WindowOption &windowOption, const uint8_t *data, size_t size) +{ + size_t startPos = 0; + Rect windowRect; + startPos += GetObject(windowRect, data + startPos, size - startPos); + windowOption.SetWindowRect(windowRect); + uint32_t type; + startPos += GetObject(type, data + startPos, size - startPos); + windowOption.SetWindowType(static_cast(type)); + uint32_t mode; + startPos += GetObject(mode, data + startPos, size - startPos); + windowOption.SetWindowMode(static_cast(mode)); + bool focusable; + startPos += GetObject(focusable, data + startPos, size - startPos); + windowOption.SetFocusable(focusable); + bool touchable; + startPos += GetObject(touchable, data + startPos, size - startPos); + windowOption.SetTouchable(touchable); + DisplayId displayId; + startPos += GetObject(displayId, data + startPos, size - startPos); + windowOption.SetDisplayId(displayId); + uint32_t parentId; + startPos += GetObject(parentId, data + startPos, size - startPos); + windowOption.SetParentId(parentId); + char name[LEN + 1]; + name[LEN] = END_CHAR; + for (int i = 0; i < LEN; i++) { + startPos += GetObject(name[i], data + startPos, size - startPos); + } + std::string windowName(name); + windowOption.SetWindowName(windowName); + return startPos; +} + +size_t InitWindowOption2(WindowOption &windowOption, const uint8_t *data, size_t size) +{ + size_t startPos = 0; + uint32_t flags; + startPos += GetObject(flags, data + startPos, size - startPos); + windowOption.SetWindowFlags(flags); + PointInfo hitOffset; + startPos += GetObject(hitOffset, data + startPos, size - startPos); + windowOption.SetHitOffset(hitOffset.x, hitOffset.y); + WindowTag windowTag; + startPos += GetObject(windowTag, data + startPos, size - startPos); + windowOption.SetWindowTag(windowTag); + bool keepScreenOn; + startPos += GetObject(keepScreenOn, data + startPos, size - startPos); + windowOption.SetKeepScreenOn(keepScreenOn); + bool turnScreenOn; + startPos += GetObject(turnScreenOn, data + startPos, size - startPos); + windowOption.SetTurnScreenOn(turnScreenOn); + float brightness; + startPos += GetObject(brightness, data + startPos, size - startPos); + windowOption.SetBrightness(brightness); + uint32_t callingWindow; + startPos += GetObject(callingWindow, data + startPos, size - startPos); + windowOption.SetCallingWindow(callingWindow); + SystemBarProperty statusBarProperty; + SystemBarProperty navigationBarProperty; + startPos += GetObject(statusBarProperty, data + startPos, size - startPos); + startPos += GetObject(navigationBarProperty, data + startPos, size - startPos); + windowOption.SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusBarProperty); + windowOption.SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, navigationBarProperty); + Orientation requestedOrientation; + startPos += GetObject(requestedOrientation, data + startPos, size - startPos); + windowOption.SetRequestedOrientation(requestedOrientation); + bool isMainHandleAvailable; + startPos += GetObject(isMainHandleAvailable, data + startPos, size - startPos); + windowOption.SetMainHandlerAvailable(isMainHandleAvailable); + return startPos; +} + +size_t InitWindowOption(WindowOption &windowOption, const uint8_t *data, size_t size) +{ + size_t startPos = 0; + startPos += InitWindowOption1(windowOption, data + startPos, size - startPos); + startPos += InitWindowOption2(windowOption, data + startPos, size - startPos); + return startPos; +} + +bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + DisplayId displayId = DisplayManager::GetInstance().GetDefaultDisplayId(); + sptr windowScene = new WindowScene(); + sptr listener = new WindowLifeCycle(); + sptr option = new WindowOption(); + size_t startPos = 0; + startPos += InitWindowOption(*option, data, size); + windowScene->Init(displayId, nullptr, listener, option); + char name[LEN + 1]; + name[LEN] = END_CHAR; + for (int i = 0; i < LEN; i++) { + startPos += GetObject(name[i], data + startPos, size - startPos); + } + std::string windowName(name); + sptr windowOption = new WindowOption(); + startPos += InitWindowOption(*windowOption, data + startPos, size - startPos); + sptr window = windowScene->CreateWindow(windowName, windowOption); + uint32_t reason; + startPos += GetObject(reason, data + startPos, size - startPos); + windowScene->GoForeground(reason); + SystemBarProperty systemBarProperty; + WindowType type; + startPos += GetObject(systemBarProperty, data + startPos, size - startPos); + startPos += GetObject(type, data + startPos, size - startPos); + windowScene->SetSystemBarProperty(type, systemBarProperty); + GetObject(reason, data + startPos, size - startPos); + windowScene->GoBackground(reason); + if (window != nullptr) { + window->Destroy(); + } + windowScene->GoDestroy(); + return true; +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoSomethingInterestingWithMyAPI(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.h b/window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.h new file mode 100644 index 0000000..1c79015 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowscene_fuzzer/windowscene_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_SCENE_FUZZER_H +#define TEST_FUZZTEST_WINDOW_SCENE_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowscene_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/BUILD.gn b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/BUILD.gn new file mode 100644 index 0000000..4d5d351 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/BUILD.gn @@ -0,0 +1,61 @@ +# 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. + +import("//build/config/features.gni") +import("//build/test.gni") + +module_output_path = "window_manager/wms" + +##############################fuzztest########################################## +ohos_fuzztest("WindowUtilMathFuzzTest") { + fuzz_config_file = "//foundation/window/window_manager/test/fuzztest/wms/windowutilmath_fuzzer" + module_out_path = module_output_path + include_dirs = [ + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/graphic/graphic_2d/interfaces/innerkits/surface", + "//commonlibrary/c_utils/base/include", + ] + + configs = [ + "//foundation/window/window_manager/test/fuzztest:configs_cc_ld", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + sources = [ "windowutilmath_fuzzer.cpp" ] + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + ] + + external_deps = [ + "c_utils:utils", + "ipc:ipc_core", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + + deps += [ + # deps file + ":WindowUtilMathFuzzTest", + ] +} +############################################################################### diff --git a/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/corpus/init b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/corpus/init new file mode 100644 index 0000000..bc977bd --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/project.xml b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/project.xml new file mode 100644 index 0000000..6e8ad2c --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.cpp b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.cpp new file mode 100644 index 0000000..6d79c76 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.cpp @@ -0,0 +1,190 @@ +/* + * 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 "windowutilmath_fuzzer.h" + +#include + +#include "display_manager.h" +#include "window.h" +#include "window_manager.h" +#include "window_scene.h" +#include "wm_math.h" + +using namespace OHOS::Rosen; +using namespace OHOS::Rosen::TransformHelper; + +namespace OHOS { +namespace { + constexpr size_t DATA_MIN_SIZE = 2; +} + +template +size_t GetObject(T &object, const uint8_t *data, size_t size) +{ + size_t objectSize = sizeof(object); + if (objectSize > size) { + return 0; + } + return memcpy_s(&object, objectSize, data, objectSize) == EOK ? objectSize : 0; +} + +size_t InitMatrix3(OHOS::Rosen::TransformHelper::Matrix3& mat3, + const uint8_t *data, size_t size, size_t startPos) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return 0; + } + const int maxRow = 3; + const int maxCol = 3; + for (int i = 0; i < maxRow; i++) { + for (int j = 0; j < maxCol; j++) { + startPos += GetObject(mat3.mat_[i][j], data + startPos, size - startPos); + } + } + return startPos; +} + +void InitMatrix4(OHOS::Rosen::TransformHelper::Matrix4& mat4, + const uint8_t *data, size_t size, size_t& startPos) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + const int maxRow = 4; + const int maxCol = 4; + for (int i = 0; i < maxRow; i++) { + for (int j = 0; j < maxCol; j++) { + startPos += GetObject(mat4.mat_[i][j], data + startPos, size - startPos); + } + } +} + +void InitVector2(OHOS::Rosen::TransformHelper::Vector2& vec2, + const uint8_t *data, size_t size, size_t& startPos) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + startPos += GetObject(vec2.x_, data + startPos, size - startPos); + startPos += GetObject(vec2.y_, data + startPos, size - startPos); +} + +void InitVector3(OHOS::Rosen::TransformHelper::Vector3& vec3, + const uint8_t *data, size_t size, size_t& startPos) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + startPos += GetObject(vec3.x_, data + startPos, size - startPos); + startPos += GetObject(vec3.y_, data + startPos, size - startPos); + startPos += GetObject(vec3.y_, data + startPos, size - startPos); +} + +void WindowUtilMathFuzzPart1(const uint8_t *data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + OHOS::Rosen::TransformHelper::Matrix3 left3; + OHOS::Rosen::TransformHelper::Matrix3 right3; + InitMatrix3(left3, data, size, startPos); + InitMatrix3(right3, data, size, startPos); + OHOS::Rosen::TransformHelper::Matrix3 result = left3 * right3; + left3 *= right3; + + OHOS::Rosen::TransformHelper::Matrix4 left4; + OHOS::Rosen::TransformHelper::Matrix4 right4; + InitMatrix4(left4, data, size, startPos); + InitMatrix4(right4, data, size, startPos); + OHOS::Rosen::TransformHelper::Matrix4 result2 = left4 * right4; + left4 *= right4; + left4.Invert(); + left4.GetScale(); + left4.GetTranslation(); + + float theta; + startPos += GetObject(theta, data + startPos, size - startPos); + OHOS::Rosen::TransformHelper::CreateRotation(theta); + OHOS::Rosen::TransformHelper::CreateRotationX(theta); + OHOS::Rosen::TransformHelper::CreateRotationY(theta); + OHOS::Rosen::TransformHelper::CreateRotationZ(theta); + + OHOS::Rosen::TransformHelper::Vector3 scaleVec; + InitVector3(scaleVec, data, size, startPos); + OHOS::Rosen::TransformHelper::CreateScale(scaleVec.x_, scaleVec.y_); + OHOS::Rosen::TransformHelper::CreateScale(scaleVec.x_, scaleVec.y_, scaleVec.z_); + + OHOS::Rosen::TransformHelper::Vector2 vec2; + InitVector2(vec2, data, size, startPos); + OHOS::Rosen::TransformHelper::CreateTranslation(vec2); + + OHOS::Rosen::TransformHelper::Vector3 vec3; + InitVector3(vec3, data, size, startPos); + OHOS::Rosen::TransformHelper::CreateTranslation(vec3); +} + +void WindowUtilMathFuzzPart2(const uint8_t *data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return; + } + size_t startPos = 0; + + OHOS::Rosen::TransformHelper::Vector3 eye, target, up; + InitVector3(eye, data, size, startPos); + InitVector3(target, data, size, startPos); + InitVector3(up, data, size, startPos); + OHOS::Rosen::TransformHelper::CreateLookAt(eye, target, up); + + OHOS::Rosen::TransformHelper::CreatePerspective(eye); + + OHOS::Rosen::TransformHelper::Matrix3 mat3; + InitMatrix3(mat3, data, size, startPos); + OHOS::Rosen::TransformHelper::Vector2 vec2; + InitVector2(vec2, data, size, startPos); + OHOS::Rosen::TransformHelper::Transform(vec2, mat3); + + OHOS::Rosen::TransformHelper::Matrix4 mat4; + InitMatrix4(mat4, data, size, startPos); + OHOS::Rosen::TransformHelper::Vector3 vec3; + InitVector3(vec3, data, size, startPos); + OHOS::Rosen::TransformHelper::Transform(vec3, mat4); + float w; + startPos += GetObject(w, data + startPos, size - startPos); + OHOS::Rosen::TransformHelper::TransformWithPerspDiv(vec3, mat4, w); + OHOS::Rosen::TransformHelper::GetOriginScreenPoint(vec2, mat4); +} + +bool DoWindowUtilMathFuzzTest(const uint8_t* data, size_t size) +{ + if (data == nullptr || size < DATA_MIN_SIZE) { + return false; + } + WindowUtilMathFuzzPart1(data, size); + WindowUtilMathFuzzPart2(data, size); + return true; +} +} // namespace.OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DoWindowUtilMathFuzzTest(data, size); + return 0; +} + diff --git a/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.h b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.h new file mode 100644 index 0000000..df71661 --- /dev/null +++ b/window_manager/test/fuzztest/wms/windowutilmath_fuzzer/windowutilmath_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TEST_FUZZTEST_WINDOW_UTIL_MATH_FUZZER_H +#define TEST_FUZZTEST_WINDOW_UTIL_MATH_FUZZER_H + +#define FUZZ_PROJECT_NAME "windowutilmath_fuzzer" + +#endif \ No newline at end of file diff --git a/window_manager/test/systemtest/BUILD.gn b/window_manager/test/systemtest/BUILD.gn new file mode 100644 index 0000000..e962186 --- /dev/null +++ b/window_manager/test/systemtest/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +group("systemtest") { + testonly = true + deps = [ + "dms:systemtest", + "extension:systemtest", + "wms:systemtest", + ] +} diff --git a/window_manager/test/systemtest/dms/BUILD.gn b/window_manager/test/systemtest/dms/BUILD.gn new file mode 100644 index 0000000..963298d --- /dev/null +++ b/window_manager/test/systemtest/dms/BUILD.gn @@ -0,0 +1,140 @@ +# Copyright (c) 2021-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. + +import("//build/test.gni") + +module_out_path = "window_manager/dms" + +group("systemtest") { + testonly = true + + deps = [ + ":dms_display_change_test", + ":dms_display_manager_test", + ":dms_display_minimal_test", + ":dms_display_power_test", + ":dms_screenshot_test", + ":dms_screen_manager_test", + ] +} + +ohos_systemtest("dms_display_minimal_test") { + module_out_path = module_out_path + + sources = [ "display_minimal_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] +} + +ohos_systemtest("dms_display_manager_test") { + module_out_path = module_out_path + + sources = [ "display_manager_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] +} + +ohos_systemtest("dms_display_power_test") { + module_out_path = module_out_path + + sources = [ "display_power_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] +} + +ohos_systemtest("dms_display_change_test") { + module_out_path = module_out_path + + sources = [ "display_change_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] +} + +ohos_systemtest("dms_screenshot_test") { + module_out_path = module_out_path + + sources = [ "screenshot_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] +} + +ohos_systemtest("dms_screen_manager_test") { + module_out_path = module_out_path + + sources = [ "screen_manager_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] + + external_deps = [ "init:libbegetutil" ] +} + +ohos_systemtest("dms_screen_gamut_test") { + module_out_path = module_out_path + + sources = [ "screen_gamut_test.cpp" ] + + deps = [ ":dms_systemtest_common" ] +} + +## Build dms_systemtest_common.a {{{ +config("dms_systemtest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/test/common/utils/include", + "//foundation/window/window_manager/utils/include", + + # RSSurface + "//foundation/graphic/graphic_2d/interfaces/inner_api/surface", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client", + ] +} + +ohos_static_library("dms_systemtest_common") { + visibility = [ ":*" ] + testonly = true + + sources = [ "display_test_utils.cpp" ] + + public_configs = [ + ":dms_systemtest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//commonlibrary/c_utils/base:utils", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/test/common/utils:libtestutil", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "hilog_native:libhilog", + "ipc:ipc_core", + ] + subsystem_name = "window" + part_name = "window_manager" +} +## Build dms_systemtest_common.a }}} diff --git a/window_manager/test/systemtest/dms/display_change_test.cpp b/window_manager/test/systemtest/dms/display_change_test.cpp new file mode 100644 index 0000000..23e0fd3 --- /dev/null +++ b/window_manager/test/systemtest/dms/display_change_test.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2021-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 "display_cutout_controller.h" +#include "display_info.h" +#include "display_manager.h" +#include "screen_manager.h" +#include "screen_manager/rs_screen_mode_info.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayChangeTest"}; + constexpr uint32_t MAX_TIME_WAITING_FOR_CALLBACK = 20; + constexpr uint32_t SLEEP_TIME_IN_US = 10000; // 10ms + constexpr uint32_t SPLIT_TEST_SLEEP_S = 2; +} + +class DisplayChangeEventListener : public DisplayManager::IDisplayListener { +public: + virtual void OnCreate(DisplayId displayId) + { + WLOGI("DisplayChangeEventListener::OnCreate displayId=%{public}" PRIu64"", displayId); + } + + virtual void OnDestroy(DisplayId displayId) + { + WLOGI("DisplayChangeEventListener::OnDestroy displayId=%{public}" PRIu64"", displayId); + } + + virtual void OnChange(DisplayId displayId) + { + WLOGI("DisplayChangeEventListener::OnChange displayId=%{public}" PRIu64"", displayId); + isCallbackCalled_ = true; + displayId_ = displayId; + } + bool isCallbackCalled_ = false; + DisplayId displayId_ = DISPLAY_ID_INVALID; +}; + +class DisplayChangeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + void ResetDisplayChangeListener(); + bool CheckDisplayChangeEventCallback(bool valueExpected); + bool ScreenSizeEqual(const sptr screen, const sptr curInfo) const; + bool DisplaySizeEqual(const sptr display, const sptr curInfo) const; + inline bool CheckModeSizeChange(const sptr usedInfo, + const sptr curInfo) const; + + static DisplayId defaultDisplayId_; + static sptr defaultScreen_; + static sptr listener_; + static uint32_t originalDisplayDpi; + static inline uint32_t times_ = 0; +}; +DisplayId DisplayChangeTest::defaultDisplayId_ = DISPLAY_ID_INVALID; +sptr DisplayChangeTest::defaultScreen_ = nullptr; +sptr DisplayChangeTest::listener_ = new DisplayChangeEventListener(); +uint32_t DisplayChangeTest::originalDisplayDpi = 0; + +void DisplayChangeTest::SetUpTestCase() +{ + defaultDisplayId_ = DisplayManager::GetInstance().GetDefaultDisplayId(); + ASSERT_NE(DISPLAY_ID_INVALID, defaultDisplayId_); + sptr defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultDisplayId_); + ASSERT_NE(nullptr, defaultDisplay); + ScreenId screenId = defaultDisplay->GetScreenId(); + ASSERT_NE(INVALID_SCREEN_ID, screenId); + defaultScreen_ = ScreenManager::GetInstance().GetScreenById(screenId); + ASSERT_NE(nullptr, defaultScreen_); + + ASSERT_EQ(true, DisplayManager::GetInstance().RegisterDisplayListener(listener_)); +} + +void DisplayChangeTest::TearDownTestCase() +{ + DisplayManager::GetInstance().UnregisterDisplayListener(listener_); +} + +void DisplayChangeTest::SetUp() +{ + times_ = 0; + ResetDisplayChangeListener(); +} + +void DisplayChangeTest::TearDown() +{ +} + +void DisplayChangeTest::ResetDisplayChangeListener() +{ + ASSERT_NE(nullptr, listener_); + listener_->isCallbackCalled_ = false; + listener_->displayId_ = DISPLAY_ID_INVALID; +} + +bool DisplayChangeTest::CheckDisplayChangeEventCallback(bool valueExpected) +{ + WLOGI("CheckDisplayChangeEventCallback in"); + do { + if (listener_->isCallbackCalled_ == valueExpected) { + WLOGI("CheckDisplayChangeEventCallback: get valueExpected %{public}d for display %{public}" PRIu64"", + static_cast(valueExpected), listener_->displayId_); + WLOGI("CheckDisplayChangeEventCallback: already wait times %{public}d", times_); + return true; + } + usleep(SLEEP_TIME_IN_US); + ++times_; + } while (times_ <= MAX_TIME_WAITING_FOR_CALLBACK); + WLOGI("CheckDisplayChangeEventCallback: cannot get valueExpected"); + return false; +} + +bool DisplayChangeTest::ScreenSizeEqual(const sptr screen, const sptr curInfo) const +{ + if (screen == nullptr || curInfo == nullptr) { + WLOGFI("param is nullptr"); + return false; + } + uint32_t sWidth = screen->GetWidth(); + uint32_t sHeight = screen->GetHeight(); + WLOGI("ScreenSizeEqual: ScreenSize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u", + sWidth, sHeight, curInfo->width_, curInfo->height_); + return ((curInfo->width_ == sWidth) && (curInfo->height_ == sHeight)); +} + +bool DisplayChangeTest::DisplaySizeEqual(const sptr display, const sptr curInfo) const +{ + if (display == nullptr || curInfo == nullptr) { + WLOGFI("param is nullptr"); + return false; + } + uint32_t dWidth = static_cast(display->GetWidth()); + uint32_t dHeight = static_cast(display->GetHeight()); + WLOGI("DisplaySizeEqual:: DisplaySize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u", + dWidth, dHeight, curInfo->width_, curInfo->height_); + return ((curInfo->width_ == dWidth) && (curInfo->height_ == dHeight)); +} + + +inline bool DisplayChangeTest::CheckModeSizeChange(const sptr usedInfo, + const sptr curInfo) const +{ + return (usedInfo->width_ != curInfo->width_ || usedInfo->height_ != curInfo->height_); +} + +namespace { +/** + * @tc.name: RegisterDisplayChangeListener01 + * @tc.desc: Register displayChangeListener with valid listener and check return true + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, RegisterDisplayChangeListener01, Function | SmallTest | Level2) +{ + sptr listener = new DisplayChangeEventListener(); + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(listener); + ASSERT_EQ(true, ret); +} + +/** + * @tc.name: RegisterDisplayChangeListener02 + * @tc.desc: Register displayChangeListener with nullptr and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, RegisterDisplayChangeListener02, Function | SmallTest | Level2) +{ + bool ret = DisplayManager::GetInstance().RegisterDisplayListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener01 + * @tc.desc: Unregister displayChangeListener with valid listener and check return true + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener01, Function | SmallTest | Level2) +{ + sptr listener = new DisplayChangeEventListener(); + DisplayManager::GetInstance().RegisterDisplayListener(listener); + bool ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener); + ASSERT_EQ(true, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener02 + * @tc.desc: Register displayChangeListener with nullptr and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener02, Function | SmallTest | Level2) +{ + bool ret = DisplayManager::GetInstance().UnregisterDisplayListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: UnregisterDisplayChangeListener03 + * @tc.desc: Register displayChangeListener with invalid listener and check return false + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener03, Function | SmallTest | Level2) +{ + sptr listener = new DisplayChangeEventListener(); + bool ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: CheckDisplayStateChange01 + * @tc.desc: DisplayState not change if screen sets same mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplayStateChange01, Function | SmallTest | Level2) +{ + WLOGFI("CheckDisplayStateChange01"); + uint32_t usedModeIdx = defaultScreen_->GetModeId(); + defaultScreen_->SetScreenActiveMode(usedModeIdx); + WLOGFI("SetScreenActiveMode: %{public}u", usedModeIdx); + ASSERT_EQ(false, CheckDisplayChangeEventCallback(true)); +} + +/** + * @tc.name: CheckDisplayStateChange02 + * @tc.desc: DisplayState changes if screen sets different mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplayStateChange02, Function | SmallTest | Level2) +{ + WLOGFI("CheckDisplayStateChange02"); + auto modes = defaultScreen_->GetSupportedModes(); + uint32_t usedModeIdx = defaultScreen_->GetModeId(); + WLOGFI("usedModeIdx / SupportMode size: %{public}u %{public}zu", usedModeIdx, modes.size()); + + for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) { + if (modeIdx != usedModeIdx && CheckModeSizeChange(modes[usedModeIdx], modes[modeIdx])) { + defaultScreen_->SetScreenActiveMode(modeIdx); + WLOGFI("SetScreenActiveMode: %{public}u -> %{public}u", usedModeIdx, modeIdx); + ASSERT_EQ(true, CheckDisplayChangeEventCallback(true)); + // reset usedMode + ResetDisplayChangeListener(); + defaultScreen_->SetScreenActiveMode(usedModeIdx); + CheckDisplayChangeEventCallback(true); + break; + } + } +} + +/** + * @tc.name: CheckDisplaySizeChange01 + * @tc.desc: Check screen size change as screen mode set if screen sets another mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplaySizeChange01, Function | MediumTest | Level2) +{ + WLOGFI("CheckDisplaySizeChange01"); + auto modes = defaultScreen_->GetSupportedModes(); + uint32_t usedModeIdx = defaultScreen_->GetModeId(); + WLOGFI("usedModeIdx / SupportMode size: %{public}u %{public}zu", usedModeIdx, modes.size()); + + for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) { + if (modeIdx != usedModeIdx && CheckModeSizeChange(modes[usedModeIdx], modes[modeIdx])) { + defaultScreen_->SetScreenActiveMode(modeIdx); + WLOGFI("SetScreenActiveMode: %{public}u -> %{public}u", usedModeIdx, modeIdx); + ASSERT_EQ(true, ScreenSizeEqual(defaultScreen_, modes[modeIdx])); + ASSERT_EQ(true, CheckDisplayChangeEventCallback(true)); + // reset usedMode + ResetDisplayChangeListener(); + defaultScreen_->SetScreenActiveMode(usedModeIdx); + CheckDisplayChangeEventCallback(true); + break; + } + } +} + +/** + * @tc.name: CheckDisplaySizeChange02 + * @tc.desc: Check display size change as screen mode set if screen sets another mode + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckDisplaySizeChange02, Function | MediumTest | Level2) +{ + WLOGFI("CheckDisplaySizeChange02"); + auto modes = defaultScreen_->GetSupportedModes(); + uint32_t usedModeIdx = defaultScreen_->GetModeId(); + WLOGFI("usedModeIdx / SupportMode size: %{public}u %{public}zu", usedModeIdx, modes.size()); + + for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) { + if (modeIdx != usedModeIdx && CheckModeSizeChange(modes[usedModeIdx], modes[modeIdx])) { + defaultScreen_->SetScreenActiveMode(modeIdx); + WLOGFI("SetScreenActiveMode: %{public}u -> %{public}u", usedModeIdx, modeIdx); + ASSERT_EQ(true, ScreenSizeEqual(defaultScreen_, modes[modeIdx])); + ASSERT_EQ(true, CheckDisplayChangeEventCallback(true)); + sptr defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultDisplayId_); + ASSERT_NE(nullptr, defaultDisplay); + ASSERT_EQ(true, DisplaySizeEqual(defaultDisplay, modes[modeIdx])); + // reset usedMode + ResetDisplayChangeListener(); + defaultScreen_->SetScreenActiveMode(usedModeIdx); + CheckDisplayChangeEventCallback(true); + break; + } + } +} + +/** + * @tc.name: CheckScreenDensityChange01 + * @tc.desc: Check screen density change as set another density for screen + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckScreenDensityChange01, Function | SmallTest | Level2) +{ + DisplayChangeTest::originalDisplayDpi = static_cast(DisplayManager::GetInstance(). + GetDisplayById(defaultDisplayId_)->GetVirtualPixelRatio() * BASELINE_DENSITY); + ASSERT_NE(0, DisplayChangeTest::originalDisplayDpi); + uint32_t densityDpi = 320; + ASSERT_EQ(true, defaultScreen_->SetDensityDpi(densityDpi)); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** + * @tc.name: CheckScreenDensityChange02 + * @tc.desc: Check screen density change as set another density for screen + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckScreenDensityChange02, Function | SmallTest | Level2) +{ + uint32_t densityDpi = 80; + ASSERT_EQ(true, defaultScreen_->SetDensityDpi(densityDpi)); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** + * @tc.name: CheckScreenDensityChange03 + * @tc.desc: Check screen density change as set an invalid density for screen + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckScreenDensityChange03, Function | SmallTest | Level2) +{ + uint32_t densityDpi = 700; + ASSERT_EQ(false, defaultScreen_->SetDensityDpi(densityDpi)); +} + +/** + * @tc.name: CheckScreenDensityChange04 + * @tc.desc: Check screen density change as set an invalid density for screen + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckScreenDensityChange04, Function | SmallTest | Level2) +{ + uint32_t densityDpi = 40; + ASSERT_EQ(false, defaultScreen_->SetDensityDpi(densityDpi)); +} + +/** + * @tc.name: CheckScreenDensityChange05 + * @tc.desc: Restore original display density + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckScreenDensityChange05, Function | SmallTest | Level2) +{ + ASSERT_EQ(true, defaultScreen_->SetDensityDpi(DisplayChangeTest::originalDisplayDpi)); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** + * @tc.name: CheckWaterfallCompression01 + * @tc.desc: check function of waterfall display compression. + * @tc.type: FUNC + */ +HWTEST_F(DisplayChangeTest, CheckWaterfallCompression01, Function | SmallTest | Level2) +{ + bool originWaterfallEnable = DisplayCutoutController::IsWaterfallDisplay(); + DisplayCutoutController::SetIsWaterfallDisplay(true); + + bool originStatus = DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal(); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(true); + + uint32_t originSize = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal(); + uint32_t testSizeInVp = 24; + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSizeInVp); + + ASSERT_EQ(true, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + ASSERT_EQ(testSizeInVp, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + + Orientation originOrientation = defaultScreen_->GetOrientation(); + DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(originSize); + ASSERT_EQ(originSize, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()); + DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(originStatus); + ASSERT_EQ(originStatus, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()); + DisplayCutoutController::SetIsWaterfallDisplay(originWaterfallEnable); + ASSERT_EQ(originOrientation, defaultScreen_->GetOrientation()); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/dms/display_manager_test.cpp b/window_manager/test/systemtest/dms/display_manager_test.cpp new file mode 100644 index 0000000..99bdd71 --- /dev/null +++ b/window_manager/test/systemtest/dms/display_manager_test.cpp @@ -0,0 +1,298 @@ +/* + * 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 "display_test_utils.h" +#include "display.h" +#include "screen.h" +#include "surface_draw.h" +#include "wm_common.h" +#include "wm_common_inner.h" +#include "window.h" +#include "window_option.h" +#include "window_manager_hilog.h" +#include "display_manager_agent_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayManagerTest"}; + const int WAIT_FOR_SYNC_US = 1; // 1s +} + +class DisplayChangeEventListener : public DisplayManager::IDisplayListener { +public: + virtual void OnCreate(DisplayId displayId) {} + + virtual void OnDestroy(DisplayId displayId) {} + + virtual void OnChange(DisplayId displayId) {} +}; + +class DisplayManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + sptr CreateWindow(std::string name, WindowMode mode, Rect rect); + bool DrawWindowColor(const sptr& window, uint32_t color, int32_t width, int32_t height); + static inline DisplayId displayId_; + static inline int32_t displayWidth_; + static inline int32_t displayHeight_; +}; + +void DisplayManagerTest::SetUpTestCase() +{ + displayId_ = DisplayManager::GetInstance().GetDefaultDisplayId(); + sptr display = DisplayManager::GetInstance().GetDefaultDisplay(); + if (display == nullptr) { + return; + } + displayWidth_ = display->GetWidth(); + displayHeight_ = display->GetHeight(); +} + +void DisplayManagerTest::TearDownTestCase() +{ +} + +void DisplayManagerTest::SetUp() +{ +} + +void DisplayManagerTest::TearDown() +{ +} + +sptr DisplayManagerTest::CreateWindow(std::string name, WindowMode mode, Rect rect) +{ + sptr option = new WindowOption(); + option->SetDisplayId(displayId_); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + int32_t width = 0; + int32_t height = 0; + if (mode != WindowMode::WINDOW_MODE_FULLSCREEN) { + option->SetWindowRect(rect); + } else { + width = displayWidth_; + height = displayHeight_; + } + option->SetWindowMode(mode); + option->SetWindowName(name); + sptr window = Window::Create(option->GetWindowName(), option); + if (window == nullptr) { + return nullptr; + } + window->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + window->Show(); + sleep(WAIT_FOR_SYNC_US); // wait for rect updated + width = window->GetRect().width_; + height = window->GetRect().height_; + DrawWindowColor(window, 0x66000000, width, height); // 0x66000000 color_black + RSTransaction::FlushImplicitTransaction(); + return window; +} + +bool DisplayManagerTest::DrawWindowColor(const sptr& window, uint32_t color, int32_t width, int32_t height) +{ + auto surfaceNode = window->GetSurfaceNode(); + if (surfaceNode == nullptr) { + WLOGFE("Failed to GetSurfaceNode!"); + return false; + } + SurfaceDraw::DrawColor(surfaceNode, width, height, color); + surfaceNode->SetAbilityBGAlpha(255); // 255 is alpha + return true; +} + +namespace { +/** + * @tc.name: HasPrivateWindow + * @tc.desc: Check whether there is a private window in the current display + * @tc.type: FUNC + * @tc.require issueI5HF6V + */ +HWTEST_F(DisplayManagerTest, HasPrivateWindow, Function | SmallTest | Level2) +{ + sptr window = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0}); + ASSERT_NE(nullptr, window); + window->SetPrivacyMode(true); + sleep(WAIT_FOR_SYNC_US); + bool hasPrivateWindow = false; + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + + window->SetPrivacyMode(false); + sleep(WAIT_FOR_SYNC_US); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + window->Destroy(); + ASSERT_TRUE(!hasPrivateWindow); +} + +/** + * @tc.name: HasPrivateWindowCovered + * @tc.desc: The private window is covered + * @tc.type: FUNC + * @tc.require issueI5HF6V + */ +HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered, Function | SmallTest | Level2) +{ + sptr window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0}); + ASSERT_NE(nullptr, window1); + // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height + sptr window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING, Rect {10, 120, 650, 500}); + ASSERT_NE(nullptr, window2); + window2->SetPrivacyMode(true); + // 10:rect.posX_, 110:rect.posY_, 650:rect.width, 500:rect.height + sptr window3 = CreateWindow("covered", WindowMode::WINDOW_MODE_FLOATING, Rect {10, 120, 650, 500}); + ASSERT_NE(nullptr, window3); + sleep(WAIT_FOR_SYNC_US); + bool hasPrivateWindow = false; + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + window1->Destroy(); + window2->Destroy(); + window3->Destroy(); + ASSERT_TRUE(!hasPrivateWindow); +} + +/** + * @tc.name: HasPrivateWindowCovered01 + * @tc.desc: The private window is partially covered + * @tc.type: FUNC + * @tc.require issueI5HF6V + */ +HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered01, Function | SmallTest | Level2) +{ + sptr window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0}); + ASSERT_NE(nullptr, window1); + // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height + sptr window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING, Rect {10, 120, 650, 500}); + ASSERT_NE(nullptr, window2); + window2->SetPrivacyMode(true); + // 5:rect.posX_, 110:rect.posY_, 650:rect.width, 500:rect.height + sptr window3 = CreateWindow("covered", WindowMode::WINDOW_MODE_FLOATING, Rect {5, 110, 650, 500}); + ASSERT_NE(nullptr, window3); + sleep(WAIT_FOR_SYNC_US); + bool hasPrivateWindow = false; + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + window1->Destroy(); + window2->Destroy(); + window3->Destroy(); + ASSERT_TRUE(hasPrivateWindow); +} + +/** + * @tc.name: HasPrivateWindowCovered02 + * @tc.desc: The private window is covered + * @tc.type: FUNC + * @tc.require issueI5HF6V + */ +HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered02, Function | SmallTest | Level2) +{ + sptr display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_NE(nullptr, display); + auto vpr = display->GetVirtualPixelRatio(); + uint32_t baseWidth = vpr * MIN_FLOATING_WIDTH; + + sptr window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0}); + ASSERT_NE(nullptr, window1); + // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height + sptr window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING, + Rect {10, 220, baseWidth + 10, 500}); + ASSERT_NE(nullptr, window2); + window2->SetPrivacyMode(true); + // 5:rect.posX_, 110:rect.posY_, 655:rect.width, 500:rect.height + sptr window3 = CreateWindow("covered1", WindowMode::WINDOW_MODE_FLOATING, + Rect {5, 210, baseWidth + 15, 500}); + ASSERT_NE(nullptr, window3); + // 5:rect.posX_, 300:rect.posY_, 655:rect.width, 500:rect.height + sptr window4 = CreateWindow("covered2", WindowMode::WINDOW_MODE_FLOATING, + Rect {5, 400, baseWidth + 15, 500}); + ASSERT_NE(nullptr, window4); + + sleep(WAIT_FOR_SYNC_US); + bool hasPrivateWindow = false; + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + window1->Destroy(); + window2->Destroy(); + window3->Destroy(); + window4->Destroy(); + ASSERT_TRUE(!hasPrivateWindow); +} + +/** + * @tc.name: HasPrivateWindowCovered03 + * @tc.desc: The private window is partially covered + * @tc.type: FUNC + * @tc.require issueI5HF6V + */ +HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered03, Function | SmallTest | Level2) +{ + sptr window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0}); + ASSERT_NE(nullptr, window1); + // 10:rect.posX_, 120:rect.pos_Y, rect.width_:650, rect.height_:700 + sptr window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING, Rect {10, 120, 650, 700}); + ASSERT_NE(nullptr, window2); + window2->SetPrivacyMode(true); + // 5:rect.posX_, 110:rect.pos_Y, rect.width_:655, rect.height_:500 + sptr window3 = CreateWindow("covered1", WindowMode::WINDOW_MODE_FLOATING, Rect {5, 110, 655, 500}); + ASSERT_NE(nullptr, window3); + // 5:rect.posX_, 700:rect.pos_Y, rect.width_:655, rect.height_:500 + sptr window4 = CreateWindow("covered2", WindowMode::WINDOW_MODE_FLOATING, Rect {5, 700, 655, 500}); + ASSERT_NE(nullptr, window4); + + sleep(WAIT_FOR_SYNC_US); + bool hasPrivateWindow = false; + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + window1->Destroy(); + window2->Destroy(); + window3->Destroy(); + window4->Destroy(); + ASSERT_TRUE(hasPrivateWindow); +} + +/** + * @tc.name: HasPrivateWindowSkipSnapShot + * @tc.desc: set snap shot skip + * @tc.type: FUNC + * @tc.require issueI5HF6V + */ +HWTEST_F(DisplayManagerTest, HasPrivateWindowSkipSnapShot, Function | SmallTest | Level2) +{ + sptr window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0}); + ASSERT_NE(nullptr, window1); + // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height + sptr window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING, Rect {10, 120, 650, 500}); + ASSERT_NE(nullptr, window2); + + window2->SetSnapshotSkip(true); + sleep(WAIT_FOR_SYNC_US); + bool hasPrivateWindow = false; + DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId(); + DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow); + window1->Destroy(); + window2->Destroy(); + ASSERT_TRUE(!hasPrivateWindow); +} +} +} // namespace OHOS::Rosen diff --git a/window_manager/test/systemtest/dms/display_minimal_test.cpp b/window_manager/test/systemtest/dms/display_minimal_test.cpp new file mode 100644 index 0000000..e435308 --- /dev/null +++ b/window_manager/test/systemtest/dms/display_minimal_test.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-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 "display_test_utils.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayMinimalTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void DisplayMinimalTest::SetUpTestCase() +{ +} + +void DisplayMinimalTest::TearDownTestCase() +{ +} + +void DisplayMinimalTest::SetUp() +{ +} + +void DisplayMinimalTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: BasicDisplay + * @tc.desc: Check default display id is valid + * @tc.type: FUNC + */ +HWTEST_F(DisplayMinimalTest, BasicDisplay01, Function | MediumTest | Level1) +{ + ASSERT_NE(DISPLAY_ID_INVALID, DisplayManager::GetInstance().GetDefaultDisplayId()); +} + +/** + * @tc.name: BasicDisplay + * @tc.desc: Check default display exists + * @tc.type: FUNC + */ +HWTEST_F(DisplayMinimalTest, BasicDisplay02, Function | MediumTest | Level1) +{ + const sptr& display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_NE(nullptr, display); +} + +/** + * @tc.name: BasicDisplay + * @tc.desc: Check all displays are valid + * @tc.type: FUNC + */ +HWTEST_F(DisplayMinimalTest, BasicDisplay03, Function | MediumTest | Level1) +{ + std::vector ids = DisplayManager::GetInstance().GetAllDisplayIds(); + for (DisplayId id : ids) { + const sptr& display = DisplayManager::GetInstance().GetDisplayById(id); + ASSERT_NE(nullptr, display); + } +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/dms/display_power_test.cpp b/window_manager/test/systemtest/dms/display_power_test.cpp new file mode 100644 index 0000000..ae6c90c --- /dev/null +++ b/window_manager/test/systemtest/dms/display_power_test.cpp @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2021-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 "common_test_utils.h" +#include "display_manager.h" +#include "screen_manager.h" +#include "window.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayPowerTest"}; + constexpr uint32_t MAX_TIME_WAITING_FOR_CALLBACK = 40; + constexpr uint32_t SLEEP_TIME_IN_US = 50000; +} + +class DisplayPowerEventListener : public IDisplayPowerEventListener { +public: + virtual void OnDisplayPowerEvent(DisplayPowerEvent event, EventStatus status) + { + isCallbackCalled_ = true; + event_ = event; + status_ = status; + } + DisplayPowerEvent event_; + EventStatus status_; + bool isCallbackCalled_ { false }; +}; + +class DisplayPowerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static void CheckDisplayStateCallback(bool valueExpected); + static void CheckDisplayPowerEventCallback(bool valueExpected); + + static inline DisplayId defaultId_; + static inline uint32_t brightnessLevel_ = 80; + static inline uint32_t invalidBrightnessLevel_ = 1000000000; + static inline uint32_t times_ = 0; + static inline bool isDisplayStateCallbackCalled_ = false; + static sptr listener_; + + DisplayState state_ { DisplayState::ON }; + DisplayStateCallback callback_ = [this](DisplayState state) { + isDisplayStateCallbackCalled_ = true; + state_ = state; + }; +}; + +sptr DisplayPowerTest::listener_ = new DisplayPowerEventListener(); + +void DisplayPowerTest::SetUpTestCase() +{ + CommonTestUtils::SetAceessTokenPermission("SetDisplayState"); + defaultId_ = DisplayManager::GetInstance().GetDefaultDisplayId(); + if (defaultId_ == DISPLAY_ID_INVALID) { + WLOGFE("GetDefaultDisplayId failed!"); + } + DisplayManager::GetInstance().RegisterDisplayPowerEventListener(listener_); +} + +void DisplayPowerTest::TearDownTestCase() +{ + DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener_); +} + +void DisplayPowerTest::SetUp() +{ + times_ = 0; + + isDisplayStateCallbackCalled_ = false; + state_ = DisplayState::UNKNOWN; + + listener_->isCallbackCalled_ = false; + listener_->event_ = static_cast(-1); + listener_->status_ = static_cast(-1); +} + +void DisplayPowerTest::TearDown() +{ +} + +void DisplayPowerTest::CheckDisplayStateCallback(bool valueExpected) +{ + do { + if (isDisplayStateCallbackCalled_ == valueExpected) { + return; + } + usleep(SLEEP_TIME_IN_US); + ++times_; + } while (times_ <= MAX_TIME_WAITING_FOR_CALLBACK); +} + +void DisplayPowerTest::CheckDisplayPowerEventCallback(bool valueExpected) +{ + do { + if (listener_->isCallbackCalled_ == valueExpected) { + return; + } + usleep(SLEEP_TIME_IN_US); + ++times_; + } while (times_ <= MAX_TIME_WAITING_FOR_CALLBACK); +} + +namespace { +/** + * @tc.name: register_display_power_event_listener_001 + * @tc.desc: call RegisterDisplayPowerEventListener with a valid listener and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, register_display_power_event_listener_001, Function | SmallTest | Level2) +{ + sptr listener = new DisplayPowerEventListener(); + bool ret = DisplayManager::GetInstance().RegisterDisplayPowerEventListener(listener); + ASSERT_EQ(true, ret); + DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener); +} + +/** + * @tc.name: register_display_power_event_listener_002 + * @tc.desc: call RegisterDisplayPowerEventListener with an invalid listener and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, register_display_power_event_listener_002, Function | SmallTest | Level2) +{ + bool ret = DisplayManager::GetInstance().RegisterDisplayPowerEventListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: unregister_display_power_event_listener_001 + * @tc.desc: call UnregisterDisplayPowerEventListener with a valid listener and check return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, unregister_display_power_event_listener_001, Function | SmallTest | Level2) +{ + sptr listener = new DisplayPowerEventListener(); + DisplayManager::GetInstance().RegisterDisplayPowerEventListener(listener); + bool ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener); + ASSERT_EQ(true, ret); +} + +/** +* @tc.name: unregister_display_power_event_listener_002 +* @tc.desc: call UnregisterDisplayPowerEventListener with nullptr and check return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, unregister_display_power_event_listener_002, Function | SmallTest | Level2) +{ + bool ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(nullptr); + ASSERT_EQ(false, ret); +} + +/** +* @tc.name: unregister_display_power_event_listener_003 +* @tc.desc: call UnregisterDisplayPowerEventListener with an invalid listener and check return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, unregister_display_power_event_listener_003, Function | SmallTest | Level2) +{ + sptr listener = new DisplayPowerEventListener(); + bool ret = DisplayManager::GetInstance().UnregisterDisplayPowerEventListener(listener); + ASSERT_EQ(false, ret); +} + +/** + * @tc.name: set_display_state_001 + * @tc.desc: Call SetDisplayState and check if it the state set is the same as calling GetDisplayState + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, set_display_state_001, Function | MediumTest | Level2) +{ + DisplayState initialState = DisplayManager::GetInstance().GetDisplayState(defaultId_); + DisplayState stateToSet = (initialState == DisplayState::OFF ? DisplayState::ON : DisplayState::OFF); + bool ret = DisplayManager::GetInstance().SetDisplayState(stateToSet, callback_); + ASSERT_EQ(true, ret); + DisplayState stateGet = DisplayManager::GetInstance().GetDisplayState(defaultId_); + ASSERT_EQ(stateGet, stateToSet); + CheckDisplayStateCallback(true); +} + +/** + * @tc.name: set_display_state_002 + * @tc.desc: Call SetDisplayState to set a value already set and check the return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, set_display_state_002, Function | MediumTest | Level2) +{ + DisplayState initialState = DisplayManager::GetInstance().GetDisplayState(defaultId_); + bool ret = DisplayManager::GetInstance().SetDisplayState(initialState, callback_); + ASSERT_EQ(false, ret); + DisplayState stateGet = DisplayManager::GetInstance().GetDisplayState(defaultId_); + ASSERT_EQ(stateGet, initialState); + CheckDisplayStateCallback(false); + ASSERT_EQ(false, isDisplayStateCallbackCalled_); +} + +/** + * @tc.name: set_display_state_003 + * @tc.desc: Call SetDisplayState with an invalid value and check the return value + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, set_display_state_003, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().SetDisplayState(DisplayState::UNKNOWN, callback_); + ASSERT_EQ(false, ret); + CheckDisplayStateCallback(false); + ASSERT_EQ(false, isDisplayStateCallbackCalled_); + CheckDisplayPowerEventCallback(false); + ASSERT_EQ(false, listener_->isCallbackCalled_); +} + +/** + * @tc.name: set_display_state_callback_001 + * @tc.desc: Call SetDisplayState and check if callback state is correct + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, set_display_state_callback_001, Function | MediumTest | Level2) +{ + DisplayState initialState = DisplayManager::GetInstance().GetDisplayState(defaultId_); + DisplayState stateToSet = (initialState == DisplayState::OFF ? DisplayState::ON : DisplayState::OFF); + DisplayManager::GetInstance().SetDisplayState(stateToSet, callback_); + CheckDisplayStateCallback(true); + ASSERT_EQ(true, isDisplayStateCallbackCalled_); + ASSERT_EQ(state_, stateToSet); +} + +/** + * @tc.name: set_display_state_callback_002 + * @tc.desc: Call SetDisplayState to set a value already set and check the DisplayStateCallback + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, set_display_state_callback_002, Function | MediumTest | Level2) +{ + DisplayState initialState = DisplayManager::GetInstance().GetDisplayState(defaultId_); + DisplayManager::GetInstance().SetDisplayState(initialState, callback_); + CheckDisplayStateCallback(false); + ASSERT_EQ(false, isDisplayStateCallbackCalled_); +} + +/** + * @tc.name: wake_up_begin_callback_001 + * @tc.desc: Call WakeUpBegin and check the OnDisplayPowerEvent callback is called + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, wake_up_begin_callback_001, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().WakeUpBegin(PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + ASSERT_EQ(DisplayPowerEvent::WAKE_UP, listener_->event_); + ASSERT_EQ(EventStatus::BEGIN, listener_->status_); +} + +/** + * @tc.name: wake_up_end_callback_001 + * @tc.desc: Call WakeUpEnd and check the OnDisplayPowerEvent callback is called + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, wake_up_end_callback_001, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().WakeUpEnd(); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + ASSERT_EQ(DisplayPowerEvent::WAKE_UP, listener_->event_); + ASSERT_EQ(EventStatus::END, listener_->status_); +} + +/** + * @tc.name: suspend_begin_callback_001 + * @tc.desc: Call SuspendBegin and check the OnDisplayPowerEvent callback is called + * @tc.type: FUNC + */ +HWTEST_F(DisplayPowerTest, suspend_begin_callback_001, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().SuspendBegin(PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + ASSERT_EQ(DisplayPowerEvent::SLEEP, listener_->event_); + ASSERT_EQ(EventStatus::BEGIN, listener_->status_); +} + +/** +* @tc.name: suspend_end_callback_001 +* @tc.desc: Call SuspendEnd and check the OnDisplayPowerEvent callback is called +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, suspend_end_callback_001, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().SuspendEnd(); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + ASSERT_EQ(DisplayPowerEvent::SLEEP, listener_->event_); + ASSERT_EQ(EventStatus::END, listener_->status_); +} + +/** +* @tc.name: set_screen_power_for_all_001 +* @tc.desc: Call SetScreenPowerForAll OFF and check the OnDisplayPowerEvent callback is called +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, set_screen_power_for_all_001, Function | MediumTest | Level2) +{ + bool ret = ScreenManager::GetInstance().SetScreenPowerForAll(ScreenPowerState::POWER_OFF, + PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + ASSERT_EQ(DisplayPowerEvent::DISPLAY_OFF, listener_->event_); + ASSERT_EQ(EventStatus::END, listener_->status_); +} + +/** +* @tc.name: set_screen_power_for_all_002 +* @tc.desc: Call SetScreenPowerForAll ON and check the OnDisplayPowerEvent callback is called +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, set_screen_power_for_all_002, Function | MediumTest | Level2) +{ + bool ret = ScreenManager::GetInstance().SetScreenPowerForAll(ScreenPowerState::POWER_ON, + PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + ASSERT_EQ(DisplayPowerEvent::DISPLAY_ON, listener_->event_); + ASSERT_EQ(EventStatus::END, listener_->status_); +} + +/** +* @tc.name: set_screen_power_for_all_003 +* @tc.desc: Call SetScreenPowerForAll with an invalid value and check the return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, set_screen_power_for_all_003, Function | MediumTest | Level2) +{ + bool ret = ScreenManager::GetInstance().SetScreenPowerForAll(ScreenPowerState::INVALID_STATE, + PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(false, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(false, listener_->isCallbackCalled_); +} + +/** +* @tc.name: set_display_state_power_event_callback_001 +* @tc.desc: Call SetDisplayState with a valid value and check the OnDisplayPowerEvent callback is called +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, set_display_state_power_event_callback_001, Function | MediumTest | Level2) +{ + DisplayState initialState = DisplayManager::GetInstance().GetDisplayState(defaultId_); + DisplayState stateToSet = (initialState == DisplayState::OFF ? DisplayState::ON : DisplayState::OFF); + bool ret = DisplayManager::GetInstance().SetDisplayState(stateToSet, callback_); + ASSERT_EQ(true, ret); + CheckDisplayPowerEventCallback(true); + ASSERT_EQ(true, listener_->isCallbackCalled_); + DisplayPowerEvent expectedEvent = (stateToSet == DisplayState::OFF ? DisplayPowerEvent::DISPLAY_OFF : + DisplayPowerEvent::DISPLAY_ON); + ASSERT_EQ(expectedEvent, listener_->event_); + ASSERT_EQ(EventStatus::BEGIN, listener_->status_); +} + +/** +* @tc.name: get_display_power_002 +* @tc.desc: Call SetScreenPowerForAll ON and check the GetScreenPower return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, get_display_power_002, Function | MediumTest | Level2) +{ + ScreenPowerState stateToSet = ScreenPowerState::POWER_ON; + bool ret = ScreenManager::GetInstance().SetScreenPowerForAll(stateToSet, PowerStateChangeReason::POWER_BUTTON); + ASSERT_EQ(true, ret); + ScreenPowerState stateGet = ScreenManager::GetInstance().GetScreenPower(defaultId_); + ASSERT_EQ(stateGet, stateToSet); +} + +/** +* @tc.name: set_screen_brightness_001 +* @tc.desc: Call SetScreenBrightness with a valid value and check the GetScreenBrightness return value +* @tc.type: FUNC +*/ +HWTEST_F(DisplayPowerTest, set_screen_brightness_001, Function | MediumTest | Level2) +{ + bool ret = DisplayManager::GetInstance().SetScreenBrightness(defaultId_, brightnessLevel_); + ASSERT_EQ(true, ret); + uint32_t level = DisplayManager::GetInstance().GetScreenBrightness(defaultId_); + ASSERT_EQ(level, brightnessLevel_); +} + +/** +* @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->GetWindowState() == WindowState::STATE_SHOWN); + + DisplayManager::GetInstance().NotifyDisplayEvent(DisplayEvent::UNLOCK); + usleep(SLEEP_TIME_IN_US); + ASSERT_EQ(true, window->GetWindowState() == WindowState::STATE_SHOWN); + + window->Destroy(); +} +} // namespace +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/dms/display_test_utils.cpp b/window_manager/test/systemtest/dms/display_test_utils.cpp new file mode 100644 index 0000000..999917a --- /dev/null +++ b/window_manager/test/systemtest/dms/display_test_utils.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021-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 "display_test_utils.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayTestUtils"}; +} + +DisplayTestUtils::~DisplayTestUtils() +{ + if (csurface_ != nullptr) { + if (prevBuffer_ != nullptr) { + SurfaceError ret = csurface_->ReleaseBuffer(prevBuffer_, -1); + if (ret != SURFACE_ERROR_OK) { + WLOGFE("buffer release failed"); + return; + } + WLOGFI("prevBuffer_ release success"); + } + csurface_->UnregisterConsumerListener(); + } + + csurface_ = nullptr; + psurface_ = nullptr; + listener_ = nullptr; + prevBuffer_ = nullptr; + bufferHandle_ = nullptr; +} + +bool DisplayTestUtils::SizeEqualToDisplay(const sptr& display, const Media::Size cur) +{ + int32_t dWidth = display->GetWidth(); + int32_t dHeight = display->GetHeight(); + + bool res = ((cur.width == dWidth) && (cur.height == dHeight)); + if (!res) { + WLOGFE("DisplaySize: %d %d, CurrentSize: %d %d", dWidth, dHeight, cur.width, cur.height); + } + return res; +} + +bool DisplayTestUtils::SizeEqual(const Media::Size dst, const Media::Size cur) +{ + bool res = ((cur.width == dst.width) && (cur.height == dst.height)); + if (!res) { + WLOGFE("Desired Size: %d %d, Current Size: %d %d", dst.width, dst.height, cur.width, cur.height); + } + return res; +} + +bool DisplayTestUtils::CreateSurface() +{ + csurface_ = Surface::CreateSurfaceAsConsumer(); + if (csurface_ == nullptr) { + WLOGFE("csurface create failed"); + return false; + } + + auto producer = csurface_->GetProducer(); + psurface_ = Surface::CreateSurfaceAsProducer(producer); + if (psurface_ == nullptr) { + WLOGFE("csurface create failed"); + return false; + } + + listener_ = new BufferListener(*this); + SurfaceError ret = csurface_->RegisterConsumerListener(listener_); + if (ret != SURFACE_ERROR_OK) { + WLOGFE("listener register failed"); + return false; + } + return true; +} + +void DisplayTestUtils::OnVsync() +{ + std::lock_guard lock(mutex_); + WLOGFI("DisplayTestUtils::OnVsync"); + sptr cbuffer = nullptr; + int32_t fence = -1; + int64_t timestamp = 0; + OHOS::Rect damage; + if (csurface_ == nullptr) { + WLOGFE("csurface_ is null"); + return; + } + auto sret = csurface_->AcquireBuffer(cbuffer, fence, timestamp, damage); + UniqueFd fenceFd(fence); + if (cbuffer == nullptr || sret != OHOS::SURFACE_ERROR_OK) { + WLOGFE("acquire buffer failed"); + return; + } + bufferHandle_ = cbuffer->GetBufferHandle(); + if (bufferHandle_ == nullptr) { + WLOGFE("get bufferHandle failed"); + return; + } + if (defaultWidth_ == static_cast(bufferHandle_->width) && + defaultHeight_ == static_cast(bufferHandle_->height)) { + successCount_++; + WLOGFI("compareWH is successful in onVsync: %d", successCount_); + } else { + failCount_++; + } + if (cbuffer != prevBuffer_) { + if (prevBuffer_ != nullptr) { + SurfaceError ret = csurface_->ReleaseBuffer(prevBuffer_, -1); + if (ret != SURFACE_ERROR_OK) { + WLOGFE("buffer release failed"); + return; + } + } + prevBuffer_ = cbuffer; + } +} + +void DisplayTestUtils::SetDefaultWH(const sptr& display) +{ + defaultWidth_ = display->GetWidth(); + defaultHeight_ = display->GetHeight(); +} +} // namespace ROSEN +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/dms/display_test_utils.h b/window_manager/test/systemtest/dms/display_test_utils.h new file mode 100644 index 0000000..7d95d69 --- /dev/null +++ b/window_manager/test/systemtest/dms/display_test_utils.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021-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 FRAMEWORKS_DM_TEST_ST_DISPLAY_TEST_UTILS_H +#define FRAMEWORKS_DM_TEST_ST_DISPLAY_TEST_UTILS_H + +#include + +#include "display_manager.h" +#include "screen_manager.h" +#include "display_property.h" +#include "display.h" +#include "screen.h" +#include "display_info.h" +#include "wm_common.h" +#include "dm_common.h" +#include "window_manager_hilog.h" +#include "unique_fd.h" +#include "ui/rs_surface_node.h" +#include "ui/rs_display_node.h" + +namespace OHOS { +namespace Rosen { +class DisplayTestUtils { +public: + ~DisplayTestUtils(); + static bool SizeEqualToDisplay(const sptr& display, const Media::Size cur); + static bool SizeEqual(const Media::Size dst, const Media::Size cur); + void init(); + bool CreateSurface(); + void SetDefaultWH(const sptr& display); + class BufferListener : public IBufferConsumerListener { + public: + explicit BufferListener(DisplayTestUtils &displayTestUtils): utils_(displayTestUtils) + { + } + ~BufferListener() noexcept override = default; + void OnBufferAvailable() override + { + utils_.OnVsync(); + } + + private: + DisplayTestUtils &utils_; + }; + friend class BufferListener; + + void OnVsync(); + uint32_t successCount_ = 0; + uint32_t failCount_ = 0; + uint32_t defaultWidth_ = 0; + uint32_t defaultHeight_ = 0; + sptr listener_ = nullptr; + sptr csurface_ = nullptr; // cosumer surface + sptr psurface_ = nullptr; // producer surface + sptr prevBuffer_ = nullptr; + BufferHandle *bufferHandle_ = nullptr; + +private: + std::mutex mutex_; +}; +} // namespace ROSEN +} // namespace OHOS +#endif // FRAMEWORKS_DM_TEST_ST_DISPLAY_TEST_UTILS_H diff --git a/window_manager/test/systemtest/dms/screen_gamut_test.cpp b/window_manager/test/systemtest/dms/screen_gamut_test.cpp new file mode 100644 index 0000000..3e3c4d9 --- /dev/null +++ b/window_manager/test/systemtest/dms/screen_gamut_test.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2021-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 "dm_common.h" +#include "screen_manager.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class ScreenGamutTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static sptr defaultScreen_; +}; + +sptr ScreenGamutTest::defaultScreen_ = nullptr; + +void ScreenGamutTest::SetUpTestCase() +{ + auto screens = ScreenManager::GetInstance().GetAllScreens(); + if (screens.size() > 0) { + defaultScreen_ = screens[0]; + } +} + +void ScreenGamutTest::TearDownTestCase() +{ + defaultScreen_ = nullptr; +} + +void ScreenGamutTest::SetUp() +{ +} + +void ScreenGamutTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetScreenSupportedColorGamuts01 + * @tc.desc: gamut GetScreenSupportedColorGamuts + * @tc.type: FUNC + */ +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); + ASSERT_GT(colorGamuts.size(), 0); +} + +/** + * @tc.name: GetScreenColorGamut01 + * @tc.desc: gamut GetScreenColorGamut + * @tc.type: FUNC + */ +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; + ScreenGamutMap gamutMap; + + ret = defaultScreen_->GetScreenGamutMap(gamutMap); + ASSERT_EQ(ret, DMError::DM_OK); +} + +/** + * @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: SetScreenColorTransform01 + * @tc.desc: gamut SetScreenColorTransform + * @tc.type: FUNC + */ +HWTEST_F(ScreenGamutTest, SetScreenColorTransform01, Function | MediumTest | Level3) +{ + ASSERT_NE(defaultScreen_, nullptr); + DMError ret; + + ret = defaultScreen_->SetScreenColorTransform(); + ASSERT_EQ(ret, DMError::DM_OK); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/dms/screen_manager_test.cpp b/window_manager/test/systemtest/dms/screen_manager_test.cpp new file mode 100644 index 0000000..e746eac --- /dev/null +++ b/window_manager/test/systemtest/dms/screen_manager_test.cpp @@ -0,0 +1,812 @@ +/* + * Copyright (c) 2021-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 "common_test_utils.h" +#include "display_test_utils.h" +#include "future.h" +#include "screen.h" +#include "surface_draw.h" +#include "virtual_screen_group_change_listener_future.h" +#include "window.h" +#include "window_option.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenManagerTest"}; + constexpr uint32_t COLOR_RED = 0xffff0000; +} +class ScreenGroupChangeListener; +class ScreenManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + sptr CreateWindowByDisplayId(DisplayId displayId); + bool DrawWindowColor(const sptr& window, uint32_t color); + void CheckScreenStateInGroup(bool, sptr, ScreenId, sptr, ScreenId); + void CheckScreenGroupState(ScreenCombination, ScreenGroupChangeEvent event, ScreenId, + sptr, sptr); + void CheckScreenGroupStateForMirror(ScreenGroupChangeEvent event, std::vector mirrorIds, + sptr virtualScreenGroupChangeListener); + static sptr defaultDisplay_; + static DisplayId defaultDisplayId_; + static ScreenId defaultScreenId_; + static std::string defaultName_; + static uint32_t defaultWidth_; + static uint32_t defaultHeight_; + static float defaultDensity_; + static int32_t defaultFlags_; + static VirtualScreenOption defaultOption_; + static uint32_t waitCount_; + const uint32_t sleepUs_ = 10 * 1000; + const uint32_t maxWaitCount_ = 2000; + const uint32_t execTimes_ = 10; + const uint32_t acquireFrames_ = 1; + static constexpr uint32_t TEST_SLEEP_S = 1; // test sleep time + static constexpr uint32_t TEST_SLEEP_S_LONG = 10; // test sleep for 10 seconds + static constexpr long TIME_OUT = 1000; +}; + +class ScreenChangeListener : public ScreenManager::IScreenListener { +public: + virtual void OnConnect(ScreenId screenId) override + { + WLOGFI("OnConnect, screenId:%{public}" PRIu64"", screenId); + connectFuture_.SetValue(screenId); + } + virtual void OnDisconnect(ScreenId screenId) override + { + WLOGFI("OnDisconnect, screenId:%{public}" PRIu64"", screenId); + disconnectFuture_.SetValue(screenId); + } + virtual void OnChange(ScreenId screenId) override + { + WLOGFI("OnChange, screenId:%{public}" PRIu64"", screenId); + changeFuture_.SetValue(screenId); + } + RunnableFuture connectFuture_; + RunnableFuture disconnectFuture_; + RunnableFuture changeFuture_; +}; + +class ScreenGroupChangeListener : public ScreenManager::IScreenGroupListener { +public: + virtual void OnChange(const std::vector& screenIds, ScreenGroupChangeEvent event) override + { + for (auto screenId : screenIds) { + changeFuture_.SetValue(std::make_pair(screenId, event)); + usleep(10 * 1000); // wait 10000 us + } + } + RunnableFuture> changeFuture_; +}; + +sptr ScreenManagerTest::defaultDisplay_ = nullptr; +DisplayId ScreenManagerTest::defaultDisplayId_ = DISPLAY_ID_INVALID; +ScreenId ScreenManagerTest::defaultScreenId_ = INVALID_SCREEN_ID; +std::string ScreenManagerTest::defaultName_ = "virtualScreen01"; +uint32_t ScreenManagerTest::defaultWidth_ = 480; +uint32_t ScreenManagerTest::defaultHeight_ = 320; +float ScreenManagerTest::defaultDensity_ = 2.0; +int32_t ScreenManagerTest::defaultFlags_ = 0; +VirtualScreenOption ScreenManagerTest::defaultOption_ = { + defaultName_, defaultWidth_, defaultHeight_, defaultDensity_, nullptr, defaultFlags_ +}; +uint32_t ScreenManagerTest::waitCount_ = 0; + +void ScreenManagerTest::SetUpTestCase() +{ + defaultDisplay_ = DisplayManager::GetInstance().GetDefaultDisplay(); + defaultDisplayId_ = defaultDisplay_->GetId(); + defaultScreenId_ = defaultDisplay_->GetScreenId(); + defaultWidth_ = defaultDisplay_->GetWidth(); + defaultHeight_ = defaultDisplay_->GetHeight(); + defaultOption_.width_ = defaultWidth_; + defaultOption_.height_ = defaultHeight_; + + CommonTestUtils::InjectTokenInfoByHapName(0, "com.ohos.systemui", 0); +} + +void ScreenManagerTest::TearDownTestCase() +{ +} + +void ScreenManagerTest::SetUp() +{ +} + +void ScreenManagerTest::TearDown() +{ +} + + +bool ScreenManagerTest::DrawWindowColor(const sptr& window, uint32_t color) +{ + auto surfaceNode = window->GetSurfaceNode(); + if (surfaceNode == nullptr) { + WLOGFE("Failed to GetSurfaceNode!"); + return false; + } + Rect rect = window->GetRequestRect(); + uint32_t windowWidth = rect.width_; + uint32_t windowHeight = rect.height_; + WLOGFI("windowWidth: %{public}u, windowHeight: %{public}u", windowWidth, windowHeight); + SurfaceDraw::DrawColor(surfaceNode, windowWidth, windowHeight, color); + return true; +} + +sptr ScreenManagerTest::CreateWindowByDisplayId(DisplayId displayId) +{ + sptr option = new WindowOption(); + if (option == nullptr) { + return nullptr; + } + Rect displayRect = {0, 0, 640, 480}; + option->SetDisplayId(displayId); + option->SetWindowRect(displayRect); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowName("VirtualWindow01"); + sptr window = Window::Create(option->GetWindowName(), option); + return window; +} + +#define CHECK_TEST_INIT_SCREEN_STATE \ + std::vector> allScreens = ScreenManager::GetInstance().GetAllScreens(); \ + ASSERT_LT(0, allScreens.size()); \ + ScreenId groupId = SCREEN_ID_INVALID; \ + for (auto screen : allScreens) { \ + if (screen->IsGroup()) { \ + groupId = screen->GetId(); \ + ASSERT_EQ(SCREEN_ID_INVALID, screen->GetParentId()); \ + } \ + } \ + ASSERT_NE(SCREEN_ID_INVALID, groupId); \ + auto group = ScreenManager::GetInstance().GetScreenGroup(groupId); \ + ASSERT_NE(nullptr, group); \ + ASSERT_EQ(groupId, group->GetId()); \ + sptr screenListener = new ScreenChangeListener(); \ + sptr screenGroupChangeListener = new ScreenGroupChangeListener(); \ + sptr virtualScreenGroupChangeListener \ + = new VirtualScreenGroupChangeListenerFuture(); \ + ScreenManager::GetInstance().RegisterScreenListener(screenListener); \ + ScreenManager::GetInstance().RegisterScreenGroupListener(screenGroupChangeListener); \ + ScreenManager::GetInstance().RegisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); \ + +#define CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN \ + auto virtualScreen = ScreenManager::GetInstance().GetScreenById(virtualScreenId); \ + ASSERT_NE(nullptr, virtualScreen); \ + ASSERT_EQ(virtualScreenId, virtualScreen->GetId()); \ + ScreenId screenId = screenListener->connectFuture_.GetResult(TIME_OUT); \ + screenListener->connectFuture_.Reset(SCREEN_ID_INVALID); \ + ASSERT_EQ(virtualScreenId, screenId); \ + +void ScreenManagerTest::CheckScreenStateInGroup( + bool isInGroup, sptr group, ScreenId groupId, sptr virtualScreen, ScreenId virtualScreenId) +{ + auto childIds = group->GetChildIds(); + ASSERT_LT(0, childIds.size()); + auto iter = std::find(childIds.begin(), childIds.end(), virtualScreenId); + if (isInGroup) { + ASSERT_EQ(groupId, virtualScreen->GetParentId()); + } else { + ASSERT_EQ(SCREEN_ID_INVALID, virtualScreen->GetParentId()); + } + if (isInGroup) { + ASSERT_NE(childIds.end(), iter); + } else { + ASSERT_EQ(childIds.end(), iter); + } +} + +void ScreenManagerTest::CheckScreenGroupState(ScreenCombination combination, ScreenGroupChangeEvent event, + ScreenId virtualScreenId, sptr group, sptr screenGroupChangeListener) +{ + auto pair = screenGroupChangeListener->changeFuture_.GetResult(TIME_OUT); + screenGroupChangeListener->changeFuture_.Reset( + std::make_pair(SCREEN_ID_INVALID, ScreenGroupChangeEvent::REMOVE_FROM_GROUP)); + ASSERT_EQ(virtualScreenId, pair.first); + ASSERT_EQ(event, pair.second); + ASSERT_EQ(combination, group->GetCombination()); +} + +void ScreenManagerTest::CheckScreenGroupStateForMirror(ScreenGroupChangeEvent event, std::vector mirrorIds, + sptr virtualScreenGroupChangeListener) +{ + auto info = virtualScreenGroupChangeListener->mirrorChangeFuture_.GetResult(TIME_OUT); + virtualScreenGroupChangeListener->mirrorChangeFuture_.Reset({ScreenGroupChangeEvent::CHANGE_GROUP, "", {}}); + ASSERT_EQ(info.event, event); + ASSERT_EQ(info.ids, mirrorIds); + ASSERT_GE(info.trigger.size(), 0UL); +} + +#define CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN \ + { \ + auto screenId = screenListener->disconnectFuture_.GetResult(TIME_OUT); \ + screenListener->disconnectFuture_.Reset(SCREEN_ID_INVALID); \ + ASSERT_EQ(virtualScreenId, screenId); \ + } + +namespace { +/** + * @tc.name: ScreenManager01 + * @tc.desc: Create a virtual screen and destroy it + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager01, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); +} + +/** + * @tc.name: ScreenManager02 + * @tc.desc: Create a virtual screen as mirror of default screen, and destroy virtual screen + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager02, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorIds); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); +} + +/** + * @tc.name: ScreenManager03 + * @tc.desc: Create a virtual screen and destroy it for 10 times + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager03, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + defaultOption_.isForShot_ = false; + for (uint32_t i = 0; i < execTimes_; i++) { + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + usleep(sleepUs_); + } +} + +/** + * @tc.name: ScreenManager04 + * @tc.desc: Create a virtual screen as mirror of default screen, and destroy virtual screen for 10 times + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager04, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + defaultOption_.isForShot_ = false; + for (uint32_t i = 0; i < execTimes_; i++) { + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorIds); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + usleep(sleepUs_); + } +} + +/** + * @tc.name: ScreenManager05 + * @tc.desc: Compare the length and width for recording screen + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager05, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + utils.SetDefaultWH(defaultDisplay_); + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = true; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + uint32_t lastCount = -1u; + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorIds); + + while (utils.successCount_ < acquireFrames_ && waitCount_ <= maxWaitCount_) { + if (lastCount != utils.successCount_) { + lastCount = utils.successCount_; + } + ASSERT_EQ(0, utils.failCount_); + waitCount_++; + usleep(sleepUs_); + } + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + ASSERT_GT(utils.successCount_, 0); + ASSERT_GT(maxWaitCount_, waitCount_); + waitCount_ = 0; +} + +/** + * @tc.name: ScreenManager06 + * @tc.desc: Compare the length and width for recording screen, set VirtualScreen Surface before make mirror. + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager06, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + utils.SetDefaultWH(defaultDisplay_); + defaultOption_.surface_ = nullptr; + defaultOption_.isForShot_ = true; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + + ASSERT_TRUE(utils.CreateSurface()); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().SetVirtualScreenSurface(virtualScreenId, utils.psurface_)); + + uint32_t lastCount = -1u; + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorIds); + + while (utils.successCount_ < acquireFrames_ && waitCount_ <= maxWaitCount_) { + if (lastCount != utils.successCount_) { + lastCount = utils.successCount_; + } + ASSERT_EQ(0, utils.failCount_); + waitCount_++; + usleep(sleepUs_); + } + DMError res = ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId); + ASSERT_EQ(DMError::DM_OK, res); + ASSERT_GT(utils.successCount_, 0); + ASSERT_GT(maxWaitCount_, waitCount_); + waitCount_ = 0; +} + +/** + * @tc.name: ScreenManager07 + * @tc.desc: Get and set screenMode + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager07, 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)); + sleep(TEST_SLEEP_S); + ASSERT_EQ(modeIdx, screen->GetModeId()); + } + ASSERT_EQ(true, screen->SetScreenActiveMode(defaultModeId)); + sleep(TEST_SLEEP_S); +} + +/** + * @tc.name: ScreenManager08 + * @tc.desc: Create a virtual screen as expansion of default screen, and destroy virtual screen + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager08, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + std::vector> screens = ScreenManager::GetInstance().GetAllScreens(); + sptr defaultScreen = screens.front(); + std::vector options = {{defaultScreen->GetId(), 0, 0}, {virtualScreenId, defaultWidth_, 0}}; + ScreenId expansionGroup = ScreenManager::GetInstance().MakeExpand(options); + ASSERT_NE(SCREEN_ID_INVALID, expansionGroup); + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); +} + +/** + * @tc.name: ScreenManager09 + * @tc.desc: Create a virtual screen as expansion of default screen, create windowNode on virtual screen, + * and destroy virtual screen + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager09, Function | MediumTest | Level2) +{ + system::SetParameter("rosen.uni.partialrender.enabled", "0"); + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + sleep(TEST_SLEEP_S); + std::vector options = {{defaultScreenId_, 0, 0}, {virtualScreenId, defaultWidth_, 0}}; + ScreenId expansionId = ScreenManager::GetInstance().MakeExpand(options); + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + sleep(TEST_SLEEP_S); + ASSERT_NE(SCREEN_ID_INVALID, expansionId); + DisplayId virtualDisplayId = DisplayManager::GetInstance().GetDisplayByScreen(virtualScreenId)->GetId(); + ASSERT_NE(DISPLAY_ID_INVALID, virtualDisplayId); + sptr window = CreateWindowByDisplayId(virtualDisplayId); + ASSERT_NE(nullptr, window); + ASSERT_EQ(true, DrawWindowColor(window, COLOR_RED)); + sleep(TEST_SLEEP_S); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); + sleep(TEST_SLEEP_S); + window->Show(); + sleep(TEST_SLEEP_S_LONG); + window->Destroy(); + sleep(TEST_SLEEP_S); // Wait for the window object to be destructed + system::SetParameter("rosen.uni.partialrender.enabled", "4"); +} + +/** + * @tc.name: ScreenManager10 + * @tc.desc: Create a virtual screen and destroy it for 10 times, it's not for shot. + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager10, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + for (uint32_t i = 0; i < execTimes_; i++) { + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + usleep(sleepUs_); + } +} + +/** + * @tc.name: ScreenManager11 + * @tc.desc: Create a virtual screen , mirror and destroy it for 10 times, it's not for shot. + * @tc.type: FUNC + * @tc.require: issueI5M2SK + */ +HWTEST_F(ScreenManagerTest, ScreenManager11, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + for (uint32_t i = 0; i < 10; i++) { + usleep(sleepUs_); + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + auto mirrorGroup = ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorIds); + ASSERT_EQ(mirrorGroup, groupId); + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenGroupStateForMirror(ScreenGroupChangeEvent::ADD_TO_GROUP, mirrorIds, + virtualScreenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + auto screen = ScreenManager::GetInstance().GetScreenById(virtualScreenId); + ASSERT_EQ(virtualScreenId, screen->GetId()); + ASSERT_NE(SCREEN_ID_INVALID, screen->GetParentId()); + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenGroupStateForMirror(ScreenGroupChangeEvent::REMOVE_FROM_GROUP, mirrorIds, + virtualScreenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); + } + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager12 + * @tc.desc: Create a virtual screen as expansion of default screen cancel Make mirror, and destroy virtual screen + * @tc.type: FUNC + * @tc.require: issueI5M2SK + */ +HWTEST_F(ScreenManagerTest, ScreenManager12, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + std::vector mirrorIds; + mirrorIds.push_back(virtualScreenId); + auto mirrorGroup = ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorIds); + ASSERT_EQ(mirrorGroup, groupId); + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenGroupStateForMirror(ScreenGroupChangeEvent::ADD_TO_GROUP, mirrorIds, + virtualScreenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(mirrorIds); + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenGroupStateForMirror(ScreenGroupChangeEvent::REMOVE_FROM_GROUP, mirrorIds, + virtualScreenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager13 + * @tc.desc: Create a virtual screen as expansion of default screen cancel MakeExpand, and destroy virtual screen + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager13, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + std::vector> screens = ScreenManager::GetInstance().GetAllScreens(); + sptr DefaultScreen = screens.front(); + std::vector options = {{DefaultScreen->GetId(), 0, 0}, {virtualScreenId, defaultWidth_, 0}}; + ScreenId expansionGroup = ScreenManager::GetInstance().MakeExpand(options); + ASSERT_NE(SCREEN_ID_INVALID, expansionGroup); + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + std::vector cancelScreens; + cancelScreens.emplace_back(virtualScreenId); + ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(cancelScreens); + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager14 + * @tc.desc: Create a virtual screen, make expand to make mirror, and destroy virtual screen + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager14, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + std::vector> screens = ScreenManager::GetInstance().GetAllScreens(); + sptr DefaultScreen = screens.front(); + std::vector options = {{DefaultScreen->GetId(), 0, 0}, {virtualScreenId, defaultWidth_, 0}}; + ScreenId expansionGroup = ScreenManager::GetInstance().MakeExpand(options); + ASSERT_EQ(expansionGroup, groupId); + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + std::vector mirrorScreens; + mirrorScreens.emplace_back(virtualScreenId); + auto mirrorGroup = ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorScreens); + ASSERT_EQ(mirrorGroup, groupId); + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::CHANGE_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager15 + * @tc.desc: Create a virtual screen, make mirror to make expand, and destroy virtual screen + * @tc.type: FUNC + * @tc.require: issueI5M2SK + */ +HWTEST_F(ScreenManagerTest, ScreenManager15, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + defaultOption_.isForShot_ = false; + + CHECK_TEST_INIT_SCREEN_STATE + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + CHECK_SCREEN_STATE_AFTER_CREATE_VIRTUAL_SCREEN + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + std::vector mirrorScreens; + mirrorScreens.emplace_back(virtualScreenId); + auto mirrorGroup = ScreenManager::GetInstance().MakeMirror(defaultScreenId_, mirrorScreens); + ASSERT_EQ(mirrorGroup, groupId); + CheckScreenGroupState(ScreenCombination::SCREEN_MIRROR, ScreenGroupChangeEvent::ADD_TO_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenGroupStateForMirror(ScreenGroupChangeEvent::ADD_TO_GROUP, mirrorScreens, + virtualScreenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + std::vector> screens = ScreenManager::GetInstance().GetAllScreens(); + sptr defaultScreen = screens.front(); + std::vector options = {{defaultScreen->GetId(), 0, 0}, {virtualScreenId, defaultWidth_, 0}}; + ScreenId expansionGroup = ScreenManager::GetInstance().MakeExpand(options); + ASSERT_EQ(expansionGroup, groupId); + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::CHANGE_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(true, group, groupId, virtualScreen, virtualScreenId); + + ASSERT_EQ(DMError::DM_OK, ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId)); + CHECK_SCREEN_STATE_AFTER_DESTROY_VIRTUAL_SCREEN + CheckScreenGroupState(ScreenCombination::SCREEN_EXPAND, ScreenGroupChangeEvent::REMOVE_FROM_GROUP, + virtualScreenId, group, screenGroupChangeListener); + CheckScreenStateInGroup(false, group, groupId, virtualScreen, virtualScreenId); + + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + ScreenManager::GetInstance().UnregisterScreenGroupListener(screenGroupChangeListener); + ScreenManager::GetInstance().UnregisterVirtualScreenGroupListener(virtualScreenGroupChangeListener); + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager16 + * @tc.desc: Screen orientation. + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(ScreenManagerTest, ScreenManager16, Function | MediumTest | Level2) +{ + auto screens = ScreenManager::GetInstance().GetAllScreens(); + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + uint32_t orientation = static_cast(Orientation::VERTICAL); + uint32_t end = static_cast(Orientation::REVERSE_HORIZONTAL); + sptr screenListener = new ScreenChangeListener(); + ScreenManager::GetInstance().RegisterScreenListener(screenListener); + for (; orientation <= end; ++orientation) { + usleep(sleepUs_); + screens[0]->SetOrientation(static_cast(orientation)); + ScreenId screenId = screenListener->changeFuture_.GetResult(TIME_OUT); + ASSERT_EQ(screenId, screens[0]->GetId()); + usleep(1E6); + ASSERT_EQ(static_cast(screens[0]->GetOrientation()), orientation); + ASSERT_EQ(static_cast(display->GetOrientation()), orientation); + } + screens[0]->SetOrientation(Orientation::UNSPECIFIED); + ASSERT_EQ(static_cast(screens[0]->GetOrientation()), static_cast(Orientation::UNSPECIFIED)); + ASSERT_EQ(static_cast(display->GetOrientation()), static_cast(Orientation::UNSPECIFIED)); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener); + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager17 + * @tc.desc: Create VirtualScreen for 10 times but do not destroy it + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager17, Function | MediumTest | Level2) +{ + DisplayTestUtils utils; + defaultOption_.isForShot_ = false; + for (uint32_t i = 0; i < execTimes_; i++) { + usleep(sleepUs_); + ASSERT_TRUE(utils.CreateSurface()); + defaultOption_.surface_ = utils.psurface_; + ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(defaultOption_); + ASSERT_NE(SCREEN_ID_INVALID, virtualScreenId); + } + usleep(sleepUs_); +} + +/** + * @tc.name: ScreenManager18 + * @tc.desc: Set screen rotation lock, and check whether screen rotation lock is Locked. + * @tc.type: FUNC + */ +HWTEST_F(ScreenManagerTest, ScreenManager18, Function | SmallTest | Level1) +{ + bool originalLockStatus = ScreenManager::GetInstance().IsScreenRotationLocked(); + ScreenManager::GetInstance().SetScreenRotationLocked(!originalLockStatus); + bool modifiedLockedStatus = ScreenManager::GetInstance().IsScreenRotationLocked(); + ScreenManager::GetInstance().SetScreenRotationLocked(originalLockStatus); + ASSERT_EQ(!originalLockStatus, modifiedLockedStatus); + usleep(sleepUs_); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/dms/screenshot_test.cpp b/window_manager/test/systemtest/dms/screenshot_test.cpp new file mode 100644 index 0000000..2f5bfb9 --- /dev/null +++ b/window_manager/test/systemtest/dms/screenshot_test.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2021-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 "common_test_utils.h" +#include "display_test_utils.h" +#include "future.h" +#include "pixel_map.h" +#include "screenshot_listener_future.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "ScreenshotTest"}; +} +using Utils = DisplayTestUtils; +class ScreenshotListener; +class ScreenshotTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static DisplayId defaultId_; + static Media::Rect defaultScreen_; + static Media::Size defaultImage_; + DisplayId invalidId_ = DISPLAY_ID_INVALID; + Media::Rect invalidRect_ = {-1, -1, -1, -1}; + uint32_t defaultRot_ = 0; +}; + +DisplayId ScreenshotTest::defaultId_ = DISPLAY_ID_INVALID; +Media::Rect ScreenshotTest::defaultScreen_ = {0, 0, 0, 0}; +Media::Size ScreenshotTest::defaultImage_ = {0, 0}; + +void ScreenshotTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + if (display == nullptr) { + WLOGFE("GetDefaultDisplay: failed!\n"); + return; + } + WLOGFI("GetDefaultDisplay: id %" PRIu64", w %d, h %d, fps %u\n", display->GetId(), display->GetWidth(), + display->GetHeight(), display->GetRefreshRate()); + + defaultId_ = display->GetId(); + defaultScreen_ = {0, 0, display->GetWidth(), display->GetHeight()}; + defaultImage_ = {display->GetWidth(), display->GetHeight()}; + + CommonTestUtils::InjectTokenInfoByHapName(0, "com.ohos.systemui", 0); +} + +void ScreenshotTest::TearDownTestCase() +{ +} + +void ScreenshotTest::SetUp() +{ +} + +void ScreenshotTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot of default display's ID is valid + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShotValid01, Function | MediumTest | Level2) +{ + ASSERT_NE(nullptr, DisplayManager::GetInstance().GetScreenshot(defaultId_)); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot of invalid display's ID is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShotValid02, Function | MediumTest | Level2) +{ + ASSERT_EQ(nullptr, DisplayManager::GetInstance().GetScreenshot(invalidId_)); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot of default display's ID match default display's Media::Size + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShotValid03, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_); + ASSERT_NE(nullptr, screenshot); + + Media::Size screenSize = {screenshot->GetWidth(), screenshot->GetHeight()}; + ASSERT_TRUE(Utils::SizeEqualToDisplay(dm.GetDefaultDisplay(), screenSize)); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot created by default parameters is valid + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShotValid04, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, + defaultImage_, defaultRot_); + ASSERT_NE(nullptr, screenshot); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot match default imageSize + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShotValid05, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, + defaultImage_, defaultRot_); + ASSERT_NE(nullptr, screenshot); + Media::Size screenSize = {screenshot->GetWidth(), screenshot->GetHeight()}; + ASSERT_TRUE(Utils::SizeEqual(defaultImage_, screenSize)); + + Media::Size halfDefault_ = {defaultImage_.width / 2, defaultImage_.height / 2}; + Media::Rect halfRect = {defaultScreen_.left, defaultScreen_.top, halfDefault_.width, halfDefault_.height}; + screenshot = dm.GetScreenshot(defaultId_, halfRect, defaultImage_, defaultRot_); + ASSERT_NE(nullptr, screenshot); + screenSize = {screenshot->GetWidth(), screenshot->GetHeight()}; + ASSERT_TRUE(Utils::SizeEqual(defaultImage_, screenSize)); + + Media::Size halfSize = {halfDefault_.width, halfDefault_.height}; + screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, halfSize, defaultRot_); + ASSERT_NE(nullptr, screenshot); + screenSize = {screenshot->GetWidth(), screenshot->GetHeight()}; + ASSERT_TRUE(Utils::SizeEqual(halfSize, screenSize)); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot created by default parameters match default display's Media::Size + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShotValid06, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, + defaultImage_, defaultRot_); + ASSERT_NE(nullptr, screenshot); + Media::Size screenSize = {screenshot->GetWidth(), screenshot->GetHeight()}; + ASSERT_TRUE(Utils::SizeEqualToDisplay(dm.GetDefaultDisplay(), screenSize)); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot created by invalid display ID is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShot07, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + std::shared_ptr screenshot = dm.GetScreenshot(invalidId_, defaultScreen_, + defaultImage_, defaultRot_); + ASSERT_EQ(nullptr, screenshot); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot created by invalid screenRect is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShot08, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_, invalidRect_, + defaultImage_, defaultRot_); + ASSERT_EQ(nullptr, screenshot); + Media::Rect invalidScreen = {invalidRect_.left, defaultScreen_.top, defaultScreen_.width, defaultScreen_.height}; + screenshot = dm.GetScreenshot(defaultId_, invalidScreen, defaultImage_, defaultRot_); + ASSERT_EQ(nullptr, screenshot); + invalidScreen = {defaultScreen_.left, defaultScreen_.top, invalidRect_.width, defaultScreen_.height}; + screenshot = dm.GetScreenshot(defaultId_, invalidScreen, defaultImage_, defaultRot_); + ASSERT_EQ(nullptr, screenshot); +} + +/** + * @tc.name: ScreenShotValid + * @tc.desc: Check if screenshot created by invalid imageSize is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ScreenshotTest, ScreenShot09, Function | MediumTest | Level2) +{ + auto& dm = DisplayManager::GetInstance(); + Media::Size invalidSize = {invalidRect_.width, invalidRect_.height}; + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, + invalidSize, defaultRot_); + ASSERT_EQ(nullptr, screenshot); + invalidSize = {invalidRect_.width, defaultScreen_.height}; + screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, invalidSize, defaultRot_); + ASSERT_EQ(nullptr, screenshot); + invalidSize = {defaultScreen_.width, invalidRect_.height}; + screenshot = dm.GetScreenshot(defaultId_, defaultScreen_, invalidSize, defaultRot_); + ASSERT_EQ(nullptr, screenshot); +} + +/** + * @tc.name: ScreenShotListener01 + * @tc.desc: Check if screenshot listener info valid + * @tc.type: FUNC + * @tc.require: issueI5G62O + */ +HWTEST_F(ScreenshotTest, ScreenShotListener01, Function | MediumTest | Level2) +{ + sptr screenShotListener = new ScreenshotListenerFuture(); + + auto& dm = DisplayManager::GetInstance(); + dm.RegisterScreenshotListener(screenShotListener); + std::shared_ptr screenshot = dm.GetScreenshot(defaultId_); + auto info = screenShotListener->future_.GetResult(1000); + + ASSERT_NE(nullptr, screenshot); + ASSERT_EQ(info.GetDisplayId(), defaultId_); + ASSERT_GT(info.GetTrigger().size(), 0UL); + + dm.UnregisterScreenshotListener(screenShotListener); +} +} // namespace +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/extension/BUILD.gn b/window_manager/test/systemtest/extension/BUILD.gn new file mode 100644 index 0000000..492e737 --- /dev/null +++ b/window_manager/test/systemtest/extension/BUILD.gn @@ -0,0 +1,58 @@ +# 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. + +import("//build/test.gni") + +module_out_path = "window_manager/extension" + +group("systemtest") { + testonly = true + deps = [ ":window_extension_connection_test" ] +} + +config("we_systemtest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/extension/extension_connection/include", + "//foundation/window/window_manager/interfaces/innerkits/extension", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//third_party/googletest/googlemock/include", + ] +} + +## SystemTest window_extension_connection_test {{{ +ohos_systemtest("window_extension_connection_test") { + module_out_path = module_out_path + + sources = [ "extension_connection_test.cpp" ] + + public_configs = [ + ":we_systemtest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//foundation/window/window_manager/extension/extension_connection:libwindow_extension_client", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "ability_base:want", + "c_utils:utils", + "input:libmmi-client", + ] +} + +## SystemTest window_extension_connection_test }}} + diff --git a/window_manager/test/systemtest/extension/extension_connection_test.cpp b/window_manager/test/systemtest/extension/extension_connection_test.cpp new file mode 100644 index 0000000..2241036 --- /dev/null +++ b/window_manager/test/systemtest/extension/extension_connection_test.cpp @@ -0,0 +1,107 @@ +/* + * 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 "window_extension_connection.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class ExtensionCallback : public Rosen::IWindowExtensionCallback { +public: + ExtensionCallback() = default; + ~ExtensionCallback() = default; + void OnWindowReady(const std::shared_ptr& rsSurfaceNode) override; + void OnExtensionDisconnected() override; + void OnKeyEvent(const std::shared_ptr& event) override; + void OnPointerEvent(const std::shared_ptr& event) override; + void OnBackPress() override; + bool isWindowReady_ = false; +}; + +void ExtensionCallback::OnWindowReady(const std::shared_ptr& rsSurfaceNode) +{ + isWindowReady_ = true; +} + +void ExtensionCallback::OnExtensionDisconnected() +{ +} + +void ExtensionCallback::OnKeyEvent(const std::shared_ptr& event) +{ +} + +void ExtensionCallback::OnPointerEvent(const std::shared_ptr& event) +{ +} + +void ExtensionCallback::OnBackPress() +{ +} + +class ExtensionConnectionTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void ExtensionConnectionTest::SetUpTestCase() +{ +} + +void ExtensionConnectionTest::TearDownTestCase() +{ +} + +void ExtensionConnectionTest::SetUp() +{ +} + +void ExtensionConnectionTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowExtensionConnection01 + * @tc.desc: connect window extension + * @tc.type: FUNC + */ +HWTEST_F(ExtensionConnectionTest, WindowExtensionConnection01, Function | SmallTest | Level2) +{ + sptr connection = new(std::nothrow)WindowExtensionConnection(); + if (connection == nullptr) { + return; + } + AppExecFwk::ElementName element; + element.SetBundleName("com.test.windowextension"); + element.SetAbilityName("WindowExtAbility"); + Rosen::Rect rect {100, 100, 60, 60}; + ASSERT_TRUE(connection->ConnectExtension(element, rect, 100, INVALID_WINDOW_ID, nullptr) != ERR_OK); + connection->Show(); + connection->RequestFocus(); + connection->SetBounds(rect); + connection->Hide(); +} +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/wms/BUILD.gn b/window_manager/test/systemtest/wms/BUILD.gn new file mode 100644 index 0000000..c7c5672 --- /dev/null +++ b/window_manager/test/systemtest/wms/BUILD.gn @@ -0,0 +1,304 @@ +# Copyright (c) 2021-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. + +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +module_out_path = "window_manager/wms" + +group("systemtest") { + testonly = true + + deps = [ + ":wms_window_animation_transition_test", + ":wms_window_app_floating_window_test", + ":wms_window_dialogwindow_test", + ":wms_window_display_zoom_test", + ":wms_window_drag_test", + ":wms_window_effect_test", + ":wms_window_focus_test", + ":wms_window_gamut_test", + ":wms_window_immersive_test", + ":wms_window_input_method_test", + ":wms_window_input_test", + ":wms_window_layout_test", + ":wms_window_mode_support_info_test", + ":wms_window_move_drag_test", + ":wms_window_multi_ability_test", + ":wms_window_occupied_area_change_test", + ":wms_window_rotation_test", + ":wms_window_split_immersive_test", + ":wms_window_split_test", + ":wms_window_subwindow_test", + ":wms_window_systemsubwindow_test", + ":wms_window_touch_outside_test", + ":wms_window_visibility_info_test", + ] +} + +ohos_systemtest("wms_window_layout_test") { + module_out_path = module_out_path + + sources = [ "window_layout_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_effect_test") { + module_out_path = module_out_path + + sources = [ "window_effect_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_multi_ability_test") { + module_out_path = module_out_path + + sources = [ "window_multi_ability_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_subwindow_test") { + module_out_path = module_out_path + + sources = [ "window_subwindow_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] + + external_deps = [ "bundle_framework:appexecfwk_base" ] +} + +ohos_systemtest("wms_window_systemsubwindow_test") { + module_out_path = module_out_path + + sources = [ "window_systemsubwindow_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] + + external_deps = [ "bundle_framework:appexecfwk_base" ] +} + +ohos_systemtest("wms_window_dialogwindow_test") { + module_out_path = module_out_path + + sources = [ "window_dialogwindow_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] + + external_deps = [ "bundle_framework:appexecfwk_base" ] +} + +ohos_systemtest("wms_window_immersive_test") { + module_out_path = module_out_path + + sources = [ "window_immersive_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_focus_test") { + module_out_path = module_out_path + + sources = [ "window_focus_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_split_immersive_test") { + module_out_path = module_out_path + + sources = [ "window_split_immersive_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_split_test") { + module_out_path = module_out_path + + sources = [ "window_split_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_move_drag_test") { + module_out_path = module_out_path + + sources = [ "window_move_drag_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] + + external_deps = [ "bundle_framework:appexecfwk_base" ] +} + +ohos_systemtest("wms_window_input_method_test") { + module_out_path = module_out_path + + sources = [ "window_input_method_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_gamut_test") { + module_out_path = module_out_path + + sources = [ "window_gamut_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_input_test") { + module_out_path = module_out_path + + sources = [ "window_input_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_visibility_info_test") { + module_out_path = module_out_path + + sources = [ "window_visibility_info_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_display_zoom_test") { + module_out_path = module_out_path + + sources = [ "window_display_zoom_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_drag_test") { + module_out_path = module_out_path + + sources = [ "window_drag_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_rotation_test") { + module_out_path = module_out_path + + sources = [ "window_rotation_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_occupied_area_change_test") { + module_out_path = module_out_path + + sources = [ "window_occupied_area_change_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_touch_outside_test") { + module_out_path = module_out_path + + sources = [ "window_touch_outside_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_mode_support_info_test") { + module_out_path = module_out_path + + sources = [ "window_mode_support_info_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_app_floating_window_test") { + module_out_path = module_out_path + + sources = [ "window_app_floating_window_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +ohos_systemtest("wms_window_animation_transition_test") { + module_out_path = module_out_path + + sources = [ "window_animation_transition_test.cpp" ] + + deps = [ ":wms_systemtest_common" ] +} + +## Build wms_systemtest_common.a {{{ +config("wms_systemtest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/utils/include", + "//commonlibrary/c_utils/base/include", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", + "//third_party/googletest/googlemock/include", + "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics/include", + + # for abilityContext + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "//base/global/resource_management/interfaces/inner_api/include", + "//third_party/node/deps/icu-small/source/common", + "${ability_runtime_inner_api_path}/ability_manager/include", + + # abilityContext end + ] +} + +ohos_static_library("wms_systemtest_common") { + visibility = [ ":*" ] + testonly = true + + sources = [ "window_test_utils.cpp" ] + + public_configs = [ + ":wms_systemtest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//base/powermgr/power_manager/interfaces/innerkits:powermgr_client", + "//foundation/arkui/ace_engine/interfaces/inner_api/ace:ace_uicontent", + + # need delete it for abilitycontext + "${ability_runtime_inner_api_path}/ability_manager:ability_manager", + "//commonlibrary/c_utils/base:utils", + "//foundation/arkui/napi:ace_napi", + "//foundation/graphic/graphic_2d/rosen/modules/animation/window_animation:window_animation", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_context_native", + "bundle_framework:appexecfwk_base", + "ipc:ipc_core", + ] +} +## Build wms_systemtest_common.a }}} diff --git a/window_manager/test/systemtest/wms/window_animation_transition_test.cpp b/window_manager/test/systemtest/wms/window_animation_transition_test.cpp new file mode 100644 index 0000000..86ad134 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_animation_transition_test.cpp @@ -0,0 +1,174 @@ +/* + * 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 "window.h" +#include "wm_common.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, "WindowAnimationTest"}; +} + +using Utils = WindowTestUtils; + +class TestAnimationTransitionController : public IAnimationTransitionController { +public: + explicit TestAnimationTransitionController(sptr window) : window_(window) {} + void AnimationForShown() override; + void AnimationForHidden() override; +private: + sptr window_ = nullptr; +}; + +class WindowAnimationTransitionTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + sptr testAnimationTransitionListener_; + Utils::TestWindowInfo windowInfo_; + Transform trans_; + Transform defaultTrans_; +}; + +void TestAnimationTransitionController::AnimationForShown() +{ + WLOGFI("TestAnimationTransitionController AnimationForShown"); + Transform trans; + window_->SetTransform(trans); +} + +void TestAnimationTransitionController::AnimationForHidden() +{ + WLOGFI("TestAnimationTransitionController AnimationForHidden"); + Transform trans; + trans.pivotX_ = 1.0f; + trans.pivotY_ = 0.6f; + window_->SetTransform(trans); +} + +void WindowAnimationTransitionTest::SetUpTestCase() +{ +} + +void WindowAnimationTransitionTest::TearDownTestCase() +{ +} + +void WindowAnimationTransitionTest::SetUp() +{ + windowInfo_ = { + .name = "AnimationTestWindow", + .rect = {0, 0, 200, 200}, + .type = WindowType::WINDOW_TYPE_FLOAT, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + trans_.pivotX_ = 1.0f; + trans_.pivotY_ = 0.6f; +} + +void WindowAnimationTransitionTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: AnimationTransitionTest01 + * @tc.desc: Register AnimationController and hide with custom animation + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowAnimationTransitionTest, AnimationTransitionTest01, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + sptr testAnimationTransitionListener = + new TestAnimationTransitionController(window); + window->RegisterAnimationTransitionController(testAnimationTransitionListener); + ASSERT_EQ(WMError::WM_OK, window->Show()); + usleep(500000); // 500000us = 0.5s + ASSERT_EQ(WMError::WM_OK, window->Hide(0, true)); + usleep(500000); // 500000us = 0.5s + ASSERT_TRUE(trans_ == window->GetTransform()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: AnimationTransitionTest02 + * @tc.desc: Register AnimationController and show without animation + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowAnimationTransitionTest, AnimationTransitionTest02, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + sptr testAnimationTransitionListener = + new TestAnimationTransitionController(window); + window->RegisterAnimationTransitionController(testAnimationTransitionListener); + ASSERT_EQ(WMError::WM_OK, window->Show()); + usleep(500000); // 500000us = 0.5s + ASSERT_TRUE(defaultTrans_ == window->GetTransform()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: AnimationTransitionTest03 + * @tc.desc: hide with default animation without register animationController + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowAnimationTransitionTest, AnimationTransitionTest03, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + ASSERT_EQ(WMError::WM_OK, window->Hide(0, true)); + usleep(500000); // 500000us = 0.5s + ASSERT_TRUE(defaultTrans_ == window->GetTransform()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: AnimationTransitionTest04 + * @tc.desc: hide without custom animation and register animationController + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowAnimationTransitionTest, AnimationTransitionTest04, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + sptr testAnimationTransitionListener = + new TestAnimationTransitionController(window); + window->RegisterAnimationTransitionController(testAnimationTransitionListener); + ASSERT_EQ(WMError::WM_OK, window->Show()); + usleep(500000); // 500000us = 0.5s + ASSERT_EQ(WMError::WM_OK, window->Hide()); + ASSERT_TRUE(defaultTrans_ == window->GetTransform()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_app_floating_window_test.cpp b/window_manager/test/systemtest/wms/window_app_floating_window_test.cpp new file mode 100644 index 0000000..a39ca3b --- /dev/null +++ b/window_manager/test/systemtest/wms/window_app_floating_window_test.cpp @@ -0,0 +1,421 @@ +/* + * 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 "ability_context_impl.h" +#include "ipc_skeleton.h" +#include "window.h" +#include "window_manager.h" +#include "window_option.h" +#include "window_scene.h" +#include "window_test_utils.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowAppFloatingWindowTest"}; +} + +class TestCameraFloatWindowChangedListener : public ICameraFloatWindowChangedListener { +public: + uint32_t accessTokenId_ = 0; + bool isShowing_ = false; + void OnCameraFloatWindowChange(uint32_t accessTokenId, bool isShowing) override; +}; + +class WindowAppFloatingWindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static inline float virtualPixelRatio_ = 1.0; + static inline Rect displayRect_ {0, 0, 0, 0}; + static inline std::shared_ptr abilityContext_ = nullptr; + static sptr testCameraFloatWindowChangedListener_; +}; + +sptr WindowAppFloatingWindowTest::testCameraFloatWindowChangedListener_ = + new TestCameraFloatWindowChangedListener(); + +void TestCameraFloatWindowChangedListener::OnCameraFloatWindowChange(uint32_t accessTokenId, bool isShowing) +{ + WLOGFI("TestCameraFloatWindowChangedListener [%{public}u, %{public}u]", accessTokenId, isShowing); + accessTokenId_ = accessTokenId; + isShowing_ = isShowing; +} + +void WindowAppFloatingWindowTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + displayRect_.width_ = display->GetWidth(); + displayRect_.height_ = display->GetHeight(); + WindowTestUtils::InitByDisplayRect(displayRect_); + virtualPixelRatio_ = WindowTestUtils::GetVirtualPixelRatio(0); +} + +void WindowAppFloatingWindowTest::TearDownTestCase() +{ +} + +void WindowAppFloatingWindowTest::SetUp() +{ +} + +void WindowAppFloatingWindowTest::TearDown() +{ +} + +static sptr CreateWindowScene() +{ + sptr listener = nullptr; + WindowAppFloatingWindowTest::abilityContext_ = std::make_shared(); + + sptr scene = new WindowScene(); + scene->Init(0, WindowAppFloatingWindowTest::abilityContext_, listener); + return scene; +} + +static sptr CreateAppFloatingWindow(WindowType type, Rect rect, std::string name = "") +{ + sptr option = new WindowOption(); + option->SetWindowType(type); + option->SetWindowRect(rect); + + static int cnt = 0; + std::string winName = (name == "") ? "FloatingWindowTest" + std::to_string(cnt++) : name; + + return Window::Create(winName, option, WindowAppFloatingWindowTest::abilityContext_); +} + +static inline Rect GetRectWithVpr(int32_t x, int32_t y, uint32_t w, uint32_t h) +{ + auto vpr = WindowAppFloatingWindowTest::virtualPixelRatio_; + return {x, y, static_cast(w * vpr), static_cast(h * vpr)}; +} + +/** + * @tc.name: AppFloatingWindow01 + * @tc.desc: AppFloatingWindow life cycle + * @tc.type: FUNC + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow01, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow02 + * @tc.desc: AppFloatingWindow life cycle, main window hide first + * @tc.type: FUNC + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow02, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + ASSERT_EQ(false, scene->GetMainWindow()->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(true, fltWin->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow03 + * @tc.desc: AppFloatingWindow life cycle, app floating window hide first + * @tc.type: FUNC + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow03, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + ASSERT_EQ(false, fltWin->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(true, scene->GetMainWindow()->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow04 + * @tc.desc: AppFloatingWindow life cycle, main window destroy first + * @tc.type: FUNC + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow04, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); + ASSERT_EQ(nullptr, scene->GetMainWindow()); + ASSERT_EQ(false, fltWin->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); +} + +/** + * @tc.name: AppFloatingWindow05 + * @tc.desc: Camera AppFloatingWindow life cycle + * @tc.type: FUNC + * @tc.require: issueI5NEHO + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow05, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow06 + * @tc.desc: Camera AppFloatingWindow life cycle, main window hide first + * @tc.type: FUNC + * @tc.require: issueI5NEHO + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow06, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + ASSERT_EQ(false, scene->GetMainWindow()->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(true, fltWin->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow07 + * @tc.desc: Camera AppFloatingWindow life cycle, app floating window hide first + * @tc.type: FUNC + * @tc.require: issueI5NEHO + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow07, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + ASSERT_EQ(false, fltWin->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(true, scene->GetMainWindow()->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow08 + * @tc.desc: Camera AppFloatingWindow life cycle, main window destroy first + * @tc.type: FUNC + * @tc.require: issueI5NEHO + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow08, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); + ASSERT_EQ(nullptr, scene->GetMainWindow()); + ASSERT_EQ(false, fltWin->GetWindowState() == WindowState::STATE_SHOWN); + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); +} + +/** + * @tc.name: AppFloatingWindow09 + * @tc.desc: Camera AppFloatingWindow rect check + * @tc.type: FUNC + * @tc.require: issueI5NEHO + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow09, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(10, 20, 10, 10); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + Rect exceptRect = {10, 20, 0, 0}; + uint32_t smallWidth = displayRect_.height_ <= displayRect_.width_ ? displayRect_.height_ : displayRect_.width_; + float hwRatio = static_cast(displayRect_.height_) / static_cast(displayRect_.width_); + if (smallWidth <= static_cast(600 * virtualPixelRatio_)) { // sw <= 600dp + if (displayRect_.width_ <= displayRect_.height_) { + exceptRect.width_= static_cast(smallWidth * 0.3); + } else { + exceptRect.width_ = static_cast(smallWidth * 0.5); + } + } else { + if (displayRect_.width_ <= displayRect_.height_) { + exceptRect.width_ = static_cast(smallWidth * 0.12); + } else { + exceptRect.width_ = static_cast(smallWidth * 0.3); + } + } + exceptRect.height_ = static_cast(exceptRect.width_ * hwRatio); + ASSERT_TRUE(WindowTestUtils::RectEqualTo(fltWin, exceptRect)); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow10 + * @tc.desc: Camera AppFloatingWindow multi create + * @tc.type: FUNC + * @tc.require: issueI5NEHO + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow10, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + sptr fltWin2 = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_EQ(nullptr, fltWin2); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + sptr fltWin3 = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin3); + + ASSERT_EQ(WMError::WM_OK, fltWin3->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); +} + +/** + * @tc.name: AppFloatingWindow11 + * @tc.desc: Camera AppFloatingWindow listener + * @tc.type: FUNC + * @tc.require: issueI5NEHR + */ +HWTEST_F(WindowAppFloatingWindowTest, AppFloatingWindow11, Function | MediumTest | Level2) +{ + uint32_t tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + WindowManager::GetInstance().RegisterCameraFloatWindowChangedListener(testCameraFloatWindowChangedListener_); + sptr scene = CreateWindowScene(); + ASSERT_NE(nullptr, scene); + + Rect fltWindRect = GetRectWithVpr(0, 0, 400, 600); + sptr fltWin = CreateAppFloatingWindow(WindowType::WINDOW_TYPE_FLOAT_CAMERA, fltWindRect); + ASSERT_NE(nullptr, fltWin); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, fltWin->Show()); + + usleep(500000); // 500000us = 0.5s + ASSERT_EQ(tokenId, testCameraFloatWindowChangedListener_->accessTokenId_); + ASSERT_EQ(true, testCameraFloatWindowChangedListener_->isShowing_); + + ASSERT_EQ(WMError::WM_OK, fltWin->Hide()); + + usleep(500000); // 500000us = 0.5s + ASSERT_EQ(tokenId, testCameraFloatWindowChangedListener_->accessTokenId_); + ASSERT_EQ(false, testCameraFloatWindowChangedListener_->isShowing_); + + ASSERT_EQ(WMError::WM_OK, fltWin->Destroy()); + ASSERT_EQ(WMError::WM_OK, scene->GoDestroy()); + + WindowManager::GetInstance().UnregisterCameraFloatWindowChangedListener(testCameraFloatWindowChangedListener_); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_dialogwindow_test.cpp b/window_manager/test/systemtest/wms/window_dialogwindow_test.cpp new file mode 100644 index 0000000..2fda282 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_dialogwindow_test.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2021-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 "ability_context_impl.h" +#include "window.h" +#include "window_manager.h" +#include "window_option.h" +#include "window_scene.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowDialogWindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static inline std::shared_ptr abilityContext_ = nullptr; +}; + +void WindowDialogWindowTest::SetUpTestCase() +{ +} + +void WindowDialogWindowTest::TearDownTestCase() +{ +} + +void WindowDialogWindowTest::SetUp() +{ +} + +void WindowDialogWindowTest::TearDown() +{ +} + +static sptr CreateWindowScene() +{ + sptr listener = nullptr; + WindowDialogWindowTest::abilityContext_ = std::make_shared(); + + sptr scene = new WindowScene(); + scene->Init(0, WindowDialogWindowTest::abilityContext_, listener); + return scene; +} + +static sptr CreateDialogWindow(sptr scene, WindowType type, Rect rect, std::string name = "") +{ + sptr option = new WindowOption(); + option->SetWindowType(type); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowRect(rect); + + static int cnt = 0; + std::string winName = (name == "") ? "DialogWindowTest" + std::to_string(cnt++) : name; + + return Window::Create(winName, option, scene->GetMainWindow()->GetContext()); +} + +/** + * @tc.name: dialogWindow01 + * @tc.desc: FullScreen Main Window + Floating dialogWindow + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow01, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect); + ASSERT_NE(nullptr, dialogWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, dialogWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + dialogWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: dialogWindow02 + * @tc.desc: FullScreen Main Window + 2 dialogWindow + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow02, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow0 = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect); + ASSERT_NE(nullptr, dialogWindow0); + + sptr dialogWindow1 = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect); + ASSERT_EQ(nullptr, dialogWindow1); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow0->Show()); + + ASSERT_EQ(WMError::WM_OK, dialogWindow0->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + dialogWindow0->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: dialogWindow03 + * @tc.desc: FullScreen Main Window + 2 dialogWindow with the same name + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow03, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow0 = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect, "dialog0"); + sptr dialogWindow1 = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect, "dialog0"); + ASSERT_NE(nullptr, dialogWindow0); + ASSERT_EQ(nullptr, dialogWindow1); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow0->Show()); + + ASSERT_EQ(WMError::WM_OK, dialogWindow0->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + dialogWindow0->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: dialogWindow04 + * @tc.desc: FullScreen Main Window + 2 dialogWindow with the same name but one create after another destroyed + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow04, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow0 = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect, "dialog0"); + ASSERT_NE(nullptr, dialogWindow0); + ASSERT_EQ(WMError::WM_OK, dialogWindow0->Show()); + ASSERT_EQ(WMError::WM_OK, dialogWindow0->Destroy()); + + + sptr dialogWindow1 = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect, "dialog0"); + ASSERT_NE(nullptr, dialogWindow1); + ASSERT_EQ(WMError::WM_OK, dialogWindow1->Show()); + ASSERT_EQ(WMError::WM_OK, dialogWindow1->Destroy()); + + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + scene->GoDestroy(); +} + +/** + * @tc.name: dialogWindow05 + * @tc.desc: FullScreen Main Window + dialogWindow & MainWindow First GoBackground + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow05, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect); + ASSERT_NE(nullptr, dialogWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow->Hide()); + + dialogWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: dialogWindow06 + * @tc.desc: FullScreen Main Window + dialogWindow & first destroy dialogWindow, then destroy MainWindow + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow06, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect); + ASSERT_NE(nullptr, dialogWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, dialogWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + + ASSERT_EQ(WMError::WM_OK, dialogWindow->Destroy()); + + dialogWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: dialogWindow07 + * @tc.desc: FullScreen Main Window + dialogWindow & first destroy MainWindow, then destroy dialogWindow + * @tc.type: FUNC + * @tc.require: issueI5GKWZ + */ +HWTEST_F(WindowDialogWindowTest, DialogWindow07, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr dialogWindow = CreateDialogWindow(scene, WindowType::WINDOW_TYPE_DIALOG, rect); + ASSERT_NE(nullptr, dialogWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, dialogWindow->Show()); + + sptr mainWindow = scene->GetMainWindow(); + ASSERT_EQ(WMError::WM_OK, mainWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, dialogWindow->Destroy()); + + scene->GoDestroy(); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_display_zoom_test.cpp b/window_manager/test/systemtest/wms/window_display_zoom_test.cpp new file mode 100644 index 0000000..7bff784 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_display_zoom_test.cpp @@ -0,0 +1,274 @@ +/* + * 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 "window_test_utils.h" +#include "window_accessibility_controller.h" +#include "window_impl.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowDisplayZoomTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + Utils::TestWindowInfo windowInfo_; +}; + +void WindowDisplayZoomTest::SetUpTestCase() +{ +} + +void WindowDisplayZoomTest::TearDownTestCase() +{ +} + +void WindowDisplayZoomTest::SetUp() +{ + windowInfo_ = { + .name = "zoomWindow", + .rect = {0, 0, 300, 100}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .showWhenLocked = true, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowDisplayZoomTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: DisplayZoom01 + * @tc.desc: test interface SetAnchorAndScale + * @tc.type: FUNC + * @tc.require: issueI5NGWL + */ +HWTEST_F(WindowDisplayZoomTest, DisplayZoom01, Function | MediumTest | Level3) +{ + WindowAccessibilityController::GetInstance().OffWindowZoom(); + sleep(1); + + windowInfo_.name = "DisplayZoom01"; + sptr window = Utils::CreateTestWindow(windowInfo_); + Window* ptr = window.GetRefPtr(); + WindowImpl* implPtr = (WindowImpl*)ptr; + ASSERT_EQ(WMError::WM_OK, window->Show()); + Transform expect; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + Rect rect = window->GetRect(); + expect.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; + expect.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; + expect.scaleX_ = expect.scaleY_ = 2; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + expect.scaleX_ = expect.scaleY_ = 4; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 0.5); + sleep(1); + expect.scaleX_ = expect.scaleY_ = 2; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 0.1); + sleep(1); + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, -0.1); + sleep(1); + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().OffWindowZoom(); + window->Destroy(); +} + +/** + * @tc.name: DisplayZoom02 + * @tc.desc: test interface SetAnchorOffset + * @tc.type: FUNC + * @tc.require: issueI5NGWL + */ +HWTEST_F(WindowDisplayZoomTest, DisplayZoom02, Function | MediumTest | Level3) +{ + windowInfo_.name = "DisplayZoom02"; + sptr window = Utils::CreateTestWindow(windowInfo_); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + WindowAccessibilityController::GetInstance().SetAnchorOffset(-100, -100); + sleep(1); + + Transform expect; + Rect rect = window->GetRect(); + expect.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; + expect.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; + expect.scaleX_ = expect.scaleY_ = 2; + expect.translateX_ = expect.translateY_ = -100; + + WindowAccessibilityController::GetInstance().SetAnchorOffset(200, 200); + sleep(1); + expect.translateX_ = expect.translateY_ = 0; + WindowAccessibilityController::GetInstance().OffWindowZoom(); + window->Destroy(); +} + +/** + * @tc.name: DisplayZoom03 + * @tc.desc: test interface OffWindowZoom + * @tc.type: FUNC + * @tc.require: issueI5NGWL + */ +HWTEST_F(WindowDisplayZoomTest, DisplayZoom03, Function | MediumTest | Level3) +{ + windowInfo_.name = "DisplayZoom03"; + sptr window = Utils::CreateTestWindow(windowInfo_); + Window* ptr = window.GetRefPtr(); + WindowImpl* implPtr = (WindowImpl*)ptr; + ASSERT_EQ(WMError::WM_OK, window->Show()); + + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + WindowAccessibilityController::GetInstance().OffWindowZoom(); + sleep(1); + + Transform expect; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + window->Destroy(); +} + +/** + * @tc.name: DisplayZoom04 + * @tc.desc: test add and remove a window after zoom display + * @tc.type: FUNC + * @tc.require: issueI5NGWL + */ +HWTEST_F(WindowDisplayZoomTest, DisplayZoom04, Function | MediumTest | Level3) +{ + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + + windowInfo_.name = "DisplayZoom04"; + sptr window = Utils::CreateTestWindow(windowInfo_); + Window* ptr = window.GetRefPtr(); + WindowImpl* implPtr = (WindowImpl*)ptr; + ASSERT_EQ(WMError::WM_OK, window->Show()); + + Transform expect; + Rect rect = window->GetRect(); + expect.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; + expect.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; + expect.scaleX_ = expect.scaleY_ = 2; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + ASSERT_EQ(WMError::WM_OK, window->Hide());; + WindowAccessibilityController::GetInstance().OffWindowZoom(); + sleep(1); + + ASSERT_EQ(WMError::WM_OK, window->Show()); + sleep(1); + Transform identity; + ASSERT_TRUE(identity == implPtr->GetWindowProperty()->GetZoomTransform()); + + window->Destroy(); +} + +/** + * @tc.name: DisplayZoom05 + * @tc.desc: test animate and zoom transform + * @tc.type: FUNC + * @tc.require: issueI5NGWL + */ +HWTEST_F(WindowDisplayZoomTest, DisplayZoom05, Function | MediumTest | Level3) +{ + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + + windowInfo_.name = "DisplayZoom05"; + sptr window = Utils::CreateTestWindow(windowInfo_); + Window* ptr = window.GetRefPtr(); + WindowImpl* implPtr = (WindowImpl*)ptr; + ASSERT_EQ(WMError::WM_OK, window->Show()); + + Transform animate; + animate.translateX_ = -100; + animate.translateZ_ = 100; + window->SetTransform(animate); + sleep(1); + + Transform expect; + Rect rect = window->GetRect(); + expect.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; + expect.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; + expect.scaleX_ = expect.scaleY_ = 1.7; + Transform actual = implPtr->GetWindowProperty()->GetZoomTransform(); + + auto isExpec = [](float a, float b) -> bool { + return abs(a - b) < 0.1; + }; + ASSERT_EQ(true, isExpec(actual.pivotX_, expect.pivotX_)); + ASSERT_EQ(true, isExpec(actual.pivotY_, expect.pivotY_)); + ASSERT_EQ(true, isExpec(actual.scaleX_, expect.scaleX_)); + ASSERT_EQ(true, isExpec(actual.scaleY_, expect.scaleY_)); + + WindowAccessibilityController::GetInstance().OffWindowZoom(); + window->Destroy(); +} + +/** + * @tc.name: DisplayZoom06 + * @tc.desc: test speical window type + * @tc.type: FUNC + * @tc.require: issueI5NGWL + */ +HWTEST_F(WindowDisplayZoomTest, DisplayZoom06, Function | MediumTest | Level3) +{ + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(1); + + windowInfo_.name = "DisplayZoom06"; + windowInfo_.type = WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT; + sptr window = Utils::CreateTestWindow(windowInfo_); + Window* ptr = window.GetRefPtr(); + WindowImpl* implPtr = (WindowImpl*)ptr; + ASSERT_EQ(WMError::WM_OK, window->Show()); + sleep(1); + + Transform expect; + ASSERT_TRUE(expect == implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().OffWindowZoom(); + window->Destroy(); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/wms/window_drag_test.cpp b/window_manager/test/systemtest/wms/window_drag_test.cpp new file mode 100644 index 0000000..cd3e339 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_drag_test.cpp @@ -0,0 +1,223 @@ +/* + * 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 "window_test_utils.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +const int WAIT_CALLBACK_US = 100000; // 100000 us + +class TestDragListener : public IWindowDragListener { +public: + PointInfo point_ { 0, 0 }; + DragEvent event_ = DragEvent::DRAG_EVENT_END; + void OnDrag(int32_t x, int32_t y, DragEvent event) override; +}; + +void TestDragListener::OnDrag(int32_t x, int32_t y, DragEvent event) +{ + event_ = event; + point_.x = x; + point_.y = y; +} + +class WindowDragTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static sptr firstWindowDragListener_; + static sptr secondWindowDragListener_; + Utils::TestWindowInfo dragWindowInfo_; + Utils::TestWindowInfo firstWindowInfo_; + Utils::TestWindowInfo secondWindowInfo_; +}; + +sptr WindowDragTest::firstWindowDragListener_ = + new TestDragListener(); +sptr WindowDragTest::secondWindowDragListener_ = + new TestDragListener(); + +void WindowDragTest::SetUpTestCase() {} + +void WindowDragTest::TearDownTestCase() {} + +void WindowDragTest::SetUp() +{ + dragWindowInfo_ = { + .name = "dragWindow", + .rect = {200, 200, 380, 380}, + .type = WindowType::WINDOW_TYPE_DRAGGING_EFFECT, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + firstWindowInfo_ = { + .name = "firstWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + secondWindowInfo_ = { + .name = "secondWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowDragTest::TearDown() {} + +namespace { +/** + * @tc.name: DragIn + * @tc.desc: Drag a window to another window + * @tc.type: FUNC + */ +HWTEST_F(WindowDragTest, DragIn, Function | MediumTest | Level3) { + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterDragListener(firstWindowDragListener_); + firstWindow->SetTurnScreenOn(true); + firstWindow->Show(); + + const sptr &dragWindow = Utils::CreateTestWindow(dragWindowInfo_); + dragWindow->Show(); + dragWindow->MoveTo(300, 300); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(300, firstWindowDragListener_->point_.x); + ASSERT_EQ(300, firstWindowDragListener_->point_.y); + ASSERT_EQ(DragEvent::DRAG_EVENT_IN, firstWindowDragListener_->event_); + + dragWindow->Destroy(); + firstWindow->UnregisterDragListener(firstWindowDragListener_); + firstWindow->Destroy(); +} + +/** + * @tc.name: DragMove + * @tc.desc: Window Move + * @tc.type: FUNC + */ +HWTEST_F(WindowDragTest, DragMove, Function | MediumTest | Level3) { + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterDragListener(firstWindowDragListener_); + firstWindow->SetTurnScreenOn(true); + firstWindow->Show(); + + const sptr &dragWindow = Utils::CreateTestWindow(dragWindowInfo_); + dragWindow->Show(); + dragWindow->MoveTo(300, 300); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(300, firstWindowDragListener_->point_.x); + ASSERT_EQ(300, firstWindowDragListener_->point_.y); + ASSERT_EQ(DragEvent::DRAG_EVENT_IN, firstWindowDragListener_->event_); + + dragWindow->MoveTo(400, 400); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(400, firstWindowDragListener_->point_.x); + ASSERT_EQ(400, firstWindowDragListener_->point_.y); + ASSERT_EQ(DragEvent::DRAG_EVENT_MOVE, firstWindowDragListener_->event_); + + dragWindow->Destroy(); + firstWindow->UnregisterDragListener(firstWindowDragListener_); + firstWindow->Destroy(); +} + +/** + * @tc.name: DragOut + * @tc.desc: Drag the drag window out of the current window + * @tc.type: FUNC + */ +HWTEST_F(WindowDragTest, DragOut, Function | MediumTest | Level3) { + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterDragListener(firstWindowDragListener_); + firstWindow->SetTurnScreenOn(true); + firstWindow->Show(); + + secondWindowInfo_.rect = {500, 500, 500, 500}; + const sptr &secondWindow = Utils::CreateTestWindow(secondWindowInfo_); + secondWindow->RegisterDragListener(secondWindowDragListener_); + secondWindow->Show(); + + const sptr &dragWindow = Utils::CreateTestWindow(dragWindowInfo_); + dragWindow->Show(); + dragWindow->MoveTo(300, 300); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(300, firstWindowDragListener_->point_.x); + ASSERT_EQ(300, firstWindowDragListener_->point_.y); + ASSERT_EQ(DragEvent::DRAG_EVENT_IN, firstWindowDragListener_->event_); + + dragWindow->MoveTo(400, 400); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(400, firstWindowDragListener_->point_.x); + ASSERT_EQ(400, firstWindowDragListener_->point_.y); + ASSERT_EQ(DragEvent::DRAG_EVENT_MOVE, firstWindowDragListener_->event_); + + dragWindow->MoveTo(600, 600); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(100, secondWindowDragListener_->point_.x); + ASSERT_EQ(100, secondWindowDragListener_->point_.y); + ASSERT_EQ(DragEvent::DRAG_EVENT_IN, secondWindowDragListener_->event_); + ASSERT_EQ(DragEvent::DRAG_EVENT_OUT, firstWindowDragListener_->event_); + + dragWindow->Destroy(); + firstWindow->UnregisterDragListener(firstWindowDragListener_); + secondWindow->UnregisterDragListener(secondWindowDragListener_); + firstWindow->Destroy(); + secondWindow->Destroy(); +} + +/** + * @tc.name: DragEnd + * @tc.desc: End window drag + * @tc.type: FUNC + */ +HWTEST_F(WindowDragTest, DragEnd, Function | MediumTest | Level3) { + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterDragListener(firstWindowDragListener_); + firstWindow->SetTurnScreenOn(true); + firstWindow->Show(); + + const sptr &dragWindow = Utils::CreateTestWindow(dragWindowInfo_); + dragWindow->Show(); + dragWindow->MoveTo(199, 199); + usleep(WAIT_CALLBACK_US); + dragWindow->Destroy(); + usleep(WAIT_CALLBACK_US); + ASSERT_EQ(DragEvent::DRAG_EVENT_END, firstWindowDragListener_->event_); + firstWindow->UnregisterDragListener(firstWindowDragListener_); + firstWindow->Destroy(); +} +} // namespace +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_effect_test.cpp b/window_manager/test/systemtest/wms/window_effect_test.cpp new file mode 100644 index 0000000..ac9150d --- /dev/null +++ b/window_manager/test/systemtest/wms/window_effect_test.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2021-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 "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowEffectTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + Utils::TestWindowInfo windowInfo_; +}; + +void WindowEffectTest::SetUpTestCase() +{ +} + +void WindowEffectTest::TearDownTestCase() +{ +} + +void WindowEffectTest::SetUp() +{ + windowInfo_ = { + .name = "TestWindow", + .rect = {0, 0, 100, 200}, + .type = WindowType::WINDOW_TYPE_FLOAT, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowEffectTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowEffect01 + * @tc.desc: Set window corner radius + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect01, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + ASSERT_EQ(WMError::WM_OK, window->SetCornerRadius(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetCornerRadius(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetCornerRadius(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetCornerRadius(-1.0)); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect02 + * @tc.desc: Set window shadow radius + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect02, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + ASSERT_EQ(WMError::WM_OK, window->SetShadowRadius(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetShadowRadius(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetShadowRadius(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowRadius(-1.0)); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect03 + * @tc.desc: Set window shadow color + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect03, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + ASSERT_EQ(WMError::WM_OK, window->SetShadowColor("#FF22EE44")); + ASSERT_EQ(WMError::WM_OK, window->SetShadowColor("#22EE44")); + ASSERT_EQ(WMError::WM_OK, window->SetShadowColor("#ff22ee44")); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("ff22ee44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("22ee44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ppEE44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#eepp44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ffeePP44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ff22ee4422")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ff")); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect04 + * @tc.desc: Set window shadow offset + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect04, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + window->SetShadowOffsetX(0.0); + window->SetShadowOffsetX(16.0); + window->SetShadowOffsetX(1000.0); + window->SetShadowOffsetX(-1.0); + + window->SetShadowOffsetY(0.0); + window->SetShadowOffsetY(16.0); + window->SetShadowOffsetY(1000.0); + window->SetShadowOffsetY(-1.0); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect05 + * @tc.desc: Set window blur radius + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect05, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + ASSERT_EQ(WMError::WM_OK, window->SetBlur(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBlur(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBlur(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBlur(-1.0)); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect06 + * @tc.desc: Set window backdrop blur radius + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect06, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlur(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlur(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlur(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackdropBlur(-1.0)); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect07 + * @tc.desc: Set window backdrop blur style + * @tc.type: FUNC + */ +HWTEST_F(WindowEffectTest, WindowEffect07, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(windowInfo_); + ASSERT_NE(nullptr, window); + + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_OFF)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_THIN)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_REGULAR)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_THICK)); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackdropBlurStyle(static_cast(-1))); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackdropBlurStyle(static_cast(5))); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} +} // namespace +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_focus_test.cpp b/window_manager/test/systemtest/wms/window_focus_test.cpp new file mode 100644 index 0000000..b811430 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_focus_test.cpp @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2021-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, "WindowFocusTest"}; +} + +using Utils = WindowTestUtils; +const int WAIT_ASYNC_US = 100000; // 100000us + +class TestFocusChangedListener : public IFocusChangedListener { +public: + uint32_t focusedWindow_ = INVALID_WINDOW_ID; + uint32_t unfocusedWindow_ = INVALID_WINDOW_ID; + void OnFocused(const sptr& focusChangeInfo) override; + void OnUnfocused(const sptr& focusChangeInfo) override; +}; + +class WindowFocusTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static sptr testFocusChangedListener_; + Utils::TestWindowInfo fullScreenAppInfo_; + Utils::TestWindowInfo floatAppInfo_; + Utils::TestWindowInfo subAppInfo_; +}; + +sptr WindowFocusTest::testFocusChangedListener_ = + new TestFocusChangedListener(); + +void TestFocusChangedListener::OnFocused(const sptr& focusChangeInfo) +{ + WLOGFI("TestFocusChangedListener Focused ID: %{public}u", focusChangeInfo->windowId_); + focusedWindow_ = focusChangeInfo->windowId_; +} + +void TestFocusChangedListener::OnUnfocused(const sptr& focusChangeInfo) +{ + WLOGFI("TestFocusChangedListener Unfocused ID: %{public}u", focusChangeInfo->windowId_); + unfocusedWindow_ = focusChangeInfo->windowId_; +} + +void WindowFocusTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); +} + +void WindowFocusTest::TearDownTestCase() +{ +} + +void WindowFocusTest::SetUp() +{ + fullScreenAppInfo_ = { + .name = "FullWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .showWhenLocked = true, + .parentId = INVALID_WINDOW_ID, + }; + floatAppInfo_ = { + .name = "ParentWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .showWhenLocked = true, + .parentId = INVALID_WINDOW_ID, + }; + subAppInfo_ = { + .name = "SubWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .showWhenLocked = false, + .parentId = INVALID_WINDOW_ID, + }; + WindowManager::GetInstance().RegisterFocusChangedListener(testFocusChangedListener_); +} + +void WindowFocusTest::TearDown() +{ + WindowManager::GetInstance().UnregisterFocusChangedListener(testFocusChangedListener_); +} + +namespace { +/** + * @tc.name: FocusChangedTest01 + * @tc.desc: add main window and sub window and show it to test focus + * @tc.type: FUNC + */ +HWTEST_F(WindowFocusTest, FocusChangedTest01, Function | MediumTest | Level3) +{ + fullScreenAppInfo_.name = "FocusChangedTest01_1"; + fullScreenAppInfo_.focusable_ = false; + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppInfo_); + ASSERT_NE(nullptr, window1); + + floatAppInfo_.name = "FocusChangedTest01_2"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& window2 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, window2); + + floatAppInfo_.name = "FocusChangedTest01_3"; + floatAppInfo_.rect = { 250, 150, 300, 500 }; + const sptr& window3 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, window3); + + subAppInfo_.name = "FocusChangedTest01_4"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = window3->GetWindowId(); + const sptr& subWindow = Utils::CreateTestWindow(subAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window3->Show()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(window3->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(window3->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, window2->Show()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(window3->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(window2->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(window2->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(subWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + window1->Destroy(); + window2->Destroy(); + window3->Destroy(); + subWindow->Destroy(); +} + +/** + * @tc.name: FocusChangedTest02 + * @tc.desc: hide focused window to test focus + * @tc.type: FUNC + */ +HWTEST_F(WindowFocusTest, FocusChangedTest02, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest02_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow); + ASSERT_EQ(WMError::WM_OK, mainWindow->Show()); + + subAppInfo_.name = "FocusChangedTest02_2"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow->GetWindowId(); + const sptr& subWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, subWindow); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(subWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + mainWindow->Destroy(); + subWindow->Destroy(); +} + +/** + * @tc.name: FocusChangedTest03 + * @tc.desc: hide focused window to test focus + * @tc.type: FUNC + */ +HWTEST_F(WindowFocusTest, FocusChangedTest03, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest03_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow1 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow1); + ASSERT_EQ(WMError::WM_OK, mainWindow1->Show()); + + subAppInfo_.name = "FocusChangedTest03_2"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow1->GetWindowId(); + const sptr& aboveSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, aboveSubWindow); + ASSERT_EQ(WMError::WM_OK, aboveSubWindow->Show()); + + floatAppInfo_.name = "FocusChangedTest03_3"; + floatAppInfo_.rect = { 200, 200, 100, 100 }; + const sptr& mainWindow2 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow2); + ASSERT_EQ(WMError::WM_OK, mainWindow2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow2->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, mainWindow2->Hide()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow2->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(aboveSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + mainWindow1->Destroy(); + mainWindow2->Destroy(); + aboveSubWindow->Destroy(); +} + +/** + * @tc.name: FocusChangedTest04 + * @tc.desc: hide focused window to test focus + * @tc.type: FUNC + */ +HWTEST_F(WindowFocusTest, FocusChangedTest04, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest04_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow1 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow1); + ASSERT_EQ(WMError::WM_OK, mainWindow1->Show()); + + subAppInfo_.name = "FocusChangedTest04_2"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow1->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + const sptr& belowSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, belowSubWindow); + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Show()); + + floatAppInfo_.name = "FocusChangedTest04_3"; + floatAppInfo_.rect = { 200, 200, 100, 100 }; + const sptr& mainWindow2 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow2); + ASSERT_EQ(WMError::WM_OK, mainWindow2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow2->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, mainWindow2->Hide()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow2->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(mainWindow1->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + mainWindow1->Destroy(); + mainWindow2->Destroy(); + belowSubWindow->Destroy(); +} + +/** + * @tc.name: FocusChangedTest05 + * @tc.desc: hide focused window to test focus + * @tc.type: FUNC + */ +HWTEST_F(WindowFocusTest, FocusChangedTest05, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest05_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow1 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow1); + ASSERT_EQ(WMError::WM_OK, mainWindow1->Show()); + + floatAppInfo_.name = "FocusChangedTest05_2"; + floatAppInfo_.rect = { 200, 200, 100, 100 }; + const sptr& mainWindow2 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow2); + ASSERT_EQ(WMError::WM_OK, mainWindow2->Show()); + + subAppInfo_.name = "FocusChangedTest05_3"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow2->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + const sptr& belowSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, belowSubWindow); + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Hide()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(mainWindow1->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow1->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(belowSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + ASSERT_EQ(WMError::WM_OK, mainWindow2->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(mainWindow1->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + mainWindow1->Destroy(); + mainWindow2->Destroy(); + belowSubWindow->Destroy(); +} + +/** +* @tc.name: FocusChangedTest06 +* @tc.desc: hide unfocused window to test focus +* @tc.type: FUNC +*/ +HWTEST_F(WindowFocusTest, FocusChangedTest06, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest06_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow); + ASSERT_EQ(WMError::WM_OK, mainWindow->Show()); + + subAppInfo_.name = "FocusChangedTest06_2"; + subAppInfo_.rect = { 100, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + const sptr& belowSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, belowSubWindow); + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Show()); + + subAppInfo_.name = "FocusChangedTest06_3"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW; + const sptr& aboveSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, aboveSubWindow); + ASSERT_EQ(WMError::WM_OK, aboveSubWindow->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(aboveSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Hide()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(aboveSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); +} + +/** +* @tc.name: FocusChangedTest07 +* @tc.desc: destroy focused window to test focus +* @tc.type: FUNC +*/ +HWTEST_F(WindowFocusTest, FocusChangedTest07, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest07_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow1 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow1); + ASSERT_EQ(WMError::WM_OK, mainWindow1->Show()); + + floatAppInfo_.name = "FocusChangedTest07_2"; + floatAppInfo_.rect = { 250, 150, 300, 500 }; + const sptr& mainWindow2 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow2); + ASSERT_EQ(WMError::WM_OK, mainWindow2->Show()); + + floatAppInfo_.name = "FocusChangedTest07_3"; + floatAppInfo_.rect = { 300, 400, 10, 400 }; + const sptr& mainWindow3 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow3); + ASSERT_EQ(WMError::WM_OK, mainWindow3->Show()); + + subAppInfo_.name = "FocusChangedTest07_4"; + subAppInfo_.rect = { 20, 100, 100, 100 }; + subAppInfo_.parentId = mainWindow1->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + const sptr& belowSubWindow1 = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, belowSubWindow1); + + subAppInfo_.name = "FocusChangedTest07_5"; + subAppInfo_.rect = { 400, 200, 100, 100 }; + subAppInfo_.parentId = mainWindow2->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW; + const sptr& aboveSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, aboveSubWindow); + + subAppInfo_.name = "FocusChangedTest07_6"; + subAppInfo_.rect = { 310, 410, 100, 100 }; + subAppInfo_.parentId = mainWindow3->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + const sptr& belowSubWindow2 = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, belowSubWindow2); + + ASSERT_EQ(WMError::WM_OK, aboveSubWindow->Show()); + ASSERT_EQ(WMError::WM_OK, belowSubWindow2->Show()); + ASSERT_EQ(WMError::WM_OK, belowSubWindow1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow1->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, mainWindow1->Destroy()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow1->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(mainWindow3->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, mainWindow3->Destroy()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(mainWindow3->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(aboveSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, aboveSubWindow->Destroy()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(aboveSubWindow->GetWindowId(), testFocusChangedListener_->unfocusedWindow_); + ASSERT_EQ(mainWindow2->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + mainWindow2->Destroy(); +} + +/** +* @tc.name: FocusChangedTest08 +* @tc.desc: destroy unfocused window to test focus +* @tc.type: FUNC +*/ +HWTEST_F(WindowFocusTest, FocusChangedTest08, Function | MediumTest | Level3) +{ + floatAppInfo_.name = "FocusChangedTest08_1"; + floatAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& mainWindow1 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow1); + ASSERT_EQ(WMError::WM_OK, mainWindow1->Show()); + + floatAppInfo_.name = "FocusChangedTest08_2"; + floatAppInfo_.rect = { 250, 150, 300, 500 }; + const sptr& mainWindow2 = Utils::CreateTestWindow(floatAppInfo_); + ASSERT_NE(nullptr, mainWindow2); + ASSERT_EQ(WMError::WM_OK, mainWindow2->Show()); + + subAppInfo_.name = "FocusChangedTest08_3"; + subAppInfo_.rect = { 20, 100, 100, 100 }; + subAppInfo_.parentId = mainWindow1->GetWindowId(); + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + const sptr& belowSubWindow = Utils::CreateTestWindow(subAppInfo_); + ASSERT_NE(nullptr, belowSubWindow); + ASSERT_EQ(WMError::WM_OK, belowSubWindow->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + ASSERT_EQ(WMError::WM_OK, mainWindow2->Destroy()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(belowSubWindow->GetWindowId(), testFocusChangedListener_->focusedWindow_); + + mainWindow1->Destroy(); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_gamut_test.cpp b/window_manager/test/systemtest/wms/window_gamut_test.cpp new file mode 100644 index 0000000..c2da94b --- /dev/null +++ b/window_manager/test/systemtest/wms/window_gamut_test.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021-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 "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +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(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + Utils::TestWindowInfo fullScreenAppInfo_; +}; + +void WindowGamutTest::SetUpTestCase() +{ +} + +void WindowGamutTest::TearDownTestCase() +{ +} + +void WindowGamutTest::SetUp() +{ + fullScreenAppInfo_ = { + .name = "FullWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowGamutTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: IsSupportWideGamut01 + * @tc.desc: IsSupportWideGamut + * @tc.type: FUNC + */ +HWTEST_F(WindowGamutTest, IsSupportWideGamut01, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullScreenAppInfo_); + + ASSERT_EQ(true, window->IsSupportWideGamut()); + + window->Destroy(); +} + +/** + * @tc.name: GetColorSpace01 + * @tc.desc: Get ColorSpace + * @tc.type: FUNC + */ +HWTEST_F(WindowGamutTest, GetColorSpace01, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullScreenAppInfo_); + + ASSERT_EQ(ColorSpace::COLOR_SPACE_DEFAULT, window->GetColorSpace()); + + window->Destroy(); +} + +/** + * @tc.name: SetColorSpace01 + * @tc.desc: Set ColorSpace, valid param + * @tc.type: FUNC + */ +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 + */ +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(colorSpaceBackup, window->GetColorSpace()); + + window->Destroy(); +} +} // namespace +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_immersive_test.cpp b/window_manager/test/systemtest/wms/window_immersive_test.cpp new file mode 100644 index 0000000..13ad4b8 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_immersive_test.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2021-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 "window_manager.h" +#include "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowImmersiveTest"}; + + const Rect SYS_BAR_REGION_NULL = { 0, 0, 0, 0 }; + const SystemBarProperty SYS_BAR_PROP_DEFAULT; + const SystemBarProperty SYS_BAR_PROP_1(true, 0xE5111111, 0xE5222222); + const SystemBarProperty SYS_BAR_PROP_2(false, 0xE5222222, 0xE5333333); + const SystemBarProperty SYS_BAR_PROP_3(false, 0xE5333333, 0xE5444444); + const SystemBarProperty SYS_BAR_PROP_4(true, 0xE5444444, 0x66555555); + const SystemBarRegionTints TEST_PROPS_DEFAULT = { + { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_DEFAULT, SYS_BAR_REGION_NULL }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_DEFAULT, SYS_BAR_REGION_NULL }, + }; + const SystemBarRegionTints TEST_PROPS_1 = { + { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_1, SYS_BAR_REGION_NULL }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_2, SYS_BAR_REGION_NULL }, + }; + const SystemBarRegionTints TEST_PROPS_2 = { + { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_1, SYS_BAR_REGION_NULL }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_3, SYS_BAR_REGION_NULL }, + }; + + const Rect EMPTY_RECT = {0, 0, 0, 0}; + const float RATIO = 0.3; +} + +using Utils = WindowTestUtils; +const int WAIT_ASYNC_US = 100000; // 100000us + +class TestSystemBarChangedListener : public ISystemBarChangedListener { +public: + SystemBarRegionTints tints_ = TEST_PROPS_DEFAULT; + void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override; +}; + +class TestAvoidAreaChangedListener : public IAvoidAreaChangedListener { +public: + AvoidArea avoidArea_; + void OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type) override; +}; + +class WindowImmersiveTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + void SetWindowSystemProps(const sptr& window, const SystemBarRegionTints& props); + bool SystemBarPropsEqualsTo(const SystemBarRegionTints& expect); + void DumpFailedInfo(const SystemBarRegionTints& expect); + void DumpFailedInfo(bool expectStatus, bool expectNav); + bool SystemBarEnableState(bool expectStatus, bool expectNav); + DisplayId displayId_ = 0; + std::vector> activeWindows_; + static vector fullScreenExpecteds_; + static sptr testSystemBarChangedListener_; + static sptr testAvoidAreaChangedListener_; + Utils::TestWindowInfo fullScreenAppinfo_; + Utils::TestWindowInfo avoidBarInfo_; + uint32_t leftAvoidW_; + uint32_t leftAvoidH_; + uint32_t topAvoidW_; + uint32_t topAvoidH_; + sptr backgroundWindow_; +}; + +vector WindowImmersiveTest::fullScreenExpecteds_; +sptr WindowImmersiveTest::testSystemBarChangedListener_ = + new TestSystemBarChangedListener(); +sptr WindowImmersiveTest::testAvoidAreaChangedListener_ = + new TestAvoidAreaChangedListener(); + +void WindowImmersiveTest::SetWindowSystemProps(const sptr& window, const SystemBarRegionTints& tints) +{ + for (auto tint : tints) { + window->SetSystemBarProperty(tint.type_, tint.prop_); + } +} + +void WindowImmersiveTest::DumpFailedInfo(const SystemBarRegionTints& expect) +{ + auto act = testSystemBarChangedListener_->tints_; + WLOGFI("WindowImmersiveTest Expected:"); + for (auto tint : expect) { + WLOGFI("WindowType: %{public}4d, Enable: %{public}4d, Color: %{public}x | %{public}x", + static_cast(tint.type_), tint.prop_.enable_, + tint.prop_.backgroundColor_, tint.prop_.contentColor_); + } + WLOGFI("WindowImmersiveTest Act: "); + for (auto tint : act) { + WLOGFI("WindowType: %{public}4d, Enable: %{public}4d, Color: %{public}x | %{public}x", + static_cast(tint.type_), tint.prop_.enable_, + tint.prop_.backgroundColor_, tint.prop_.contentColor_); + } +} + +void WindowImmersiveTest::DumpFailedInfo(bool expectStatus, bool expectNav) +{ + auto act = testSystemBarChangedListener_->tints_; + WLOGFI("WindowImmersiveTest Expected:"); + WLOGFI("expectStatus: %{public}4d, expectNav: %{public}4d", expectStatus, expectNav); + WLOGFI("WindowImmersiveTest Act: "); + for (auto tint : act) { + WLOGFI("WindowType: %{public}4d, Enable: %{public}4d, Color: %{public}x | %{public}x", + static_cast(tint.type_), tint.prop_.enable_, + tint.prop_.backgroundColor_, tint.prop_.contentColor_); + } +} + +bool WindowImmersiveTest::SystemBarPropsEqualsTo(const SystemBarRegionTints& expect) +{ + usleep(WAIT_ASYNC_US); + auto act = testSystemBarChangedListener_->tints_; + if (act.size() != expect.size()) { + DumpFailedInfo(expect); + return false; + } + for (auto item : expect) { + bool check = false; + for (auto tint : act) { + if (item.prop_ == tint.prop_ && item.type_ == tint.type_) { + check = true; + break; + } + } + if (!check) { + DumpFailedInfo(expect); + return false; + } + check = false; + } + return true; +} + +bool WindowImmersiveTest::SystemBarEnableState(bool expectStatus, bool expectNav) +{ + usleep(WAIT_ASYNC_US); + auto act = testSystemBarChangedListener_->tints_; + bool check = false; + for (auto tint : act) { + if ((tint.type_ == WindowType::WINDOW_TYPE_STATUS_BAR && tint.prop_.enable_ == expectStatus) + || (tint.type_ == WindowType::WINDOW_TYPE_NAVIGATION_BAR && tint.prop_.enable_ == expectNav)) { + check = true; + } else { + check = false; + } + } + if (!check) { + DumpFailedInfo(expectStatus, expectNav); + } + return check; +} + +void TestSystemBarChangedListener::OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) +{ + WLOGFI("TestSystemBarChangedListener Display ID: %{public}" PRIu64"", displayId); + for (auto tint : tints) { + auto type = tint.type_; + for (uint32_t i = 0; i < tints_.size(); i++) { + if (tints_[i].type_ == type) { + tints_[i] = tint; + } + } + } +} + +void TestAvoidAreaChangedListener::OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type) +{ + avoidArea_ = avoidArea; +} + +void WindowImmersiveTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); +} + +void WindowImmersiveTest::TearDownTestCase() +{ +} + +void WindowImmersiveTest::SetUp() +{ + fullScreenAppinfo_ = { + .name = "main", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, // immersive setting + .needAvoid = false, // immersive setting + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + avoidBarInfo_ = { + .name = "LeftAvoidTest", + .rect = EMPTY_RECT, + .type = WindowType::WINDOW_TYPE_STATUS_BAR, + .mode = WindowMode::WINDOW_MODE_FLOATING, + }; + // makesure left avoid win w < h + leftAvoidW_ = std::min(Utils::displayRect_.width_, static_cast(Utils::displayRect_.height_ * RATIO)); + leftAvoidH_ = Utils::displayRect_.height_; + // makesure top avoid win h < w + topAvoidW_ = Utils::displayRect_.width_; + topAvoidH_ = std::min(Utils::displayRect_.height_, static_cast(Utils::displayRect_.width_ * RATIO)); + + WindowManager::GetInstance().RegisterSystemBarChangedListener(testSystemBarChangedListener_); + activeWindows_.clear(); +} + +void WindowImmersiveTest::TearDown() +{ + while (!activeWindows_.empty()) { + ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy()); + activeWindows_.pop_back(); + } + WindowManager::GetInstance().UnregisterSystemBarChangedListener(testSystemBarChangedListener_); +} + +namespace { +/** + * @tc.name: ImmersiveTest01 + * @tc.desc: Add one immersive window and hide + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, ImmersiveTest01, Function | MediumTest | Level3) +{ + fullScreenAppinfo_.name = "immer01"; + const sptr& window = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window); + SetWindowSystemProps(window, TEST_PROPS_1); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: ImmersiveTest02 + * @tc.desc: Add two immersive window and switch + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, ImmersiveTest02, Function | MediumTest | Level3) +{ + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window1); + SetWindowSystemProps(window1, TEST_PROPS_1); + fullScreenAppinfo_.name = "Immer02"; + const sptr& window2 = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window2); + SetWindowSystemProps(window2, TEST_PROPS_2); + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window2->Show()); + + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_2)); + ASSERT_EQ(WMError::WM_OK, window2->Hide()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window1->Hide()); +} + +/** + * @tc.name: ImmersiveTest03 + * @tc.desc: Add one no immersive window + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, ImmersiveTest03, Function | MediumTest | Level3) +{ + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window1); + SetWindowSystemProps(window1, TEST_PROPS_1); + fullScreenAppinfo_.name = "Immer03"; + fullScreenAppinfo_.needAvoid = true; // no immersive setting + const sptr& window2 = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window2); + SetWindowSystemProps(window2, TEST_PROPS_2); + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window2->Show()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_2)); + ASSERT_EQ(WMError::WM_OK, window1->Hide()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_2)); +} + +/** + * @tc.name: ImmersiveTest04 + * @tc.desc: SetLayoutFullScreen + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, ImmersiveTest04, Function | MediumTest | Level3) +{ + fullScreenAppinfo_.needAvoid = true; // no immersive setting + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window1); + SetWindowSystemProps(window1, TEST_PROPS_1); + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window1->SetLayoutFullScreen(true)); + ASSERT_EQ(true, window1->IsLayoutFullScreen()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window1->SetLayoutFullScreen(false)); + ASSERT_EQ(false, window1->IsLayoutFullScreen()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window1->Hide()); +} + +/** + * @tc.name: ImmersiveTest05 + * @tc.desc: SetFullScreen + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, ImmersiveTest05, Function | MediumTest | Level3) +{ + fullScreenAppinfo_.needAvoid = true; // no immersive setting + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window1); + SetWindowSystemProps(window1, TEST_PROPS_1); + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1)); + ASSERT_EQ(WMError::WM_OK, window1->SetFullScreen(true)); + ASSERT_EQ(true, window1->IsFullScreen()); + ASSERT_TRUE(SystemBarEnableState(false, false)); + ASSERT_EQ(WMError::WM_OK, window1->SetFullScreen(false)); + ASSERT_EQ(false, window1->IsFullScreen()); + ASSERT_EQ(WMError::WM_OK, window1->Hide()); +} + +/** + * @tc.name: ImmersiveNegativeTest01 + * @tc.desc: set systembar props with wrong window type + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, ImmersiveNegativeTest01, Function | MediumTest | Level3) +{ + const SystemBarRegionTints TEST_PROPS_NEGATIVE = { + { WindowType::WINDOW_TYPE_KEYGUARD, SYS_BAR_PROP_1, SYS_BAR_REGION_NULL }, + { WindowType::WINDOW_TYPE_POINTER, SYS_BAR_PROP_2, SYS_BAR_REGION_NULL }, + }; + const sptr& window = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(window); + SetWindowSystemProps(window, TEST_PROPS_NEGATIVE); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_FALSE(SystemBarPropsEqualsTo(TEST_PROPS_NEGATIVE)); + ASSERT_EQ(WMError::WM_OK, window->Hide()); + ASSERT_FALSE(SystemBarPropsEqualsTo(TEST_PROPS_NEGATIVE)); +} + +/** + * @tc.name: GetAvoidAreaByTypeTest01 + * @tc.desc: Test GetAvoidArea use unsupported Type(TYPE_CUTOUT). + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, GetAvoidAreaByTypeTest01, Function | MediumTest | Level3) +{ + // Add full screenwindow for call GetAvoidArea, and push_back in activeWindows_ + const sptr& win = Utils::CreateTestWindow(fullScreenAppinfo_); + activeWindows_.push_back(win); + + // Test GetAvoidArea + AvoidArea avoidarea; + WMError ret = win->GetAvoidAreaByType(AvoidAreaType::TYPE_CUTOUT, avoidarea); + ASSERT_EQ(WMError::WM_OK, ret); + ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.leftRect_)); + ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.rightRect_)); + ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.topRect_)); + ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.bottomRect_)); + ASSERT_EQ(WMError::WM_OK, win->Hide()); +} + +/** + * @tc.name: DockWindowTest01 + * @tc.desc: Add unexistavoid and remove this avoid. Test OnAvoidAreaChanged listener + * @tc.type: FUNC + */ +HWTEST_F(WindowImmersiveTest, DockWindowTest01, Function | MediumTest | Level3) +{ + const sptr& dockWindow = Utils::CreateDockWindow(); + ASSERT_EQ(WMError::WM_OK, dockWindow->Show()); + + const sptr& window = Utils::CreateTestWindow(fullScreenAppinfo_); + + usleep(WAIT_ASYNC_US); + auto act = testSystemBarChangedListener_->tints_; + for (SystemBarRegionTint tint : act) { + if (tint.type_ == WindowType::WINDOW_TYPE_LAUNCHER_DOCK) { + ASSERT_FALSE(tint.prop_.enable_); + } + } + + ASSERT_EQ(WMError::WM_OK, window->Hide()); + + usleep(WAIT_ASYNC_US); + act = testSystemBarChangedListener_->tints_; + for (SystemBarRegionTint tint : act) { + if (tint.type_ == WindowType::WINDOW_TYPE_LAUNCHER_DOCK) { + ASSERT_TRUE(tint.prop_.enable_); + } + } + ASSERT_EQ(WMError::WM_OK, dockWindow->Destroy()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_input_method_test.cpp b/window_manager/test/systemtest/wms/window_input_method_test.cpp new file mode 100644 index 0000000..efe9480 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_input_method_test.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021-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 "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowInputMethodTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + Utils::TestWindowInfo inputMethodWindowInfo_; + Utils::TestWindowInfo keyGuardWindowInfo_; +}; + +void WindowInputMethodTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); +} + +void WindowInputMethodTest::TearDownTestCase() +{ +} + +void WindowInputMethodTest::SetUp() +{ + inputMethodWindowInfo_ = { + .name = "", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + keyGuardWindowInfo_ = { + .name = "", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_KEYGUARD, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowInputMethodTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: InputMethodWindow01 + * @tc.desc: One InputMethod Floating Window + * @tc.type: FUNC + */ +HWTEST_F(WindowInputMethodTest, InputMethodWindow01, Function | MediumTest | Level3) +{ + inputMethodWindowInfo_.name = "input_method.1"; + const sptr& window = Utils::CreateTestWindow(inputMethodWindowInfo_); + ASSERT_EQ(WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, window->GetType()); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: InputMethodWindow02 + * @tc.desc: One KeyGuard Window + * @tc.type: FUNC + */ +HWTEST_F(WindowInputMethodTest, InputMethodWindow02, Function | MediumTest | Level3) +{ + keyGuardWindowInfo_.name = "keyGuard.1"; + const sptr& window = Utils::CreateTestWindow(keyGuardWindowInfo_); + ASSERT_EQ(WindowType::WINDOW_TYPE_KEYGUARD, window->GetType()); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: InputMethodWindow03 + * @tc.desc: One InputMethod Floating Window & One KeyGuard Window + * @tc.type: FUNC + */ +HWTEST_F(WindowInputMethodTest, InputMethodWindow03, Function | MediumTest | Level3) +{ + inputMethodWindowInfo_.name = "input_method.2"; + keyGuardWindowInfo_.name = "keyGuard.2"; + const sptr& inputMethodWindow = Utils::CreateTestWindow(inputMethodWindowInfo_); + const sptr& keyGuardWindow = Utils::CreateTestWindow(keyGuardWindowInfo_); + keyGuardWindow->Show(); + inputMethodWindow->Show(); + ASSERT_TRUE(Utils::RectEqualTo(keyGuardWindow, Utils::displayRect_)); + ASSERT_EQ(inputMethodWindow->GetRect().width_, Utils::customAppRect_.width_); + ASSERT_EQ(inputMethodWindow->GetRect().height_, Utils::customAppRect_.height_); +} +} // namespace +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_input_test.cpp b/window_manager/test/systemtest/wms/window_input_test.cpp new file mode 100644 index 0000000..2e27d45 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_input_test.cpp @@ -0,0 +1,173 @@ +/* + * 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 "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr uint32_t WAIT_ASYNC_US = 100000; // 100ms +} +using Utils = WindowTestUtils; +class WindowInputTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + Utils::TestWindowInfo fullScreenWindow_; +}; + +void WindowInputTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); +} + +void WindowInputTest::TearDownTestCase() +{ +} + +void WindowInputTest::SetUp() +{ + fullScreenWindow_ = { + .name = "FullWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowInputTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: SetTouchHotAreas01 + * @tc.desc: Normal scenario testing for Window#SetTouchHotAreas + * @tc.type: FUNC + */ +HWTEST_F(WindowInputTest, SetTouchHotAreas01, Function | MediumTest | Level3) +{ + fullScreenWindow_.name = "window_hot_areas.1"; + const sptr& window = Utils::CreateTestWindow(fullScreenWindow_); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + std::vector requestedTouchHotAreas; + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_TRUE(requestedTouchHotAreas.empty()); + + usleep(WAIT_ASYNC_US); + Rect windowRect = window->GetRect(); + + std::vector rects; + uint32_t hotAreasNum = 10; + uint32_t hotAreaWidth = windowRect.width_ / hotAreasNum; + uint32_t hotAreaHeight = windowRect.height_ / hotAreasNum; + for (uint32_t i = 0; i < hotAreasNum; ++i) { + rects.emplace_back(Rect{ hotAreaWidth * i, hotAreaHeight * i, hotAreaWidth, hotAreaHeight }); + } + ASSERT_EQ(WMError::WM_OK, window->SetTouchHotAreas(rects)); + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_EQ(rects.size(), requestedTouchHotAreas.size()); + for (uint32_t i = 0; i < rects.size(); ++i) { + ASSERT_TRUE(rects[i] == requestedTouchHotAreas[i]); + } + + rects.clear(); + rects.emplace_back(Rect{ 0, 0, hotAreaWidth, hotAreaHeight }); + ASSERT_EQ(WMError::WM_OK, window->SetTouchHotAreas(rects)); + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_EQ(rects.size(), requestedTouchHotAreas.size()); + for (uint32_t i = 0; i < rects.size(); ++i) { + ASSERT_TRUE(rects[i] == requestedTouchHotAreas[i]); + } + + rects.clear(); + ASSERT_EQ(WMError::WM_OK, window->SetTouchHotAreas(rects)); + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_TRUE(requestedTouchHotAreas.empty()); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTouchHotAreas02 + * @tc.desc: Abnormal scenario testing for Window#SetTouchHotAreas + * @tc.type: FUNC + */ +HWTEST_F(WindowInputTest, SetTouchHotAreas02, Function | MediumTest | Level3) +{ + fullScreenWindow_.name = "window_hot_areas.2"; + const sptr& window = Utils::CreateTestWindow(fullScreenWindow_); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + usleep(WAIT_ASYNC_US); + Rect windowRect = window->GetRect(); + + std::vector rects; + /* maximum hot areas: 10, test exceeding maximum hot areas */ + uint32_t hotAreasNum = 11; + uint32_t hotAreaWidth = windowRect.width_ / hotAreasNum; + uint32_t hotAreaHeight = windowRect.height_ / hotAreasNum; + for (uint32_t i = 0; i < hotAreasNum; ++i) { + rects.emplace_back(Rect{ hotAreaWidth * i, hotAreaHeight * i, hotAreaWidth, hotAreaHeight }); + } + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + rects.clear(); + rects.emplace_back(Rect{ -1, 0, windowRect.width_ / 2, windowRect.height_ / 2 }); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + rects.clear(); + rects.emplace_back(Rect{ 0, -1, windowRect.width_ / 2, windowRect.height_ / 2 }); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + rects.clear(); + rects.emplace_back(Rect{ 0, 0, 0, windowRect.height_ / 2 }); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + rects.clear(); + rects.emplace_back(Rect{ 0, 0, windowRect.width_ / 2, 0 }); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + rects.clear(); + rects.emplace_back(Rect{ windowRect.width_, 0, windowRect.width_ / 2, windowRect.height_ / 2 }); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + rects.clear(); + rects.emplace_back(Rect{ 0, windowRect.height_, windowRect.width_ / 2, windowRect.height_ / 2 }); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetTouchHotAreas(rects)); + + std::vector requestedTouchHotAreas; + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_TRUE(requestedTouchHotAreas.empty()); + + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} +} // namespace +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/wms/window_layout_test.cpp b/window_manager/test/systemtest/wms/window_layout_test.cpp new file mode 100644 index 0000000..47247d8 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_layout_test.cpp @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2021-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 "window_manager.h" +#include "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowLayoutTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + DisplayId displayId_ = 0; + std::vector> activeWindows_; + static vector fullScreenExpecteds_; + static inline float virtualPixelRatio_ = 0.0; +private: + static constexpr uint32_t WAIT_SYANC_US = 100000; + static void InitAvoidArea(); +}; + +vector WindowLayoutTest::fullScreenExpecteds_; + +void WindowLayoutTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); + + virtualPixelRatio_ = WindowTestUtils::GetVirtualPixelRatio(0); + + // calc expected rects + Rect expected = { // 0. only statusBar + 0, + Utils::statusBarRect_.height_, + Utils::displayRect_.width_, + Utils::displayRect_.height_ - Utils::statusBarRect_.height_, + }; + fullScreenExpecteds_.push_back(expected); + expected = { // 1. both statusBar and naviBar + 0, + Utils::statusBarRect_.height_, + Utils::displayRect_.width_, + Utils::displayRect_.height_ - Utils::statusBarRect_.height_ - Utils::naviBarRect_.height_, + }; + fullScreenExpecteds_.push_back(expected); + expected = { // 2. only naviBar + 0, + 0, + Utils::displayRect_.width_, + Utils::displayRect_.height_ - Utils::naviBarRect_.height_, + }; + fullScreenExpecteds_.push_back(expected); + InitAvoidArea(); +} + +void WindowLayoutTest::InitAvoidArea() +{ + Utils::TestWindowInfo info = { + .name = "avoidArea", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + window->Show(); + window->SetLayoutFullScreen(true); + window->GetAvoidAreaByType(AvoidAreaType::TYPE_SYSTEM, WindowTestUtils::systemAvoidArea_); + window->Hide(); + window->Destroy(); +} + +void WindowLayoutTest::TearDownTestCase() +{ +} + +void WindowLayoutTest::SetUp() +{ + activeWindows_.clear(); +} + +void WindowLayoutTest::TearDown() +{ + while (!activeWindows_.empty()) { + ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy()); + activeWindows_.pop_back(); + } +} + +namespace { +/** + * @tc.name: LayoutWindow01 + * @tc.desc: One FLOATING APP Window with on custom rect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow01, Function | MediumTest | Level3) +{ + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::TILE); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::TILE); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + + Utils::TestWindowInfo info = { + .name = "main1", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + ASSERT_EQ(true, window != nullptr); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::GetFloatingLimitedRect(expect, virtualPixelRatio_))); + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: LayoutWindow02 + * @tc.desc: One FLOATING APP Window + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow02, Function | MediumTest | Level3) +{ + Rect res = Utils::GetFloatingLimitedRect(Utils::customAppRect_, virtualPixelRatio_); + Utils::TestWindowInfo info = { + .name = "main2", + .rect = res, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + + ASSERT_EQ(WMError::WM_OK, window->Show()); + if (window->IsDecorEnable()) { + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::GetDecorateRect(res, virtualPixelRatio_))); + } else { + ASSERT_TRUE(Utils::RectEqualTo(window, res)); + } + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: LayoutWindow04 + * @tc.desc: One FLOATING APP Window & One StatusBar Window + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow04, Function | MediumTest | Level3) +{ + // app window + Rect res = Utils::GetFloatingLimitedRect(Utils::customAppRect_, virtualPixelRatio_); + Utils::TestWindowInfo info = { + .name = "main4", + .rect = res, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + sptr appWin = Utils::CreateTestWindow(info); + activeWindows_.push_back(appWin); + + // statusBar window + sptr statBar = Utils::CreateStatusBarWindow(); + activeWindows_.push_back(statBar); + + ASSERT_EQ(WMError::WM_OK, appWin->Show()); + if (appWin->IsDecorEnable()) { + ASSERT_TRUE(Utils::RectEqualTo(appWin, Utils::GetDecorateRect(res, virtualPixelRatio_))); + } else { + ASSERT_TRUE(Utils::RectEqualTo(appWin, res)); + } + ASSERT_EQ(WMError::WM_OK, statBar->Show()); + if (appWin->IsDecorEnable()) { + ASSERT_TRUE(Utils::RectEqualTo(appWin, Utils::GetDecorateRect(res, virtualPixelRatio_))); + } else { + ASSERT_TRUE(Utils::RectEqualTo(appWin, res)); + } + ASSERT_EQ(WMError::WM_OK, statBar->Hide()); + if (appWin->IsDecorEnable()) { + ASSERT_TRUE(Utils::RectEqualTo(appWin, Utils::GetDecorateRect(res, virtualPixelRatio_))); + } else { + ASSERT_TRUE(Utils::RectEqualTo(appWin, res)); + } +} + +/** + * @tc.name: LayoutWindow06 + * @tc.desc: StatusBar Window and NaviBar & Sys Window FULLSCRENN,NOT NEEDVOID,PARENTLIMIT + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow06, Function | MediumTest | Level3) +{ + // statusBar window + sptr statBar = Utils::CreateStatusBarWindow(); + activeWindows_.push_back(statBar); + + // naviBar window + sptr naviBar = Utils::CreateNavigationBarWindow(); + activeWindows_.push_back(naviBar); + + // sys window + Utils::TestWindowInfo info = { + .name = "main6", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_PANEL, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = true, + .parentId = INVALID_WINDOW_ID, + }; + sptr sysWin = Utils::CreateTestWindow(info); + activeWindows_.push_back(sysWin); + + ASSERT_EQ(WMError::WM_OK, statBar->Show()); + ASSERT_EQ(WMError::WM_OK, sysWin->Show()); + ASSERT_TRUE(Utils::RectEqualTo(sysWin, Utils::displayRect_)); + ASSERT_EQ(WMError::WM_OK, naviBar->Show()); + ASSERT_TRUE(Utils::RectEqualTo(sysWin, Utils::displayRect_)); + ASSERT_EQ(WMError::WM_OK, statBar->Hide()); + ASSERT_TRUE(Utils::RectEqualTo(sysWin, Utils::displayRect_)); +} + +/** + * @tc.name: LayoutWindow07 + * @tc.desc: StatusBar Window and NaviBar & One Floating Sys Window + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow07, Function | MediumTest | Level3) +{ + // statusBar window + sptr statBar = Utils::CreateStatusBarWindow(); + activeWindows_.push_back(statBar); + + // naviBar window + sptr naviBar = Utils::CreateNavigationBarWindow(); + activeWindows_.push_back(naviBar); + + // sys window + Utils::TestWindowInfo info = { + .name = "main7", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_PANEL, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = true, + .parentId = INVALID_WINDOW_ID, + }; + sptr sysWin = Utils::CreateTestWindow(info); + activeWindows_.push_back(sysWin); + + ASSERT_EQ(WMError::WM_OK, statBar->Show()); + ASSERT_EQ(WMError::WM_OK, sysWin->Show()); + ASSERT_TRUE(Utils::RectEqualTo(sysWin, Utils::customAppRect_)); + ASSERT_EQ(WMError::WM_OK, naviBar->Show()); + ASSERT_TRUE(Utils::RectEqualTo(sysWin, Utils::customAppRect_)); + ASSERT_EQ(WMError::WM_OK, statBar->Hide()); + ASSERT_TRUE(Utils::RectEqualTo(sysWin, Utils::customAppRect_)); +} + +/** + * @tc.name: LayoutWindow08 + * @tc.desc: One FLOATING APP Window with on custom rect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow08, Function | MediumTest | Level3) +{ + Utils::TestWindowInfo info = { + .name = "main8", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: LayoutWindow09 + * @tc.desc: Add a floating and resize(2, 2) + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow09, Function | MediumTest | Level3) +{ + Utils::TestWindowInfo info = { + .name = "main9", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); + + 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, virtualPixelRatio_); + ASSERT_TRUE(Utils::RectEqualTo(window, finalExcept)); + ASSERT_EQ(WMError::WM_OK, window->Hide()); +} + +/** + * @tc.name: LayoutWindow10 + * @tc.desc: One FLOATING APP Window do max and recovery + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutWindow10, Function | MediumTest | Level3) +{ + Utils::TestWindowInfo info = { + .name = "main10", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); + ASSERT_EQ(WMError::WM_OK, window->Maximize()); + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::displayRect_)); + ASSERT_EQ(WMError::WM_OK, window->Recover()); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); + ASSERT_EQ(WMError::WM_OK, window->Minimize()); + ASSERT_EQ(WMError::WM_OK, window->Close()); +} + +/** + * @tc.name: LayoutTile01 + * @tc.desc: One FLOATING APP Window into tile mode, show 4 new window + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutTile01, Function | MediumTest | Level3) +{ + Utils::TestWindowInfo info = { + .name = "mainTile1", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + // init tile window rects and get max tile window num + Utils::InitTileWindowRects(window); + uint32_t maxTileNum = Utils::GetMaxTileWinNum(); + if (maxTileNum < 1) { + return; + } + + usleep(WAIT_SYANC_US); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::TILE); + usleep(WAIT_SYANC_US); + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::singleTileRect_)); + + info.name = "test1"; + const sptr& test1 = Utils::CreateTestWindow(info); + activeWindows_.push_back(test1); + ASSERT_EQ(WMError::WM_OK, test1->Show()); + usleep(WAIT_SYANC_US); + if (maxTileNum == 1) { + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::singleTileRect_)); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + return; + } + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::doubleTileRects_[0])); + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::doubleTileRects_[1])); + + info.name = "test2"; + const sptr& test2 = Utils::CreateTestWindow(info); + activeWindows_.push_back(test2); + ASSERT_EQ(WMError::WM_OK, test2->Show()); + usleep(WAIT_SYANC_US); + if (maxTileNum == 2) { + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::doubleTileRects_[0])); + ASSERT_TRUE(Utils::RectEqualTo(test2, Utils::doubleTileRects_[1])); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + return; + } + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::tripleTileRects_[0])); + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::tripleTileRects_[1])); + ASSERT_TRUE(Utils::RectEqualTo(test2, Utils::tripleTileRects_[2])); // 2 is second rect idx + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); +} + +/** + * @tc.name: LayoutTileNegative01 + * @tc.desc: negative test for tile window + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutTileNegative01, Function | MediumTest | Level3) +{ + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + Utils::TestWindowInfo info = { + .name = "mainTileNegative1", + .rect = {-1, -100, -1, -100}, // -1, -100, -1, -100 is typical negative case nums + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + // init tile window rects and get max tile window num + Utils::InitTileWindowRects(window); + uint32_t maxTileNum = Utils::GetMaxTileWinNum(); + if (maxTileNum < 1) { + return; + } + + usleep(WAIT_SYANC_US); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::TILE); + usleep(WAIT_SYANC_US); + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::singleTileRect_)); + + info.name = "test1"; + const sptr& test1 = Utils::CreateTestWindow(info); + activeWindows_.push_back(test1); + ASSERT_EQ(WMError::WM_OK, test1->Show()); + usleep(WAIT_SYANC_US); + if (maxTileNum == 1) { + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::singleTileRect_)); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + return; + } + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::doubleTileRects_[0])); + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::doubleTileRects_[1])); + + info.name = "test2"; + const sptr& test2 = Utils::CreateTestWindow(info); + activeWindows_.push_back(test2); + ASSERT_EQ(WMError::WM_OK, test2->Show()); + usleep(WAIT_SYANC_US); + if (maxTileNum == 2) { + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::doubleTileRects_[0])); + ASSERT_TRUE(Utils::RectEqualTo(test2, Utils::doubleTileRects_[1])); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + return; + } + ASSERT_TRUE(Utils::RectEqualTo(window, Utils::tripleTileRects_[0])); + ASSERT_TRUE(Utils::RectEqualTo(test1, Utils::tripleTileRects_[1])); + ASSERT_TRUE(Utils::RectEqualTo(test2, Utils::tripleTileRects_[2])); // 2 is second rect idx + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); +} + +/** + * @tc.name: LayoutTileNegative01 + * @tc.desc: move window out of the display + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutNegative01, Function | MediumTest | Level3) +{ + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + Utils::TestWindowInfo info = { + .name = "mainNegative1", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + usleep(WAIT_SYANC_US); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); +} + +/** + * @tc.name: LayoutNegative02 + * @tc.desc: resize window to negative size + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutTest, LayoutNegative02, Function | MediumTest | Level3) +{ + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + const uint32_t negativeW = 0; + const uint32_t negativeH = 0; + Utils::TestWindowInfo info = { + .name = "mainNegative2", + .rect = {0, 0, 0, 0}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + const sptr& window = Utils::CreateTestWindow(info); + activeWindows_.push_back(window); + Rect expect = Utils::GetDefaultFloatingRect(window); + ASSERT_EQ(WMError::WM_OK, window->Show()); + usleep(WAIT_SYANC_US); + ASSERT_TRUE(Utils::RectEqualTo(window, expect)); + window->Resize(negativeW, negativeH); + usleep(WAIT_SYANC_US); + Rect expect2 = {expect.posX_, expect.posY_, negativeW, negativeH}; + expect2 = Utils::CalcLimitedRect(expect2, virtualPixelRatio_); + ASSERT_TRUE(Utils::RectEqualTo(window, expect2)); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_mode_support_info_test.cpp b/window_manager/test/systemtest/wms/window_mode_support_info_test.cpp new file mode 100644 index 0000000..e11eb4f --- /dev/null +++ b/window_manager/test/systemtest/wms/window_mode_support_info_test.cpp @@ -0,0 +1,208 @@ +/* + * 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 "window_manager.h" +#include "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowModeSupportInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + Utils::TestWindowInfo fullAppInfo_1_; + Utils::TestWindowInfo fullAppInfo_2_; +private: + static constexpr uint32_t WAIT_SYANC_US = 100000; +}; + +void WindowModeSupportInfoTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); +} + +void WindowModeSupportInfoTest::TearDownTestCase() +{ +} + +void WindowModeSupportInfoTest::SetUp() +{ + fullAppInfo_1_ = { + .name = "FullWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + fullAppInfo_2_ = { + .name = "FullWindow2", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowModeSupportInfoTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowModeSupportInfo01 + * @tc.desc: SetRequestModeSupportInfo | GetRequestModeSupportInfo + * @tc.type: FUNC + */ +HWTEST_F(WindowModeSupportInfoTest, WindowModeSupportInfo01, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullAppInfo_1_); + + window->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN); + ASSERT_EQ(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN, window->GetRequestModeSupportInfo()); + window->Destroy(); +} + +/** + * @tc.name: WindowModeSupportInfo02 + * @tc.desc: modeSupportInfo test for single window, only support fullScreen mode + * @tc.type: FUNC + */ +HWTEST_F(WindowModeSupportInfoTest, WindowModeSupportInfo02, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullAppInfo_1_); + + window->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + ASSERT_EQ(WMError::WM_OK, window->Hide()); + window->Destroy(); +} + +/** + * @tc.name: WindowModeSupportInfo03 + * @tc.desc: modeSupportInfo test for single window, support both fullScreen and floating mode + * @tc.type: FUNC + */ +HWTEST_F(WindowModeSupportInfoTest, WindowModeSupportInfo03, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullAppInfo_1_); + + window->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN | + WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + ASSERT_EQ(WMError::WM_OK, window->Hide()); + window->Destroy(); +} + +/** + * @tc.name: WindowModeSupportInfo04 + * @tc.desc: modeSupportInfo test for single window, window mode is not supported when show, show failed + * @tc.type: FUNC + */ +HWTEST_F(WindowModeSupportInfoTest, WindowModeSupportInfo04, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullAppInfo_1_); + window->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING | + WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | + WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY); + ASSERT_NE(WMError::WM_OK, window->Show()); + ASSERT_EQ(WMError::WM_OK, window->Hide()); + window->Destroy(); +} + +/** + * @tc.name: WindowModeSupportInfo05 + * @tc.desc: modeSupportInfo test for layout cascade + * @tc.type: FUNC + */ +HWTEST_F(WindowModeSupportInfoTest, WindowModeSupportInfo05, Function | MediumTest | Level3) +{ + const sptr& window1 = Utils::CreateTestWindow(fullAppInfo_1_); + window1->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN); + const sptr& window2 = Utils::CreateTestWindow(fullAppInfo_2_); + window2->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL); + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_EQ(WMError::WM_OK, window2->Show()); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + usleep(WAIT_SYANC_US); + + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window1->GetMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, window2->GetMode()); + + window1->Destroy(); + window2->Destroy(); +} + +/** + * @tc.name: WindowModeSupportInfo06 + * @tc.desc: modeSupportInfo test for layout tile + * @tc.type: FUNC + */ +HWTEST_F(WindowModeSupportInfoTest, WindowModeSupportInfo06, Function | MediumTest | Level3) +{ + const sptr& window = Utils::CreateTestWindow(fullAppInfo_1_); + window->SetRequestModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN); + ASSERT_EQ(WMError::WM_OK, window->Show()); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::TILE); + usleep(WAIT_SYANC_US); + + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + + window->Destroy(); + WindowManager::GetInstance().SetWindowLayoutMode(WindowLayoutMode::CASCADE); + usleep(WAIT_SYANC_US); +} +} // namespace +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/wms/window_move_drag_test.cpp b/window_manager/test/systemtest/wms/window_move_drag_test.cpp new file mode 100755 index 0000000..3a39500 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_move_drag_test.cpp @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2021-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 "pointer_event.h" +#include "window_helper.h" +#include "window_impl.h" +#include "window_test_utils.h" +#include "wm_common_inner.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowMoveDragTest"}; + constexpr float POINT_HOTZONE_RATIO = 0.5; + constexpr int WAIT_SYANC_MS = 100000; +} +using Utils = WindowTestUtils; +class WindowMoveDragTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + +private: + std::shared_ptr CreatePointerEvent(int32_t posX, + int32_t posY, + uint32_t pointerId, + int32_t pointerAction); + void DoMoveOrDrag(bool isMove, bool isDrag); + static inline std::vector> activeWindows_; + static inline uint32_t pointerId_ = 0; + static inline int32_t startPointX_ = 0; + static inline int32_t startPointY_ = 0; + 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() +{ + startPointX_ = 0; + startPointY_ = 0; + startPointRect_ = {0, 0, 0, 0}; + expectRect_ = {0, 0, 0, 0}; + usleep(WAIT_SYANC_MS); +} + +void WindowMoveDragTest::TearDownTestCase() +{ +} + +void WindowMoveDragTest::SetUp() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}llu, w %{public}d, h %{public}d, fps %{public}u\n", + (unsigned long long)display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); + + virtualPixelRatio_ = WindowTestUtils::GetVirtualPixelRatio(0); + hotZone_ = static_cast(HOTZONE_TOUCH * virtualPixelRatio_); + + sptr option = new WindowOption(); + option->SetWindowName("WindowMoveDragTest"); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + window_ = new WindowImpl(option); + window_->Create(INVALID_WINDOW_ID); + usleep(WAIT_SYANC_MS); + ASSERT_TRUE((window_ != nullptr)); +} + +void WindowMoveDragTest::TearDown() +{ + ASSERT_EQ(WMError::WM_OK, window_->Destroy()); + window_ = nullptr; + usleep(WAIT_SYANC_MS); +} + +std::shared_ptr WindowMoveDragTest::CreatePointerEvent(int32_t posX, + int32_t posY, + uint32_t pointerId, + int32_t pointerAction) +{ + MMI::PointerEvent::PointerItem pointerItem; + pointerItem.SetPointerId(pointerId); + pointerItem.SetDisplayX(posX); + pointerItem.SetDisplayY(posY); + + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + pointerEvent->SetTargetDisplayId(0); + pointerEvent->AddPointerItem(pointerItem); + pointerEvent->SetPointerId(pointerId); + pointerEvent->SetPointerAction(pointerAction); + pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); + return pointerEvent; +} + +void WindowMoveDragTest::DoMoveOrDrag(bool isMove, bool isDrag) +{ + pointerId_++; + std::shared_ptr pointerEvent = + CreatePointerEvent(startPointX_, startPointY_, pointerId_, MMI::PointerEvent::POINTER_ACTION_DOWN); + window_->ConsumePointerEvent(pointerEvent); + ASSERT_TRUE(Utils::RectEqualToRect(window_->GetRect(), startPointRect_)); + + usleep(WAIT_SYANC_MS); + ASSERT_EQ(isMove, window_->moveDragProperty_->startMoveFlag_); + ASSERT_EQ(isDrag, window_->moveDragProperty_->startDragFlag_); + + pointerEvent = CreatePointerEvent(startPointX_, startPointY_, pointerId_, MMI::PointerEvent::POINTER_ACTION_UP); + window_->ConsumePointerEvent(pointerEvent); + ASSERT_EQ(false, window_->moveDragProperty_->startMoveFlag_); + ASSERT_EQ(false, window_->moveDragProperty_->startDragFlag_); +} + +namespace { +/** + * @tc.name: DragWindow01 + * @tc.desc: drag left + * @tc.type: FUNC + * @tc.require: I5KYG1 + */ +HWTEST_F(WindowMoveDragTest, DragWindow01, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ - static_cast(hotZone_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + static_cast(startPointRect_.height_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow02 + * @tc.desc: drag left top + * @tc.type: FUNC + * @tc.require: I5KYG1 + */ +HWTEST_F(WindowMoveDragTest, DragWindow02, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ - static_cast(hotZone_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ - static_cast(hotZone_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow03 + * @tc.desc: drag left bottom + * @tc.type: FUNC + * @tc.require: I5KYG1 + */ +HWTEST_F(WindowMoveDragTest, DragWindow03, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ - static_cast(hotZone_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + + static_cast(startPointRect_.height_ + hotZone_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow04 + * @tc.desc: drag right + * @tc.type: FUNC + * @tc.require: I5KYG1 + */ +HWTEST_F(WindowMoveDragTest, DragWindow04, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + + static_cast(startPointRect_.width_ + hotZone_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + static_cast(startPointRect_.height_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow05 + * @tc.desc: drag right top + * @tc.type: FUNC + * @tc.require: I5KYG1 + */ +HWTEST_F(WindowMoveDragTest, DragWindow05, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + + static_cast(startPointRect_.width_ + hotZone_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ - static_cast(hotZone_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow06 + * @tc.desc: drag right bottom + * @tc.type: FUNC + */ +HWTEST_F(WindowMoveDragTest, DragWindow06, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + + static_cast(startPointRect_.width_ + hotZone_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + + static_cast(startPointRect_.height_ + hotZone_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow07 + * @tc.desc: drag top + * @tc.type: FUNC + */ +HWTEST_F(WindowMoveDragTest, DragWindow07, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + static_cast(startPointRect_.width_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ - static_cast(hotZone_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow08 + * @tc.desc: drag bottom + * @tc.type: FUNC + */ +HWTEST_F(WindowMoveDragTest, DragWindow08, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + static_cast(startPointRect_.width_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + + static_cast(startPointRect_.height_ + hotZone_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, true); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow09 + * @tc.desc: point in decorZone, uiContent is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowMoveDragTest, DragWindow09, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + static_cast(startPointRect_.width_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + + static_cast(WINDOW_TITLE_BAR_HEIGHT * POINT_HOTZONE_RATIO * virtualPixelRatio_); + + DoMoveOrDrag(false, false); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} + +/** + * @tc.name: DragWindow10 + * @tc.desc: drag inner + * @tc.type: FUNC + */ +HWTEST_F(WindowMoveDragTest, DragWindow10, Function | MediumTest | Level3) +{ + ASSERT_EQ(WMError::WM_OK, window_->Show()); + usleep(WAIT_SYANC_MS); + startPointRect_ = window_->GetRect(); + startPointX_ = startPointRect_.posX_ + static_cast(startPointRect_.width_ * POINT_HOTZONE_RATIO); + startPointY_ = startPointRect_.posY_ + static_cast(startPointRect_.height_ * POINT_HOTZONE_RATIO); + + DoMoveOrDrag(false, false); + ASSERT_EQ(WMError::WM_OK, window_->Hide()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_multi_ability_test.cpp b/window_manager/test/systemtest/wms/window_multi_ability_test.cpp new file mode 100644 index 0000000..ffb6cf2 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_multi_ability_test.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021-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 "window_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowMultiAbilityTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowMultiAbilityTest::SetUpTestCase() +{ +} + +void WindowMultiAbilityTest::TearDownTestCase() +{ +} + +void WindowMultiAbilityTest::SetUp() +{ +} + +void WindowMultiAbilityTest::TearDown() +{ +} + +/** + * @tc.name: MultiAbilityWindow01 + * @tc.desc: Five scene process in one thread + * @tc.type: FUNC + */ +HWTEST_F(WindowMultiAbilityTest, MultiAbilityWindow01, Function | MediumTest | Level2) +{ + sptr scene1 = Utils::CreateWindowScene(); + sptr scene2 = Utils::CreateWindowScene(); + sptr scene3 = Utils::CreateWindowScene(); + sptr scene4 = Utils::CreateWindowScene(); + sptr scene5 = Utils::CreateWindowScene(); + + ASSERT_EQ(WMError::WM_OK, scene1->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene2->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene3->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene5->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene5->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene3->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene2->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene1->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene1->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene2->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene3->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene4->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene5->GoDestroy()); +} + +/** + * @tc.name: MultiAbilityWindow04 + * @tc.desc: Five scene process in one thread, create/show/hide/destroy in order + * @tc.type: FUNC + */ +HWTEST_F(WindowMultiAbilityTest, MultiAbilityWindow02, Function | MediumTest | Level3) +{ + sptr scene1 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene1->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene1->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene1->GoDestroy()); + + sptr scene2 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene2->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene2->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene2->GoDestroy()); + + sptr scene3 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene3->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene3->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene3->GoDestroy()); + + sptr scene4 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene4->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoDestroy()); + + sptr scene5 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene5->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene5->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene5->GoDestroy()); +} + +/** + * @tc.name: MultiAbilityWindow05 + * @tc.desc: Five scene process in one thread, create/show/hide/destroy out of order + * @tc.type: FUNC + */ +HWTEST_F(WindowMultiAbilityTest, MultiAbilityWindow03, Function | MediumTest | Level3) +{ + sptr scene1 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene1->GoForeground()); + sptr scene2 = Utils::CreateWindowScene(); + sptr scene3 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene3->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene1->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene1->GoDestroy()); + sptr scene4 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene3->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene2->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene2->GoBackground()); + sptr scene5 = Utils::CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene3->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene5->GoForeground()); + ASSERT_EQ(WMError::WM_OK, scene5->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoBackground()); + ASSERT_EQ(WMError::WM_OK, scene4->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene5->GoDestroy()); + ASSERT_EQ(WMError::WM_OK, scene2->GoDestroy()); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_occupied_area_change_test.cpp b/window_manager/test/systemtest/wms/window_occupied_area_change_test.cpp new file mode 100644 index 0000000..c12cf40 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_occupied_area_change_test.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2021-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_test_utils.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowOccupiedAreaChangeTest"}; +} + +using Utils = WindowTestUtils; +const int WAIT_ASYNC_US = 100000; // 100000us + +class TestOccupiedAreaChangeListener : public IOccupiedAreaChangeListener { +public: + OccupiedAreaType type_ = OccupiedAreaType::TYPE_INPUT; + Rect rect_ = { 0, 0, 0, 0 }; + void OnSizeChange(const sptr& info) override; +}; + +class WindowOccupiedAreaChangeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static sptr testOccupiedAreaChangeListener_; + Utils::TestWindowInfo fullScreenAppInfo_; + Utils::TestWindowInfo imeAppInfo_; +}; + +sptr WindowOccupiedAreaChangeTest::testOccupiedAreaChangeListener_ = + new TestOccupiedAreaChangeListener(); + +void TestOccupiedAreaChangeListener::OnSizeChange(const sptr& info) +{ + WLOGFI("OccupiedAreaChangeInfo: [%{public}u, {%{public}u, %{public}u}]", + info->type_, info->rect_.width_, info->rect_.height_); + type_ = info->type_; + rect_ = info->rect_; +} + +void WindowOccupiedAreaChangeTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + Utils::InitByDisplayRect(displayRect); +} + +void WindowOccupiedAreaChangeTest::TearDownTestCase() +{ +} + +void WindowOccupiedAreaChangeTest::SetUp() +{ + fullScreenAppInfo_ = { + .name = "FullWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + imeAppInfo_ = { + .name = "ImeWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, + .mode = WindowMode::WINDOW_MODE_FLOATING, + }; +} + +void WindowOccupiedAreaChangeTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: KeyboardHeightChangeTest01 + * @tc.desc: test get keyboard height when WINDOW_TYPE_INPUT_METHOD_FLOAT show + * @tc.type: FUNC + */ +HWTEST_F(WindowOccupiedAreaChangeTest, KeyboardHeightChangeTest01, Function | MediumTest | Level3) +{ + fullScreenAppInfo_.name = "KeyboardHeightChangeTest01"; + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppInfo_); + ASSERT_NE(nullptr, window1); + window1->RegisterOccupiedAreaChangeListener(testOccupiedAreaChangeListener_); + + imeAppInfo_.name = "imeWindow1"; + imeAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& window2 = Utils::CreateTestWindow(imeAppInfo_); + ASSERT_NE(nullptr, window2); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_EQ(WMError::WM_OK, window2->SetCallingWindow(window1->GetWindowId())); + ASSERT_EQ(WMError::WM_OK, window2->Show()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posX_, window2->GetRect().posX_); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posY_, window2->GetRect().posY_); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.width_, window2->GetRect().width_); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.height_, window2->GetRect().height_); +} + +/** + * @tc.name: KeyboardHeightChangeTest02 + * @tc.desc: test get keyboard height when WINDOW_TYPE_INPUT_METHOD_FLOAT hide + * @tc.type: FUNC + */ +HWTEST_F(WindowOccupiedAreaChangeTest, KeyboardHeightChangeTest02, Function | MediumTest | Level3) +{ + fullScreenAppInfo_.name = "KeyboardHeightChangeTest02"; + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppInfo_); + ASSERT_NE(nullptr, window1); + window1->RegisterOccupiedAreaChangeListener(testOccupiedAreaChangeListener_); + + imeAppInfo_.name = "imeWindow2"; + imeAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& window2 = Utils::CreateTestWindow(imeAppInfo_); + ASSERT_NE(nullptr, window2); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_EQ(WMError::WM_OK, window2->SetCallingWindow(window1->GetWindowId())); + ASSERT_EQ(WMError::WM_OK, window2->Show()); + ASSERT_EQ(WMError::WM_OK, window2->Hide()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posX_, 0); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posY_, 0); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.width_, 0); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.height_, 0); +} + +/** + * @tc.name: KeyboardHeightChangeTest03 + * @tc.desc: test get keyboard height when WINDOW_TYPE_INPUT_METHOD_FLOAT destroy + * @tc.type: FUNC + */ +HWTEST_F(WindowOccupiedAreaChangeTest, KeyboardHeightChangeTest03, Function | MediumTest | Level3) +{ + fullScreenAppInfo_.name = "KeyboardHeightChangeTest03"; + const sptr& window1 = Utils::CreateTestWindow(fullScreenAppInfo_); + ASSERT_NE(nullptr, window1); + window1->RegisterOccupiedAreaChangeListener(testOccupiedAreaChangeListener_); + + imeAppInfo_.name = "imeWindow3"; + imeAppInfo_.rect = { 10, 200, 300, 400 }; + const sptr& window2 = Utils::CreateTestWindow(imeAppInfo_); + ASSERT_NE(nullptr, window2); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + ASSERT_EQ(WMError::WM_OK, window2->SetCallingWindow(window1->GetWindowId())); + ASSERT_EQ(WMError::WM_OK, window2->Show()); + ASSERT_EQ(WMError::WM_OK, window2->Destroy()); + // Await 100ms and get callback result in listener. + usleep(WAIT_ASYNC_US); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posX_, 0); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.posY_, 0); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.width_, 0); + ASSERT_EQ(testOccupiedAreaChangeListener_->rect_.height_, 0); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_rotation_test.cpp b/window_manager/test/systemtest/wms/window_rotation_test.cpp new file mode 100644 index 0000000..ee573a7 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_rotation_test.cpp @@ -0,0 +1,329 @@ +/* + * 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 "window_test_utils.h" + +#include "display_manager.h" +#include "future.h" +#include "screen_manager.h" +#include "window_manager.h" +#include "window_accessibility_controller.h" +#include "window_impl.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class DisplayListener : public DisplayManager::IDisplayListener { +public: + virtual void OnCreate(DisplayId) override; + virtual void OnDestroy(DisplayId) override; + virtual void OnChange(DisplayId) override; + RunnableFuture changeFuture_; +}; + +class ScreenListener : public ScreenManager::IScreenListener { +public: + virtual void OnConnect(ScreenId) override; + virtual void OnDisconnect(ScreenId) override; + virtual void OnChange(ScreenId) override; + RunnableFuture changeFuture_; +}; + +class WindowRotationTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + std::vector> activeWindows_; + Utils::TestWindowInfo fullInfo_; + sptr displayListener_; + sptr screenListener_; +private: + static constexpr uint32_t SPLIT_TEST_SLEEP_S = 1; + static constexpr long FUTURE_GET_RESULT_TIMEOUT = 1000; +}; + +void DisplayListener::OnCreate(DisplayId displayId) +{ +} + +void DisplayListener::OnDestroy(DisplayId displayId) +{ +} + +void DisplayListener::OnChange(DisplayId displayId) +{ + changeFuture_.SetValue(displayId); +} + +void ScreenListener::OnConnect(ScreenId screenId) +{ +} + +void ScreenListener::OnDisconnect(ScreenId screenId) +{ +} + +void ScreenListener::OnChange(ScreenId screenId) +{ + changeFuture_.SetValue(screenId); +} + +void WindowRotationTest::SetUpTestCase() +{ +} + +void WindowRotationTest::TearDownTestCase() +{ +} + +void WindowRotationTest::SetUp() +{ + fullInfo_ = { + .name = "", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + activeWindows_.clear(); + displayListener_ = new DisplayListener(); + DisplayManager::GetInstance().RegisterDisplayListener(displayListener_); + screenListener_ = new ScreenListener(); + ScreenManager::GetInstance().RegisterScreenListener(screenListener_); +} + +void WindowRotationTest::TearDown() +{ + while (!activeWindows_.empty()) { + ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy()); + activeWindows_.pop_back(); + } + DisplayManager::GetInstance().UnregisterDisplayListener(displayListener_); + ScreenManager::GetInstance().UnregisterScreenListener(screenListener_); +} + +namespace { +/** +* @tc.name: WindowRotationTest1 +* @tc.desc: create window and SetRequestedOrientation. +* @tc.type: FUNC +*/ +HWTEST_F(WindowRotationTest, WindowRotationTest1, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.1"; + fullInfo_.orientation_ = Orientation::UNSPECIFIED; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, fullWindow->GetMode()); + sleep(SPLIT_TEST_SLEEP_S); + + fullWindow->SetRequestedOrientation(Orientation::REVERSE_HORIZONTAL); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, fullWindow->GetRequestedOrientation()); + DisplayId displayId = displayListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + displayListener_->changeFuture_.Reset(-1); + ScreenId screenId = screenListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + screenListener_->changeFuture_.Reset(-1); + auto screen = ScreenManager::GetInstance().GetScreenById(screenId); + auto display = DisplayManager::GetInstance().GetDisplayById(displayId); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, screen->GetOrientation()); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** +* @tc.name: WindowRotationTest2 +* @tc.desc: create window with orientation property. +* @tc.type: FUNC +*/ +HWTEST_F(WindowRotationTest, WindowRotationTest2, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.2"; + fullInfo_.orientation_ = Orientation::REVERSE_HORIZONTAL; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, fullWindow->GetMode()); + + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, fullWindow->GetRequestedOrientation()); + DisplayId displayId = displayListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + ScreenId screenId = screenListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + auto screen = ScreenManager::GetInstance().GetScreenById(screenId); + auto display = DisplayManager::GetInstance().GetDisplayById(displayId); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, screen->GetOrientation()); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + screen->SetOrientation(Orientation::UNSPECIFIED); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** +* @tc.name: WindowRotationTest3 +* @tc.desc: create floating window with orientation property +* @tc.type: FUNC +*/ +HWTEST_F(WindowRotationTest, WindowRotationTest3, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.4"; + fullInfo_.orientation_ = Orientation::REVERSE_HORIZONTAL; + fullInfo_.mode = WindowMode::WINDOW_MODE_FLOATING; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + fullInfo_.mode = WindowMode::WINDOW_MODE_FULLSCREEN; + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, fullWindow->GetMode()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, fullWindow->GetRequestedOrientation()); + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + auto screen = ScreenManager::GetInstance().GetAllScreens()[0]; + ASSERT_EQ(Orientation::UNSPECIFIED, screen->GetOrientation()); + ASSERT_EQ(Orientation::UNSPECIFIED, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + ASSERT_EQ(Orientation::UNSPECIFIED, screen->GetOrientation()); + ASSERT_EQ(Orientation::UNSPECIFIED, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** +* @tc.name: WindowRotationTest4 +* @tc.desc: create window with orientation after setting screen default orientation. +* @tc.type: FUNC +*/ +HWTEST_F(WindowRotationTest, WindowRotationTest4, Function | MediumTest | Level3) +{ + ScreenId defaultScreenId = DisplayManager::GetInstance().GetDefaultDisplay()->GetScreenId(); + auto defaultScreen = ScreenManager::GetInstance().GetScreenById(defaultScreenId); + defaultScreen->SetOrientation(Orientation::REVERSE_HORIZONTAL); + fullInfo_.name = "fullscreen.5"; + fullInfo_.orientation_ = Orientation::HORIZONTAL; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, fullWindow->GetMode()); + + ASSERT_EQ(Orientation::HORIZONTAL, fullWindow->GetRequestedOrientation()); + DisplayId displayId = displayListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + displayListener_->changeFuture_.Reset(-1); + ScreenId screenId = screenListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + screenListener_->changeFuture_.Reset(-1); + auto screen = ScreenManager::GetInstance().GetScreenById(screenId); + auto display = DisplayManager::GetInstance().GetDisplayById(displayId); + ASSERT_EQ(Orientation::HORIZONTAL, screen->GetOrientation()); + ASSERT_EQ(Orientation::HORIZONTAL, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + defaultScreen->SetOrientation(Orientation::UNSPECIFIED); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** +* @tc.name: WindowRotationTest5 +* @tc.desc: create window with orientation after setting screen default orientation, and toggle shown state for all app +* windows. +* @tc.type: FUNC +*/ +HWTEST_F(WindowRotationTest, WindowRotationTest5, Function | MediumTest | Level3) +{ + ScreenId defaultScreenId = DisplayManager::GetInstance().GetDefaultDisplay()->GetScreenId(); + auto defaultScreen = ScreenManager::GetInstance().GetScreenById(defaultScreenId); + defaultScreen->SetOrientation(Orientation::REVERSE_HORIZONTAL); + fullInfo_.name = "fullscreen.5"; + fullInfo_.orientation_ = Orientation::HORIZONTAL; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, fullWindow->GetMode()); + + ASSERT_EQ(Orientation::HORIZONTAL, fullWindow->GetRequestedOrientation()); + DisplayId displayId = displayListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + displayListener_->changeFuture_.Reset(-1); + ScreenId screenId = screenListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + screenListener_->changeFuture_.Reset(-1); + auto screen = ScreenManager::GetInstance().GetScreenById(screenId); + auto display = DisplayManager::GetInstance().GetDisplayById(displayId); + ASSERT_EQ(Orientation::HORIZONTAL, screen->GetOrientation()); + ASSERT_EQ(Orientation::HORIZONTAL, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); + + WindowManager::GetInstance().ToggleShownStateForAllAppWindows(); + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); + + WindowManager::GetInstance().ToggleShownStateForAllAppWindows(); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + defaultScreen->SetOrientation(Orientation::UNSPECIFIED); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** +* @tc.name: WindowRotationTest6 +* @tc.desc: test window rotation when display is zoomed. +* @tc.type: FUNC +* @tc.require: issueI5NGWL +*/ +HWTEST_F(WindowRotationTest, WindowRotationTest6, Function | MediumTest | Level3) +{ + WindowAccessibilityController::GetInstance().SetAnchorAndScale(0, 0, 2); + sleep(SPLIT_TEST_SLEEP_S); + + fullInfo_.name = "fullscreen.2"; + fullInfo_.orientation_ = Orientation::REVERSE_HORIZONTAL; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + + DisplayId displayId = displayListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + ScreenId screenId = screenListener_->changeFuture_.GetResult(FUTURE_GET_RESULT_TIMEOUT); + auto screen = ScreenManager::GetInstance().GetScreenById(screenId); + auto display = DisplayManager::GetInstance().GetDisplayById(displayId); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, screen->GetOrientation()); + ASSERT_EQ(Orientation::REVERSE_HORIZONTAL, display->GetOrientation()); + sleep(SPLIT_TEST_SLEEP_S); + + Window* ptr = fullWindow.GetRefPtr(); + WindowImpl* implPtr = (WindowImpl*)ptr; + Transform expect; + ASSERT_NE(expect, implPtr->GetWindowProperty()->GetZoomTransform()); + + WindowAccessibilityController::GetInstance().OffWindowZoom(); + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + screen->SetOrientation(Orientation::UNSPECIFIED); + sleep(SPLIT_TEST_SLEEP_S); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_split_immersive_test.cpp b/window_manager/test/systemtest/wms/window_split_immersive_test.cpp new file mode 100644 index 0000000..12de01b --- /dev/null +++ b/window_manager/test/systemtest/wms/window_split_immersive_test.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021-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 "avoid_area_controller.h" +#include "window_manager.h" +#include "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; + +class WindowSplitImmersiveTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + void IsShowTopBar(const sptr& top, bool isShow); + void HideAndUnregister(const sptr& fullWindow, const sptr& priWindow, const sptr& top); + + std::vector> activeWindows_; + Utils::TestWindowInfo fullInfo_; + Utils::TestWindowInfo splitInfo_; + +private: + static constexpr uint32_t SPLIT_TEST_SLEEP_S = 1; // split test sleep time +}; + +void WindowSplitImmersiveTest::SetUpTestCase() +{ +} + +void WindowSplitImmersiveTest::TearDownTestCase() +{ +} + +void WindowSplitImmersiveTest::SetUp() +{ + fullInfo_ = { + .name = "fullscreen.1", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + splitInfo_ = { + .name = "primary.1", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + activeWindows_.clear(); +} + +void WindowSplitImmersiveTest::TearDown() +{ + while (!activeWindows_.empty()) { + ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy()); + activeWindows_.pop_back(); + } +} + +namespace { +/** + * @tc.name: SplitImmersive01 + * @tc.desc: one primary window and one fullscreen window, test enter and out split immersive + * @tc.type: FUNC + */ +HWTEST_F(WindowSplitImmersiveTest, SplitImmersive01, Function | MediumTest | Level3) +{ + // create fullscreen win and show + fullInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + // enter split mode + splitInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + const sptr& priWindow = Utils::CreateTestWindow(splitInfo_); + activeWindows_.push_back(priWindow); + ASSERT_EQ(WMError::WM_OK, priWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + // check is enter split Immersive + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, priWindow->GetMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, fullWindow->GetMode()); + Rect immersivePriRect = priWindow->GetRect(); + ASSERT_EQ(0, immersivePriRect.posX_); + ASSERT_EQ(0, immersivePriRect.posY_); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); + ASSERT_EQ(WMError::WM_OK, priWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_split_test.cpp b/window_manager/test/systemtest/wms/window_split_test.cpp new file mode 100644 index 0000000..6dfdff1 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_split_test.cpp @@ -0,0 +1,213 @@ +/* + * 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. + */ + +// gtest +#include +#include "window_test_utils.h" +#include "wm_common.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +class WindowSplitTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + std::vector> activeWindows_; + Utils::TestWindowInfo fullInfo_; + Utils::TestWindowInfo splitInfo_; + +private: + static constexpr uint32_t SPLIT_TEST_SLEEP_S = 1; // split test sleep time +}; + +void WindowSplitTest::SetUpTestCase() +{ +} + +void WindowSplitTest::TearDownTestCase() +{ +} + +void WindowSplitTest::SetUp() +{ + fullInfo_ = { + .name = "", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + splitInfo_ = { + .name = "", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + activeWindows_.clear(); +} + +void WindowSplitTest::TearDown() +{ + while (!activeWindows_.empty()) { + ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy()); + activeWindows_.pop_back(); + } +} + +namespace { +/** + * @tc.name: SplitWindow01 + * @tc.desc: first create a secondary window, then create a primary window, test mode change + * @tc.type: FUNC + */ +HWTEST_F(WindowSplitTest, SplitWindow01, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.1"; + fullInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + splitInfo_.name = "primary.1"; + splitInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + const sptr& priWindow = Utils::CreateTestWindow(splitInfo_); + activeWindows_.push_back(priWindow); + ASSERT_EQ(WMError::WM_OK, priWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, priWindow->GetMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, fullWindow->GetMode()); + + ASSERT_EQ(WMError::WM_OK, priWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, fullWindow->GetMode()); + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** + * @tc.name: SplitWindow02 + * @tc.desc: first create a primary window, then create a secondary window, test mode change + * @tc.type: FUNC + */ +HWTEST_F(WindowSplitTest, SplitWindow02, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.2"; + fullInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + splitInfo_.name = "secondary.2"; + splitInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + const sptr& secWindow = Utils::CreateTestWindow(splitInfo_); + activeWindows_.push_back(secWindow); + ASSERT_EQ(WMError::WM_OK, secWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, secWindow->GetMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, fullWindow->GetMode()); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, secWindow->GetMode()); + ASSERT_EQ(WMError::WM_OK, secWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** + * @tc.name: SplitScreen03 + * @tc.desc: first create a secondary window, then create a primary window, test rects + * @tc.type: FUNC + */ +HWTEST_F(WindowSplitTest, SplitScreen03, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.3"; + fullInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + splitInfo_.name = "primary.3"; + splitInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + + ASSERT_TRUE(Utils::InitSplitRects()); + + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + const sptr& priWindow = Utils::CreateTestWindow(splitInfo_); + activeWindows_.push_back(priWindow); + ASSERT_EQ(WMError::WM_OK, priWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + Utils::UpdateSplitRects(fullWindow); + + ASSERT_TRUE(Utils::RectEqualTo(fullWindow, Utils::splitRects_.secondaryRect)); + ASSERT_TRUE(Utils::RectEqualTo(priWindow, Utils::splitRects_.primaryRect)); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); + ASSERT_EQ(WMError::WM_OK, priWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); +} + +/** + * @tc.name: SplitScreen04 + * @tc.desc: first create a primary window, then create a secondary window, test rects + * @tc.type: FUNC + */ +HWTEST_F(WindowSplitTest, SplitScreen04, Function | MediumTest | Level3) +{ + fullInfo_.name = "fullscreen.4"; + splitInfo_.name = "secondary.4"; + splitInfo_.mode = WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + + ASSERT_TRUE(Utils::InitSplitRects()); + + const sptr& fullWindow = Utils::CreateTestWindow(fullInfo_); + activeWindows_.push_back(fullWindow); + ASSERT_EQ(WMError::WM_OK, fullWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + const sptr& secWindow = Utils::CreateTestWindow(splitInfo_); + activeWindows_.push_back(secWindow); + ASSERT_EQ(WMError::WM_OK, secWindow->Show()); + sleep(SPLIT_TEST_SLEEP_S); + + Utils::UpdateSplitRects(fullWindow); + + ASSERT_TRUE(Utils::RectEqualTo(fullWindow, Utils::splitRects_.primaryRect)); + ASSERT_TRUE(Utils::RectEqualTo(secWindow, Utils::splitRects_.secondaryRect)); + + ASSERT_EQ(WMError::WM_OK, fullWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); + ASSERT_EQ(WMError::WM_OK, secWindow->Hide()); + sleep(SPLIT_TEST_SLEEP_S); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_subwindow_test.cpp b/window_manager/test/systemtest/wms/window_subwindow_test.cpp new file mode 100644 index 0000000..1569233 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_subwindow_test.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2021-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 +#include "window.h" +#include "window_option.h" +#include "window_scene.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowSubWindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowSubWindowTest::SetUpTestCase() +{ +} + +void WindowSubWindowTest::TearDownTestCase() +{ +} + +void WindowSubWindowTest::SetUp() +{ +} + +void WindowSubWindowTest::TearDown() +{ +} + +static sptr CreateWindowScene() +{ + sptr listener = nullptr; + std::shared_ptr abilityContext = nullptr; + + sptr scene = new WindowScene(); + scene->Init(0, abilityContext, listener); + return scene; +} + +static sptr CreateSubWindow(sptr scene, WindowType type, + struct Rect rect, uint32_t flags, std::string name = "") +{ + sptr subOp = new WindowOption(); + subOp->SetWindowType(type); + subOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + subOp->SetWindowRect(rect); + subOp->SetWindowFlags(flags); + + static int cnt = 0; + std::string subWinName = (name == "") ? "SubWindow" + std::to_string(cnt++) : name; + + return scene->CreateWindow(subWinName, subOp); +} + +/** + * @tc.name: SubWindow01 + * @tc.desc: FullScreen Main Window + Floating SubWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow01, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow02 + * @tc.desc: FullScreen Main Window + Floating SubWindow & Parent Limit work + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow02, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow03 + * @tc.desc: FullScreen Main Window + Floating MediaWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow03, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 2000, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_MEDIA, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow04 + * @tc.desc: FullScreen Main Window + Floating MediaWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow04, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 2000, 3000, 2000}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_MEDIA, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow05 + * @tc.desc: FullScreen Main Window + Floating MediaWindow + Floating SubWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow05, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_MEDIA, rect, flags); + ASSERT_NE(nullptr, subWindow); + + sptr subWindow2 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow2); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow2->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, subWindow2->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow->Destroy(); + subWindow2->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow06 + * @tc.desc: FullScreen Main Window + 2 SubWindows + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow06, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow0); + + sptr subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow1); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow0->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow0->Hide()); + ASSERT_EQ(WMError::WM_OK, subWindow1->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow0->Destroy(); + subWindow1->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow07 + * @tc.desc: FullScreen Main Window + Floating SubWindow & MainWindow First GoBackground + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow07, Function | MediumTest | Level4) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + sleep(1); + + subWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow08 + * @tc.desc: FullScreen Main Window + Floating SubWindow & only show SubWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow08, Function | MediumTest | Level4) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, subWindow->Show()); +} + +/** + * @tc.name: SubWindow09 + * @tc.desc: FullScreen Main Window + Floating SubWindow & first destroy SubWindow, then destroy MainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow09, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + ASSERT_EQ(WMError::WM_OK, subWindow->Destroy()); + + subWindow->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow10 + * @tc.desc: FullScreen Main Window + Floating SubWindow & first destroy MainWindow, then destroy SubWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow10, Function | MediumTest | Level2) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + sptr subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + sleep(1); + + sptr mainWindow = scene->GetMainWindow(); + ASSERT_EQ(WMError::WM_OK, mainWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, subWindow->Destroy()); + + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow11 + * @tc.desc: FullScreen Main Window + 5 subWindows + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow11, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow0); + + sptr subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow1); + + sptr subWindow2 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow2); + + sptr subWindow3 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow3); + + sptr subWindow4 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0); + ASSERT_NE(nullptr, subWindow4); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow0->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow2->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow3->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow4->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow0->Hide()); + ASSERT_EQ(WMError::WM_OK, subWindow1->Hide()); + ASSERT_EQ(WMError::WM_OK, subWindow2->Hide()); + ASSERT_EQ(WMError::WM_OK, subWindow3->Hide()); + ASSERT_EQ(WMError::WM_OK, subWindow4->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow0->Destroy(); + subWindow1->Destroy(); + subWindow2->Destroy(); + subWindow3->Destroy(); + subWindow4->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow12 + * @tc.desc: FullScreen Main Window + 2 SubWindows with the same name + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow12, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + + struct Rect rect = {0, 0, 100, 200}; + sptr subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub0"); + sptr subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub0"); + ASSERT_NE(nullptr, subWindow0); + ASSERT_EQ(nullptr, subWindow1); + + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + ASSERT_EQ(WMError::WM_OK, subWindow0->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow0->Hide()); + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + + subWindow0->Destroy(); + scene->GoDestroy(); +} + +/** + * @tc.name: SubWindow13 + * @tc.desc: FullScreen Main Window + 2 subwindows with the same name but one create after another destroyed + * @tc.type: FUNC + */ +HWTEST_F(WindowSubWindowTest, SubWindow13, Function | MediumTest | Level3) +{ + sptr scene = CreateWindowScene(); + ASSERT_EQ(WMError::WM_OK, scene->GoForeground()); + + struct Rect rect = {0, 0, 100, 200}; + sptr subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub1"); + ASSERT_NE(nullptr, subWindow0); + ASSERT_EQ(WMError::WM_OK, subWindow0->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow0->Destroy()); + + + sptr subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub1"); + ASSERT_NE(nullptr, subWindow1); + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow1->Destroy()); + + ASSERT_EQ(WMError::WM_OK, scene->GoBackground()); + sleep(1); + scene->GoDestroy(); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_systemsubwindow_test.cpp b/window_manager/test/systemtest/wms/window_systemsubwindow_test.cpp new file mode 100644 index 0000000..caad38b --- /dev/null +++ b/window_manager/test/systemtest/wms/window_systemsubwindow_test.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2021-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 +#include "window.h" +#include "window_option.h" +#include "window_scene.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowSystemSubWindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowSystemSubWindowTest::SetUpTestCase() +{ +} + +void WindowSystemSubWindowTest::TearDownTestCase() +{ +} + +void WindowSystemSubWindowTest::SetUp() +{ +} + +void WindowSystemSubWindowTest::TearDown() +{ +} + +static sptr CreateBaseWindow(WindowType type, struct Rect rect, uint32_t flags) +{ + sptr baseOp = new WindowOption(); + baseOp->SetWindowType(type); + baseOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + baseOp->SetWindowRect(rect); + baseOp->SetWindowFlags(flags); + + static int baseCount = 0; + std::string baseWindowName = "BaseWindow" + std::to_string(baseCount++); + sptr window = Window::Create(baseWindowName, baseOp, nullptr); + return window; +} + +static sptr CreateAppSubWindow(sptr parentWindow, WindowType type, struct Rect rect, + uint32_t flags, std::string name = "") +{ + sptr subOp = new WindowOption(); + subOp->SetWindowType(type); + subOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + subOp->SetWindowRect(rect); + subOp->SetWindowFlags(flags); + subOp->SetParentId(parentWindow->GetWindowId()); + + static int cnt = 0; + std::string subWinName = (name == "") ? "AppSubWindow" + std::to_string(cnt++) : name; + sptr window = Window::Create(subWinName, subOp); + return window; +} + +static sptr CreateSystemSubWindow(sptr parentWindow, struct Rect rect, + uint32_t flags, std::string name = "") +{ + sptr subOp = new WindowOption(); + subOp->SetWindowType(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW); + subOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + subOp->SetWindowRect(rect); + subOp->SetWindowFlags(flags); + subOp->SetParentId(parentWindow->GetWindowId()); + + static int cnt = 0; + std::string subWinName = (name == "") ? "SystemSubWindow" + std::to_string(cnt++) : name; + sptr window = Window::Create(subWinName, subOp); + return window; +} + +/** + * @tc.name: SystemSubWindow01 + * @tc.desc: create sub windows with below system Windows + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow01, Function | MediumTest | Level2) +{ + std::vector windowTypes = { + WindowType::WINDOW_TYPE_WALLPAPER, + WindowType::WINDOW_TYPE_DESKTOP, + }; + for (auto itor = windowTypes.begin(); itor != windowTypes.end(); itor++) { + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(static_cast(*itor), baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(baseWindow, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, baseWindow->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Hide()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); + } +} + +/** + * @tc.name: SystemSubWindow02 + * @tc.desc: create sub windows with above system Windows except WINDOW_TYPE_DIALOG + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow02, Function | MediumTest | Level2) +{ + std::vector windowTypes = { + WindowType::WINDOW_TYPE_APP_LAUNCHING, + WindowType::WINDOW_TYPE_DOCK_SLICE, + WindowType::WINDOW_TYPE_INCOMING_CALL, + WindowType::WINDOW_TYPE_SEARCHING_BAR, + WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW, + WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, + WindowType::WINDOW_TYPE_FLOAT, + WindowType::WINDOW_TYPE_TOAST, + WindowType::WINDOW_TYPE_STATUS_BAR, + WindowType::WINDOW_TYPE_PANEL, + WindowType::WINDOW_TYPE_KEYGUARD, + WindowType::WINDOW_TYPE_VOLUME_OVERLAY, + WindowType::WINDOW_TYPE_NAVIGATION_BAR, + WindowType::WINDOW_TYPE_DRAGGING_EFFECT, + WindowType::WINDOW_TYPE_POINTER, + WindowType::WINDOW_TYPE_LAUNCHER_RECENT, + WindowType::WINDOW_TYPE_LAUNCHER_DOCK, + WindowType::WINDOW_TYPE_BOOT_ANIMATION, + WindowType::WINDOW_TYPE_FREEZE_DISPLAY, + WindowType::WINDOW_TYPE_VOICE_INTERACTION, + WindowType::WINDOW_TYPE_FLOAT_CAMERA, + WindowType::WINDOW_TYPE_PLACEHOLDER, + WindowType::WINDOW_TYPE_SCREENSHOT, + }; + for (auto itor = windowTypes.begin(); itor != windowTypes.end(); itor++) { + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(static_cast(*itor), baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(baseWindow, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, baseWindow->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Hide()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); + } +} + +/** + * @tc.name: SystemSubWindow03 + * @tc.desc: create sub windows with app main Windows + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow03, Function | MediumTest | Level2) +{ + std::vector windowTypes = { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; + for (auto itor = windowTypes.begin(); itor != windowTypes.end(); itor++) { + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(static_cast(*itor), baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(baseWindow, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, baseWindow->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Hide()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); + } +} + +/** + * @tc.name: SystemSubWindow04 + * @tc.desc: create sub windows with app sub Windows + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow04, Function | MediumTest | Level2) +{ + std::vector windowTypes = { + WindowType::WINDOW_TYPE_MEDIA, + WindowType::WINDOW_TYPE_APP_SUB_WINDOW, + WindowType::WINDOW_TYPE_APP_COMPONENT, + }; + for (auto itor = windowTypes.begin(); itor != windowTypes.end(); itor++) { + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + + sptr appSubWindow = CreateAppSubWindow(baseWindow, static_cast(*itor), baseRect, baseFlags); + ASSERT_NE(nullptr, appSubWindow); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(appSubWindow, rect, flags); + ASSERT_EQ(nullptr, subWindow); + ASSERT_EQ(WMError::WM_OK, appSubWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); + } +} + +/** + * @tc.name: SystemSubWindow05 + * @tc.desc: create sub windows with system sub Windows + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow05, Function | MediumTest | Level3) +{ + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(WindowType::WINDOW_TYPE_DOCK_SLICE, baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + + sptr systemSubWindow = CreateSystemSubWindow(baseWindow, baseRect, baseFlags); + ASSERT_NE(nullptr, systemSubWindow); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(systemSubWindow, rect, flags); + ASSERT_EQ(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, baseWindow->Show()); + ASSERT_EQ(WMError::WM_OK, systemSubWindow->Show()); + + ASSERT_EQ(WMError::WM_OK, systemSubWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Hide()); + + ASSERT_EQ(WMError::WM_OK, systemSubWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); +} + +/** + * @tc.name: SystemSubWindow06 + * @tc.desc: FullScreen Main Window + 2 SubWindows + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow06, Function | MediumTest | Level3) +{ + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(WindowType::WINDOW_TYPE_DOCK_SLICE, baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(baseWindow, rect, flags); + ASSERT_NE(nullptr, subWindow); + + ASSERT_EQ(WMError::WM_OK, baseWindow->Show()); + ASSERT_EQ(WMError::WM_OK, subWindow->Show()); + + bool isFocus = subWindow->GetFocusable(); + ASSERT_EQ(WMError::WM_OK, subWindow->SetFocusable(!isFocus)); + ASSERT_EQ(WMError::WM_OK, subWindow->MoveTo(0, 0)); + ASSERT_EQ(WMError::WM_OK, subWindow->Resize(200, 400)); + ASSERT_EQ(WMError::WM_OK, subWindow->SetTurnScreenOn(true)); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_TYPE, subWindow->SetBrightness(0.5f)); + ASSERT_EQ(WMError::WM_OK, subWindow->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN)); + + ASSERT_EQ(WMError::WM_OK, subWindow->Hide()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Hide()); + + ASSERT_EQ(WMError::WM_OK, subWindow->Destroy()); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); +} +/** + * @tc.name: SystemSubWindow07 + * @tc.desc: create sub windows with dialog + * @tc.type: FUNC + */ +HWTEST_F(WindowSystemSubWindowTest, SystemSubWindow07, Function | MediumTest | Level3) +{ + struct Rect baseRect = {0, 0, 100, 200}; + uint32_t baseFlags = 0; + sptr baseWindow = CreateBaseWindow(WindowType::WINDOW_TYPE_DIALOG, baseRect, baseFlags); + ASSERT_NE(nullptr, baseWindow); + + struct Rect rect = {0, 0, 100, 200}; + uint32_t flags = 0; + sptr subWindow = CreateSystemSubWindow(baseWindow, rect, flags); + ASSERT_EQ(nullptr, subWindow); + ASSERT_EQ(WMError::WM_OK, baseWindow->Destroy()); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_test_utils.cpp b/window_manager/test/systemtest/wms/window_test_utils.cpp new file mode 100755 index 0000000..7da7565 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_test_utils.cpp @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2021-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 "window_test_utils.h" +#include +#include "window_helper.h" +#include "wm_common_inner.h" +#include "wm_common.h" +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowTestUtils"}; + constexpr uint32_t EDGE_INTERVAL = 48; + constexpr uint32_t MID_INTERVAL = 24; +} + +Rect WindowTestUtils::displayRect_ = {0, 0, 0, 0}; +Rect WindowTestUtils::statusBarRect_ = {0, 0, 0, 0}; +Rect WindowTestUtils::naviBarRect_ = {0, 0, 0, 0}; +Rect WindowTestUtils::customAppRect_ = {0, 0, 0, 0}; +Rect WindowTestUtils::limitDisplayRect_ = {0, 0, 0, 0}; +Rect WindowTestUtils::dockWindowRect_ = {0, 0, 0, 0}; +SplitRects WindowTestUtils::splitRects_ = { + .primaryRect = {0, 0, 0, 0}, + .secondaryRect = {0, 0, 0, 0}, + .dividerRect = {0, 0, 0, 0}, +}; +Rect WindowTestUtils::singleTileRect_ = {0, 0, 0, 0}; +std::vector WindowTestUtils::doubleTileRects_ = std::vector(2); +std::vector WindowTestUtils::tripleTileRects_ = std::vector(3); +AvoidArea WindowTestUtils::systemAvoidArea_ = {}; + +bool WindowTestUtils::isVerticalDisplay_ = false; + +sptr WindowTestUtils::CreateTestWindow(const TestWindowInfo& info) +{ + sptr option = new WindowOption(); + option->SetWindowRect(info.rect); + option->SetWindowType(info.type); + option->SetWindowMode(info.mode); + option->SetFocusable(info.focusable_); + option->SetRequestedOrientation(info.orientation_); + if (info.parentId != INVALID_WINDOW_ID) { + option->SetParentId(info.parentId); + } + if (info.needAvoid) { + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + } else { + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + } + if (info.parentLimit) { + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + } else { + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + } + if (info.forbidSplitMove) { + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE); + } else { + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE); + } + if (info.showWhenLocked) { + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + } else { + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + } + sptr window = Window::Create(info.name, option); + return window; +} + +sptr WindowTestUtils::CreateDockWindow() +{ + TestWindowInfo info = { + .name = "dockWindow", + .rect = dockWindowRect_, + .type = WindowType::WINDOW_TYPE_LAUNCHER_DOCK, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + return CreateTestWindow(info); +} + +sptr WindowTestUtils::CreateStatusBarWindow() +{ + TestWindowInfo info = { + .name = "statusBar", + .rect = statusBarRect_, + .type = WindowType::WINDOW_TYPE_STATUS_BAR, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + return CreateTestWindow(info); +} + +sptr WindowTestUtils::CreateNavigationBarWindow() +{ + TestWindowInfo info = { + .name = "naviBar", + .rect = naviBarRect_, + .type = WindowType::WINDOW_TYPE_NAVIGATION_BAR, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + return CreateTestWindow(info); +} + +sptr WindowTestUtils::CreateWindowScene() +{ + sptr listener = nullptr; + std::shared_ptr abilityContext = nullptr; + + sptr scene = new WindowScene(); + scene->Init(0, abilityContext, listener); + return scene; +} + +Rect WindowTestUtils::GetDefaultFloatingRect(const sptr& window) +{ + limitDisplayRect_ = displayRect_; + UpdateSplitRects(window); + constexpr uint32_t half = 2; + constexpr float ratio = DEFAULT_ASPECT_RATIO; // 0.67: default height/width ratio + float vpr = GetVirtualPixelRatio(0); + + /* + * Calculate default width and height, if width or height is + * smaller than minWidth or minHeight, use the minimum limits + */ + uint32_t defaultW = std::max(static_cast(displayRect_.width_ * ratio), + static_cast(MIN_FLOATING_WIDTH * vpr)); + uint32_t defaultH = std::max(static_cast(displayRect_.height_ * ratio), + static_cast(MIN_FLOATING_HEIGHT * vpr)); + // calculate default x and y + Rect resRect = {0, 0, defaultW, defaultH}; + if (defaultW <= limitDisplayRect_.width_ && defaultH <= limitDisplayRect_.height_) { + int32_t centerPosX = limitDisplayRect_.posX_ + static_cast(limitDisplayRect_.width_ / half); + resRect.posX_ = centerPosX - static_cast(defaultW / half); + + int32_t centerPosY = limitDisplayRect_.posY_ + static_cast(limitDisplayRect_.height_ / half); + resRect.posY_ = centerPosY - static_cast(defaultH / half); + } + + return resRect; +} + +Rect WindowTestUtils::CalcLimitedRect(const Rect& rect, float virtualPixelRatio) +{ + constexpr uint32_t maxLimitLen = 2560; + constexpr int32_t maxPosRemain = 48; + uint32_t minFloatingW = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minFloatingH = static_cast(MIN_FLOATING_HEIGHT * virtualPixelRatio); + Rect resRect = { + std::min(std::max(rect.posX_, maxPosRemain - static_cast(rect.width_)), + static_cast(displayRect_.width_) - maxPosRemain), + std::min(std::max(rect.posY_, maxPosRemain), static_cast(displayRect_.height_) - maxPosRemain), + std::min(std::max(minFloatingW, rect.width_), maxLimitLen), + std::min(std::max(minFloatingH, rect.height_), maxLimitLen), + }; + return resRect; +} + +Rect WindowTestUtils::GetFloatingLimitedRect(const Rect& rect, float virtualPixelRatio) +{ + uint32_t minFloatingW = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minFloatingH = static_cast(MIN_FLOATING_HEIGHT * virtualPixelRatio); + Rect resRect = { + rect.posX_, + rect.posY_, + std::max(minFloatingW, rect.width_), + std::max(minFloatingH, rect.height_), + }; + return resRect; +} + +Rect WindowTestUtils::GetDecorateRect(const Rect& rect, float virtualPixelRatio) +{ + uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * virtualPixelRatio); + uint32_t winTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + + Rect resRect; + resRect.posX_ = rect.posX_; + resRect.posY_ = rect.posY_; + resRect.width_ = rect.width_ + winFrameW + winFrameW; + resRect.height_ = rect.height_ + winTitleBarH + winFrameW; + return resRect; +} + +void WindowTestUtils::InitByDisplayRect(const Rect& displayRect) +{ + const float barRatio = 0.07; + const float spaceRation = 0.125; + displayRect_ = displayRect; + limitDisplayRect_ = displayRect; + if (displayRect_.width_ < displayRect_.height_) { + isVerticalDisplay_ = true; + } + statusBarRect_ = {0, 0, displayRect_.width_, displayRect_.height_ * barRatio}; + naviBarRect_ = {0, displayRect_.height_ * (1 - barRatio), displayRect_.width_, displayRect_.height_ * barRatio}; + dockWindowRect_ = {0, displayRect_.height_ * (1 - barRatio), displayRect_.width_, displayRect_.height_ * barRatio}; + customAppRect_ = { + displayRect_.width_ * spaceRation, + displayRect_.height_ * spaceRation, + displayRect_.width_ * DEFAULT_ASPECT_RATIO, + displayRect_.height_ * DEFAULT_ASPECT_RATIO + }; +} + +std::shared_ptr WindowTestUtils::CreatePointerEvent(int32_t posX, int32_t posY, uint32_t pointerId, + int32_t pointerAction) +{ + MMI::PointerEvent::PointerItem pointerItem; + pointerItem.SetPointerId(pointerId); + pointerItem.SetDisplayX(posX); + pointerItem.SetDisplayY(posY); + + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + pointerEvent->AddPointerItem(pointerItem); + pointerEvent->SetPointerId(pointerId); + pointerEvent->SetPointerAction(pointerAction); + pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); + return pointerEvent; +} + +uint32_t WindowTestUtils::GetMaxTileWinNum() +{ + float virtualPixelRatio = GetVirtualPixelRatio(0); + constexpr uint32_t half = 2; + uint32_t edgeIntervalVp = static_cast(EDGE_INTERVAL * half * virtualPixelRatio); + uint32_t midIntervalVp = static_cast(MID_INTERVAL * virtualPixelRatio); + uint32_t minFloatingW = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + uint32_t drawableW = limitDisplayRect_.width_ - edgeIntervalVp + midIntervalVp; + uint32_t maxNum = static_cast(drawableW / (minFloatingW + midIntervalVp)); + WLOGFI("maxNum: %{public}d", maxNum); + return maxNum; +} + +void WindowTestUtils::InitTileWindowRects(const sptr& window) +{ + float virtualPixelRatio = GetVirtualPixelRatio(0); + uint32_t edgeInterval = static_cast(EDGE_INTERVAL * virtualPixelRatio); // 48 is edge interval + uint32_t midInterval = static_cast(MID_INTERVAL * virtualPixelRatio); // 24 is mid interval + constexpr float ratio = DEFAULT_ASPECT_RATIO; + constexpr int half = 2; + limitDisplayRect_ = displayRect_; + UpdateSplitRects(window); + + uint32_t minFloatingW = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minFloatingH = static_cast(MIN_FLOATING_HEIGHT * virtualPixelRatio); + uint32_t w = std::max(static_cast(displayRect_.width_ * ratio), minFloatingW); + uint32_t h = std::max(static_cast(displayRect_.height_ * ratio), minFloatingH); + w = w > limitDisplayRect_.width_ ? limitDisplayRect_.width_ : w; + h = h > limitDisplayRect_.height_ ? limitDisplayRect_.height_ : h; + int x = limitDisplayRect_.posX_ + ((limitDisplayRect_.width_ - w) / half); + int y = limitDisplayRect_.posY_ + ((limitDisplayRect_.height_ - h) / half); + singleTileRect_ = { x, y, w, h }; + WLOGFI("singleRect_: %{public}d %{public}d %{public}d %{public}d", x, y, w, h); + x = edgeInterval; + w = (limitDisplayRect_.width_ - edgeInterval * half - midInterval) / half; + // calc doubleRect + doubleTileRects_[0] = {x, y, w, h}; + doubleTileRects_[1] = {x + w + midInterval, y, w, h}; + WLOGFI("doubleRects_: %{public}d %{public}d %{public}d %{public}d", x, y, w, h); + // calc tripleRect + w = (limitDisplayRect_.width_ - edgeInterval * half - midInterval * half) / 3; // 3 is triple rects num + tripleTileRects_[0] = {x, y, w, h}; + tripleTileRects_[1] = {x + w + midInterval, y, w, h}; + tripleTileRects_[2] = {x + w * half + midInterval * half, y, w, h}; // 2 is third index + WLOGFI("tripleRects_: %{public}d %{public}d %{public}d %{public}d", x, y, w, h); +} + +bool WindowTestUtils::RectEqualTo(const sptr& window, const Rect& r) +{ + usleep(100000); // 100000us + Rect l = window->GetRect(); + bool res = ((l.posX_ == r.posX_) && (l.posY_ == r.posY_) && (l.width_ == r.width_) && (l.height_ == r.height_)); + if (!res) { + WLOGFE("GetLayoutRect: %{public}d %{public}d %{public}d %{public}d, " \ + "Expect: %{public}d %{public}d %{public}d %{public}d", l.posX_, l.posY_, l.width_, l.height_, + r.posX_, r.posY_, r.width_, r.height_); + } + return res; +} + +bool WindowTestUtils::RectEqualToRect(const Rect& l, const Rect& r) +{ + bool res = ((l.posX_ == r.posX_) && (l.posY_ == r.posY_) && (l.width_ == r.width_) && (l.height_ == r.height_)); + if (!res) { + WLOGFE("GetLayoutRect: %{public}d %{public}d %{public}d %{public}d, " \ + "Expect: %{public}d %{public}d %{public}d %{public}d", l.posX_, l.posY_, l.width_, l.height_, + r.posX_, r.posY_, r.width_, r.height_); + } + return res; +} + +AvoidPosType WindowTestUtils::GetAvoidPosType(const Rect& rect) +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + if (display == nullptr) { + WLOGFE("GetAvoidPosType fail. Get display fail. displayId: 0"); + return AvoidPosType::AVOID_POS_UNKNOWN; + } + auto displayInfo = display->GetDisplayInfo(); + Rect displayRect = {displayInfo->GetOffsetX(), displayInfo->GetOffsetY(), displayInfo->GetWidth(), + displayInfo->GetHeight()}; + return WindowHelper::GetAvoidPosType(rect, displayRect); +} + +bool WindowTestUtils::InitSplitRects() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + if (display == nullptr) { + WLOGFE("GetDefaultDisplay: failed!"); + return false; + } + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + + Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()}; + 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_ - dividerWidth) * DEFAULT_SPLIT_RATIO), + displayRect_.width_, + dividerWidth, }; + } else { + splitRects_.dividerRect = { static_cast((displayRect_.width_ - dividerWidth) * DEFAULT_SPLIT_RATIO), + 0, + dividerWidth, + displayRect_.height_ }; + } + return true; +} + +void WindowTestUtils::UpdateSplitRects(const sptr& window) +{ + std::unique_ptr testUtils = std::make_unique(); + testUtils->avoidArea_ = systemAvoidArea_; + testUtils->UpdateLimitDisplayRect(testUtils->avoidArea_.leftRect_); + testUtils->UpdateLimitDisplayRect(testUtils->avoidArea_.topRect_); + testUtils->UpdateLimitDisplayRect(testUtils->avoidArea_.rightRect_); + testUtils->UpdateLimitDisplayRect(testUtils->avoidArea_.bottomRect_); + + if (isVerticalDisplay_) { + splitRects_.dividerRect.posY_ = limitDisplayRect_.posY_ + + static_cast((limitDisplayRect_.height_ - splitRects_.dividerRect.height_) * DEFAULT_SPLIT_RATIO); + testUtils->UpdateLimitSplitRects(splitRects_.dividerRect.posY_); + } else { + splitRects_.dividerRect.posX_ = limitDisplayRect_.posX_ + + static_cast((limitDisplayRect_.width_ - splitRects_.dividerRect.width_) * DEFAULT_SPLIT_RATIO); + testUtils->UpdateLimitSplitRects(splitRects_.dividerRect.posX_); + } +} + +void WindowTestUtils::UpdateLimitDisplayRect(const Rect& avoidRect) +{ + if (((avoidRect.posX_ == 0) && (avoidRect.posY_ == 0) && + (avoidRect.width_ == 0) && (avoidRect.height_ == 0))) { + return; + } + auto avoidPosType = GetAvoidPosType(avoidRect); + int32_t offsetH = 0; + int32_t offsetW = 0; + switch (avoidPosType) { + case AvoidPosType::AVOID_POS_TOP: + offsetH = avoidRect.posY_ + avoidRect.height_ - limitDisplayRect_.posY_; + limitDisplayRect_.posY_ += offsetH; + limitDisplayRect_.height_ -= offsetH; + break; + case AvoidPosType::AVOID_POS_BOTTOM: + offsetH = limitDisplayRect_.posY_ + limitDisplayRect_.height_ - avoidRect.posY_; + limitDisplayRect_.height_ -= offsetH; + break; + case AvoidPosType::AVOID_POS_LEFT: + offsetW = avoidRect.posX_ + avoidRect.width_ - limitDisplayRect_.posX_; + limitDisplayRect_.posX_ += offsetW; + limitDisplayRect_.width_ -= offsetW; + break; + case AvoidPosType::AVOID_POS_RIGHT: + offsetW = limitDisplayRect_.posX_ + limitDisplayRect_.width_ - avoidRect.posX_; + limitDisplayRect_.width_ -= offsetW; + break; + default: + WLOGFE("invalid avoidPosType: %{public}d", avoidPosType); + } +} + +void WindowTestUtils::UpdateLimitSplitRects(int32_t divPos) +{ + std::unique_ptr testUtils = std::make_unique(); + if (isVerticalDisplay_) { + splitRects_.dividerRect.posY_ = divPos; + + splitRects_.primaryRect.posX_ = displayRect_.posX_; + splitRects_.primaryRect.posY_ = displayRect_.posY_; + splitRects_.primaryRect.height_ = divPos; + splitRects_.primaryRect.width_ = displayRect_.width_; + + splitRects_.secondaryRect.posX_ = displayRect_.posX_; + splitRects_.secondaryRect.posY_ = splitRects_.dividerRect.posY_ + splitRects_.dividerRect.height_; + splitRects_.secondaryRect.height_ = displayRect_.height_ - splitRects_.secondaryRect.posY_; + splitRects_.secondaryRect.width_ = displayRect_.width_; + } else { + splitRects_.dividerRect.posX_ = divPos; + + splitRects_.primaryRect.posX_ = displayRect_.posX_; + splitRects_.primaryRect.posY_ = displayRect_.posY_; + splitRects_.primaryRect.width_ = divPos; + splitRects_.primaryRect.height_ = displayRect_.height_; + + splitRects_.secondaryRect.posX_ = splitRects_.dividerRect.posX_ + splitRects_.dividerRect.width_; + splitRects_.secondaryRect.posY_ = displayRect_.posY_; + splitRects_.secondaryRect.width_ = displayRect_.width_ - splitRects_.secondaryRect.posX_; + splitRects_.secondaryRect.height_ = displayRect_.height_; + } + + testUtils->UpdateLimitSplitRect(splitRects_.primaryRect); + testUtils->UpdateLimitSplitRect(splitRects_.secondaryRect); +} + +void WindowTestUtils::UpdateLimitSplitRect(Rect& limitSplitRect) +{ + Rect curLimitRect = limitSplitRect; + limitSplitRect.posX_ = std::max(limitDisplayRect_.posX_, curLimitRect.posX_); + limitSplitRect.posY_ = std::max(limitDisplayRect_.posY_, curLimitRect.posY_); + limitSplitRect.width_ = std::min(limitDisplayRect_.posX_ + limitDisplayRect_.width_, + curLimitRect.posX_ + curLimitRect.width_) - + limitSplitRect.posX_; + limitSplitRect.height_ = std::min(limitDisplayRect_.posY_ + limitDisplayRect_.height_, + 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", use Default vpr:1.0", displayId); + return 1.0; // Use DefaultVPR 1.0 + } + + float virtualPixelRatio = display->GetVirtualPixelRatio(); + if (virtualPixelRatio == 0.0) { + WLOGFE("GetVirtualPixel fail. vpr is 0.0. displayId:%{public}" PRIu64", use Default vpr:1.0", displayId); + return 1.0; // Use DefaultVPR 1.0 + } + + WLOGFI("GetVirtualPixel success. displayId:%{public}" PRIu64", vpr:%{public}f", displayId, virtualPixelRatio); + return virtualPixelRatio; +} +} // namespace ROSEN +} // namespace OHOS diff --git a/window_manager/test/systemtest/wms/window_test_utils.h b/window_manager/test/systemtest/wms/window_test_utils.h new file mode 100644 index 0000000..c83ab34 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_test_utils.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021-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 FRAMEWORKS_WM_TEST_ST_WINDOW_TEST_UTILS_H +#define FRAMEWORKS_WM_TEST_ST_WINDOW_TEST_UTILS_H + +#include "pointer_event.h" +#include "display_manager.h" +#include "window.h" +#include "window_layout_policy.h" +#include "window_option.h" +#include "window_scene.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +struct SplitRects { + Rect primaryRect; + Rect secondaryRect; + Rect dividerRect; +}; + +class WindowTestUtils { +public: + struct TestWindowInfo { + std::string name; + Rect rect; + WindowType type; + WindowMode mode; + bool needAvoid; + bool parentLimit; + bool forbidSplitMove {false}; + bool showWhenLocked; + uint32_t parentId; + bool focusable_ { true }; + Orientation orientation_ { Orientation::UNSPECIFIED }; + }; + static Rect displayRect_; + static Rect limitDisplayRect_; + static Rect statusBarRect_; + static Rect naviBarRect_; + static Rect customAppRect_; + static Rect customAppDecoRect_; + static Rect dockWindowRect_; + static SplitRects splitRects_; + static bool isVerticalDisplay_; + static Rect singleTileRect_; + static std::vector doubleTileRects_; + static std::vector tripleTileRects_; + static AvoidArea systemAvoidArea_; + + static void InitByDisplayRect(const Rect& displayRect); + static sptr CreateTestWindow(const TestWindowInfo& info); + static sptr CreateStatusBarWindow(); + static sptr CreateNavigationBarWindow(); + static sptr CreateDockWindow(); + static sptr CreateWindowScene(); + static bool RectEqualTo(const sptr& window, const Rect& r); + static bool InitSplitRects(); + static void UpdateSplitRects(const sptr& window); + static bool RectEqualToRect(const Rect& l, const Rect& r); + static Rect GetDefaultFloatingRect(const sptr& window); + static Rect CalcLimitedRect(const Rect& rect, float virtualPixelRatio); + static Rect GetDecorateRect(const Rect& rect, float virtualPixelRatio); + static Rect GetFloatingLimitedRect(const Rect& rect, float virtualPixelRatio); + static void InitTileWindowRects(const sptr& window); + static float GetVirtualPixelRatio(DisplayId displayId); + static std::shared_ptr CreatePointerEvent(int32_t posX, int32_t posY, uint32_t pointerId, + int32_t pointerAction); + static uint32_t GetMaxTileWinNum(); + +private: + void UpdateLimitDisplayRect(const Rect& avoidRect); + static void UpdateLimitSplitRects(int32_t divPos); + static void UpdateLimitSplitRect(Rect& limitSplitRect); + static AvoidPosType GetAvoidPosType(const Rect& rect); + AvoidArea avoidArea_; +}; +} // namespace ROSEN +} // namespace OHOS +#endif // FRAMEWORKS_WM_TEST_ST_WINDOW_TEST_UTILS_H diff --git a/window_manager/test/systemtest/wms/window_touch_outside_test.cpp b/window_manager/test/systemtest/wms/window_touch_outside_test.cpp new file mode 100644 index 0000000..00a9b1e --- /dev/null +++ b/window_manager/test/systemtest/wms/window_touch_outside_test.cpp @@ -0,0 +1,188 @@ +/* + * 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 "singleton_container.h" +#include "wm_common.h" +#include "window_adapter.h" +#include "window_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Utils = WindowTestUtils; +const int WAIT_CALLBACK_US = 10000; // 10000 us + +class WindowTouchOutsideTestListener : public ITouchOutsideListener { +public: + void OnTouchOutside() const override + { + isTouchOutside_ = true; + } + mutable bool isTouchOutside_ { false }; +}; + +class WindowTouchOutsideTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static sptr windowlistener1_; + static sptr windowlistener2_; + Utils::TestWindowInfo firstWindowInfo_; + Utils::TestWindowInfo secondWindowInfo_; + Utils::TestWindowInfo thirdWindowInfo_; +}; + +sptr WindowTouchOutsideTest::windowlistener1_ = + new WindowTouchOutsideTestListener(); +sptr WindowTouchOutsideTest::windowlistener2_ = + new WindowTouchOutsideTestListener(); + +void WindowTouchOutsideTest::SetUp() +{ + firstWindowInfo_ = { + .name = "firstWindow", + .rect = { 100, 100, 200, 200 }, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + secondWindowInfo_ = { + .name = "secondWindow", + .rect = { 400, 400, 200, 200 }, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; + + thirdWindowInfo_ = { + .name = "thirdWindow", + .rect = { 400, 400, 200, 200 }, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowTouchOutsideTest::TearDown() +{ + windowlistener1_->isTouchOutside_ = false; + windowlistener2_->isTouchOutside_ = false; +} + +void WindowTouchOutsideTest::SetUpTestCase() +{ +} + +void WindowTouchOutsideTest::TearDownTestCase() +{ +} + +namespace { +/** + * @tc.name: onTouchInside + * @tc.desc: can't not receive a inside touch event + * @tc.type: FUNC + */ +HWTEST_F(WindowTouchOutsideTest, onTouchInside, Function | MediumTest | Level3) +{ + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterTouchOutsideListener(windowlistener1_); + firstWindow->Show(); + SingletonContainer::Get().ProcessPointDown(firstWindow->GetWindowId()); + usleep(WAIT_CALLBACK_US); + ASSERT_TRUE(!windowlistener1_->isTouchOutside_); + firstWindow->Destroy(); +} + +/** + * @tc.name: onTouchOutside + * @tc.desc: received an outside touch event when window state is show + * @tc.type: FUNC + */ +HWTEST_F(WindowTouchOutsideTest, onTouchOutside, Function | MediumTest | Level3) +{ + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterTouchOutsideListener(windowlistener1_); + const sptr &secondWindow = Utils::CreateTestWindow(secondWindowInfo_); + firstWindow->Show(); + secondWindow->Show(); + SingletonContainer::Get().ProcessPointDown(secondWindow->GetWindowId()); + usleep(WAIT_CALLBACK_US); + ASSERT_TRUE(windowlistener1_->isTouchOutside_); + firstWindow->Destroy(); + secondWindow->Destroy(); +} + +/** + * @tc.name: onTouchOutsideNotShow + * @tc.desc: If the window is not in the show state, the touch outside event cannot be received + * @tc.type: FUNC + */ +HWTEST_F(WindowTouchOutsideTest, onTouchOutsideNotShow, Function | MediumTest | Level3) +{ + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterTouchOutsideListener(windowlistener1_); + const sptr &secondWindow = Utils::CreateTestWindow(secondWindowInfo_); + secondWindow->Show(); + SingletonContainer::Get().ProcessPointDown(secondWindow->GetWindowId()); + usleep(WAIT_CALLBACK_US); + ASSERT_TRUE(!windowlistener1_->isTouchOutside_); + firstWindow->Destroy(); + secondWindow->Destroy(); +} + +/** + * @tc.name: onTouchOutsideForAllWindow + * @tc.desc: All windows can receive the touch outside event + * @tc.type: FUNC + */ +HWTEST_F(WindowTouchOutsideTest, onTouchOutsideForAllWindow, Function | MediumTest | Level3) +{ + const sptr &firstWindow = Utils::CreateTestWindow(firstWindowInfo_); + firstWindow->RegisterTouchOutsideListener(windowlistener1_); + const sptr &secondWindow = Utils::CreateTestWindow(secondWindowInfo_); + firstWindow->RegisterTouchOutsideListener(windowlistener2_); + + firstWindow->Show(); + secondWindow->Show(); + + const sptr &thirdWindow = Utils::CreateTestWindow(thirdWindowInfo_); + thirdWindow->Show(); + SingletonContainer::Get().ProcessPointDown(thirdWindow->GetWindowId()); + usleep(WAIT_CALLBACK_US); + ASSERT_TRUE(windowlistener1_->isTouchOutside_); + ASSERT_TRUE(windowlistener2_->isTouchOutside_); + firstWindow->Destroy(); + secondWindow->Destroy(); + thirdWindow->Destroy(); +} +} // namespace +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/test/systemtest/wms/window_visibility_info_test.cpp b/window_manager/test/systemtest/wms/window_visibility_info_test.cpp new file mode 100644 index 0000000..881b943 --- /dev/null +++ b/window_manager/test/systemtest/wms/window_visibility_info_test.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021-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 +#include +#include +#include + +#include +#include "display_manager.h" +#include "wm_common.h" +#include "window_manager.h" +#include "window_test_utils.h" +#include "surface_draw.h" +#include "window_manager.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr uint32_t COLOR_RED = 0xffff0000; + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowVisibilityInfoTest"}; + constexpr uint8_t ALPHA = 255; +} + +using Utils = WindowTestUtils; +constexpr int WAIT_ASYNC_MS_TIME_OUT = 5000; // 5000ms, filling color is slow + +class VisibilityChangedListenerImpl : public IVisibilityChangedListener { +public: + VisibilityChangedListenerImpl(std::mutex& mutex, std::condition_variable& cv) : mutex_(mutex), cv_(cv) {} + void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override; + std::vector> windowVisibilityInfos_; + bool isCallbackCalled_ { false }; +private: + std::mutex& mutex_; + std::condition_variable& cv_; +}; + +void VisibilityChangedListenerImpl::OnWindowVisibilityChanged( + const std::vector>& windowVisibilityInfo) +{ + std::unique_lock lock(mutex_); + WLOGFI("size:%{public}zu", windowVisibilityInfo.size()); + windowVisibilityInfos_ = std::move(windowVisibilityInfo); + for (auto& info : windowVisibilityInfos_) { + WLOGFI("windowId:%{public}u, isVisible_:%{public}d, pid:%{public}d, uid:%{public}d, windowType:%{public}u", + info->windowId_, info->isVisible_, info->pid_, info->uid_, static_cast(info->windowType_)); + } + isCallbackCalled_ = true; + cv_.notify_all(); +} + +class WindowVisibilityInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + + static void TearDownTestCase(); + + virtual void SetUp() override; + + virtual void TearDown() override; + + static inline std::mutex mutex_; + static inline std::condition_variable cv_; + static inline sptr visibilityChangedListener_ = + new VisibilityChangedListenerImpl(mutex_, cv_); + + static inline void ResetCallbackCalledFLag() + { + std::unique_lock lock(mutex_); + visibilityChangedListener_->isCallbackCalled_ = false; + visibilityChangedListener_->windowVisibilityInfos_.clear(); + } + + static void WaitForCallback(); + Utils::TestWindowInfo fullScreenAppInfo_; + Utils::TestWindowInfo floatAppInfo_; + Utils::TestWindowInfo subAppInfo_; + bool FillColor(sptr window); +}; + +bool WindowVisibilityInfoTest::FillColor(sptr window) +{ + if (window == nullptr) { + return false; + } + auto surfaceNode = window->GetSurfaceNode(); + if (surfaceNode == nullptr) { + return false; + } + Rect rect = window->GetRect(); + bool isDrawSuccess = SurfaceDraw::DrawColor(surfaceNode, rect.width_, rect.height_, COLOR_RED); + surfaceNode->SetAbilityBGAlpha(ALPHA); + RSTransaction::FlushImplicitTransaction(); + return isDrawSuccess; +} + +void WindowVisibilityInfoTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + ASSERT_TRUE((display != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + Rect displayRect = {0, 0, + static_cast(display->GetWidth()), static_cast(display->GetHeight())}; + Utils::InitByDisplayRect(displayRect); + WindowManager::GetInstance().RegisterVisibilityChangedListener(visibilityChangedListener_); + auto displayId = DisplayManager::GetInstance().GetDefaultDisplayId(); + WindowManager::GetInstance().MinimizeAllAppWindows(displayId); +} + +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, + .showWhenLocked = true, + .parentId = INVALID_WINDOW_ID, + }; + floatAppInfo_ = { + .name = "ParentWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .showWhenLocked = true, + .parentId = INVALID_WINDOW_ID, + }; + subAppInfo_ = { + .name = "SubWindow", + .rect = Utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .showWhenLocked = true, + .parentId = INVALID_WINDOW_ID, + }; +} + +void WindowVisibilityInfoTest::TearDown() +{ +} + +void WindowVisibilityInfoTest::WaitForCallback() +{ + std::unique_lock lock(mutex_); + visibilityChangedListener_->isCallbackCalled_ = false; + visibilityChangedListener_->windowVisibilityInfos_.clear(); + auto now = std::chrono::system_clock::now(); + if (!cv_.wait_until(lock, now + std::chrono::milliseconds(WAIT_ASYNC_MS_TIME_OUT), + []() { return visibilityChangedListener_->isCallbackCalled_; })) { + WLOGFI("wait_until time out"); + } +} + +namespace { +/** +* @tc.name: WindowVisibilityInfoTest01 +* @tc.desc: window show or hide +* @tc.type: FUNC +* @tc.require: issueI5FSQW +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest01, Function | MediumTest | Level1) +{ + floatAppInfo_.name = "window1"; + floatAppInfo_.rect = {0, 0, 300, 100}; + sptr window1 = Utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow1"; + subAppInfo_.rect = {0, 600, 300, 100}; + subAppInfo_.parentId = window1->GetWindowId(); + sptr subWindow1 = Utils::CreateTestWindow(subAppInfo_); + + bool isWindowVisible = false; + bool isSubWindowVisible = false; + + uint32_t visibilityInfoCount = 0; + ASSERT_EQ(WMError::WM_OK, window1->Show()); + isWindowVisible = FillColor(window1); + WaitForCallback(); + visibilityInfoCount = isWindowVisible ? 1 : 0; + ResetCallbackCalledFLag(); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + isSubWindowVisible = FillColor(subWindow1); + WaitForCallback(); + visibilityInfoCount = isSubWindowVisible ? 1 : 0; + ResetCallbackCalledFLag(); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Hide()); + WaitForCallback(); + visibilityInfoCount = isSubWindowVisible ? 1 : 0; + ResetCallbackCalledFLag(); + + ASSERT_EQ(WMError::WM_OK, window1->Hide()); + WaitForCallback(); + visibilityInfoCount = isWindowVisible ? 1 : 0; + ResetCallbackCalledFLag(); + + window1->Destroy(); + subWindow1->Destroy(); + sleep(2); +} +} +} // namespace Rosen +} // namespace OHOS + diff --git a/window_manager/utils/BUILD.gn b/window_manager/utils/BUILD.gn new file mode 100644 index 0000000..d7024da --- /dev/null +++ b/window_manager/utils/BUILD.gn @@ -0,0 +1,87 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") +config("libwmutil_private_config") { + include_dirs = [ + "include", + "//foundation/window/window_manager/dmserver/include", + "../interfaces/innerkits/dm", + "../interfaces/innerkits/wm", + ] +} + +config("libwmutil_public_config") { + include_dirs = [ + "//foundation/window/window_manager/utils/include", + "//foundation/multimodalinput/input/interfaces/native/innerkits/event/include", + ] +} + +## Build libwmutil.so +ohos_shared_library("libwmutil") { + sources = [ + "src/agent_death_recipient.cpp", + "src/cutout_info.cpp", + "src/display_info.cpp", + "src/perform_reporter.cpp", + "src/permission.cpp", + "src/screen_group_info.cpp", + "src/screen_info.cpp", + "src/screenshot_info.cpp", + "src/singleton_container.cpp", + "src/string_util.cpp", + "src/surface_draw.cpp", + "src/surface_reader.cpp", + "src/surface_reader_handler_impl.cpp", + "src/sys_cap_util.cpp", + "src/window_property.cpp", + "src/window_transition_info.cpp", + "src/wm_math.cpp", + "src/wm_occlusion_region.cpp", + "src/xml_config_base.cpp", + ] + + configs = [ + ":libwmutil_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + public_configs = [ ":libwmutil_public_config" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "graphic_standard:surface", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "input:libmmi-client", + "ipc:ipc_core", + "multimedia_image_framework:image_native", + "samgr:samgr_proxy", + ] + part_name = "window_manager" + subsystem_name = "window" +} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/utils/include/agent_death_recipient.h b/window_manager/utils/include/agent_death_recipient.h new file mode 100644 index 0000000..f4db0ba --- /dev/null +++ b/window_manager/utils/include/agent_death_recipient.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021-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_ROSEN_AGENT_DEATH_RECIPIENT_H +#define OHOS_ROSEN_AGENT_DEATH_RECIPIENT_H + +#include + +namespace OHOS { +namespace Rosen { +class AgentDeathRecipient : public IRemoteObject::DeathRecipient { +public: + AgentDeathRecipient(std::function&)> callback = nullptr) : callback_(callback) {} + ~AgentDeathRecipient() = default; + + virtual void OnRemoteDied(const wptr& wptrDeath) override; + +private: + std::function&)> callback_; +}; +} +} +#endif // OHOS_ROSEN_AGENT_DEATH_RECIPIENT_H \ No newline at end of file diff --git a/window_manager/utils/include/atomic_map.h b/window_manager/utils/include/atomic_map.h new file mode 100644 index 0000000..f2f56c0 --- /dev/null +++ b/window_manager/utils/include/atomic_map.h @@ -0,0 +1,106 @@ +/* + * 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 ATOMIC_MAP_H +#define ATOMIC_MAP_H + +#include +#include +#include "nocopyable.h" + +namespace OHOS { +namespace Rosen { +template +class AtomicMap { +public: + void insert(const std::pair& kv) + { + locked(); + data_.insert(kv); + unlocked(); + } + + void erase(const Key& key) + { + locked(); + data_.erase(key); + unlocked(); + } + + auto find(Key k) + { + locked(); + auto key = data_.find(k); + unlocked(); + return key; + } + + int count(Key k) + { + locked(); + int size = data_.count(k); + unlocked(); + return size; + } + + bool isExistAndRemove(Key k, uint32_t value) + { + locked(); + if (data_.count(k) <= 0) { + unlocked(); + return false; + } + if (data_[k] == value) { + data_.erase(k); + unlocked(); + return true; + } + unlocked(); + return false; + } + + bool isExist(Key k, uint32_t value) + { + locked(); + if (data_.count(k) <= 0) { + unlocked(); + return false; + } + if (data_[k] == value) { + unlocked(); + return true; + } + unlocked(); + return false; + } +private: + void locked() + { + bool expect = false; + while (!isWritingOrReading_.compare_exchange_weak(expect, true, std::memory_order_relaxed)) { + expect = false; + } + } + + void unlocked() + { + isWritingOrReading_.store(false); + } + + std::map data_; + std::atomic isWritingOrReading_ { false }; +}; +} // Rosen +} // OHOS +#endif // ATOMIC_MAP_H \ No newline at end of file diff --git a/window_manager/utils/include/class_var_definition.h b/window_manager/utils/include/class_var_definition.h new file mode 100644 index 0000000..c12d0f8 --- /dev/null +++ b/window_manager/utils/include/class_var_definition.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021-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_WITH_LOCK(type, memberName) \ +private: \ + std::atomic memberName##atomicBool_ { false }; \ + 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_GET_WITH_LOCK(type, funcName, memberName) \ +public: \ + type Get##funcName() \ + { \ + bool expect = false; \ + type res; \ + while (!memberName##atomicBool_.compare_exchange_weak(expect, true, \ + std::memory_order_relaxed)) { \ + expect = false; \ + } \ + res = memberName##_; \ + memberName##atomicBool_.store(false); \ + return res; \ + } + +#define DEFINE_FUNC_SET(type, funcName, memberName) \ +public: \ + void Set##funcName(type value) \ + { \ + memberName##_ = value; \ + } + +#define DEFINE_FUNC_SET_WITH_LOCK(type, funcName, memberName) \ +public: \ + void Set##funcName(type value) \ + { \ + bool expect = false; \ + while (!memberName##atomicBool_.compare_exchange_weak(expect, true, \ + std::memory_order_relaxed)) { \ + expect = false; \ + } \ + \ + memberName##_ = value; \ + memberName##atomicBool_.store(false); \ + } + +#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_DEFAULT_FUNC_SET(type, funcName, memberName, defaultValue) \ + DEFINE_VAR_DEFAULT(type, memberName, defaultValue) \ + DEFINE_FUNC_SET(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_FUNC_GET_SET_WITH_LOCK(type, funcName, memberName) \ + DEFINE_VAR_WITH_LOCK(type, memberName) \ + DEFINE_FUNC_GET_WITH_LOCK(type, funcName, memberName) \ + DEFINE_FUNC_SET_WITH_LOCK(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/window_manager/utils/include/client_agent_container.h b/window_manager/utils/include/client_agent_container.h new file mode 100644 index 0000000..bca632d --- /dev/null +++ b/window_manager/utils/include/client_agent_container.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021-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_ROSEN_CLIENT_AGENT_MANAGER_H +#define OHOS_ROSEN_CLIENT_AGENT_MANAGER_H + +#include +#include +#include +#include "agent_death_recipient.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +template +class ClientAgentContainer { +public: + ClientAgentContainer(); + virtual ~ClientAgentContainer() = default; + + bool RegisterAgent(const sptr& agent, T2 type); + bool UnregisterAgent(const sptr& agent, T2 type); + std::set> GetAgentsByType(T2 type); + +private: + void RemoveAgent(const sptr& remoteObject); + bool UnregisterAgentLocked(std::set>& agents, const sptr& agent); + + static constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "ClientAgentContainer"}; + + struct finder_t { + finder_t(sptr remoteObject) : remoteObject_(remoteObject) {} + + bool operator()(sptr agent) + { + return agent->AsObject() == remoteObject_; + } + + sptr remoteObject_; + }; + + std::recursive_mutex mutex_; + std::map>> agentMap_; + sptr deathRecipient_; +}; + +template +ClientAgentContainer::ClientAgentContainer() : deathRecipient_( + new AgentDeathRecipient(std::bind(&ClientAgentContainer::RemoveAgent, this, std::placeholders::_1))) {} + +template +bool ClientAgentContainer::RegisterAgent(const sptr& agent, T2 type) +{ + std::lock_guard lock(mutex_); + auto iter = std::find_if(agentMap_[type].begin(), agentMap_[type].end(), finder_t(agent->AsObject())); + if (iter != agentMap_[type].end()) { + WLOGFW("failed to register agent"); + return false; + } + agentMap_[type].insert(agent); + if (deathRecipient_ == nullptr || !agent->AsObject()->AddDeathRecipient(deathRecipient_)) { + WLOGFI("failed to add death recipient"); + } + return true; +} + +template +bool ClientAgentContainer::UnregisterAgent(const sptr& agent, T2 type) +{ + std::lock_guard lock(mutex_); + if (agent == nullptr || agentMap_.count(type) == 0) { + WLOGFE("agent or type is invalid"); + return false; + } + auto& agents = agentMap_.at(type); + bool ret = UnregisterAgentLocked(agents, agent->AsObject()); + agent->AsObject()->RemoveDeathRecipient(deathRecipient_); + return ret; +} + +template +std::set> ClientAgentContainer::GetAgentsByType(T2 type) +{ + std::lock_guard lock(mutex_); + if (agentMap_.count(type) == 0) { + WLOGFI("no such type of agent registered! type:%{public}u", type); + return std::set>(); + } + return agentMap_.at(type); +} + +template +bool ClientAgentContainer::UnregisterAgentLocked(std::set>& agents, + const sptr& agent) +{ + auto iter = std::find_if(agents.begin(), agents.end(), finder_t(agent)); + if (iter == agents.end()) { + WLOGFW("could not find this agent"); + return false; + } + agents.erase(iter); + WLOGFI("agent unregistered"); + return true; +} + +template +void ClientAgentContainer::RemoveAgent(const sptr& remoteObject) +{ + WLOGFI("RemoveAgent"); + std::lock_guard lock(mutex_); + for (auto& elem : agentMap_) { + if (UnregisterAgentLocked(elem.second, remoteObject)) { + break; + } + } + remoteObject->RemoveDeathRecipient(deathRecipient_); +} +} +} +#endif // OHOS_ROSEN_CLIENT_AGENT_MANAGER_H diff --git a/window_manager/utils/include/cutout_info.h b/window_manager/utils/include/cutout_info.h new file mode 100644 index 0000000..4b82c1f --- /dev/null +++ b/window_manager/utils/include/cutout_info.h @@ -0,0 +1,85 @@ +/* + * 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 FOUNDATION_DMSERVER_CUTOUT_INFO_H +#define FOUNDATION_DMSERVER_CUTOUT_INFO_H + +#include + +#include "class_var_definition.h" +#include "display.h" +#include "dm_common.h" + +namespace OHOS::Rosen { +struct DMRect { + int32_t posX_; + int32_t posY_; + uint32_t width_; + uint32_t height_; + + bool operator==(const DMRect& a) const + { + return (posX_ == a.posX_ && posY_ == a.posY_ && width_ == a.width_ && height_ == a.height_); + } + + bool operator!=(const DMRect& a) const + { + return !this->operator==(a); + } + + bool isUninitializedRect() const + { + return (posX_ == 0 && posY_ == 0 && width_ == 0 && height_ == 0); + } + + bool IsInsideOf(const DMRect& a) const + { + return (posX_ >= a.posX_ && posY_ >= a.posY_ && + posX_ + width_ <= a.posX_ + a.width_ && posY_ + height_ <= a.posY_ + a.height_); + } +}; + +struct WaterfallDisplayAreaRects { + DMRect left; + DMRect top; + DMRect right; + DMRect bottom; + + bool isUninitialized() const + { + return (left.isUninitializedRect() && top.isUninitializedRect() && right.isUninitializedRect() && + bottom.isUninitializedRect()); + } +}; + +class CutoutInfo : public Parcelable { +public: + CutoutInfo() = default; + CutoutInfo(const std::vector& boundingRects, WaterfallDisplayAreaRects waterfallDisplayAreaRects); + ~CutoutInfo() = default; + WM_DISALLOW_COPY_AND_MOVE(CutoutInfo); + + virtual bool Marshalling(Parcel& parcel) const override; + static CutoutInfo *Unmarshalling(Parcel& parcel); + + DEFINE_VAR_FUNC_GET_SET(WaterfallDisplayAreaRects, WaterfallDisplayAreaRects, waterfallDisplayAreaRects); + DEFINE_VAR_FUNC_GET_SET(std::vector, BoundingRects, boundingRects); +private: + bool WriteBoundingRectsVector(const std::vector& boundingRects, Parcel &parcel) const; + static bool ReadBoundingRectsVector(std::vector& unmarBoundingRects, Parcel &parcel); + static bool ReadWaterfallDisplayAreaRects(WaterfallDisplayAreaRects& waterfallDisplayAreaRects, Parcel &parcel); +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_CUTOUT_INFO_H \ No newline at end of file diff --git a/window_manager/utils/include/display_change_listener.h b/window_manager/utils/include/display_change_listener.h new file mode 100644 index 0000000..22ea4df --- /dev/null +++ b/window_manager/utils/include/display_change_listener.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-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_ROSEN_DISPLAY_CHANGE_LISTENER_H +#define OHOS_ROSEN_DISPLAY_CHANGE_LISTENER_H + +#include + +namespace OHOS { +namespace Rosen { +enum class DisplayStateChangeType : uint32_t { + BEFORE_SUSPEND, + BEFORE_UNLOCK, + UPDATE_ROTATION, + SIZE_CHANGE, + CREATE, + DESTROY, + FREEZE, + UNFREEZE, + VIRTUAL_PIXEL_RATIO_CHANGE, + DISPLAY_COMPRESS, +}; +class IDisplayChangeListener : public RefBase { +public: + virtual void OnDisplayStateChange(DisplayId defaultDisplayId, sptr info, + const std::map>& displayInfoMap, DisplayStateChangeType type) = 0; + virtual void OnScreenshot(DisplayId displayId) = 0; +}; +} +} +#endif // OHOS_ROSEN_DISPLAY_CHANGE_LISTENER_H diff --git a/window_manager/utils/include/display_info.h b/window_manager/utils/include/display_info.h new file mode 100644 index 0000000..291d9c8 --- /dev/null +++ b/window_manager/utils/include/display_info.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_DISPLAY_INFO_H +#define FOUNDATION_DMSERVER_DISPLAY_INFO_H + +#include +#include + +#include "class_var_definition.h" +#include "display.h" +#include "dm_common.h" +#include "noncopyable.h" + +namespace OHOS::Rosen { +class DisplayInfo : public Parcelable { +friend class AbstractDisplay; +public: + DisplayInfo() = default; + ~DisplayInfo() = default; + WM_DISALLOW_COPY_AND_MOVE(DisplayInfo); + + virtual bool Marshalling(Parcel& parcel) const override; + static DisplayInfo *Unmarshalling(Parcel& parcel); + + DEFINE_VAR_DEFAULT_FUNC_GET(std::string, Name, name, ""); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(DisplayId, DisplayId, id, DISPLAY_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(DisplayType, DisplayType, type, DisplayType::DEFAULT); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(int32_t, Width, width, 0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(int32_t, Height, height, 0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, RefreshRate, refreshRate, 0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(ScreenId, ScreenId, screenId, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(ScreenId, ScreenGroupId, screenGroupId, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(float, VirtualPixelRatio, virtualPixelRatio, 1.0f); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(float, XDpi, xDpi, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(float, YDpi, yDpi, 0.0f); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(Rotation, Rotation, rotation, Rotation::ROTATION_0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(Orientation, Orientation, orientation, Orientation::UNSPECIFIED); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(int32_t, OffsetX, offsetX, 0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(int32_t, OffsetY, offsetY, 0); + DEFINE_VAR_DEFAULT_FUNC_GET(DisplayState, DisplayState, displayState, DisplayState::UNKNOWN); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(bool, WaterfallDisplayCompressionStatus, waterfallDisplayCompressionStatus, false); +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H \ No newline at end of file diff --git a/window_manager/utils/include/future.h b/window_manager/utils/include/future.h new file mode 100644 index 0000000..6dc6ee0 --- /dev/null +++ b/window_manager/utils/include/future.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021-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_WM_INCLUDE_FUTURE_H +#define OHOS_WM_INCLUDE_FUTURE_H + +#include +#include "hilog/log.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +template +class Future { + constexpr static HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Future"}; +public: + T GetResult(long timeOut) + { + std::unique_lock lock(mutex_); + if (!conditionVariable_.wait_for(lock, std::chrono::milliseconds(timeOut), [this] { return IsReady(); })) { + OHOS::HiviewDFX::HiLog::Error(LABEL, "wait for %{public}ld, timeout.", timeOut); + } + return FetchResult(); + } + +protected: + virtual bool IsReady() = 0; + + virtual T FetchResult() = 0; + + virtual void Call(T) = 0; + + void FutureCall(T t) + { + std::unique_lock lock(mutex_); + Call(t); + conditionVariable_.notify_one(); + } + + std::mutex mutex_; + +private: + std::condition_variable conditionVariable_; +}; + +template +class RunnableFuture : public Future { +public: + void SetValue(T res) + { + Future::FutureCall(res); + } + void Reset(T defaultValue) + { + flag_ = false; + result_ = defaultValue; + } + void ResetLock(T defaultValue) + { + std::unique_lock lock(Future::mutex_); + flag_ = false; + result_ = defaultValue; + } +protected: + void Call(T res) override + { + if (!flag_) { + flag_ = true; + result_ = res; + } + } + bool IsReady() override + { + return flag_; + } + T FetchResult() override + { + return result_; + } +private: + bool flag_ {false}; + T result_; +}; +} // namespace OHOS::Rosen +#endif // OHOS_WM_INCLUDE_FUTURE_H diff --git a/window_manager/utils/include/marshalling_helper.h b/window_manager/utils/include/marshalling_helper.h new file mode 100644 index 0000000..ae69404 --- /dev/null +++ b/window_manager/utils/include/marshalling_helper.h @@ -0,0 +1,121 @@ +/* + * 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 FOUNDATION_MARSHALLING_HELPER_H +#define FOUNDATION_MARSHALLING_HELPER_H + +#include + +namespace OHOS::Rosen { +class MarshallingHelper : public Parcelable { +public: + MarshallingHelper() = delete; + template + static bool MarshallingVectorParcelableObj(Parcel &parcel, const std::vector>& data) + { + if (data.size() > INT_MAX) { + return false; + } + if (!parcel.WriteInt32(static_cast(data.size()))) { + return false; + } + for (const auto &v : data) { + if (!parcel.WriteParcelable(v)) { + return false; + } + } + return true; + } + + template + static bool UnmarshallingVectorParcelableObj(Parcel &parcel, std::vector>& data) + { + int32_t len = parcel.ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > data.max_size())) { + return false; + } + data.resize(size); + if (data.size() < size) { + return false; + } + size_t minDesireCapacity = sizeof(int32_t); + for (size_t i = 0; i < size; i++) { + readAbleSize = parcel.GetReadableBytes(); + if (minDesireCapacity > readAbleSize) { + return false; + } + data[i] = parcel.ReadParcelable(); + } + return true; + } + + template + static bool MarshallingVectorObj(Parcel &parcel, const std::vector& data, + std::function func) + { + if (data.size() > INT_MAX) { + return false; + } + if (func == nullptr) { + return false; + } + if (!parcel.WriteInt32(static_cast(data.size()))) { + return false; + } + for (const auto &v : data) { + if (!func(parcel, v)) { + return false; + } + } + return true; + } + + template + static bool UnmarshallingVectorObj(Parcel &parcel, std::vector& data, std::function func) + { + if (func == nullptr) { + return false; + } + int32_t len = parcel.ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > data.max_size())) { + return false; + } + data.resize(size); + if (data.size() < size) { + return false; + } + + for (size_t i = 0; i < size; i++) { + if (!func(parcel, data[i])) { + return false; + } + } + return true; + } +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_MARSHALLING_HELPER_H \ No newline at end of file diff --git a/window_manager/utils/include/noncopyable.h b/window_manager/utils/include/noncopyable.h new file mode 100644 index 0000000..5f87bb9 --- /dev/null +++ b/window_manager/utils/include/noncopyable.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-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_WM_INCLUDE_NONCOPYABLE_H +#define OHOS_WM_INCLUDE_NONCOPYABLE_H + +#define WM_DISALLOW_COPY_AND_MOVE(className) \ + WM_DISALLOW_COPY(className); \ + WM_DISALLOW_MOVE(className) + +#define WM_DISALLOW_COPY(className) \ + className(const className&) = delete; \ + className& operator=(const className&) = delete + +#define WM_DISALLOW_MOVE(className) \ + className(className&&) = delete; \ + className& operator=(className&&) = delete + +namespace OHOS::Rosen { +class NonCopyable { +protected: + NonCopyable() = default; + virtual ~NonCopyable() = default; + +private: + WM_DISALLOW_COPY_AND_MOVE(NonCopyable); +}; +} // namespace OHOS::Rosen + +#endif // OHOS_WM_INCLUDE_NONCOPYABLE_H diff --git a/window_manager/utils/include/perform_reporter.h b/window_manager/utils/include/perform_reporter.h new file mode 100644 index 0000000..8804904 --- /dev/null +++ b/window_manager/utils/include/perform_reporter.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_ROSEN_WM_UTILS_PERFORM_REPORTER_H +#define OHOS_ROSEN_WM_UTILS_PERFORM_REPORTER_H + +#include +#include +#include +#include +#include + +namespace OHOS { +namespace Rosen { +class PerformReporter { +public: + PerformReporter(const std::string& tag, const std::vector& timeSpiltsMs, uint32_t reportInterval = 50); + void start(); + void end(); +private: + void count(int64_t costTime); + bool report(); + void clear(); + + std::string tag_; + std::atomic totalCount_; + std::map> timeSplitCount_; + std::chrono::steady_clock::time_point startTime_; + uint32_t reportInterval_; + + static constexpr auto BARRIER = std::numeric_limits::max(); +}; +} +} +#endif \ No newline at end of file diff --git a/window_manager/utils/include/permission.h b/window_manager/utils/include/permission.h new file mode 100644 index 0000000..62c4ee5 --- /dev/null +++ b/window_manager/utils/include/permission.h @@ -0,0 +1,32 @@ +/* + * 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 WM_PERMISSION_H +#define WM_PERMISSION_H + +#include + +namespace OHOS { +namespace Rosen { +class Permission { +public: + static bool IsSystemServiceCalling(bool needPrintLog = true); + static bool IsSystemCalling(); + static bool CheckCallingPermission(const std::string& permission); + static bool IsStartByHdcd(); +}; +} // Rosen +} // OHOS +#endif // WM_PERMISSION_H \ No newline at end of file diff --git a/window_manager/utils/include/rsscreen_change_listener.h b/window_manager/utils/include/rsscreen_change_listener.h new file mode 100644 index 0000000..27f19e7 --- /dev/null +++ b/window_manager/utils/include/rsscreen_change_listener.h @@ -0,0 +1,31 @@ +/* + * 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_ROSEN_RSSCREEN_CHANGE_LISTENER_H +#define OHOS_ROSEN_RSSCREEN_CHANGE_LISTENER_H + +#include + +namespace OHOS { +namespace Rosen { +using OnRSScreenConnectedCb = std::function; +struct IRSScreenChangeListener : public RefBase { +public: + OnRSScreenConnectedCb onConnected_; + OnRSScreenConnectedCb onDisconnected_; +}; +} +} +#endif // OHOS_ROSEN_RSSCREEN_CHANGE_LISTENER_H diff --git a/window_manager/utils/include/screen_group_info.h b/window_manager/utils/include/screen_group_info.h new file mode 100644 index 0000000..a625ed7 --- /dev/null +++ b/window_manager/utils/include/screen_group_info.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_SCREEN_GROUP_INFO_H +#define FOUNDATION_DMSERVER_SCREEN_GROUP_INFO_H + +#include + +#include "screen_group.h" +#include "screen_info.h" + +namespace OHOS::Rosen { +class ScreenGroupInfo : public ScreenInfo { +friend class AbstractScreenGroup; +public: + ScreenGroupInfo() = default; + ~ScreenGroupInfo() = default; + WM_DISALLOW_COPY_AND_MOVE(ScreenGroupInfo); + + virtual bool Marshalling(Parcel& parcel) const override; + static ScreenGroupInfo* Unmarshalling(Parcel& parcel); + + DEFINE_VAR_FUNC_GET_SET(std::vector, Children, children); + DEFINE_VAR_FUNC_GET_SET(std::vector, Position, position); + DEFINE_VAR_DEFAULT_FUNC_GET(ScreenCombination, Combination, combination, ScreenCombination::SCREEN_ALONE); +private: + bool InnerUnmarshalling(Parcel& parcel); +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_SCREEN_GROUP_INFO_H \ No newline at end of file diff --git a/window_manager/utils/include/screen_info.h b/window_manager/utils/include/screen_info.h new file mode 100644 index 0000000..10ce835 --- /dev/null +++ b/window_manager/utils/include/screen_info.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-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 FOUNDATION_DMSERVER_SCREEN_INFO_H +#define FOUNDATION_DMSERVER_SCREEN_INFO_H + +#include + +#include "class_var_definition.h" +#include "screen.h" + +namespace OHOS::Rosen { +enum class ScreenType : uint32_t { + UNDEFINED, + REAL, + VIRTUAL +}; +class ScreenInfo : public Parcelable { +friend class AbstractScreen; +public: + ScreenInfo() = default; + ~ScreenInfo() = default; + WM_DISALLOW_COPY_AND_MOVE(ScreenInfo); + + virtual bool Marshalling(Parcel& parcel) const override; + static ScreenInfo* Unmarshalling(Parcel& parcel); + + DEFINE_VAR_DEFAULT_FUNC_GET_SET(std::string, Name, name, ""); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(ScreenId, ScreenId, id, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, VirtualWidth, virtualWidth, 0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, VirtualHeight, virtualHeight, 0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(float, VirtualPixelRatio, virtualPixelRatio, 1.0f); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(ScreenId, LastParentId, lastParent, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(ScreenId, ParentId, parent, SCREEN_ID_INVALID); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(bool, IsScreenGroup, isScreenGroup, false); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(Rotation, Rotation, rotation, Rotation::ROTATION_0); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(Orientation, Orientation, orientation, Orientation::UNSPECIFIED); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(ScreenType, Type, type, ScreenType::UNDEFINED); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(uint32_t, ModeId, modeId, 0); + DEFINE_VAR_FUNC_GET(std::vector>, Modes, modes); +protected: + bool InnerUnmarshalling(Parcel& parcel); +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H diff --git a/window_manager/utils/include/screenshot_info.h b/window_manager/utils/include/screenshot_info.h new file mode 100644 index 0000000..e4b9160 --- /dev/null +++ b/window_manager/utils/include/screenshot_info.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 FOUNDATION_DMSERVER_SNAPSHOT_INFO_H +#define FOUNDATION_DMSERVER_SNAPSHOT_INFO_H + +#include +#include + +#include "class_var_definition.h" +#include "dm_common.h" +#include "noncopyable.h" + +namespace OHOS::Rosen { +class ScreenshotInfo : public Parcelable { +public: + ScreenshotInfo() = default; + ~ScreenshotInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + static ScreenshotInfo *Unmarshalling(Parcel& parcel); + + DEFINE_VAR_DEFAULT_FUNC_GET_SET(std::string, Trigger, trigger, ""); + DEFINE_VAR_DEFAULT_FUNC_GET_SET(DisplayId, DisplayId, displayId, DISPLAY_ID_INVALID); +}; +} // namespace OHOS::Rosen +#endif // FOUNDATION_DMSERVER_DISPLAY_INFO_H \ No newline at end of file diff --git a/window_manager/utils/include/singleton_container.h b/window_manager/utils/include/singleton_container.h new file mode 100644 index 0000000..4ab5d11 --- /dev/null +++ b/window_manager/utils/include/singleton_container.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021-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_SINGLETON_CONTAINER_H +#define OHOS_SINGLETON_CONTAINER_H + +#include +#include +#include +#include +#include + +#include "wm_single_instance.h" +namespace OHOS { +namespace Rosen { +class SingletonContainer { +WM_DECLARE_SINGLE_INSTANCE_BASE(SingletonContainer); + +public: + void AddSingleton(const std::string& name, void* instance); + + void SetSingleton(const std::string& name, void* instance); + + void* GetSingleton(const std::string& name); + + void* DependOn(const std::string& instance, const std::string& name); + + static bool IsDestroyed() + { + return SingletonContainer::GetInstance().destroyed_; + } + + template + static T& Get() + { + std::string nameT = __PRETTY_FUNCTION__; + nameT = nameT.substr(nameT.find("T = ")); + nameT = nameT.substr(sizeof("T ="), nameT.length() - sizeof("T = ")); + if (SingletonContainer::GetInstance().GetSingleton(nameT) == nullptr) { + return T::GetInstance(); + } + return *(reinterpret_cast(SingletonContainer::GetInstance().GetSingleton(nameT))); + } + + template + static void Set(T& instance) + { + std::string nameT = __PRETTY_FUNCTION__; + nameT = nameT.substr(nameT.find("T = ")); + nameT = nameT.substr(sizeof("T ="), nameT.length() - sizeof("T = ")); + SingletonContainer::GetInstance().SetSingleton(nameT, &instance); + } + +private: + SingletonContainer() = default; + + virtual ~SingletonContainer(); + + struct Singleton { + void* value; + int32_t refCount; + }; + std::map stringMap; + std::map singletonMap; + std::map> dependencySetMap; + bool destroyed_ { false }; +}; +} // namespace Rosen +} // namespace OHOS +#endif // FRAMEWORKS_WM_INCLUDE_SINGLETON_CONTAINER_H diff --git a/window_manager/utils/include/singleton_delegator.h b/window_manager/utils/include/singleton_delegator.h new file mode 100644 index 0000000..00a1d38 --- /dev/null +++ b/window_manager/utils/include/singleton_delegator.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-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_SINGLETON_DELEGATOR_H +#define OHOS_SINGLETON_DELEGATOR_H + +#include "singleton_container.h" + +#define MOCKABLE virtual + +namespace OHOS { +namespace Rosen { +template +class SingletonDelegator { +public: + SingletonDelegator() + { + nameT = __PRETTY_FUNCTION__; + nameT = nameT.substr(nameT.find("T = ")); + nameT = nameT.substr(sizeof("T ="), nameT.length() - sizeof("T = ")); + SingletonContainer::GetInstance().AddSingleton(nameT, &T::GetInstance()); + } + ~SingletonDelegator() = default; + + template + S& Dep() + { + std::string nameS = __PRETTY_FUNCTION__; + nameS = nameS.substr(nameS.find("S = ")); + nameS = nameS.substr(sizeof("S ="), nameS.length() - sizeof("S = ")); + + auto ret = SingletonContainer::Get(); + SingletonContainer::GetInstance().DependOn(nameT, nameS); + return ret; + } + +private: + std::string nameT; +}; +} // namespace Rosen +} // namespace OHOS + +#endif // FRAMEWORKS_WM_INCLUDE_SINGLETON_DELEGATOR_H diff --git a/window_manager/utils/include/string_util.h b/window_manager/utils/include/string_util.h new file mode 100644 index 0000000..96c5eb1 --- /dev/null +++ b/window_manager/utils/include/string_util.h @@ -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. + */ + +#ifndef WM_STRING_UTIL_H +#define WM_STRING_UTIL_H + +#include + +namespace OHOS { +namespace Rosen { +class StringUtil { +public: + static std::string Trim(std::string s); +}; +} // Rosen +} // OHOS +#endif // WM_BUNDLE_MGR_UTIL_H \ No newline at end of file diff --git a/window_manager/utils/include/surface_capture_future.h b/window_manager/utils/include/surface_capture_future.h new file mode 100644 index 0000000..852b238 --- /dev/null +++ b/window_manager/utils/include/surface_capture_future.h @@ -0,0 +1,55 @@ +/* + * 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_CAPTURE_FUTURE_H +#define SURFACE_CAPTURE_FUTURE_H + +#include "future.h" +#include "pixel_map.h" +#include "transaction/rs_render_service_client.h" + +namespace OHOS { +namespace Rosen { +class SurfaceCaptureFuture : public SurfaceCaptureCallback, public Future> { +public: + SurfaceCaptureFuture() = default; + ~SurfaceCaptureFuture() {}; + void OnSurfaceCapture(std::shared_ptr pixelmap) override + { + FutureCall(pixelmap); + } +protected: + void Call(std::shared_ptr pixelmap) override + { + if (!flag_) { + pixelMap_ = pixelmap; + flag_ = true; + } + } + bool IsReady() override + { + return flag_; + } + std::shared_ptr FetchResult() override + { + return pixelMap_; + } +private: + bool flag_ = false; + std::shared_ptr pixelMap_ = nullptr; +}; +} // Rosen +} // OHOS +#endif // SURFACE_CAPTURE_FUTURE_H \ No newline at end of file diff --git a/window_manager/utils/include/surface_draw.h b/window_manager/utils/include/surface_draw.h new file mode 100644 index 0000000..48d7814 --- /dev/null +++ b/window_manager/utils/include/surface_draw.h @@ -0,0 +1,61 @@ +/* + * 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_DRAW_H +#define SURFACE_DRAW_H + +#include +#include "pixel_map.h" + +#include "refbase.h" +#include "wm_common.h" +#include "draw/canvas.h" +#include "nocopyable.h" +#include "pixel_map.h" + +namespace OHOS { +namespace Rosen { +class SurfaceDraw { +public: + SurfaceDraw() = default; + ~SurfaceDraw() = default; + static bool DrawColor(std::shared_ptr surfaceNode, int32_t bufferWidth, + int32_t bufferHeight, uint32_t color); + static bool DrawImage(std::shared_ptr surfaceNode, int32_t bufferWidth, + int32_t bufferHeight, const std::string& imagePath); + static bool DrawImage(std::shared_ptr surfaceNode, int32_t bufferWidth, + int32_t bufferHeight, std::shared_ptr pixelMap); + static bool DrawImageRect(std::shared_ptr surfaceNode, Rect winRect, + std::shared_ptr pixelMap, uint32_t bkgColor, bool fillWindow = false); + static bool GetSurfaceSnapshot(const std::shared_ptr surfaceNode, + std::shared_ptr& pixelMap, int32_t timeoutMs, float scaleW = 0.5, float scaleH = 0.5); + static bool DrawMasking(std::shared_ptr surfaceNode, Rect screenRect, + Rect transparentRect); + +private: + static bool DoDraw(uint8_t *addr, uint32_t width, uint32_t height, const std::string& imagePath); + static bool DoDraw(uint8_t *addr, uint32_t width, uint32_t height, uint32_t color); + static bool DoDraw(uint8_t *addr, uint32_t width, uint32_t height, std::shared_ptr pixelMap); + static sptr GetLayer(std::shared_ptr surfaceNode); + static sptr GetSurfaceBuffer(sptr layer, int32_t bufferWidth, + int32_t bufferHeight); + static void DrawPixelmap(Drawing::Canvas &canvas, const std::string& imagePath); + static std::unique_ptr DecodeImageToPixelMap(const std::string &imagePath); + static bool DoDrawImageRect(sptr buffer, const Rect& rect, + std::shared_ptr pixelMap, uint32_t color, bool fillWindow = false); +}; +} // Rosen +} // OHOS +#endif // SURFACE_DRAW_H \ No newline at end of file diff --git a/window_manager/utils/include/surface_reader.h b/window_manager/utils/include/surface_reader.h new file mode 100644 index 0000000..260c605 --- /dev/null +++ b/window_manager/utils/include/surface_reader.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021-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/window_manager/utils/include/surface_reader_handler.h b/window_manager/utils/include/surface_reader_handler.h new file mode 100644 index 0000000..dfb4619 --- /dev/null +++ b/window_manager/utils/include/surface_reader_handler.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021-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 OnImageAvailable(sptr pixelMap) = 0; +}; +} +} + +#endif // IMAGE_READER_HANDLER_H diff --git a/window_manager/utils/include/surface_reader_handler_impl.h b/window_manager/utils/include/surface_reader_handler_impl.h new file mode 100644 index 0000000..54cec74 --- /dev/null +++ b/window_manager/utils/include/surface_reader_handler_impl.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-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 +#include +#include "surface_reader_handler.h" + +namespace OHOS::Rosen { +class SurfaceReaderHandlerImpl : public SurfaceReaderHandler { +public: + bool OnImageAvailable(sptr pixelMap) override; + bool IsImageOk(); + void ResetFlag(); + sptr GetPixelMap(); + +private: + bool flag_ = false; + sptr pixelMap_ = nullptr; + std::recursive_mutex mutex_; +}; +} // namespace OHOS::Rosen + +#endif // SURFACE_READER_HANDLER_IMPL_H diff --git a/window_manager/utils/include/sys_cap_util.h b/window_manager/utils/include/sys_cap_util.h new file mode 100644 index 0000000..f4ca41f --- /dev/null +++ b/window_manager/utils/include/sys_cap_util.h @@ -0,0 +1,32 @@ +/* + * 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 WM_SYS_CAP_UTIL_H +#define WM_SYS_CAP_UTIL_H + +#include + +namespace OHOS { +namespace Rosen { +class SysCapUtil { +public: + static std::string GetClientName(); + static std::string GetBundleName(); +private: + static std::string GetProcessName(); +}; +} // Rosen +} // OHOS +#endif // WM_BUNDLE_MGR_UTIL_H \ No newline at end of file diff --git a/window_manager/utils/include/window_helper.h b/window_manager/utils/include/window_helper.h new file mode 100644 index 0000000..b23023e --- /dev/null +++ b/window_manager/utils/include/window_helper.h @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2021-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_WM_INCLUDE_WM_HELPER_H +#define OHOS_WM_INCLUDE_WM_HELPER_H + +#include +#include +#include "ability_info.h" +#include "window_transition_info.h" +#include "wm_common.h" +#include "wm_common_inner.h" +#include "wm_math.h" + +namespace OHOS { +namespace Rosen { +namespace { + const char DISABLE_WINDOW_ANIMATION_PATH[] = "/etc/disable_window_animation"; +} +class WindowHelper { +public: + static inline bool IsMainWindow(WindowType type) + { + return (type >= WindowType::APP_MAIN_WINDOW_BASE && type < WindowType::APP_MAIN_WINDOW_END); + } + + static inline bool IsSubWindow(WindowType type) + { + return (type >= WindowType::APP_SUB_WINDOW_BASE && type < WindowType::APP_SUB_WINDOW_END); + } + + static inline bool IsAppWindow(WindowType type) + { + return (IsMainWindow(type) || IsSubWindow(type)); + } + + static inline bool IsAppFloatingWindow(WindowType type) + { + return (type == WindowType::WINDOW_TYPE_FLOAT) || (type == WindowType::WINDOW_TYPE_FLOAT_CAMERA); + } + + static inline bool IsBelowSystemWindow(WindowType type) + { + return (type >= WindowType::BELOW_APP_SYSTEM_WINDOW_BASE && type < WindowType::BELOW_APP_SYSTEM_WINDOW_END); + } + + static inline bool IsAboveSystemWindow(WindowType type) + { + return (type >= WindowType::ABOVE_APP_SYSTEM_WINDOW_BASE && type < WindowType::ABOVE_APP_SYSTEM_WINDOW_END); + } + + static inline bool IsSystemSubWindow(WindowType type) + { + return (type >= WindowType::SYSTEM_SUB_WINDOW_BASE && type < WindowType::SYSTEM_SUB_WINDOW_END); + } + + static inline bool IsSystemWindow(WindowType type) + { + return (IsBelowSystemWindow(type) || IsAboveSystemWindow(type) || IsSystemSubWindow(type)); + } + + static inline bool IsMainFloatingWindow(WindowType type, WindowMode mode) + { + return ((IsMainWindow(type)) && (mode == WindowMode::WINDOW_MODE_FLOATING)); + } + + static inline bool IsMainFullScreenWindow(WindowType type, WindowMode mode) + { + return ((IsMainWindow(type)) && (mode == WindowMode::WINDOW_MODE_FULLSCREEN)); + } + + static inline bool IsFloatingWindow(WindowMode mode) + { + return mode == WindowMode::WINDOW_MODE_FLOATING; + } + + static inline bool IsSystemBarWindow(WindowType type) + { + return (type == WindowType::WINDOW_TYPE_STATUS_BAR || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR); + } + + static inline bool IsOverlayWindow(WindowType type) + { + return (type == WindowType::WINDOW_TYPE_STATUS_BAR + || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR + || type == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT); + } + + static inline bool IsRotatableWindow(WindowType type, WindowMode mode) + { + return WindowHelper::IsMainFullScreenWindow(type, mode) || type == WindowType::WINDOW_TYPE_KEYGUARD || + type == WindowType::WINDOW_TYPE_DESKTOP || + ((type == WindowType::WINDOW_TYPE_LAUNCHER_RECENT) && (mode == WindowMode::WINDOW_MODE_FULLSCREEN)); + } + + static inline bool IsFullScreenWindow(WindowMode mode) + { + return mode == WindowMode::WINDOW_MODE_FULLSCREEN; + } + + static inline bool IsSplitWindowMode(WindowMode mode) + { + return mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + } + + static inline bool IsValidWindowMode(WindowMode mode) + { + return mode == WindowMode::WINDOW_MODE_FULLSCREEN || mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY || mode == WindowMode::WINDOW_MODE_FLOATING || + mode == WindowMode::WINDOW_MODE_PIP; + } + + static inline bool IsEmptyRect(const Rect& r) + { + return (r.posX_ == 0 && r.posY_ == 0 && r.width_ == 0 && r.height_ == 0); + } + + static inline bool IsLandscapeRect(const Rect& r) + { + return r.width_ > r.height_; + } + + static inline bool IsShowWhenLocked(uint32_t flags) + { + return flags & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + } + + static Rect GetOverlap(const Rect& rect1, const Rect& rect2, const int offsetX, const int offsetY) + { + int32_t x_begin = std::max(rect1.posX_, rect2.posX_); + int32_t x_end = std::min(rect1.posX_ + static_cast(rect1.width_), + rect2.posX_ + static_cast(rect2.width_)); + int32_t y_begin = std::max(rect1.posY_, rect2.posY_); + int32_t y_end = std::min(rect1.posY_ + static_cast(rect1.height_), + rect2.posY_ + static_cast(rect2.height_)); + if (y_begin >= y_end || x_begin >= x_end) { + return { 0, 0, 0, 0 }; + } + return { x_begin - offsetX, y_begin - offsetY, + static_cast(x_end - x_begin), static_cast(y_end - y_begin) }; + } + + static bool IsWindowModeSupported(uint32_t modeSupportInfo, WindowMode mode) + { + switch (mode) { + case WindowMode::WINDOW_MODE_FULLSCREEN: + return WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN & modeSupportInfo; + case WindowMode::WINDOW_MODE_FLOATING: + return WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING & modeSupportInfo; + case WindowMode::WINDOW_MODE_SPLIT_PRIMARY: + return WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY & modeSupportInfo; + case WindowMode::WINDOW_MODE_SPLIT_SECONDARY: + return WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY & modeSupportInfo; + case WindowMode::WINDOW_MODE_PIP: + return WindowModeSupport::WINDOW_MODE_SUPPORT_PIP & modeSupportInfo; + default: + return true; + } + } + + static WindowMode GetWindowModeFromModeSupportInfo(uint32_t modeSupportInfo) + { + // get the binary number consists of the last 1 and 0 behind it + uint32_t windowModeSupport = modeSupportInfo & (~modeSupportInfo + 1); + + switch (windowModeSupport) { + case WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN: + return WindowMode::WINDOW_MODE_FULLSCREEN; + case WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING: + return WindowMode::WINDOW_MODE_FLOATING; + case WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY: + return WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + case WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY: + return WindowMode::WINDOW_MODE_SPLIT_SECONDARY; + case WindowModeSupport::WINDOW_MODE_SUPPORT_PIP: + return WindowMode::WINDOW_MODE_PIP; + default: + return WindowMode::WINDOW_MODE_UNDEFINED; + } + } + + static uint32_t ConvertSupportModesToSupportInfo(const std::vector& supportModes) + { + uint32_t modeSupportInfo = 0; + for (auto& mode : supportModes) { + if (mode == AppExecFwk::SupportWindowMode::FULLSCREEN) { + modeSupportInfo |= WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN; + } else if (mode == AppExecFwk::SupportWindowMode::SPLIT) { + modeSupportInfo |= (WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | + WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY); + } else if (mode == AppExecFwk::SupportWindowMode::FLOATING) { + modeSupportInfo |= WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING; + } + } + return modeSupportInfo; + } + + static Rect GetFixedWindowRectByLimitSize(const Rect& oriDstRect, const Rect& lastRect, bool isVertical, + float virtualPixelRatio) + { + uint32_t minFloatingW = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + uint32_t minFloatingH = static_cast(MIN_FLOATING_HEIGHT * virtualPixelRatio); + Rect dstRect = oriDstRect; + // fix minimum size + dstRect.width_ = std::max(minFloatingW, oriDstRect.width_); + dstRect.height_ = std::max(minFloatingH, oriDstRect.height_); + + // fix maximum size + dstRect.width_ = std::min(static_cast(MAX_FLOATING_SIZE * virtualPixelRatio), dstRect.width_); + dstRect.height_ = std::min(static_cast(MAX_FLOATING_SIZE * virtualPixelRatio), dstRect.height_); + + // limit position by fixed width or height + if (oriDstRect.posX_ != lastRect.posX_) { + dstRect.posX_ = oriDstRect.posX_ + static_cast(oriDstRect.width_) - + static_cast(dstRect.width_); + } + if (oriDstRect.posY_ != lastRect.posY_) { + dstRect.posY_ = oriDstRect.posY_ + static_cast(oriDstRect.height_) - + static_cast(dstRect.height_); + } + return dstRect; + } + + static bool IsPointInTargetRect(int32_t pointPosX, int32_t pointPosY, const Rect& targetRect) + { + if ((pointPosX > targetRect.posX_) && + (pointPosX < (targetRect.posX_ + static_cast(targetRect.width_)) - 1) && + (pointPosY > targetRect.posY_) && + (pointPosY < (targetRect.posY_ + static_cast(targetRect.height_)) - 1)) { + return true; + } + return false; + } + + static bool IsPointInTargetRectWithBound(int32_t pointPosX, int32_t pointPosY, const Rect& targetRect) + { + if ((pointPosX >= targetRect.posX_) && + (pointPosX < (targetRect.posX_ + static_cast(targetRect.width_))) && + (pointPosY >= targetRect.posY_) && + (pointPosY < (targetRect.posY_ + static_cast(targetRect.height_)))) { + return true; + } + return false; + } + + static bool IsPointInWindowExceptCorner(int32_t pointPosX, int32_t pointPosY, const Rect& rectExceptCorner) + { + if ((pointPosX > rectExceptCorner.posX_ && + pointPosX < (rectExceptCorner.posX_ + static_cast(rectExceptCorner.width_)) - 1) || + (pointPosY > rectExceptCorner.posY_ && + pointPosY < (rectExceptCorner.posY_ + static_cast(rectExceptCorner.height_)) - 1)) { + return true; + } + return false; + } + + static inline bool IsSwitchCascadeReason(WindowUpdateReason reason) + { + return (reason >= WindowUpdateReason::NEED_SWITCH_CASCADE_BASE) && + (reason < WindowUpdateReason::NEED_SWITCH_CASCADE_END); + } + + static AvoidPosType GetAvoidPosType(const Rect& rect, const Rect& displayRect) + { + if (rect.width_ == displayRect.width_) { + if (rect.posY_ == displayRect.posY_) { + return AvoidPosType::AVOID_POS_TOP; + } else { + return AvoidPosType::AVOID_POS_BOTTOM; + } + } else if (rect.height_ == displayRect.height_) { + if (rect.posX_ == displayRect.posX_) { + return AvoidPosType::AVOID_POS_LEFT; + } else { + return AvoidPosType::AVOID_POS_RIGHT; + } + } + + return AvoidPosType::AVOID_POS_UNKNOWN; + } + + static inline bool IsNumber(std::string str) + { + if (str.size() == 0) { + return false; + } + for (int32_t i = 0; i < static_cast(str.size()); i++) { + if (str.at(i) < '0' || str.at(i) > '9') { + return false; + } + } + return true; + } + + static bool IsFloatingNumber(std::string str, bool allowNeg = false) + { + if (str.size() == 0) { + return false; + } + + int32_t i = 0; + if (allowNeg && str.at(i) == '-') { + i++; + } + + for (; i < static_cast(str.size()); i++) { + if ((str.at(i) < '0' || str.at(i) > '9') && + (str.at(i) != '.' || std::count(str.begin(), str.end(), '.') > 1)) { + return false; + } + } + return true; + } + + static std::vector Split(std::string str, std::string pattern) + { + int32_t position; + std::vector result; + str += pattern; + int32_t length = static_cast(str.size()); + for (int32_t i = 0; i < length; i++) { + position = static_cast(str.find(pattern, i)); + if (position < length) { + std::string tmp = str.substr(i, position - i); + result.push_back(tmp); + i = position + static_cast(pattern.size()) - 1; + } + } + return result; + } + + static PointInfo CalculateOriginPosition(const Rect& rOrigin, const Rect& rActial, const PointInfo& pos) + { + PointInfo ret = pos; + ret.x += rActial.posX_ - pos.x; + ret.y += rActial.posY_ - pos.y; + ret.x += rOrigin.posX_ - rActial.posX_; + ret.y += rOrigin.posY_ - rActial.posY_; + ret.x += (pos.x - rActial.posX_) * rOrigin.width_ / rActial.width_; + ret.y += (pos.y - rActial.posY_) * rOrigin.height_ / rActial.height_; + return ret; + } + + // Transform a point at screen to its oringin position in 3D world and project to xy plane + static PointInfo CalculateOriginPosition(const TransformHelper::Matrix4& transformMat, const PointInfo& pointPos) + { + TransformHelper::Vector2 p(static_cast(pointPos.x), static_cast(pointPos.y)); + TransformHelper::Vector2 originPos = TransformHelper::GetOriginScreenPoint(p, transformMat); + return PointInfo { static_cast(originPos.x_), static_cast(originPos.y_) }; + } + + // This method is used to update transform when rect changed, but world transform matrix should not change. + static void GetTransformFromWorldMat4(const TransformHelper::Matrix4& inWorldMat, const Rect& rect, + Transform& transform) + { + TransformHelper::Vector3 pivotPos = { rect.posX_ + transform.pivotX_ * rect.width_, + rect.posY_ + transform.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 worldMat = TransformHelper::CreateTranslation(pivotPos) * inWorldMat * + TransformHelper::CreateTranslation(-pivotPos); + auto scale = worldMat.GetScale(); + auto translation = worldMat.GetTranslation(); + transform.scaleX_ = scale.x_; + transform.scaleY_ = scale.y_; + transform.scaleZ_ = scale.z_; + transform.translateX_ = translation.x_; + transform.translateY_ = translation.y_; + transform.translateZ_ = translation.z_; + } + + static TransformHelper::Matrix4 ComputeWorldTransformMat4(const Transform& transform) + { + TransformHelper::Matrix4 ret = TransformHelper::Matrix4::Identity; + // set scale + if ((transform.scaleX_ - 1) || (transform.scaleY_ - 1) || (transform.scaleY_ - 1)) { + ret *= TransformHelper::CreateScale(transform.scaleX_, transform.scaleY_, transform.scaleZ_); + } + // set rotation + if (transform.rotationX_) { + ret *= TransformHelper::CreateRotationX(MathHelper::ToRadians(-transform.rotationX_)); + } + if (transform.rotationY_) { + ret *= TransformHelper::CreateRotationY(MathHelper::ToRadians(-transform.rotationY_)); + } + if (transform.rotationZ_) { + ret *= TransformHelper::CreateRotationZ(MathHelper::ToRadians(transform.rotationZ_)); + } + // set translation + if (transform.translateX_ || transform.translateY_ || transform.translateZ_) { + ret *= TransformHelper::CreateTranslation(TransformHelper::Vector3(transform.translateX_, + transform.translateY_, transform.translateZ_)); + } + return ret; + } + + // Transform rect by matrix and get the circumscribed rect + static Rect TransformRect(const TransformHelper::Matrix4& transformMat, const Rect& rect) + { + TransformHelper::Vector3 a = TransformHelper::TransformWithPerspDiv( + TransformHelper::Vector3(rect.posX_, rect.posY_, 0), transformMat); + TransformHelper::Vector3 b = TransformHelper::TransformWithPerspDiv( + TransformHelper::Vector3(rect.posX_ + rect.width_, rect.posY_, 0), transformMat); + TransformHelper::Vector3 c = TransformHelper::TransformWithPerspDiv( + TransformHelper::Vector3(rect.posX_, rect.posY_ + rect.height_, 0), transformMat); + TransformHelper::Vector3 d = TransformHelper::TransformWithPerspDiv( + TransformHelper::Vector3(rect.posX_ + rect.width_, rect.posY_ + rect.height_, 0), transformMat); + // Return smallest rect involve transformed rect(abcd) + int32_t xmin = MathHelper::Min(a.x_, b.x_, c.x_, d.x_); + int32_t ymin = MathHelper::Min(a.y_, b.y_, c.y_, d.y_); + int32_t xmax = MathHelper::Max(a.x_, b.x_, c.x_, d.x_); + int32_t ymax = MathHelper::Max(a.y_, b.y_, c.y_, d.y_); + uint32_t w = static_cast(xmax - xmin); + uint32_t h = static_cast(ymax - ymin); + return Rect { xmin, ymin, w, h }; + } + + static TransformHelper::Vector2 CalculateHotZoneScale(const TransformHelper::Matrix4& transformMat) + { + TransformHelper::Vector2 hotZoneScale; + TransformHelper::Vector3 a = TransformHelper::TransformWithPerspDiv(TransformHelper::Vector3(0, 0, 0), + transformMat); + TransformHelper::Vector3 b = TransformHelper::TransformWithPerspDiv(TransformHelper::Vector3(1, 0, 0), + transformMat); + TransformHelper::Vector3 c = TransformHelper::TransformWithPerspDiv(TransformHelper::Vector3(0, 1, 0), + transformMat); + TransformHelper::Vector2 axy(a.x_, a.y_); + TransformHelper::Vector2 bxy(b.x_, b.y_); + TransformHelper::Vector2 cxy(c.x_, c.y_); + hotZoneScale.x_ = (axy - bxy).Length(); + hotZoneScale.y_ = (axy - cxy).Length(); + if (std::isnan(hotZoneScale.x_) || std::isnan(hotZoneScale.y_) || + MathHelper::NearZero(hotZoneScale.x_) || MathHelper::NearZero(hotZoneScale.y_)) { + return TransformHelper::Vector2(1, 1); + } else { + return hotZoneScale; + } + } + + static bool CalculateTouchHotAreas(const Rect& windowRect, const std::vector& requestRects, + std::vector& outRects) + { + bool isOk = true; + for (const auto& rect : requestRects) { + if (rect.posX_ < 0 || rect.posY_ < 0 || rect.width_ == 0 || rect.height_ == 0) { + return false; + } + Rect hotArea; + if (rect.posX_ >= static_cast(windowRect.width_) || + rect.posY_ >= static_cast(windowRect.height_)) { + isOk = false; + continue; + } + hotArea.posX_ = windowRect.posX_ + rect.posX_; + hotArea.posY_ = windowRect.posY_ + rect.posY_; + hotArea.width_ = static_cast(std::min(hotArea.posX_ + rect.width_, + windowRect.posX_ + windowRect.width_) - hotArea.posX_); + hotArea.height_ = static_cast(std::min(hotArea.posY_ + rect.height_, + windowRect.posY_ + windowRect.height_) - hotArea.posY_); + outRects.emplace_back(hotArea); + } + return isOk; + } + + static bool IsRectSatisfiedWithSizeLimits(const Rect& rect, const WindowSizeLimits& sizeLimits) + { + if (rect.height_ == 0) { + return false; + } + auto curRatio = static_cast(rect.width_) / static_cast(rect.height_); + if (sizeLimits.minWidth_ <= rect.width_ && rect.width_ <= sizeLimits.maxWidth_ && + sizeLimits.minHeight_ <= rect.height_ && rect.height_ <= sizeLimits.maxHeight_ && + sizeLimits.minRatio_ <= curRatio && curRatio <= sizeLimits.maxRatio_) { + return true; + } + return false; + } + + static bool IsOnlySupportSplitAndShowWhenLocked(bool isShowWhenLocked, uint32_t modeSupportInfo) + { + uint32_t splitModeInfo = (WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | + WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY); + if (isShowWhenLocked && (splitModeInfo == modeSupportInfo)) { + return true; + } + return false; + } + + static bool IsInvalidWindowInTileLayoutMode(uint32_t supportModeInfo, WindowLayoutMode layoutMode) + { + if ((!IsWindowModeSupported(supportModeInfo, WindowMode::WINDOW_MODE_FLOATING)) && + (layoutMode == WindowLayoutMode::TILE)) { + return true; + } + return false; + } + + static bool CheckSupportWindowMode(WindowMode winMode, uint32_t modeSupportInfo, + const sptr& info) + { + if (!WindowHelper::IsMainWindow(info->GetWindowType())) { + return true; + } + + if ((!IsWindowModeSupported(modeSupportInfo, winMode)) || + (IsOnlySupportSplitAndShowWhenLocked(info->GetShowFlagWhenLocked(), modeSupportInfo))) { + return false; + } + return true; + } + +private: + WindowHelper() = default; + ~WindowHelper() = default; +}; +} // namespace OHOS +} // namespace Rosen +#endif // OHOS_WM_INCLUDE_WM_HELPER_H diff --git a/window_manager/utils/include/window_info_queried_listener.h b/window_manager/utils/include/window_info_queried_listener.h new file mode 100644 index 0000000..17ae6d2 --- /dev/null +++ b/window_manager/utils/include/window_info_queried_listener.h @@ -0,0 +1,28 @@ +/* + * 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_ROSEN_WINDOW_INFO_QUERIED_LISTENER_H +#define OHOS_ROSEN_WINDOW_INFO_QUERIED_LISTENER_H +#include + +#include "dm_common.h" + +namespace OHOS::Rosen { +class IWindowInfoQueriedListener : public RefBase { +public: + virtual void HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) = 0; +}; +} // OHOS::Rosen +#endif // OHOS_ROSEN_WINDOW_INFO_QUERIED_LISTENER_H \ No newline at end of file diff --git a/window_manager/utils/include/window_manager_hilog.h b/window_manager/utils/include/window_manager_hilog.h new file mode 100644 index 0000000..8db4eb1 --- /dev/null +++ b/window_manager/utils/include/window_manager_hilog.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-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_WM_INCLUDE_WINDOW_MANAGER_HILOG_H +#define OHOS_WM_INCLUDE_WINDOW_MANAGER_HILOG_H + +#include "hilog/log.h" +namespace OHOS { +namespace Rosen { +static constexpr unsigned int HILOG_DOMAIN_WINDOW = 0xD004200; +static constexpr unsigned int HILOG_DOMAIN_DISPLAY = 0xD004201; +static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManager"}; + +#define WLOG_F(...) (void)OHOS::HiviewDFX::HiLog::Fatal(LOG_LABEL, __VA_ARGS__) +#define WLOG_E(...) (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, __VA_ARGS__) +#define WLOG_W(...) (void)OHOS::HiviewDFX::HiLog::Warn(LOG_LABEL, __VA_ARGS__) +#define WLOG_I(...) (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, __VA_ARGS__) +#define WLOG_D(...) (void)OHOS::HiviewDFX::HiLog::Debug(LOG_LABEL, __VA_ARGS__) + +#define _W_DFUNC HiviewDFX::HiLog::Debug +#define _W_IFUNC HiviewDFX::HiLog::Info +#define _W_WFUNC HiviewDFX::HiLog::Warn +#define _W_EFUNC HiviewDFX::HiLog::Error + +#define _W_CPRINTF(func, fmt, ...) func(LABEL, "<%{public}d>" fmt, __LINE__, ##__VA_ARGS__) + +#define WLOGD(fmt, ...) _W_CPRINTF(_W_DFUNC, fmt, ##__VA_ARGS__) +#define WLOGI(fmt, ...) _W_CPRINTF(_W_IFUNC, fmt, ##__VA_ARGS__) +#define WLOGW(fmt, ...) _W_CPRINTF(_W_WFUNC, fmt, ##__VA_ARGS__) +#define WLOGE(fmt, ...) _W_CPRINTF(_W_EFUNC, fmt, ##__VA_ARGS__) + +#define _W_FUNC __func__ + +#define WLOGFD(fmt, ...) WLOGD("%{public}s: " fmt, _W_FUNC, ##__VA_ARGS__) +#define WLOGFI(fmt, ...) WLOGI("%{public}s: " fmt, _W_FUNC, ##__VA_ARGS__) +#define WLOGFW(fmt, ...) WLOGW("%{public}s: " fmt, _W_FUNC, ##__VA_ARGS__) +#define WLOGFE(fmt, ...) WLOGE("%{public}s: " fmt, _W_FUNC, ##__VA_ARGS__) +} // namespace OHOS +} +#endif // FRAMEWORKS_WM_INCLUDE_WINDOW_MANAGER_HILOG_H diff --git a/window_manager/utils/include/window_property.h b/window_manager/utils/include/window_property.h new file mode 100644 index 0000000..632900e --- /dev/null +++ b/window_manager/utils/include/window_property.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_PROPERTY_H +#define OHOS_ROSEN_WINDOW_PROPERTY_H + +#include +#include +#include +#include +#include "class_var_definition.h" +#include "pointer_event.h" +#include "dm_common.h" +#include "wm_common.h" +#include "wm_common_inner.h" +#include "wm_math.h" + +namespace OHOS { +namespace Rosen { +class WindowProperty : public Parcelable { +public: + WindowProperty() = default; + WindowProperty(const sptr& property); + ~WindowProperty() = default; + + void CopyFrom(const sptr& property); + + void SetWindowName(const std::string& name); + void SetAbilityInfo(const AbilityInfo& info); + void SetRequestRect(const struct Rect& rect); + void SetWindowRect(const struct Rect& rect); + void SetDecoStatus(bool decoStatus); + void SetWindowHotZoneRect(const struct Rect& rect); + void SetWindowType(WindowType type); + void SetWindowMode(WindowMode mode); + void SetLastWindowMode(WindowMode mode); + void ResumeLastWindowMode(); + void SetFullScreen(bool isFullScreen); + void SetFocusable(bool isFocusable); + void SetTouchable(bool isTouchable); + void SetPrivacyMode(bool isPrivate); + void SetSystemPrivacyMode(bool isSystemPrivate); + void SetTransparent(bool isTransparent); + void SetAlpha(float alpha); + void SetBrightness(float brightness); + void SetTurnScreenOn(bool turnScreenOn); + void SetKeepScreenOn(bool keepScreenOn); + void SetCallingWindow(uint32_t windowId); + void SetDisplayId(DisplayId displayId); + void SetWindowId(uint32_t windowId); + void SetParentId(uint32_t parentId); + void SetWindowFlags(uint32_t flags); + void AddWindowFlag(WindowFlag flag); + void SetSystemBarProperty(WindowType type, const SystemBarProperty& state); + void SetDecorEnable(bool decorEnable); + void SetHitOffset(const PointInfo& offset); + void SetAnimationFlag(uint32_t animationFlag); + void SetWindowSizeChangeReason(WindowSizeChangeReason reason); + void SetTokenState(bool hasToken); + void SetModeSupportInfo(uint32_t modeSupportInfo); + void SetRequestModeSupportInfo(uint32_t requestModeSupportInfo); + void SetDragType(DragType dragType); + void SetStretchable(bool stretchable); + void SetOriginRect(const Rect& rect); + void SetTouchHotAreas(const std::vector& rects); + void SetAccessTokenId(uint32_t accessTokenId); + void SetSizeLimits(const WindowSizeLimits& sizeLimits); + void SetUpdatedSizeLimits(const WindowSizeLimits& sizeLimits); + WindowSizeChangeReason GetWindowSizeChangeReason() const; + void SetTransform(const Transform& trans); + void ComputeTransform(); + void SetZoomTransform(const Transform& trans); + void SetDisplayZoomState(bool isDisplayZoomOn); + void SetAnimateWindowFlag(bool isAnimateWindow); + void UpdatePointerEvent(const std::shared_ptr& pointerEvent); + bool isNeedComputerTransform(); + void ClearTransformZAxisOffset(Transform& trans); + + const std::string& GetWindowName() const; + const AbilityInfo& GetAbilityInfo() const; + Rect GetRequestRect() const; + Rect GetWindowRect() const; + bool GetDecoStatus() const; + Rect GetWindowHotZoneRect() const; + WindowType GetWindowType() const; + WindowMode GetWindowMode() const; + WindowMode GetLastWindowMode() const; + bool GetFullScreen() const; + bool GetFocusable() const; + bool GetTouchable() const; + uint32_t GetCallingWindow() const; + bool GetPrivacyMode() const; + bool GetSystemPrivacyMode() const; + bool GetTransparent() const; + bool GetTokenState() const; + float GetAlpha() const; + float GetBrightness() const; + bool IsTurnScreenOn() const; + bool IsKeepScreenOn() const; + DisplayId GetDisplayId() const; + uint32_t GetWindowId() const; + uint32_t GetParentId() const; + uint32_t GetWindowFlags() const; + const std::unordered_map& GetSystemBarProperty() const; + bool GetDecorEnable() const; + const PointInfo& GetHitOffset() const; + uint32_t GetAnimationFlag() const; + uint32_t GetModeSupportInfo() const; + uint32_t GetRequestModeSupportInfo() const; + DragType GetDragType() const; + bool GetStretchable() const; + const Rect& GetOriginRect() const; + void GetTouchHotAreas(std::vector& rects) const; + uint32_t GetAccessTokenId() const; + const Transform& GetTransform() const; + const Transform& GetZoomTransform() const; + bool IsDisplayZoomOn() const; + bool IsAnimateWindow() const; + WindowSizeLimits GetSizeLimits() const; + WindowSizeLimits GetUpdatedSizeLimits() const; + const TransformHelper::Matrix4& GetTransformMat() const; + const TransformHelper::Matrix4& GetWorldTransformMat() const; + + virtual bool Marshalling(Parcel& parcel) const override; + static WindowProperty* Unmarshalling(Parcel& parcel); + + bool Write(Parcel& parcel, PropertyChangeAction action); + void Read(Parcel& parcel, PropertyChangeAction action); +private: + bool MapMarshalling(Parcel& parcel) const; + static void MapUnmarshalling(Parcel& parcel, WindowProperty* property); + bool MarshallingTouchHotAreas(Parcel& parcel) const; + static void UnmarshallingTouchHotAreas(Parcel& parcel, WindowProperty* property); + bool MarshallingTransform(Parcel& parcel) const; + static void UnmarshallingTransform(Parcel& parcel, WindowProperty* property); + bool MarshallingWindowSizeLimits(Parcel& parcel) const; + static void UnmarshallingWindowSizeLimits(Parcel& parcel, WindowProperty* property); + void HandleComputeTransform(const Transform& trans); + + std::string windowName_; + AbilityInfo abilityInfo_; + Rect requestRect_ { 0, 0, 0, 0 }; // window rect requested by the client (without decoration size) + Rect windowRect_ { 0, 0, 0, 0 }; // actual window rect + bool decoStatus_ { false }; // window has been decorated or not + WindowType type_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; + WindowMode mode_ { WindowMode::WINDOW_MODE_UNDEFINED }; + WindowMode lastMode_ { WindowMode::WINDOW_MODE_UNDEFINED }; + uint32_t flags_ { 0 }; + bool isFullScreen_ { true }; + bool focusable_ { true }; + bool touchable_ { true }; + bool isPrivacyMode_ { false }; + bool isSystemPrivacyMode_ { false }; + bool isTransparent_ { false }; + bool tokenState_ { false }; + float alpha_ { 1.0f }; + float brightness_ = UNDEFINED_BRIGHTNESS; + bool turnScreenOn_ = false; + bool keepScreenOn_ = false; + uint32_t callingWindow_ = INVALID_WINDOW_ID; + DisplayId displayId_ { 0 }; + uint32_t windowId_ = INVALID_WINDOW_ID; + uint32_t parentId_ = INVALID_WINDOW_ID; + PointInfo hitOffset_ { 0, 0 }; + uint32_t animationFlag_ { static_cast(WindowAnimation::DEFAULT) }; + // modeSupportInfo_ means supported modes in runtime, which can be changed + uint32_t modeSupportInfo_ {WindowModeSupport::WINDOW_MODE_SUPPORT_ALL}; + // requestModeSupportInfo_ is configured in abilityInfo, usually can't be changed + uint32_t requestModeSupportInfo_ {WindowModeSupport::WINDOW_MODE_SUPPORT_ALL}; + WindowSizeChangeReason windowSizeChangeReason_ = WindowSizeChangeReason::UNDEFINED; + std::unordered_map sysBarPropMap_ { + { WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarProperty() }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarProperty() }, + }; + bool isDecorEnable_ { false }; + Rect originRect_ = { 0, 0, 0, 0 }; + bool isStretchable_ {false}; + DragType dragType_ = DragType::DRAG_UNDEFINED; + std::vector touchHotAreas_; // coordinates relative to window. + uint32_t accessTokenId_ { 0 }; + // Transform info + Transform trans_; + bool recomputeTransformMat_ { false }; + TransformHelper::Matrix4 transformMat_ = TransformHelper::Matrix4::Identity; + TransformHelper::Matrix4 worldTransformMat_ = TransformHelper::Matrix4::Identity; + // Display Zoom transform info + Transform zoomTrans_; // Compared with original window rect, including class member trans_ + bool reCalcuZoomTransformMat_ {true}; + // if scale of trans_ is less than 1.0, zoomTrans_ may be an identity matrix + bool isDisplayZoomOn_ {false}; + bool isAnimateWindow_ {false}; + + DEFINE_VAR_DEFAULT_FUNC_GET_SET(Orientation, RequestedOrientation, requestedOrientation, Orientation::UNSPECIFIED); + WindowSizeLimits sizeLimits_; + WindowSizeLimits updatedSizeLimits_; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_PROPERTY_H diff --git a/window_manager/utils/include/window_transition_info.h b/window_manager/utils/include/window_transition_info.h new file mode 100644 index 0000000..7bcd174 --- /dev/null +++ b/window_manager/utils/include/window_transition_info.h @@ -0,0 +1,85 @@ +/* + * 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_ROSEN_WINDOW_TRANSITION_INFO_H +#define OHOS_ROSEN_WINDOW_TRANSITION_INFO_H +#include +#include + +#include "ability_info.h" +#include "window_info.h" +#include "wm_common.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +enum class TransitionReason : uint32_t { + MINIMIZE = 0, + CLOSE, + ABILITY_TRANSITION, + BACK_TRANSITION, +}; + +class WindowTransitionInfo : public Parcelable { +public: + WindowTransitionInfo() = default; + ~WindowTransitionInfo() = default; + WindowTransitionInfo(sptr info); + + virtual bool Marshalling(Parcel& parcel) const override; + static WindowTransitionInfo* Unmarshalling(Parcel& parcel); + void SetBundleName(std::string name); + std::string GetBundleName(); + void SetAbilityName(std::string name); + std::string GetAbilityName(); + void SetWindowMode(WindowMode mode); + WindowMode GetWindowMode(); + void SetWindowRect(Rect rect); + Rect GetWindowRect(); + void SetAbilityToken(sptr abilityToken); + sptr GetAbilityToken(); + void SetDisplayId(DisplayId displayId); + DisplayId GetDisplayId(); + void SetWindowType(WindowType windowType); + WindowType GetWindowType(); + void SetShowFlagWhenLocked(bool isShow); + void SetWindowSupportModes(const std::vector supportModes); + std::vector GetWindowSupportModes(); + bool GetShowFlagWhenLocked(); + void SetTransitionReason(TransitionReason reason); + TransitionReason GetTransitionReason(); + void SetIsRecent(bool isRecent); + bool GetIsRecent() const; + WindowSizeLimits GetWindowSizeLimits() const; + void SetMissionId(int32_t missionId); + int32_t GetMissionId() const; +private: + std::string bundleName_; + std::string abilityName_; + WindowMode mode_ = WindowMode::WINDOW_MODE_FULLSCREEN; + Rect windowRect_ = {0, 0, 0, 0}; + sptr abilityToken_ = nullptr; + DisplayId displayId_ = 0; + WindowType windowType_ = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW; + bool isShowWhenLocked_ = false; + bool isRecent_ = false; + TransitionReason reason_ = TransitionReason::ABILITY_TRANSITION; + std::vector supportWindowModes_; + WindowSizeLimits sizeLimits_; + int32_t missionId_ = -1; +}; +} // Rosen +} // OHOS +#endif \ No newline at end of file diff --git a/window_manager/utils/include/wm_common_inner.h b/window_manager/utils/include/wm_common_inner.h new file mode 100644 index 0000000..77267de --- /dev/null +++ b/window_manager/utils/include/wm_common_inner.h @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2021-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_ROSEN_WM_COMMON_INNER_H +#define OHOS_ROSEN_WM_COMMON_INNER_H + +#include +#include +#include +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +enum class LifeCycleEvent : uint32_t { + CREATE_EVENT, + SHOW_EVENT, + HIDE_EVENT, + DESTROY_EVENT, +}; + +enum class WindowStateChangeReason : uint32_t { + NORMAL, + KEYGUARD, + TOGGLING, +}; + +enum class WindowUpdateReason : uint32_t { + NEED_SWITCH_CASCADE_BASE, + UPDATE_ALL = NEED_SWITCH_CASCADE_BASE, + UPDATE_MODE, + UPDATE_RECT, + UPDATE_FLAGS, + UPDATE_TYPE, + NEED_SWITCH_CASCADE_END, + UPDATE_OTHER_PROPS, + UPDATE_TRANSFORM, +}; + +enum class AvoidPosType : uint32_t { + AVOID_POS_LEFT, + AVOID_POS_TOP, + AVOID_POS_RIGHT, + AVOID_POS_BOTTOM, + AVOID_POS_UNKNOWN +}; + +enum class WindowRootNodeType : uint32_t { + APP_WINDOW_NODE, + ABOVE_WINDOW_NODE, + BELOW_WINDOW_NODE, +}; + +enum class PropertyChangeAction : uint32_t { + ACTION_UPDATE_RECT = 1, + ACTION_UPDATE_MODE = 1 << 1, + ACTION_UPDATE_FLAGS = 1 << 2, + ACTION_UPDATE_OTHER_PROPS = 1 << 3, + ACTION_UPDATE_FOCUSABLE = 1 << 4, + ACTION_UPDATE_TOUCHABLE = 1 << 5, + ACTION_UPDATE_CALLING_WINDOW = 1 << 6, + ACTION_UPDATE_ORIENTATION = 1 << 7, + ACTION_UPDATE_TURN_SCREEN_ON = 1 << 8, + ACTION_UPDATE_KEEP_SCREEN_ON = 1 << 9, + ACTION_UPDATE_SET_BRIGHTNESS = 1 << 10, + ACTION_UPDATE_MODE_SUPPORT_INFO = 1 << 11, + ACTION_UPDATE_TOUCH_HOT_AREA = 1 << 12, + ACTION_UPDATE_TRANSFORM_PROPERTY = 1 << 13, + ACTION_UPDATE_ANIMATION_FLAG = 1 << 14, + ACTION_UPDATE_PRIVACY_MODE = 1 << 15, +}; + +struct ModeChangeHotZonesConfig { + bool isModeChangeHotZoneConfigured_; + uint32_t fullscreenRange_; + uint32_t primaryRange_; + uint32_t secondaryRange_; +}; + +struct WindowShadowParameters { + float elevation_; + std::string color_; + float offsetX_; + float offsetY_; + float alpha_; +}; + +struct AppWindowEffectConfig { + float fullScreenCornerRadius_; + float splitCornerRadius_; + float floatCornerRadius_; + + WindowShadowParameters focusedShadow_; + WindowShadowParameters unfocusedShadow_; + + // defaultCornerRadiusL = 16.0vp + AppWindowEffectConfig() : fullScreenCornerRadius_(0.0), splitCornerRadius_(0.0), floatCornerRadius_(0.0) + { + focusedShadow_ = {0, "#000000", 0, 0, 0}; + unfocusedShadow_ = {0, "#000000", 0, 0, 0}; + } +}; + +struct SystemConfig : public Parcelable { + bool isSystemDecorEnable_ = true; + bool isStretchable_ = false; + WindowMode defaultWindowMode_ = WindowMode::WINDOW_MODE_FULLSCREEN; + AppWindowEffectConfig effectConfig_; + + virtual bool Marshalling(Parcel& parcel) const override + { + if (!parcel.WriteBool(isSystemDecorEnable_) || !parcel.WriteBool(isStretchable_)) { + return false; + } + + if (!parcel.WriteUint32(static_cast(defaultWindowMode_))) { + return false; + } + + if (!parcel.WriteFloat(effectConfig_.fullScreenCornerRadius_) || + !parcel.WriteFloat(effectConfig_.splitCornerRadius_) || + !parcel.WriteFloat(effectConfig_.floatCornerRadius_)) { + return false; + } + + if (!parcel.WriteFloat(effectConfig_.focusedShadow_.elevation_) || + !parcel.WriteString(effectConfig_.focusedShadow_.color_) || + !parcel.WriteFloat(effectConfig_.focusedShadow_.offsetX_) || + !parcel.WriteFloat(effectConfig_.focusedShadow_.offsetY_) || + !parcel.WriteFloat(effectConfig_.focusedShadow_.alpha_)) { + return false; + } + + if (!parcel.WriteFloat(effectConfig_.unfocusedShadow_.elevation_) || + !parcel.WriteString(effectConfig_.unfocusedShadow_.color_) || + !parcel.WriteFloat(effectConfig_.unfocusedShadow_.offsetX_) || + !parcel.WriteFloat(effectConfig_.unfocusedShadow_.offsetY_) || + !parcel.WriteFloat(effectConfig_.unfocusedShadow_.alpha_)) { + return false; + } + return true; + } + + static SystemConfig* Unmarshalling(Parcel& parcel) + { + SystemConfig* config = new SystemConfig(); + config->isSystemDecorEnable_ = parcel.ReadBool(); + config->isStretchable_ = parcel.ReadBool(); + config->defaultWindowMode_ = static_cast(parcel.ReadUint32()); + config->effectConfig_.fullScreenCornerRadius_ = parcel.ReadFloat(); + config->effectConfig_.splitCornerRadius_ = parcel.ReadFloat(); + config->effectConfig_.floatCornerRadius_ = parcel.ReadFloat(); + config->effectConfig_.focusedShadow_.elevation_ = parcel.ReadFloat(); + config->effectConfig_.focusedShadow_.color_ = parcel.ReadString(); + config->effectConfig_.focusedShadow_.offsetX_ = parcel.ReadFloat(); + config->effectConfig_.focusedShadow_.offsetY_ = parcel.ReadFloat(); + config->effectConfig_.focusedShadow_.alpha_ = parcel.ReadFloat(); + config->effectConfig_.unfocusedShadow_.elevation_ = parcel.ReadFloat(); + config->effectConfig_.unfocusedShadow_.color_ = parcel.ReadString(); + config->effectConfig_.unfocusedShadow_.offsetX_ = parcel.ReadFloat(); + config->effectConfig_.unfocusedShadow_.offsetY_ = parcel.ReadFloat(); + config->effectConfig_.unfocusedShadow_.alpha_ = parcel.ReadFloat(); + return config; + } +}; + +struct WindowSizeLimits { + uint32_t maxWidth_; + uint32_t maxHeight_; + uint32_t minWidth_; + uint32_t minHeight_; + float maxRatio_; + float minRatio_; + WindowSizeLimits() : maxWidth_(UINT32_MAX), maxHeight_(UINT32_MAX), + minWidth_(0), minHeight_(0), maxRatio_(FLT_MAX), minRatio_(0.0f) {} + WindowSizeLimits(uint32_t maxWidth, uint32_t maxHeight, + uint32_t minWidth, uint32_t minHeight, float maxRatio, float minRatio) + : maxWidth_(maxWidth), maxHeight_(maxHeight), + minWidth_(minWidth), minHeight_(minHeight), maxRatio_(maxRatio), minRatio_(minRatio) {} +}; + +struct ModeChangeHotZones { + Rect fullscreen_; + Rect primary_; + Rect secondary_; +}; + +struct SplitRatioConfig { + // when divider reaches this position, the top/left window will hide. Valid range: (0, 0.5) + float exitSplitStartRatio; + // when divider reaches this position, the bottom/right window will hide. Valid range: (0.5, 1) + float exitSplitEndRatio; + std::vector splitRatios; +}; + +enum class DragType : uint32_t { + DRAG_UNDEFINED, + DRAG_LEFT_OR_RIGHT, + DRAG_BOTTOM_OR_TOP, + DRAG_LEFT_TOP_CORNER, + DRAG_RIGHT_TOP_CORNER, +}; + +enum class TraceTaskId : int32_t { + STARTING_WINDOW = 0, + REMOTE_ANIMATION, + CONNECT_EXTENSION, +}; + +struct MoveDragProperty : public Parcelable { + int32_t startPointPosX_; + int32_t startPointPosY_; + int32_t startPointerId_; + int32_t targetDisplayId_; + int32_t sourceType_; + bool startDragFlag_; + bool startMoveFlag_; + bool pointEventStarted_; + DragType dragType_; + Rect startPointRect_; + Rect startRectExceptFrame_; + Rect startRectExceptCorner_; + + MoveDragProperty() : startPointPosX_(0), startPointPosY_(0), startPointerId_(0), targetDisplayId_(0), + sourceType_(0), startDragFlag_(false), startMoveFlag_(false), pointEventStarted_(false), + dragType_(DragType::DRAG_UNDEFINED) + { + startPointRect_ = {0, 0, 0, 0}; + startRectExceptFrame_ = {0, 0, 0, 0}; + startRectExceptCorner_ = {0, 0, 0, 0}; + } + + MoveDragProperty(int32_t startPointPosX, int32_t startPointPosY, int32_t startPointerId, int32_t targetDisplayId, + int32_t sourceType, bool startDragFlag, bool startMoveFlag, bool pointEventStarted, DragType dragType, + Rect startPointRect, Rect startRectExceptFrame, Rect startRectExceptCorner) + : startPointPosX_(startPointPosX), startPointPosY_(startPointPosY), startPointerId_(startPointerId), + targetDisplayId_(targetDisplayId), sourceType_(sourceType), startDragFlag_(startDragFlag), + startMoveFlag_(startMoveFlag), pointEventStarted_(pointEventStarted), dragType_(dragType), + startPointRect_(startPointRect), startRectExceptFrame_(startRectExceptFrame), + startRectExceptCorner_(startRectExceptCorner) {} + + virtual bool Marshalling(Parcel& parcel) const override + { + if (!parcel.WriteInt32(startPointPosX_) || !parcel.WriteInt32(startPointPosY_) || + !parcel.WriteInt32(startPointerId_) || !parcel.WriteInt32(targetDisplayId_) || + !parcel.WriteInt32(sourceType_) || !parcel.WriteBool(startDragFlag_) || + !parcel.WriteBool(startMoveFlag_) || !parcel.WriteBool(pointEventStarted_) || + !parcel.WriteUint32(static_cast(dragType_))) { + return false; + } + + if (!parcel.WriteInt32(startPointRect_.posX_) || !parcel.WriteInt32(startPointRect_.posY_) || + !parcel.WriteUint32(startPointRect_.width_) || !parcel.WriteUint32(startPointRect_.height_)) { + return false; + } + + if (!parcel.WriteInt32(startRectExceptFrame_.posX_) || !parcel.WriteInt32(startRectExceptFrame_.posY_) || + !parcel.WriteUint32(startRectExceptFrame_.width_) || !parcel.WriteUint32(startRectExceptFrame_.height_)) { + return false; + } + + if (!parcel.WriteInt32(startRectExceptCorner_.posX_) || !parcel.WriteInt32(startRectExceptCorner_.posY_) || + !parcel.WriteUint32(startRectExceptCorner_.width_) || !parcel.WriteUint32(startRectExceptCorner_.height_)) { + return false; + } + + return true; + } + + static MoveDragProperty* Unmarshalling(Parcel& parcel) + { + MoveDragProperty* info = new MoveDragProperty(); + info->startPointPosX_ = parcel.ReadInt32(); + info->startPointPosY_ = parcel.ReadInt32(); + info->startPointerId_ = parcel.ReadInt32(); + info->targetDisplayId_ = parcel.ReadInt32(); + info->sourceType_ = parcel.ReadInt32(); + info->startDragFlag_ = parcel.ReadBool(); + info->startMoveFlag_ = parcel.ReadBool(); + info->pointEventStarted_ = parcel.ReadBool(); + info->dragType_ = static_cast(parcel.ReadUint32()); + Rect startPointRect = { parcel.ReadInt32(), parcel.ReadInt32(), + parcel.ReadUint32(), parcel.ReadUint32() }; + Rect startRectExceptFrame = { parcel.ReadInt32(), parcel.ReadInt32(), + parcel.ReadUint32(), parcel.ReadUint32() }; + Rect startRectExceptCorner = { parcel.ReadInt32(), parcel.ReadInt32(), + parcel.ReadUint32(), parcel.ReadUint32() }; + info->startPointRect_ = startPointRect; + info->startRectExceptFrame_ = startRectExceptFrame; + info->startRectExceptCorner_ = startRectExceptCorner; + return info; + } + + void CopyFrom(const sptr& property) + { + startPointPosX_ = property->startPointPosX_; + startPointPosY_ = property->startPointPosY_; + startPointerId_ = property->startPointerId_; + targetDisplayId_ = property->targetDisplayId_; + sourceType_ = property->sourceType_; + startDragFlag_ = property->startDragFlag_; + startMoveFlag_ = property->startMoveFlag_; + pointEventStarted_ = property->pointEventStarted_; + dragType_ = property->dragType_; + startPointRect_ = property->startPointRect_; + startRectExceptFrame_ = property->startRectExceptFrame_; + startRectExceptCorner_ = property->startRectExceptCorner_; + } +}; + +struct AbilityInfo { + std::string bundleName_ = ""; + std::string abilityName_ = ""; + int32_t missionId_ = -1; +}; + +namespace { + constexpr float DEFAULT_SPLIT_RATIO = 0.5; + constexpr float DEFAULT_ASPECT_RATIO = 0.67; + constexpr float DISPLAY_ZOOM_OFF_SCALE = 1.0; + constexpr float DISPLAY_ZOOM_MIN_SCALE = 2.0; + constexpr float DISPLAY_ZOOM_MAX_SCALE = 8.0; + constexpr int32_t IVALID_DIALOG_WINDOW_ID = -1; + constexpr uint32_t DIVIDER_WIDTH = 8; + constexpr uint32_t WINDOW_TITLE_BAR_HEIGHT = 37; + constexpr uint32_t WINDOW_FRAME_WIDTH = 5; + constexpr uint32_t WINDOW_FRAME_CORNER_WIDTH = 16; // the frame width of corner + constexpr uint32_t HOTZONE_TOUCH = 20; + constexpr uint32_t HOTZONE_POINTER = 4; + constexpr uint32_t MIN_FLOATING_WIDTH = 320; + constexpr uint32_t MIN_FLOATING_HEIGHT = 240; + constexpr uint32_t MIN_VERTICAL_SPLIT_HEIGHT = 240; + constexpr uint32_t MIN_HORIZONTAL_SPLIT_WIDTH = 320; + constexpr uint32_t MAX_FLOATING_SIZE = 1920; + constexpr unsigned int WMS_WATCHDOG_CHECK_INTERVAL = 6; // actual check interval is 3000ms(6 * 500) + const Rect INVALID_EMPTY_RECT = {0, 0, 0, 0}; + const Rect DEFAULT_PLACE_HOLDER_RECT = {0, 0, 512, 512}; + const std::unordered_set INPUT_WINDOW_TYPE_SKIPPED { + WindowType::WINDOW_TYPE_POINTER, + WindowType::WINDOW_TYPE_DRAGGING_EFFECT, + }; +} +} +} +#endif // OHOS_ROSEN_WM_COMMON_INNER_H \ No newline at end of file diff --git a/window_manager/utils/include/wm_math.h b/window_manager/utils/include/wm_math.h new file mode 100644 index 0000000..6c19c7b --- /dev/null +++ b/window_manager/utils/include/wm_math.h @@ -0,0 +1,244 @@ +/* + * 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_ROSEN_WM_MATH_H +#define OHOS_ROSEN_WM_MATH_H + +#include +#include + +namespace OHOS::Rosen { +namespace MathHelper { +constexpr float PI = 3.14159265f; +constexpr float INF = std::numeric_limits::infinity(); +constexpr float NAG_INF = -std::numeric_limits::infinity(); +constexpr float POS_ZERO = 0.001f; +constexpr float NAG_ZERO = -POS_ZERO; +inline bool NearZero(float val) +{ + return val < POS_ZERO && val > NAG_ZERO; +} + +inline float ToRadians(float degrees) +{ + return degrees * PI / 180.0f; +} + +inline float ToDegrees(float radians) +{ + return radians * 180.0f / PI; +} + +inline bool LessNotEqual(double left, double right) +{ + static constexpr double eps = -0.001f; + return (left - right) < eps; +} + +inline bool GreatNotEqual(double left, double right) +{ + static constexpr double eps = 0.001f; + return (left - right) > eps; +} + +template +T Max(const T& a, const T& b) +{ + return (a < b ? b : a); +} + +template +T Max(const T& a, const Ts&... bs) +{ + return Max(a, Max(bs...)); +} + +template +T Min(const T& a, const T& b) +{ + return (a < b ? a : b); +} + +template +T Min(const T& a, const Ts&... bs) +{ + return Min(a, Min(bs...)); +} + +template +T Clamp(const T& value, const T& lower, const T& upper) +{ + return Min(upper, Max(lower, value)); +} +} // namespace MathHelper + +namespace TransformHelper { +struct Vector2 { + float x_, y_; + Vector2() : x_(0.0f), y_(0.0f) {} + Vector2(float inX, float inY) + : x_(inX), y_(inY) {} + friend Vector2 operator-(const Vector2& v) + { + return Vector2 { -v.x_, -v.y_ }; + } + friend Vector2 operator+(const Vector2& a, const Vector2& b) + { + return Vector2 { a.x_ + b.x_, a.y_ + b.y_ }; + } + friend Vector2 operator-(const Vector2& a, const Vector2& b) + { + return Vector2 { a.x_ - b.x_, a.y_ - b.y_ }; + } + float LengthSq() const + { + return (x_ * x_ + y_ * y_); + } + float Length() const + { + return (std::sqrt(LengthSq())); + } +}; + +struct Vector3 { + float x_, y_, z_; + Vector3() : x_(0.0f), y_(0.0f), z_(0.0f) {} + Vector3(float inX, float inY, float inZ) + : x_(inX), y_(inY), z_(inZ) {} + friend Vector3 operator-(const Vector3& v) + { + return Vector3 { -v.x_, -v.y_, -v.z_ }; + } + friend Vector3 operator+(const Vector3& a, const Vector3& b) + { + return Vector3 { a.x_ + b.x_, a.y_ + b.y_, a.z_ + b.z_ }; + } + friend Vector3 operator-(const Vector3& a, const Vector3& b) + { + return Vector3 { a.x_ - b.x_, a.y_ - b.y_, a.z_ - b.z_ }; + } + // Scalar multiplication + friend Vector3 operator*(const Vector3& vec, float scalar) + { + return Vector3(vec.x_ * scalar, vec.y_ * scalar, vec.z_ * scalar); + } + // Scalar multiplication + friend Vector3 operator*(float scalar, const Vector3& vec) + { + return Vector3(vec.x_ * scalar, vec.y_ * scalar, vec.z_ * scalar); + } + // Scalar *= + Vector3& operator*=(float scalar) + { + x_ *= scalar; + y_ *= scalar; + z_ *= scalar; + return *this; + } + float LengthSq() const + { + return (x_ * x_ + y_ * y_ + z_ * z_); + } + float Length() const + { + return (std::sqrt(LengthSq())); + } + void Normalize() + { + float length = Length(); + if (length > MathHelper::POS_ZERO) { + x_ /= length; + y_ /= length; + z_ /= length; + } + } + static Vector3 Normalize(const Vector3& vec) + { + Vector3 temp = vec; + temp.Normalize(); + return temp; + } + static float Dot(const Vector3& a, const Vector3& b) + { + return (a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_); + } + static Vector3 Cross(const Vector3& a, const Vector3& b) + { + Vector3 temp; + temp.x_ = a.y_ * b.z_ - a.z_ * b.y_; + temp.y_ = a.z_ * b.x_ - a.x_ * b.z_; + temp.z_ = a.x_ * b.y_ - a.y_ * b.x_; + return temp; + } +}; + +struct Matrix3 { + float mat_[3][3]; + + friend Matrix3 operator*(const Matrix3& left, const Matrix3& right); + Matrix3& operator*=(const Matrix3& right); + static const Matrix3 Identity; +}; + +struct Matrix4 { + float mat_[4][4]; + + friend Matrix4 operator*(const Matrix4& left, const Matrix4& right); + Matrix4& operator*=(const Matrix4& right); + void SwapRow(int row1, int row2); + // Inverse matrix with Gauss-Jordan method + void Invert(); + // Extract the scale component from the matrix + Vector3 GetScale() const; + // Get the translation component of the matrix + Vector3 GetTranslation() const; + static const Matrix4 Identity; + static constexpr int MAT_SIZE = 4; +}; + +// Create a scale matrix with x and y scales(in xy-plane) +Matrix3 CreateScale(float xScale, float yScale); +// Create a rotation matrix about the Z axis +// theta is in radians +Matrix3 CreateRotation(float theta); +// Create a translation matrix (on the xy-plane) +Matrix3 CreateTranslation(const Vector2& trans); +// Create a scale matrix with x, y, and z scales +Matrix4 CreateScale(float xScale, float yScale, float zScale); +// Create a rotation matrix about X axis +// theta is in radians +Matrix4 CreateRotationX(float theta); +// Create a rotation matrix about Y axis +// theta is in radians +Matrix4 CreateRotationY(float theta); +// Create a rotation matrix about Z axis +// theta is in radians +Matrix4 CreateRotationZ(float theta); +// Create a 3D translation matrix +Matrix4 CreateTranslation(const Vector3& trans); +Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up); +Matrix4 CreatePerspective(const Vector3& camera); +// Transform a Vector2 in xy-plane by matrix3 +Vector2 Transform(const Vector2& vec, const Matrix3& mat); +// Transform a Vector3 in 3D world by matrix4 +Vector3 Transform(const Vector3& vec, const Matrix4& mat); +// Transform the vector and renormalize the w component +Vector3 TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w = 1.0f); +// Given a screen point, unprojects it into origin position at screen, +// based on the current transform matrix +Vector2 GetOriginScreenPoint(const Vector2& p, const Matrix4& mat); +} // namespace TransformHelper +} // namespace OHOS::Rosen +#endif // OHOS_ROSEN_WM_MATH_H \ No newline at end of file diff --git a/window_manager/utils/include/wm_occlusion_region.h b/window_manager/utils/include/wm_occlusion_region.h new file mode 100644 index 0000000..7dbf168 --- /dev/null +++ b/window_manager/utils/include/wm_occlusion_region.h @@ -0,0 +1,268 @@ +/* + * 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_ROSEN_WM_OCCLUSION_REGION_H +#define OHOS_ROSEN_WM_OCCLUSION_REGION_H + +#include +#include +#include +#include +#include + +namespace OHOS::Rosen::WmOcclusion { +class Rect { +public: + int left_ = 0; + int top_ = 0; + int right_ = 0; + int bottom_ = 0; + static Rect _s_empty_rect_; + static Rect _s_invalid_rect_; + + Rect() : left_(0), top_(0), right_(0), bottom_(0) {} + Rect(int l, int t, int r, int b) : left_(l), top_(t), right_(r), bottom_(b) {} + + bool IsEmpty() const + { + return left_ >= right_ || top_ >= bottom_; + } + + std::string GetRectInfo() const + { + return std::string("[" + + std::to_string(left_) + ", " + + std::to_string(top_) + ", " + + std::to_string(right_ - left_) + ", " + + std::to_string(bottom_ - top_) + "]"); + } +}; + +std::ostream& operator<<(std::ostream& os, const Rect& r); + +/* + Event: Used for record a rect edge in/out event + y_: rect edge Y value + type: OPEN/CLOSE: lhs rect in/out; VOID_OPEN/VOID_CLOSE: rhs rect in/out +*/ +class Event { +public: + // Use different value to differentiate lhs and rhs ranges + enum Type { OPEN = 1, CLOSE = -1, VOID_OPEN = 2, VOID_CLOSE = -2 }; + int y_ = 0; + Type type_ = Type::OPEN; + int left_ = 0; + int right_ = 0; + + Event(int y, Type type, int l, int r) : y_(y), type_(type), left_(l), right_(r) {} +}; +bool EventSortByY(const Event& e1, const Event& e2); + +class Range { +public: + int start_ = 0; + int end_ = 0; + Range(int s, int e) : start_(s), end_(e) {} + bool operator==(const Range& r) + { + return start_ == r.start_ && end_ == r.end_; + } +}; + +class Node { +public: + int start_ = 0; + int end_ = 0; + int mid_ = 0; + int positive_count_ = 0; // used for counting current lhs ranges + int negative_count_ = 0; // used for counting current rhs ranges + Node* left_ = nullptr; + Node* right_ = nullptr; + + Node(int s, int e) : start_(s), end_(e), mid_((s + e) >> 1) {} + ~Node() + { + if (left_ != nullptr) { + delete left_; + left_ = nullptr; + } + if (right_ != nullptr) { + delete right_; + right_ = nullptr; + } + } + + // push current node [start, end] into range result, merge last range if possible + inline void PushRange(std::vector& res) + { + if (res.size() > 0 && start_ == res[res.size() - 1].end_) { + // merge range with previous range if their end and start share same point + res[res.size() - 1].end_ = end_; + } else { + res.emplace_back(Range { start_, end_ }); + } + } + + inline bool IsLeaf() + { + return left_ == nullptr && right_ == nullptr; + } + + // update segment tree + void Update(int updateStart, int updateEnd, Event::Type type); + // get ranges where positive_count_ and negtive_count_ are both positive + void GetAndRange(std::vector& res, bool isParentNodePos, bool isParentNodeNeg); + // get ranges where positive_count_ or negtive_count_ is positive + void GetOrRange(std::vector& res, bool isParentNodePos, bool isParentNodeNeg); + // get ranges where either positive_count_ and negtive_count_ are both positive + void GetXOrRange(std::vector& res, bool isParentNodePos, bool isParentNodeNeg); + // get ranges where positive_count_ is positive and negtive_count_ not + void GetSubRange(std::vector& res, bool isParentNodePos, bool isParentNodeNeg); +}; + +class Region { +public: + enum OP { + // bit index 0: lhs + // bit index 1: lhs & rhs + // bit index 2: rhs + AND = 2, // 010 + OR = 7, // 111 + XOR = 5, // 101 + SUB = 1 // 001 + }; + + Region() = default; + explicit Region(Rect& r) + { + rects_.push_back(r); + bound_ = Rect { r }; + } + + Region(const Region& reg) : rects_(reg.rects_), bound_(reg.bound_) {} + ~Region() {} + + std::vector GetRegionRects() const + { + return rects_; + } + + std::vector& GetRegionRects() + { + return rects_; + } + + int GetSize() const + { + return rects_.size(); + } + + Rect GetBound() const + { + return bound_; + } + + Rect& GetBoundRef() + { + return bound_; + } + + bool IsEmpty() const + { + return rects_.size() == 0; + } + + std::string GetRegionInfo() const + { + std::string info = "{ Region Size " + std::to_string(rects_.size()) + ": "; + for (auto& r : rects_) { + info.append(r.GetRectInfo()); + } + info.append(" }"); + return info; + } + + inline std::vector::const_iterator CBegin() const + { + return rects_.cbegin(); + } + + inline std::vector::const_iterator CEnd() const + { + return rects_.cend(); + } + + inline std::vector::iterator Begin() + { + return rects_.begin(); + } + + inline std::vector::const_iterator End() + { + return rects_.end(); + } + + inline size_t Size() const + { + return rects_.size(); + } + + // bound of all region rects + void MakeBound(); + /* core Region logic operation function, the return region's rects is guaranteed no-intersection + (rect in rects_ do not intersect with each other) + */ + void RegionOp(Region& r1, Region& r2, Region& res, Region::OP op); + void RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op); + + Region& OperationSelf(Region& r, Region::OP op); + // replace region with and result + Region& AndSelf(Region& r); + // replace region with or result + Region& OrSelf(Region& r); + // replace region with xor result + Region& XOrSelf(Region& r); + // replace region with sub result + Region& SubSelf(Region& r); + + // return intersection region + Region And(Region& r); + // return merge region + Region Or(Region& r); + // return merge region subtract intersection region + Region Xor(Region& r); + // return region belongs to Region(lhs) but not Region(rhs) + Region Sub(Region& r); + +private: + class Rects { + public: + std::vector preRects; + std::vector curRects; + int preY = 0; + int curY = 0; + }; + // get ranges from segmentTree node according to logical operation type + void getRange(std::vector& ranges, Node& node, OP op); + // update tmp rects and region according to current ranges + void UpdateRects(Rects& r, std::vector& ranges, std::vector& indexAt, Region& res); + +private: + std::vector rects_; + Rect bound_; + static bool _s_so_loaded_; +}; +std::ostream& operator<<(std::ostream& os, const Region& r); +} // namespace OHOS::Rosen::Occlusion +#endif // OHOS_ROSEN_WM_OCCLUSION_REGION_H \ No newline at end of file diff --git a/window_manager/utils/include/wm_single_instance.h b/window_manager/utils/include/wm_single_instance.h new file mode 100644 index 0000000..4541914 --- /dev/null +++ b/window_manager/utils/include/wm_single_instance.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-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_WM_SINGLE_INSTANCE_H +#define OHOS_WM_SINGLE_INSTANCE_H +namespace OHOS { +namespace Rosen { +#define WM_DECLARE_SINGLE_INSTANCE_BASE(className) \ +public: \ + static className& GetInstance(); \ + className(const className&) = delete; \ + className& operator= (const className&) = delete; \ + className(className&&) = delete; \ + className& operator= (className&&) = delete; \ + +#define WM_DECLARE_SINGLE_INSTANCE(className) \ + WM_DECLARE_SINGLE_INSTANCE_BASE(className) \ +protected: \ + className() = default; \ + virtual ~className() = default; \ + +#define WM_IMPLEMENT_SINGLE_INSTANCE(className) \ +className& className::GetInstance() \ +{ \ + static className instance; \ + return instance; \ +} \ + +} // namespace OHOS +} +#endif // OHOS_SINGLE_INSTANCE_H diff --git a/window_manager/utils/include/xml_config_base.h b/window_manager/utils/include/xml_config_base.h new file mode 100644 index 0000000..cfc149f --- /dev/null +++ b/window_manager/utils/include/xml_config_base.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ROSEN_XML_CONFIG_BASE_H +#define OHOS_ROSEN_XML_CONFIG_BASE_H + +#include +#include +#include +#include + +namespace OHOS { +namespace Rosen { +class XmlConfigBase { +public: + enum class ValueType { + UNDIFINED, + MAP, + BOOL, + STRING, + INTS, + FLOATS, + POSITIVE_FLOATS, + }; + struct ConfigItem { + std::map* property_ = nullptr; + ValueType type_ = ValueType::UNDIFINED; + union { + std::map* mapValue_ = nullptr; + bool boolValue_; + std::string stringValue_; + std::vector* intsValue_; + std::vector* floatsValue_; + }; + ConfigItem() {} + ~ConfigItem() + { + Destroy(); + }; + void Destroy() + { + ClearValue(); + if (property_) { + delete property_; + property_ = nullptr; + } + } + void ClearValue() + { + switch (type_) { + case ValueType::MAP: + delete mapValue_; + mapValue_ = nullptr; + break; + case ValueType::STRING: + stringValue_.~basic_string(); + break; + case ValueType::INTS: + delete intsValue_; + intsValue_ = nullptr; + break; + case ValueType::FLOATS: + delete floatsValue_; + floatsValue_ = nullptr; + break; + default: + break; + } + } + ConfigItem(const ConfigItem& value) + { + *this = value; + } + ConfigItem& operator=(const ConfigItem& value) + { + Destroy(); + switch (value.type_) { + case ValueType::MAP: + mapValue_ = new std::map(*value.mapValue_); + break; + case ValueType::BOOL: + boolValue_ = value.boolValue_; + break; + case ValueType::STRING: + new(&stringValue_)std::string(value.stringValue_); + break; + case ValueType::INTS: + intsValue_ = new std::vector(*value.intsValue_); + break; + case ValueType::FLOATS: + floatsValue_ = new std::vector(*value.floatsValue_); + break; + default: + break; + } + type_ = value.type_; + if (value.property_) { + property_ = new std::map(*value.property_); + } + return *this; + } + ConfigItem(ConfigItem&& value) noexcept + { + *this = std::move(value); + } + ConfigItem& operator=(ConfigItem&& value) noexcept + { + Destroy(); + switch (value.type_) { + case ValueType::MAP: + mapValue_ = value.mapValue_; + value.mapValue_ = nullptr; + break; + case ValueType::BOOL: + boolValue_ = value.boolValue_; + break; + case ValueType::STRING: + new(&stringValue_)std::string(std::move(value.stringValue_)); + break; + case ValueType::INTS: + intsValue_ = value.intsValue_; + value.intsValue_ = nullptr; + break; + case ValueType::FLOATS: + floatsValue_ = value.floatsValue_; + value.floatsValue_ = nullptr; + break; + default: + break; + } + type_ = value.type_; + property_ = value.property_; + value.type_ = ValueType::UNDIFINED; + value.property_ = nullptr; + return *this; + } + void SetProperty(const std::map& prop) + { + if (property_) { + delete property_; + } + property_ = new std::map(prop); + } + // set map value + void SetValue(const std::map& value) + { + ClearValue(); + type_ = ValueType::MAP; + mapValue_ = new std::map(value); + } + // set bool value + void SetValue(bool value) + { + ClearValue(); + type_ = ValueType::BOOL; + boolValue_ = value; + } + // set string value + void SetValue(const std::string& value) + { + ClearValue(); + type_ = ValueType::STRING; + new(&stringValue_)std::string(value); + } + // set ints value + void SetValue(const std::vector& value) + { + ClearValue(); + type_ = ValueType::INTS; + intsValue_ = new std::vector(value); + } + // set floats value + void SetValue(const std::vector& value) + { + ClearValue(); + type_ = ValueType::FLOATS; + floatsValue_ = new std::vector(value); + } + bool IsInts() const + { + return type_ == ValueType::INTS; + } + bool IsFloats() const + { + return type_ == ValueType::FLOATS; + } + bool IsString() const + { + return type_ == ValueType::STRING; + } + bool IsBool() const + { + return type_ == ValueType::BOOL; + } + bool IsMap() const + { + return type_ == ValueType::MAP; + } + const ConfigItem& operator[](const std::string& key) const + { + if (type_ != ValueType::MAP) { + return DEFAULT; + } + if (mapValue_->count(key) == 0) { + return DEFAULT; + } + return mapValue_->at(key); + } + const ConfigItem& GetProp(const std::string& key) const + { + if (!property_) { + return DEFAULT; + } + if (property_->count(key) == 0) { + return DEFAULT; + } + return property_->at(key); + } + static const ConfigItem DEFAULT; + }; + static std::recursive_mutex mutex_; +}; +} // namespace Rosen +} // namespace OHOS + +#endif // OHOS_ROSEN_XML_CONFIG_BASE_H \ No newline at end of file diff --git a/window_manager/utils/src/agent_death_recipient.cpp b/window_manager/utils/src/agent_death_recipient.cpp new file mode 100644 index 0000000..3cc45b9 --- /dev/null +++ b/window_manager/utils/src/agent_death_recipient.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-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 "agent_death_recipient.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "AgentDeathRecipient"}; +} + +void AgentDeathRecipient::OnRemoteDied(const wptr& wptrDeath) +{ + if (wptrDeath == nullptr) { + WLOGFE("wptrDeath is null"); + return; + } + + sptr object = wptrDeath.promote(); + if (!object) { + WLOGFE("object is null"); + return; + } + if (callback_ != nullptr) { + WLOGFI("call OnRemoteDied callback"); + callback_(object); + } +} +} // namespace Rosen +} // namepsace OHOS \ No newline at end of file diff --git a/window_manager/utils/src/cutout_info.cpp b/window_manager/utils/src/cutout_info.cpp new file mode 100644 index 0000000..bc552f4 --- /dev/null +++ b/window_manager/utils/src/cutout_info.cpp @@ -0,0 +1,113 @@ +/* + * 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 "cutout_info.h" + +namespace OHOS::Rosen { +CutoutInfo::CutoutInfo(const std::vector& boundingRects, + WaterfallDisplayAreaRects waterfallDisplayAreaRects) : waterfallDisplayAreaRects_(waterfallDisplayAreaRects), + boundingRects_(boundingRects) +{ +} + +bool CutoutInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteInt32(waterfallDisplayAreaRects_.left.posX_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.left.posY_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.left.width_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.left.height_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.top.posX_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.top.posY_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.top.width_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.top.height_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.right.posX_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.right.posY_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.right.width_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.right.height_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.bottom.posX_) && + parcel.WriteInt32(waterfallDisplayAreaRects_.bottom.posY_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.bottom.width_) && + parcel.WriteUint32(waterfallDisplayAreaRects_.bottom.height_) && + WriteBoundingRectsVector(boundingRects_, parcel); +} + +CutoutInfo *CutoutInfo::Unmarshalling(Parcel &parcel) +{ + WaterfallDisplayAreaRects waterfallDisplayAreaRects; + std::vector boundingRects; + ReadWaterfallDisplayAreaRects(waterfallDisplayAreaRects, parcel); + ReadBoundingRectsVector(boundingRects, parcel); + CutoutInfo *cutoutInfo = new CutoutInfo(boundingRects, waterfallDisplayAreaRects); + return cutoutInfo; +} + +bool CutoutInfo::WriteBoundingRectsVector(const std::vector& boundingRects, Parcel &parcel) const +{ + if (!parcel.WriteUint32(static_cast(boundingRects.size()))) { + return false; + } + for (DMRect rect : boundingRects) { + if (!(parcel.WriteInt32(rect.posX_) && parcel.WriteInt32(rect.posY_) && + parcel.WriteUint32(rect.width_) && parcel.WriteUint32(rect.height_))) { + return false; + } + } + return true; +} + +bool CutoutInfo::ReadBoundingRectsVector(std::vector& unmarBoundingRects, Parcel &parcel) +{ + uint32_t size; + if (!parcel.ReadUint32(size)) { + return false; + } + for (uint32_t index = 0; index < size; index++) { + int32_t posX; + int32_t posY; + uint32_t width; + uint32_t height; + if (!(parcel.ReadInt32(posX) && parcel.ReadInt32(posY) && + parcel.ReadUint32(width) && parcel.ReadUint32(height))) { + return false; + } + DMRect rect = {posX, posY, width, height}; + unmarBoundingRects.push_back(rect); + } + return true; +} + +bool CutoutInfo::ReadWaterfallDisplayAreaRects(WaterfallDisplayAreaRects& waterfallDisplayAreaRects, Parcel &parcel) +{ + if (!(parcel.ReadInt32(waterfallDisplayAreaRects.left.posX_) && + parcel.ReadInt32(waterfallDisplayAreaRects.left.posY_) && + parcel.ReadUint32(waterfallDisplayAreaRects.left.width_) && + parcel.ReadUint32(waterfallDisplayAreaRects.left.height_) && + parcel.ReadInt32(waterfallDisplayAreaRects.top.posX_) && + parcel.ReadInt32(waterfallDisplayAreaRects.top.posY_) && + parcel.ReadUint32(waterfallDisplayAreaRects.top.width_) && + parcel.ReadUint32(waterfallDisplayAreaRects.top.height_) && + parcel.ReadInt32(waterfallDisplayAreaRects.right.posX_) && + parcel.ReadInt32(waterfallDisplayAreaRects.right.posY_) && + parcel.ReadUint32(waterfallDisplayAreaRects.right.width_) && + parcel.ReadUint32(waterfallDisplayAreaRects.right.height_) && + parcel.ReadInt32(waterfallDisplayAreaRects.bottom.posX_) && + parcel.ReadInt32(waterfallDisplayAreaRects.bottom.posY_) && + parcel.ReadUint32(waterfallDisplayAreaRects.bottom.width_) && + parcel.ReadUint32(waterfallDisplayAreaRects.bottom.height_))) { + return false; + } + return true; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/utils/src/display_info.cpp b/window_manager/utils/src/display_info.cpp new file mode 100644 index 0000000..47a034b --- /dev/null +++ b/window_manager/utils/src/display_info.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-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 "display_info.h" + +#include +#include + + +namespace OHOS::Rosen { +bool DisplayInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteString(name_) && parcel.WriteUint64(id_) && parcel.WriteUint32(static_cast(type_)) && + parcel.WriteInt32(width_) && parcel.WriteInt32(height_) && + parcel.WriteUint32(refreshRate_) && parcel.WriteUint64(screenId_) && + parcel.WriteFloat(virtualPixelRatio_) && parcel.WriteFloat(xDpi_) && parcel.WriteFloat(yDpi_) && + parcel.WriteUint32(static_cast(rotation_)) && + parcel.WriteUint32(static_cast(orientation_)) && + parcel.WriteInt32(offsetX_) && parcel.WriteInt32(offsetY_) && + parcel.WriteUint32(static_cast(displayState_)) && + parcel.WriteBool(waterfallDisplayCompressionStatus_); +} + +DisplayInfo *DisplayInfo::Unmarshalling(Parcel &parcel) +{ + DisplayInfo *displayInfo = new(std::nothrow) DisplayInfo(); + if (displayInfo == nullptr) { + return nullptr; + } + uint32_t type = (uint32_t)DisplayType::DEFAULT; + uint32_t rotation; + uint32_t orientation; + uint32_t displayState; + bool res = parcel.ReadString(displayInfo->name_) && + parcel.ReadUint64(displayInfo->id_) && parcel.ReadUint32(type) && + parcel.ReadInt32(displayInfo->width_) && parcel.ReadInt32(displayInfo->height_) && + parcel.ReadUint32(displayInfo->refreshRate_) && parcel.ReadUint64(displayInfo->screenId_) && + parcel.ReadFloat(displayInfo->virtualPixelRatio_) && + parcel.ReadFloat(displayInfo->xDpi_) && parcel.ReadFloat(displayInfo->yDpi_) && + parcel.ReadUint32(rotation) && parcel.ReadUint32(orientation) && + parcel.ReadInt32(displayInfo->offsetX_) && parcel.ReadInt32(displayInfo->offsetY_) && + parcel.ReadUint32(displayState) && parcel.ReadBool(displayInfo->waterfallDisplayCompressionStatus_); + if (!res) { + delete displayInfo; + return nullptr; + } + displayInfo->type_ = (DisplayType)type; + displayInfo->rotation_ = static_cast(rotation); + displayInfo->orientation_ = static_cast(orientation); + displayInfo->displayState_ = static_cast(displayState); + return displayInfo; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/utils/src/perform_reporter.cpp b/window_manager/utils/src/perform_reporter.cpp new file mode 100644 index 0000000..6d83e79 --- /dev/null +++ b/window_manager/utils/src/perform_reporter.cpp @@ -0,0 +1,114 @@ +/* + * 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 "perform_reporter.h" +#include "window_manager_hilog.h" + +#include + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "PerformReporter"}; +} + +/** + * @brief Construct a new Perform Reporter:: Perform Reporter object + * + * @param tag A tag that in report string + * @param timeSpiltsMs The time-interval that data statistic, details look up the comments in function body + * @param reportInterval Report data after reportInterval round start-end + */ +PerformReporter::PerformReporter(const std::string& tag, + const std::vector& timeSpiltsMs, uint32_t reportInterval) + : tag_(tag), reportInterval_(reportInterval) +{ + // re-organ data struct + // a, b, c, d --> + // (0, a] : cnt=0, (a, b] : cnt=0, (b, c] : cnt=0, (c, d] : cnt=0 + for (auto split : timeSpiltsMs) { + timeSplitCount_[split] = 0; + } + // (d, +limit] : cnt=0 + timeSplitCount_[BARRIER] = 0; + totalCount_ = 0; +} + +void PerformReporter::start() +{ + startTime_ = std::chrono::steady_clock::now(); +} + +void PerformReporter::end() +{ + auto currentTime = std::chrono::steady_clock::now(); + int64_t costTime = std::chrono::duration_cast(currentTime - startTime_).count(); + + count(costTime); + + bool repSucc = report(); + if (repSucc) { + clear(); + } +} + +bool PerformReporter::report() +{ + if (totalCount_ < reportInterval_) { + return false; + } + + std::ostringstream oss; + oss << tag_ << ": "; + auto maxSplit = 0; + for (const auto& iter: timeSplitCount_) { + if (iter.first != BARRIER) { + oss << "BELLOW" << iter.first << "(ms): " << iter.second << ", "; + maxSplit = iter.first; + } + } + oss << "ABOVE" << maxSplit << "(ms): " << timeSplitCount_[BARRIER]; + + int32_t ret = OHOS::HiviewDFX::HiSysEvent::Write( + OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, tag_, + OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "MSG", oss.str()); + WLOGFI("Write HiSysEvent ret:%{public}d", ret); + return ret == 0; +} + +void PerformReporter::count(int64_t costTime) +{ + totalCount_++; + for (auto& iter: timeSplitCount_) { + if (costTime <= iter.first) { + iter.second++; + break; + } + } + + std::ostringstream oss; + oss << tag_ << " cost " << costTime << "ms, total count " << totalCount_; + WLOGFI("%{public}s", oss.str().c_str()); +} + +void PerformReporter::clear() +{ + totalCount_ = 0; + for (auto& iter: timeSplitCount_) { + iter.second = 0; + } +} +} +} \ No newline at end of file diff --git a/window_manager/utils/src/permission.cpp b/window_manager/utils/src/permission.cpp new file mode 100644 index 0000000..f14af5f --- /dev/null +++ b/window_manager/utils/src/permission.cpp @@ -0,0 +1,106 @@ +/* + * 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 "permission.h" + +#include +#include +#include +#include +#include +#include + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WMPermission"}; +} + +bool Permission::IsSystemServiceCalling(bool needPrintLog) +{ + Security::AccessToken::NativeTokenInfo tokenInfo; + Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(IPCSkeleton::GetCallingTokenID(), tokenInfo); + if (tokenInfo.apl == Security::AccessToken::ATokenAplEnum::APL_SYSTEM_CORE || + tokenInfo.apl == Security::AccessToken::ATokenAplEnum::APL_SYSTEM_BASIC) { + return true; + } + if (needPrintLog) { + WLOGFE("Is not system service calling, native apl: %{public}d", tokenInfo.apl); + } + return false; +} + +bool Permission::IsSystemCalling() +{ + if (IsSystemServiceCalling(false)) { + return true; + } + int32_t uid = IPCSkeleton::GetCallingUid(); + if (uid < 0) { + WLOGFE("Is not system calling, app caller uid is: %d,", uid); + return false; + } + + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityManager == nullptr) { + WLOGFE("Is not system calling, failed to get system ability mgr."); + return false; + } + sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObject == nullptr) { + WLOGFE("Is not system calling, failed to get bundle manager proxy."); + return false; + } + sptr iBundleMgr = iface_cast(remoteObject); + if (iBundleMgr == nullptr) { + WLOGFE("Is not system calling, iBundleMgr is nullptr"); + return false; + } + bool isSystemAppCalling = iBundleMgr->CheckIsSystemAppByUid(uid); + if (!isSystemAppCalling) { + WLOGFE("Is not system calling, UID:%{public}d IsSystemApp:%{public}d", uid, isSystemAppCalling); + } + return isSystemAppCalling; +} + +bool Permission::CheckCallingPermission(const std::string& permission) +{ + WLOGFI("permission:%{public}s", permission.c_str()); + + if (Security::AccessToken::AccessTokenKit::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission) != + AppExecFwk::Constants::PERMISSION_GRANTED) { + WLOGFI("permission denied!"); + return false; + } + WLOGFI("permission ok!"); + return true; +} + +bool Permission::IsStartByHdcd() +{ + OHOS::Security::AccessToken::NativeTokenInfo info; + if (Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(IPCSkeleton::GetCallingTokenID(), info) != 0) { + return false; + } + if (info.processName.compare("hdcd") == 0) { + return true; + } + return false; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/src/screen_group_info.cpp b/window_manager/utils/src/screen_group_info.cpp new file mode 100644 index 0000000..86e8b5e --- /dev/null +++ b/window_manager/utils/src/screen_group_info.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021-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 "screen_group_info.h" + +namespace OHOS::Rosen { +bool ScreenGroupInfo::Marshalling(Parcel &parcel) const +{ + bool res = ScreenInfo::Marshalling(parcel) && parcel.WriteUint32((uint32_t)combination_) && + parcel.WriteUInt64Vector(children_); + if (!res) { + return false; + } + size_t size = position_.size(); + if (!parcel.WriteUint32(size)) { + return false; + } + for (size_t i = 0; i < size; i++) { + if (!parcel.WriteInt32(position_[i].posX_) || !parcel.WriteInt32(position_[i].posY_)) { + return false; + } + } + return true; +} + +ScreenGroupInfo* ScreenGroupInfo::Unmarshalling(Parcel &parcel) +{ + ScreenGroupInfo* screenGroupInfo = new(std::nothrow) ScreenGroupInfo(); + if (screenGroupInfo == nullptr) { + return screenGroupInfo; + } + bool res = screenGroupInfo->InnerUnmarshalling(parcel); + if (res) { + return screenGroupInfo; + } + delete screenGroupInfo; + return nullptr; +} + +bool ScreenGroupInfo::InnerUnmarshalling(Parcel& parcel) +{ + uint32_t combination; + if (!ScreenInfo::InnerUnmarshalling(parcel) || !parcel.ReadUint32(combination) || + !parcel.ReadUInt64Vector(&children_)) { + return false; + } + combination_ = (ScreenCombination) combination; + uint32_t size; + if (!parcel.ReadUint32(size)) { + 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 false; + } + } + return true; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/utils/src/screen_info.cpp b/window_manager/utils/src/screen_info.cpp new file mode 100644 index 0000000..aa4cc53 --- /dev/null +++ b/window_manager/utils/src/screen_info.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021-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 "screen_info.h" + +namespace OHOS::Rosen { +bool ScreenInfo::Marshalling(Parcel &parcel) const +{ + bool res = parcel.WriteString(name_) && parcel.WriteUint64(id_) && + parcel.WriteUint32(virtualWidth_) && parcel.WriteUint32(virtualHeight_) && + parcel.WriteFloat(virtualPixelRatio_) && parcel.WriteUint64(lastParent_) && parcel.WriteUint64(parent_) && + parcel.WriteBool(isScreenGroup_) && parcel.WriteUint32(static_cast(rotation_)) && + parcel.WriteUint32(static_cast(orientation_)) && + parcel.WriteUint32(static_cast(type_)) && + parcel.WriteUint32(modeId_) && parcel.WriteUint32(static_cast(modes_.size())); + if (!res) { + return false; + } + for (uint32_t modeIndex = 0; modeIndex < modes_.size(); modeIndex++) { + if (parcel.WriteUint32(modes_[modeIndex]->height_) && + parcel.WriteUint32(modes_[modeIndex]->width_) && + parcel.WriteUint32(modes_[modeIndex]->refreshRate_)) { + continue; + } + return false; + } + return true; +} + +ScreenInfo* ScreenInfo::Unmarshalling(Parcel &parcel) +{ + ScreenInfo* info = new(std::nothrow) ScreenInfo(); + if (info == nullptr) { + return info; + } + bool res = info->InnerUnmarshalling(parcel); + if (res) { + return info; + } + delete info; + return nullptr; +} + +bool ScreenInfo::InnerUnmarshalling(Parcel& parcel) +{ + uint32_t size = 0; + uint32_t rotation; + uint32_t orientation; + uint32_t type; + name_ = parcel.ReadString(); + bool res1 = parcel.ReadUint64(id_) && + parcel.ReadUint32(virtualWidth_) && parcel.ReadUint32(virtualHeight_) && + parcel.ReadFloat(virtualPixelRatio_) && parcel.ReadUint64(lastParent_) && parcel.ReadUint64(parent_) && + parcel.ReadBool(isScreenGroup_) && parcel.ReadUint32(rotation) && + parcel.ReadUint32(orientation) && parcel.ReadUint32(type) && + parcel.ReadUint32(modeId_) && parcel.ReadUint32(size); + if (!res1) { + return false; + } + modes_.clear(); + for (uint32_t modeIndex = 0; modeIndex < size; modeIndex++) { + sptr mode = new(std::nothrow) SupportedScreenModes(); + if (mode == nullptr) { + return false; + } + if (parcel.ReadUint32(mode->height_) && + parcel.ReadUint32(mode->width_) && + parcel.ReadUint32(mode->refreshRate_)) { + modes_.push_back(mode); + } else { + return false; + } + } + rotation_ = static_cast(rotation); + orientation_ = static_cast(orientation); + type_ = static_cast(type); + return true; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/utils/src/screenshot_info.cpp b/window_manager/utils/src/screenshot_info.cpp new file mode 100644 index 0000000..70ffd9e --- /dev/null +++ b/window_manager/utils/src/screenshot_info.cpp @@ -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. + */ + +#include "screenshot_info.h" + +namespace OHOS::Rosen { +bool ScreenshotInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteString(trigger_) && parcel.WriteUint64(displayId_); +} + +ScreenshotInfo *ScreenshotInfo::Unmarshalling(Parcel &parcel) +{ + ScreenshotInfo *info = new(std::nothrow) ScreenshotInfo(); + if (info == nullptr) { + return nullptr; + } + bool res = parcel.ReadString(info->trigger_) && parcel.ReadUint64(info->displayId_); + if (!res) { + delete info; + return nullptr; + } + return info; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/utils/src/singleton_container.cpp b/window_manager/utils/src/singleton_container.cpp new file mode 100644 index 0000000..0edc484 --- /dev/null +++ b/window_manager/utils/src/singleton_container.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021-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 "singleton_container.h" +#include +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { +constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SingletonContainer"}; +} // namespace +WM_IMPLEMENT_SINGLE_INSTANCE(SingletonContainer) + +SingletonContainer::~SingletonContainer() +{ + destroyed_ = true; + while (singletonMap.empty() == false) { + auto it = singletonMap.begin(); + while (it != singletonMap.end()) { + if (it->second.refCount > 0) { + it++; + continue; + } + + if (dependencySetMap.find(it->first) != dependencySetMap.end()) { + for (auto mid : dependencySetMap[it->first]) { + singletonMap[mid].refCount--; + } + dependencySetMap.erase(it->first); + } + + for (const auto &[k, v] : stringMap) { + if (v == it->first) { + WLOGFD("remove %{public}s", k.c_str()); + break; + } + } + singletonMap.erase(it++); + } + } +} + +void SingletonContainer::AddSingleton(const std::string& name, void* instance) +{ + if (stringMap.find(name) == stringMap.end()) { + static int32_t nextId = 0; + singletonMap[nextId].value = instance; + singletonMap[nextId].refCount = 0; + WLOGFI("add %{public}s", name.c_str()); + stringMap[name] = nextId++; + } else { + WLOGFE("add failed: %{public}s", name.c_str()); + } +} + +void SingletonContainer::SetSingleton(const std::string& name, void* instance) +{ + if (stringMap.find(name) == stringMap.end()) { + AddSingleton(name, instance); + } else { + WLOGFI("set %{public}s", name.c_str()); + singletonMap[stringMap[name]].value = instance; + } +} + +void* SingletonContainer::GetSingleton(const std::string& name) +{ + if (stringMap.find(name) == stringMap.end()) { + WLOGFE("can not get %{public}s", name.c_str()); + return nullptr; + } + return singletonMap[stringMap[name]].value; +} + +void* SingletonContainer::DependOn(const std::string& instance, const std::string& name) +{ + auto& instanceDependencySet = dependencySetMap[stringMap[instance]]; + if (instanceDependencySet.find(stringMap[name]) == instanceDependencySet.end()) { + WLOGFD("%{public}s DependOn %{public}s", instance.c_str(), name.c_str()); + instanceDependencySet.insert(stringMap[name]); + singletonMap[stringMap[name]].refCount++; + } + return GetSingleton(name); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/utils/src/string_util.cpp b/window_manager/utils/src/string_util.cpp new file mode 100644 index 0000000..b75b526 --- /dev/null +++ b/window_manager/utils/src/string_util.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 "string_util.h" + +namespace OHOS { +namespace Rosen { +std::string StringUtil::Trim(std::string s) +{ + if (!s.empty()) { + s.erase(0, s.find_first_not_of(" ")); + s.erase(s.find_last_not_of(" ") + 1); + } + return s; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/src/surface_draw.cpp b/window_manager/utils/src/surface_draw.cpp new file mode 100644 index 0000000..f56a047 --- /dev/null +++ b/window_manager/utils/src/surface_draw.cpp @@ -0,0 +1,420 @@ +/* + * 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_draw.h" +#include +#include +#include +#include + +#include "image/bitmap.h" +#include "image_source.h" +#include "image_type.h" +#include "image_utils.h" +#include "pixel_map.h" +#include "surface_capture_future.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SurfaceDraw"}; + constexpr uint32_t IMAGE_BYTES_STRIDE = 4; +} // namespace + +bool SurfaceDraw::DrawImage(std::shared_ptr surfaceNode, int32_t bufferWidth, + int32_t bufferHeight, const std::string& imagePath) +{ + sptr layer = GetLayer(surfaceNode); + if (layer == nullptr) { + WLOGFE("layer is nullptr"); + return false; + } + sptr buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight); + if (buffer == nullptr || buffer->GetVirAddr() == nullptr) { + return false; + } + auto addr = static_cast(buffer->GetVirAddr()); + if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), imagePath)) { + WLOGE("draw window pixel failed"); + return false; + } + OHOS::BufferFlushConfig flushConfig = { + .damage = { + .w = buffer->GetWidth(), + .h = buffer->GetHeight(), + }, + }; + OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig); + if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) { + WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str()); + return false; + } + return true; +} + +bool SurfaceDraw::DrawImage(std::shared_ptr surfaceNode, int32_t bufferWidth, + int32_t bufferHeight, std::shared_ptr pixelMap) +{ + sptr layer = GetLayer(surfaceNode); + if (layer == nullptr) { + WLOGFE("layer is nullptr"); + return false; + } + sptr buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight); + if (buffer == nullptr || buffer->GetVirAddr() == nullptr) { + return false; + } + auto addr = static_cast(buffer->GetVirAddr()); + if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), pixelMap)) { + WLOGE("draw window pixel failed"); + return false; + } + OHOS::BufferFlushConfig flushConfig = { + .damage = { + .w = buffer->GetWidth(), + .h = buffer->GetHeight(), + }, + }; + OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig); + if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) { + WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str()); + return false; + } + return true; +} + +bool SurfaceDraw::DrawColor(std::shared_ptr surfaceNode, int32_t bufferWidth, + int32_t bufferHeight, uint32_t color) +{ + sptr layer = GetLayer(surfaceNode); + if (layer == nullptr) { + WLOGFE("layer is nullptr"); + return false; + } + sptr buffer = GetSurfaceBuffer(layer, bufferWidth, bufferHeight); + if (buffer == nullptr || buffer->GetVirAddr() == nullptr) { + return false; + } + auto addr = static_cast(buffer->GetVirAddr()); + if (!DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), color)) { + WLOGE("draw window color failed"); + return false; + } + OHOS::BufferFlushConfig flushConfig = { + .damage = { + .w = buffer->GetWidth(), + .h = buffer->GetHeight(), + }, + }; + OHOS::SurfaceError ret = layer->FlushBuffer(buffer, -1, flushConfig); + if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) { + WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(ret).c_str()); + return false; + } + return true; +} + +sptr SurfaceDraw::GetLayer(std::shared_ptr surfaceNode) +{ + if (surfaceNode == nullptr) { + return nullptr; + } + return surfaceNode->GetSurface(); +} + +sptr SurfaceDraw::GetSurfaceBuffer(sptr layer, + int32_t bufferWidth, int32_t bufferHeight) +{ + sptr buffer; + int32_t releaseFence = 0; + OHOS::BufferRequestConfig config = { + .width = bufferWidth, + .height = bufferHeight, + .strideAlignment = 0x8, + .format = PIXEL_FMT_RGBA_8888, + .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA, + }; + + OHOS::SurfaceError ret = layer->RequestBuffer(buffer, releaseFence, config); + if (ret != OHOS::SURFACE_ERROR_OK) { + WLOGFE("request buffer ret:%{public}s", SurfaceErrorStr(ret).c_str()); + return nullptr; + } + return buffer; +} + +std::unique_ptr SurfaceDraw::DecodeImageToPixelMap(const std::string &imagePath) +{ + OHOS::Media::SourceOptions opts; + opts.formatHint = "image/png"; + uint32_t ret = 0; + auto imageSource = OHOS::Media::ImageSource::CreateImageSource(imagePath, opts, ret); + if (imageSource == nullptr) { + WLOGFE("invalid image path."); + return nullptr; + } + std::set formats; + ret = imageSource->GetSupportedFormats(formats); + WLOGFD("get supported format ret:%{public}u", ret); + + OHOS::Media::DecodeOptions decodeOpts; + std::unique_ptr pixelMap = imageSource->CreatePixelMap(decodeOpts, ret); + if (pixelMap == nullptr) { + WLOGFE("pixelMap is nullptr"); + } + return pixelMap; +} + +void SurfaceDraw::DrawPixelmap(Drawing::Canvas &canvas, const std::string& imagePath) +{ + std::unique_ptr pixelmap = DecodeImageToPixelMap(imagePath); + if (pixelmap == nullptr) { + WLOGFE("drawing pixel map is nullptr"); + return; + } + Drawing::Pen pen; + pen.SetAntiAlias(true); + pen.SetColor(Drawing::Color::COLOR_BLUE); + Drawing::scalar penWidth = 1; + pen.SetWidth(penWidth); + canvas.AttachPen(pen); + canvas.DrawBitmap(*pixelmap, 0, 0); +} + +bool SurfaceDraw::DoDraw(uint8_t *addr, uint32_t width, uint32_t height, const std::string& imagePath) +{ + Drawing::Bitmap bitmap; + Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, + Drawing::AlphaType::ALPHATYPE_OPAQUE }; + bitmap.Build(width, height, format); + Drawing::Canvas canvas; + canvas.Bind(bitmap); + canvas.Clear(Drawing::Color::COLOR_TRANSPARENT); + DrawPixelmap(canvas, imagePath); + uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE; + errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize); + if (ret != EOK) { + WLOGFE("draw failed"); + return false; + } + return true; +} + +bool SurfaceDraw::DoDraw(uint8_t *addr, uint32_t width, uint32_t height, std::shared_ptr pixelMap) +{ + Drawing::Bitmap bitmap; + Drawing::Canvas canvas; + Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_OPAQUE }; + bitmap.Build(width, height, format); + canvas.Bind(bitmap); + canvas.Clear(Drawing::Color::COLOR_TRANSPARENT); + + Drawing::Image image; + Drawing::Bitmap imageBitmap; + Drawing::SamplingOptions sampling = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, + Drawing::MipmapMode::NEAREST); + imageBitmap.Build(pixelMap->GetWidth(), pixelMap->GetHeight(), format); + imageBitmap.SetPixels(const_cast(pixelMap->GetPixels())); + image.BuildFromBitmap(imageBitmap); + + Drawing::Rect dst(0, 0, width, height); + Drawing::Rect src(0, 0, pixelMap->GetWidth(), pixelMap->GetHeight()); + canvas.DrawImageRect(image, src, dst, sampling); + + uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE; + errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize); + if (ret != EOK) { + WLOGFE("draw failed"); + return false; + } + return true; +} + +bool SurfaceDraw::DoDraw(uint8_t *addr, uint32_t width, uint32_t height, uint32_t color) +{ + Drawing::Bitmap bitmap; + Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, + Drawing::AlphaType::ALPHATYPE_OPAQUE }; + bitmap.Build(width, height, format); + Drawing::Canvas canvas; + canvas.Bind(bitmap); + canvas.Clear(color); + + uint32_t addrSize = width * height * IMAGE_BYTES_STRIDE; + errno_t ret = memcpy_s(addr, addrSize, bitmap.GetPixels(), addrSize); + if (ret != EOK) { + WLOGFE("draw failed"); + return false; + } + return true; +} + +bool SurfaceDraw::DrawImageRect(std::shared_ptr surfaceNode, Rect rect, + std::shared_ptr pixelMap, uint32_t color, bool fillWindow) +{ + int32_t winHeight = static_cast(rect.height_); + int32_t winWidth = static_cast(rect.width_); + sptr layer = GetLayer(surfaceNode); + if (layer == nullptr) { + WLOGFE("layer is nullptr"); + return false; + } + sptr buffer = GetSurfaceBuffer(layer, winWidth, winHeight); + if (buffer == nullptr || buffer->GetVirAddr() == nullptr) { + return false; + } + if (!DoDrawImageRect(buffer, rect, pixelMap, color, fillWindow)) { + WLOGE("draw image rect failed."); + return false; + } + OHOS::BufferFlushConfig flushConfig = { + .damage = { + .w = buffer->GetWidth(), + .h = buffer->GetHeight(), + }, + }; + OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig); + if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) { + WLOGFE("draw pointer FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str()); + return false; + } + return true; +} + +bool SurfaceDraw::DoDrawImageRect(sptr buffer, const Rect& rect, + std::shared_ptr pixelMap, uint32_t color, bool fillWindow) +{ + int32_t winWidth = static_cast(rect.width_); + int32_t winHeight = static_cast(rect.height_); + // actual width of the surface buffer after alignment + auto bufferStride = buffer->GetStride(); + int32_t alignWidth = bufferStride / static_cast(IMAGE_BYTES_STRIDE); + WLOGFD("drawing image rect win width: %{public}d win height: %{public}d align width:%{public}d.", + winWidth, winHeight, alignWidth); + if (pixelMap == nullptr) { + WLOGFE("drawing pixel map failed, because pixel map is nullptr."); + return false; + } + if (pixelMap->GetHeight() <= 0 || pixelMap->GetWidth() <= 0 || winWidth <= 0 || winHeight <= 0) { + WLOGFE("drawing pixel map failed, because width or height is invalid."); + return false; + } + float xAxis = static_cast(winWidth) / pixelMap->GetWidth(); + float yAxis = static_cast(winHeight) / pixelMap->GetHeight(); + float axis = std::min(xAxis, yAxis); + if (axis < 1.0) { + // scale when the size of the pixel map is larger than the window + // use axis to scale equally + pixelMap->scale(axis, axis); + } else if (fillWindow) { + // scale snapshot to whole window + pixelMap->scale(xAxis, yAxis); + } + int left = (winWidth - pixelMap->GetWidth()) / 2; // 2 is the left and right boundaries of the window + int top = (winHeight - pixelMap->GetHeight()) / 2; // 2 is the top and bottom boundaries of the window + WLOGFD("pixelMap width: %{public}d win height: %{public}d left:%{public}d top:%{public}d.", + pixelMap->GetWidth(), pixelMap->GetHeight(), left, top); + Drawing::Bitmap bitmap; + Drawing::BitmapFormat format { Drawing::ColorType::COLORTYPE_RGBA_8888, + Drawing::AlphaType::ALPHATYPE_OPAQUE }; + bitmap.Build(alignWidth, winHeight, format); + Drawing::Canvas canvas; + canvas.Bind(bitmap); + canvas.Clear(color); + canvas.DrawBitmap(*pixelMap, left, top); + // bufferSize is actual size of the surface buffer after alignment + int32_t bufferSize = bufferStride * winHeight; + uint8_t* bitmapAddr = static_cast(bitmap.GetPixels()); + auto addr = static_cast(buffer->GetVirAddr()); + errno_t ret = memcpy_s(addr, bufferSize, bitmapAddr, bufferSize); + if (ret != EOK) { + WLOGFE("draw image rect failed, because copy bitmap to buffer failed."); + return false; + } + return true; +} + +bool SurfaceDraw::GetSurfaceSnapshot(const std::shared_ptr surfaceNode, + std::shared_ptr&pixelMap, int32_t timeoutMs, float scaleW, float scaleH) +{ + if (surfaceNode == nullptr) { + WLOGFE("surfaceNode is null"); + return false; + } + std::shared_ptr callback = std::make_shared(); + if (RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode, callback, scaleW, scaleH)) { + pixelMap = callback->GetResult(timeoutMs); // get pixelmap time out ms + } + if (pixelMap == nullptr) { + WLOGE("get surface snapshot timeout."); + return false; + } + return true; +} + +bool SurfaceDraw::DrawMasking(std::shared_ptr surfaceNode, Rect screenRect, + Rect transparentRect) +{ + int32_t screenHeight = static_cast(screenRect.height_); + int32_t screenWidth = static_cast(screenRect.width_); + int32_t transparentHeight = static_cast(transparentRect.height_); + int32_t transparentWidth = static_cast(transparentRect.width_); + sptr layer = GetLayer(surfaceNode); + if (layer == nullptr) { + WLOGFE("layer is nullptr"); + return false; + } + sptr buffer = GetSurfaceBuffer(layer, screenWidth, screenHeight); + if (buffer == nullptr || buffer->GetVirAddr() == nullptr) { + return false; + } + auto addr = static_cast(buffer->GetVirAddr()); + Drawing::Bitmap fullbitmap; + Drawing::BitmapFormat fullBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888, + Drawing::AlphaType::ALPHATYPE_OPAQUE }; + fullbitmap.Build(screenWidth, screenHeight, fullBitmapFormat); + Drawing::Canvas canvas; + canvas.Bind(fullbitmap); + canvas.Clear(0xFF000000); + Drawing::Bitmap transBitmap; + Drawing::BitmapFormat transBitmapFormat { Drawing::ColorType::COLORTYPE_RGBA_8888, + Drawing::AlphaType::ALPHATYPE_OPAQUE }; + transBitmap.Build(transparentWidth, transparentHeight, transBitmapFormat); + transBitmap.ClearWithColor(0); + canvas.DrawBitmap(transBitmap, static_cast(transparentRect.posX_), + static_cast(transparentRect.posY_)); + + uint32_t addrSize = static_cast(screenWidth * screenHeight * IMAGE_BYTES_STRIDE); + errno_t ret = memcpy_s(addr, addrSize, fullbitmap.GetPixels(), addrSize); + if (ret != EOK) { + WLOGFE("draw failed"); + return false; + } + OHOS::BufferFlushConfig flushConfig = { + .damage = { + .w = buffer->GetWidth(), + .h = buffer->GetHeight(), + }, + }; + OHOS::SurfaceError surfaceRet = layer->FlushBuffer(buffer, -1, flushConfig); + if (surfaceRet != OHOS::SurfaceError::SURFACE_ERROR_OK) { + WLOGFE("draw masking FlushBuffer ret:%{public}s", SurfaceErrorStr(surfaceRet).c_str()); + return false; + } + return true; +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/utils/src/surface_reader.cpp b/window_manager/utils/src/surface_reader.cpp new file mode 100644 index 0000000..9cf1cd1 --- /dev/null +++ b/window_manager/utils/src/surface_reader.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021-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 = static_cast(bufferHandle->width); + uint32_t height = static_cast(bufferHandle->height); + uint32_t stride = static_cast(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"); + free(data); + return false; + } + } + + sptr pixelMap = new(std::nothrow) PixelMap(); + if (pixelMap == nullptr) { + WLOGFE("create pixelMap failed"); + free(data); + return false; + } + + ImageInfo info; + info.size.width = static_cast(width); + info.size.height = static_cast(height); + info.pixelFormat = OHOS::Media::PixelFormat::RGBA_8888; + info.colorSpace = ColorSpace::SRGB; + pixelMap->SetImageInfo(info); + + pixelMap->SetPixelsAddr(data, nullptr, width * height, AllocatorType::HEAP_ALLOC, nullptr); + + handler_->OnImageAvailable(pixelMap); + return true; +} +} +} diff --git a/window_manager/utils/src/surface_reader_handler_impl.cpp b/window_manager/utils/src/surface_reader_handler_impl.cpp new file mode 100644 index 0000000..88c7eb8 --- /dev/null +++ b/window_manager/utils/src/surface_reader_handler_impl.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-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::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReaderHandlerImpl"}; +} // namespace +bool SurfaceReaderHandlerImpl::OnImageAvailable(sptr pixelMap) +{ + std::lock_guard lock(mutex_); + if (!flag_) { + flag_ = true; + pixelMap_ = pixelMap; + 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() +{ + std::lock_guard lock(mutex_); + return pixelMap_; +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/utils/src/sys_cap_util.cpp b/window_manager/utils/src/sys_cap_util.cpp new file mode 100644 index 0000000..f469272 --- /dev/null +++ b/window_manager/utils/src/sys_cap_util.cpp @@ -0,0 +1,77 @@ +/* + * 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 "sys_cap_util.h" +#include "string_util.h" +#include "window_manager_hilog.h" + +#include +#include +#include +#include +#include + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WmSysCapUtil"}; +} + +std::string SysCapUtil::GetClientName() +{ + std::string bn = GetBundleName(); + if (!bn.empty()) { + WLOGFD("bundle name [%{public}s]", bn.c_str()); + return bn; + } + + std::string pn = GetProcessName(); + if (!pn.empty()) { + WLOGFD("process name [%{public}s]", pn.c_str()); + return pn; + } + + WLOGFD("unknow name"); + return "unknown"; +} + +std::string SysCapUtil::GetBundleName() +{ + OHOS::sptr systemAbilityManager = + OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + OHOS::sptr remoteObject = + systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + sptr iBundleMgr = OHOS::iface_cast(remoteObject); + if (iBundleMgr == nullptr) { + WLOGFW("IBundleMgr is null"); + return ""; + } + + std::string bundleName = ""; + iBundleMgr->GetBundleNameForUid(IPCSkeleton::GetCallingUid(), bundleName); + return StringUtil::Trim(bundleName); +} + +std::string SysCapUtil::GetProcessName() +{ + OHOS::Security::AccessToken::NativeTokenInfo info; + if (Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(IPCSkeleton::GetCallingTokenID(), info) != 0) { + WLOGFW("get token info failed"); + return ""; + } + return StringUtil::Trim(info.processName); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/src/window_property.cpp b/window_manager/utils/src/window_property.cpp new file mode 100644 index 0000000..b40f852 --- /dev/null +++ b/window_manager/utils/src/window_property.cpp @@ -0,0 +1,916 @@ +/* + * Copyright (c) 2021-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 "window_property.h" +#include "window_helper.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +WindowProperty::WindowProperty(const sptr& property) +{ + CopyFrom(property); +} + +void WindowProperty::SetWindowName(const std::string& name) +{ + windowName_ = name; +} + +void WindowProperty::SetAbilityInfo(const AbilityInfo& info) +{ + abilityInfo_ = info; +} + +void WindowProperty::SetWindowRect(const struct Rect& rect) +{ + ComputeTransform(); + windowRect_ = rect; +} + +void WindowProperty::SetDecoStatus(bool decoStatus) +{ + decoStatus_ = decoStatus; +} + +void WindowProperty::SetRequestRect(const Rect& requestRect) +{ + requestRect_ = requestRect; +} + +void WindowProperty::SetWindowType(WindowType type) +{ + type_ = type; +} + +void WindowProperty::SetWindowMode(WindowMode mode) +{ + if (!WindowHelper::IsValidWindowMode(mode) || !WindowHelper::IsWindowModeSupported(modeSupportInfo_, mode)) { + return; + } + if (!WindowHelper::IsSplitWindowMode(mode_)) { + lastMode_ = mode_; + } + mode_ = mode; +} + +void WindowProperty::SetLastWindowMode(WindowMode mode) +{ + if (!WindowHelper::IsWindowModeSupported(modeSupportInfo_, mode)) { + return; + } + lastMode_ = mode; +} + +void WindowProperty::SetFullScreen(bool isFullScreen) +{ + isFullScreen_ = isFullScreen; +} + +void WindowProperty::SetFocusable(bool isFocusable) +{ + focusable_ = isFocusable; +} + +void WindowProperty::SetTouchable(bool isTouchable) +{ + touchable_ = isTouchable; +} + +void WindowProperty::SetPrivacyMode(bool isPrivate) +{ + isPrivacyMode_ = isPrivate; +} + +void WindowProperty::SetSystemPrivacyMode(bool isSystemPrivate) +{ + isSystemPrivacyMode_ = isSystemPrivate; +} + +void WindowProperty::SetTransparent(bool isTransparent) +{ + isTransparent_ = isTransparent; +} + +void WindowProperty::SetAlpha(float alpha) +{ + alpha_ = alpha; +} + +void WindowProperty::SetTransform(const Transform& trans) +{ + recomputeTransformMat_ = true; + trans_ = trans; +} + +void WindowProperty::HandleComputeTransform(const Transform& trans) +{ + TransformHelper::Vector3 pivotPos = { windowRect_.posX_ + trans.pivotX_ * windowRect_.width_, + windowRect_.posY_ + trans.pivotY_ * windowRect_.height_, 0 }; + worldTransformMat_ = TransformHelper::CreateTranslation(-pivotPos) * + WindowHelper::ComputeWorldTransformMat4(trans) * + TransformHelper::CreateTranslation(pivotPos); + // transformMat = worldTransformMat * viewProjectionMat + transformMat_ = worldTransformMat_; + // Z component of camera position is constant value + constexpr float cameraZ = -576.f; + TransformHelper::Vector3 cameraPos(pivotPos.x_ + trans.translateX_, pivotPos.y_ + trans.translateY_, cameraZ); + // Concatenate with view projection matrix + transformMat_ *= TransformHelper::CreateLookAt(cameraPos, + TransformHelper::Vector3(cameraPos.x_, cameraPos.y_, 0), TransformHelper::Vector3(0, 1, 0)) * + TransformHelper::CreatePerspective(cameraPos); +} + +void WindowProperty::ComputeTransform() +{ + if (isDisplayZoomOn_) { + if (reCalcuZoomTransformMat_) { + HandleComputeTransform(zoomTrans_); + reCalcuZoomTransformMat_ = false; + } + } else if (recomputeTransformMat_) { + HandleComputeTransform(trans_); + recomputeTransformMat_ = false; + } +} + +void WindowProperty::SetZoomTransform(const Transform& trans) +{ + zoomTrans_ = trans; + reCalcuZoomTransformMat_ = true; +} + +void WindowProperty::ClearTransformZAxisOffset(Transform& trans) +{ + // replace Z axis translation by scaling + TransformHelper::Matrix4 preTransformMat = transformMat_; + HandleComputeTransform(trans); + Rect rect = WindowHelper::TransformRect(transformMat_, windowRect_); + float translateZ = trans.translateZ_; + trans.translateZ_ = 0.f; + HandleComputeTransform(trans); + Rect rectWithoutZAxisOffset = WindowHelper::TransformRect(transformMat_, windowRect_); + if (rectWithoutZAxisOffset.width_ == 0) { + trans.translateZ_ = translateZ; + return; + } + float scale = rect.width_ * 1.0f / rectWithoutZAxisOffset.width_; + trans.scaleX_ *= scale; + trans.scaleY_ *= scale; + transformMat_ = preTransformMat; +} + +void WindowProperty::UpdatePointerEvent(const std::shared_ptr& pointerEvent) +{ + if (trans_ == Transform::Identity() && zoomTrans_ == Transform::Identity()) { + return; + } + ComputeTransform(); + MMI::PointerEvent::PointerItem pointerItem; + if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + return; + } + PointInfo originPos = + WindowHelper::CalculateOriginPosition(transformMat_, + { pointerItem.GetDisplayX(), pointerItem.GetDisplayY() }); + pointerItem.SetDisplayX(originPos.x); + pointerItem.SetDisplayY(originPos.y); + pointerItem.SetWindowX(originPos.x - windowRect_.posX_); + pointerItem.SetWindowY(originPos.y - windowRect_.posY_); + pointerEvent->UpdatePointerItem(pointerEvent->GetPointerId(), pointerItem); +} + +bool WindowProperty::isNeedComputerTransform() +{ + return ((!isDisplayZoomOn_ && trans_ != Transform::Identity()) || zoomTrans_ != Transform::Identity()); +} + +void WindowProperty::SetAnimateWindowFlag(bool isAnimateWindow) +{ + isAnimateWindow_ = isAnimateWindow; +} + +void WindowProperty::SetDisplayZoomState(bool isDisplayZoomOn) +{ + isDisplayZoomOn_ = isDisplayZoomOn; +} + +bool WindowProperty::IsDisplayZoomOn() const +{ + return isDisplayZoomOn_; +} + +bool WindowProperty::IsAnimateWindow() const +{ + return isAnimateWindow_; +} + +const Transform& WindowProperty::GetZoomTransform() const +{ + return zoomTrans_; +} + +void WindowProperty::SetBrightness(float brightness) +{ + brightness_ = brightness; +} + +void WindowProperty::SetTurnScreenOn(bool turnScreenOn) +{ + turnScreenOn_ = turnScreenOn; +} + +void WindowProperty::SetKeepScreenOn(bool keepScreenOn) +{ + keepScreenOn_ = keepScreenOn; +} + +void WindowProperty::SetCallingWindow(uint32_t windowId) +{ + callingWindow_ = windowId; +} + +void WindowProperty::SetDisplayId(DisplayId displayId) +{ + displayId_ = displayId; +} + +void WindowProperty::SetWindowFlags(uint32_t flags) +{ + flags_ = flags; +} + +void WindowProperty::SetSizeLimits(const WindowSizeLimits& sizeLimits) +{ + sizeLimits_ = sizeLimits; +} + +void WindowProperty::SetUpdatedSizeLimits(const WindowSizeLimits& sizeLimits) +{ + updatedSizeLimits_ = sizeLimits; +} + +void WindowProperty::AddWindowFlag(WindowFlag flag) +{ + flags_ |= static_cast(flag); +} + +void WindowProperty::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) +{ + if (type == WindowType::WINDOW_TYPE_STATUS_BAR || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR) { + sysBarPropMap_[type] = property; + } +} + +void WindowProperty::SetDecorEnable(bool decorEnable) +{ + isDecorEnable_ = decorEnable; +} + +void WindowProperty::SetHitOffset(const PointInfo& offset) +{ + hitOffset_ = offset; +} + +void WindowProperty::SetAnimationFlag(uint32_t animationFlag) +{ + animationFlag_ = animationFlag; +} + +void WindowProperty::SetWindowSizeChangeReason(WindowSizeChangeReason reason) +{ + windowSizeChangeReason_ = reason; +} + +void WindowProperty::SetDragType(DragType dragType) +{ + dragType_ = dragType; +} + +void WindowProperty::SetStretchable(bool stretchable) +{ + isStretchable_ = stretchable; +} + +void WindowProperty::SetOriginRect(const Rect& rect) +{ + originRect_ = rect; +} + +void WindowProperty::SetAccessTokenId(uint32_t accessTokenId) +{ + accessTokenId_ = accessTokenId; +} + +WindowSizeChangeReason WindowProperty::GetWindowSizeChangeReason() const +{ + return windowSizeChangeReason_; +} + +void WindowProperty::ResumeLastWindowMode() +{ + // if lastMode isn't supported, get supported mode from supportModeInfo + if (!WindowHelper::IsWindowModeSupported(modeSupportInfo_, lastMode_)) { + auto mode = WindowHelper::GetWindowModeFromModeSupportInfo(modeSupportInfo_); + if (!WindowHelper::IsSplitWindowMode(mode)) { + mode_ = mode; + } + return; + } + mode_ = lastMode_; +} + +const std::string& WindowProperty::GetWindowName() const +{ + return windowName_ ; +} + +const AbilityInfo& WindowProperty::GetAbilityInfo() const +{ + return abilityInfo_ ; +} + +Rect WindowProperty::GetWindowRect() const +{ + return windowRect_; +} + +bool WindowProperty::GetDecoStatus() const +{ + return decoStatus_; +} + +Rect WindowProperty::GetRequestRect() const +{ + return requestRect_; +} + +WindowType WindowProperty::GetWindowType() const +{ + return type_; +} + +WindowMode WindowProperty::GetWindowMode() const +{ + return mode_; +} + +WindowMode WindowProperty::GetLastWindowMode() const +{ + return lastMode_; +} + +bool WindowProperty::GetFullScreen() const +{ + return isFullScreen_; +} + +bool WindowProperty::GetFocusable() const +{ + return focusable_; +} + +bool WindowProperty::GetTouchable() const +{ + return touchable_; +} + +uint32_t WindowProperty::GetCallingWindow() const +{ + return callingWindow_; +} + +bool WindowProperty::GetPrivacyMode() const +{ + return isPrivacyMode_; +} + +bool WindowProperty::GetSystemPrivacyMode() const +{ + return isSystemPrivacyMode_; +} + +bool WindowProperty::GetTransparent() const +{ + return isTransparent_; +} + +float WindowProperty::GetAlpha() const +{ + return alpha_; +} + +const Transform& WindowProperty::GetTransform() const +{ + return trans_; +} + +float WindowProperty::GetBrightness() const +{ + return brightness_; +} + +bool WindowProperty::IsTurnScreenOn() const +{ + return turnScreenOn_; +} + +bool WindowProperty::IsKeepScreenOn() const +{ + return keepScreenOn_; +} + +DisplayId WindowProperty::GetDisplayId() const +{ + return displayId_; +} + +uint32_t WindowProperty::GetWindowFlags() const +{ + return flags_; +} + +const std::unordered_map& WindowProperty::GetSystemBarProperty() const +{ + return sysBarPropMap_; +} + +bool WindowProperty::GetDecorEnable() const +{ + return isDecorEnable_; +} + +void WindowProperty::SetWindowId(uint32_t windowId) +{ + windowId_ = windowId; +} + +void WindowProperty::SetParentId(uint32_t parentId) +{ + parentId_ = parentId; +} + +void WindowProperty::SetTokenState(bool hasToken) +{ + tokenState_ = hasToken; +} + +void WindowProperty::SetModeSupportInfo(uint32_t modeSupportInfo) +{ + modeSupportInfo_ = modeSupportInfo; +} + +void WindowProperty::SetRequestModeSupportInfo(uint32_t requestModeSupportInfo) +{ + requestModeSupportInfo_ = requestModeSupportInfo; +} + +uint32_t WindowProperty::GetWindowId() const +{ + return windowId_; +} + +uint32_t WindowProperty::GetParentId() const +{ + return parentId_; +} + +const PointInfo& WindowProperty::GetHitOffset() const +{ + return hitOffset_; +} + +uint32_t WindowProperty::GetAnimationFlag() const +{ + return animationFlag_; +} + +uint32_t WindowProperty::GetModeSupportInfo() const +{ + return modeSupportInfo_; +} + +uint32_t WindowProperty::GetRequestModeSupportInfo() const +{ + return requestModeSupportInfo_; +} + +bool WindowProperty::GetTokenState() const +{ + return tokenState_; +} + +DragType WindowProperty::GetDragType() const +{ + return dragType_; +} + +const Rect& WindowProperty::GetOriginRect() const +{ + return originRect_; +} + +bool WindowProperty::GetStretchable() const +{ + return isStretchable_; +} + +WindowSizeLimits WindowProperty::GetSizeLimits() const +{ + return sizeLimits_; +} + +WindowSizeLimits WindowProperty::GetUpdatedSizeLimits() const +{ + return updatedSizeLimits_; +} + +const TransformHelper::Matrix4& WindowProperty::GetTransformMat() const +{ + return transformMat_; +} + +const TransformHelper::Matrix4& WindowProperty::GetWorldTransformMat() const +{ + return worldTransformMat_; +} + +void WindowProperty::SetTouchHotAreas(const std::vector& rects) +{ + touchHotAreas_ = rects; +} + +void WindowProperty::GetTouchHotAreas(std::vector& rects) const +{ + rects = touchHotAreas_; +} + +uint32_t WindowProperty::GetAccessTokenId() const +{ + return accessTokenId_; +} + +bool WindowProperty::MapMarshalling(Parcel& parcel) const +{ + auto size = sysBarPropMap_.size(); + if (!parcel.WriteUint32(static_cast(size))) { + return false; + } + for (auto it : sysBarPropMap_) { + // write key(type) + if (!parcel.WriteUint32(static_cast(it.first))) { + return false; + } + // write val(sysBarProps) + if (!(parcel.WriteBool(it.second.enable_) && parcel.WriteUint32(it.second.backgroundColor_) && + parcel.WriteUint32(it.second.contentColor_))) { + return false; + } + } + return true; +} + +void WindowProperty::MapUnmarshalling(Parcel& parcel, WindowProperty* property) +{ + uint32_t size = parcel.ReadUint32(); + for (uint32_t i = 0; i < size; i++) { + WindowType type = static_cast(parcel.ReadUint32()); + SystemBarProperty prop = { parcel.ReadBool(), parcel.ReadUint32(), parcel.ReadUint32() }; + property->SetSystemBarProperty(type, prop); + } +} + +bool WindowProperty::MarshallingTouchHotAreas(Parcel& parcel) const +{ + auto size = touchHotAreas_.size(); + if (!parcel.WriteUint32(static_cast(size))) { + return false; + } + for (const auto& rect : touchHotAreas_) { + if (!(parcel.WriteInt32(rect.posX_) && parcel.WriteInt32(rect.posY_) && + parcel.WriteUint32(rect.width_) && parcel.WriteUint32(rect.height_))) { + return false; + } + } + return true; +} + +void WindowProperty::UnmarshallingTouchHotAreas(Parcel& parcel, WindowProperty* property) +{ + auto size = parcel.ReadUint32(); + for (uint32_t i = 0; i < size; i++) { + property->touchHotAreas_.emplace_back( + Rect{ parcel.ReadInt32(), parcel.ReadInt32(), parcel.ReadUint32(), parcel.ReadUint32() }); + } +} + +bool WindowProperty::MarshallingTransform(Parcel& parcel) const +{ + return parcel.WriteFloat(trans_.pivotX_) && parcel.WriteFloat(trans_.pivotY_) && + parcel.WriteFloat(trans_.scaleX_) && parcel.WriteFloat(trans_.scaleY_) && + parcel.WriteFloat(trans_.rotationX_) && parcel.WriteFloat(trans_.rotationY_) && + parcel.WriteFloat(trans_.rotationZ_) && parcel.WriteFloat(trans_.translateX_) && + parcel.WriteFloat(trans_.translateY_) && parcel.WriteFloat(trans_.translateZ_); +} + +void WindowProperty::UnmarshallingTransform(Parcel& parcel, WindowProperty* property) +{ + Transform trans; + trans.pivotX_ = parcel.ReadFloat(); + trans.pivotY_ = parcel.ReadFloat(); + trans.scaleX_ = parcel.ReadFloat(); + trans.scaleY_ = parcel.ReadFloat(); + trans.rotationX_ = parcel.ReadFloat(); + trans.rotationY_ = parcel.ReadFloat(); + trans.rotationZ_ = parcel.ReadFloat(); + trans.translateX_ = parcel.ReadFloat(); + trans.translateY_ = parcel.ReadFloat(); + trans.translateZ_ = parcel.ReadFloat(); + property->SetTransform(trans); +} + +bool WindowProperty::MarshallingWindowSizeLimits(Parcel& parcel) const +{ + if (parcel.WriteUint32(sizeLimits_.maxWidth_) && + parcel.WriteUint32(sizeLimits_.maxHeight_) && parcel.WriteUint32(sizeLimits_.minWidth_) && + parcel.WriteUint32(sizeLimits_.minHeight_) && parcel.WriteFloat(sizeLimits_.maxRatio_) && + parcel.WriteFloat(sizeLimits_.minRatio_)) { + return true; + } + return false; +} + +void WindowProperty::UnmarshallingWindowSizeLimits(Parcel& parcel, WindowProperty* property) +{ + WindowSizeLimits sizeLimits = { parcel.ReadUint32(), parcel.ReadUint32(), parcel.ReadUint32(), + parcel.ReadUint32(), parcel.ReadFloat(), parcel.ReadFloat() }; + property->SetSizeLimits(sizeLimits); +} + +bool WindowProperty::Marshalling(Parcel& parcel) const +{ + return parcel.WriteString(windowName_) && parcel.WriteInt32(windowRect_.posX_) && + parcel.WriteInt32(windowRect_.posY_) && parcel.WriteUint32(windowRect_.width_) && + parcel.WriteUint32(windowRect_.height_) && parcel.WriteInt32(requestRect_.posX_) && + parcel.WriteInt32(requestRect_.posY_) && parcel.WriteUint32(requestRect_.width_) && + parcel.WriteUint32(requestRect_.height_) && parcel.WriteBool(decoStatus_) && + parcel.WriteUint32(static_cast(type_)) && + parcel.WriteUint32(static_cast(mode_)) && parcel.WriteUint32(static_cast(lastMode_)) && + parcel.WriteUint32(flags_) && + parcel.WriteBool(isFullScreen_) && parcel.WriteBool(focusable_) && parcel.WriteBool(touchable_) && + parcel.WriteBool(isPrivacyMode_) && parcel.WriteBool(isTransparent_) && parcel.WriteFloat(alpha_) && + parcel.WriteFloat(brightness_) && parcel.WriteUint64(displayId_) && parcel.WriteUint32(windowId_) && + parcel.WriteUint32(parentId_) && MapMarshalling(parcel) && parcel.WriteBool(isDecorEnable_) && + parcel.WriteInt32(hitOffset_.x) && parcel.WriteInt32(hitOffset_.y) && parcel.WriteUint32(animationFlag_) && + parcel.WriteUint32(static_cast(windowSizeChangeReason_)) && parcel.WriteBool(tokenState_) && + parcel.WriteUint32(callingWindow_) && parcel.WriteUint32(static_cast(requestedOrientation_)) && + parcel.WriteBool(turnScreenOn_) && parcel.WriteBool(keepScreenOn_) && + parcel.WriteUint32(modeSupportInfo_) && parcel.WriteUint32(requestModeSupportInfo_) && + parcel.WriteUint32(static_cast(dragType_)) && + parcel.WriteUint32(originRect_.width_) && parcel.WriteUint32(originRect_.height_) && + parcel.WriteBool(isStretchable_) && MarshallingTouchHotAreas(parcel) && parcel.WriteUint32(accessTokenId_) && + MarshallingTransform(parcel) && MarshallingWindowSizeLimits(parcel) && zoomTrans_.Marshalling(parcel) && + parcel.WriteBool(isDisplayZoomOn_) && parcel.WriteString(abilityInfo_.bundleName_) && + parcel.WriteString(abilityInfo_.abilityName_) && parcel.WriteInt32(abilityInfo_.missionId_); +} + +WindowProperty* WindowProperty::Unmarshalling(Parcel& parcel) +{ + WindowProperty* property = new(std::nothrow) WindowProperty(); + if (property == nullptr) { + return nullptr; + } + property->SetWindowName(parcel.ReadString()); + Rect rect = { parcel.ReadInt32(), parcel.ReadInt32(), parcel.ReadUint32(), parcel.ReadUint32() }; + property->SetWindowRect(rect); + Rect reqRect = { parcel.ReadInt32(), parcel.ReadInt32(), parcel.ReadUint32(), parcel.ReadUint32() }; + property->SetRequestRect(reqRect); + property->SetDecoStatus(parcel.ReadBool()); + property->SetWindowType(static_cast(parcel.ReadUint32())); + property->SetWindowMode(static_cast(parcel.ReadUint32())); + property->SetLastWindowMode(static_cast(parcel.ReadUint32())); + property->SetWindowFlags(parcel.ReadUint32()); + property->SetFullScreen(parcel.ReadBool()); + property->SetFocusable(parcel.ReadBool()); + property->SetTouchable(parcel.ReadBool()); + property->SetPrivacyMode(parcel.ReadBool()); + property->SetTransparent(parcel.ReadBool()); + property->SetAlpha(parcel.ReadFloat()); + property->SetBrightness(parcel.ReadFloat()); + property->SetDisplayId(parcel.ReadUint64()); + property->SetWindowId(parcel.ReadUint32()); + property->SetParentId(parcel.ReadUint32()); + MapUnmarshalling(parcel, property); + property->SetDecorEnable(parcel.ReadBool()); + PointInfo offset = {parcel.ReadInt32(), parcel.ReadInt32()}; + property->SetHitOffset(offset); + property->SetAnimationFlag(parcel.ReadUint32()); + property->SetWindowSizeChangeReason(static_cast(parcel.ReadUint32())); + property->SetTokenState(parcel.ReadBool()); + property->SetCallingWindow(parcel.ReadUint32()); + property->SetRequestedOrientation(static_cast(parcel.ReadUint32())); + property->SetTurnScreenOn(parcel.ReadBool()); + property->SetKeepScreenOn(parcel.ReadBool()); + property->SetModeSupportInfo(parcel.ReadUint32()); + property->SetRequestModeSupportInfo(parcel.ReadUint32()); + property->SetDragType(static_cast(parcel.ReadUint32())); + uint32_t w = parcel.ReadUint32(); + uint32_t h = parcel.ReadUint32(); + property->SetOriginRect(Rect { 0, 0, w, h }); + property->SetStretchable(parcel.ReadBool()); + UnmarshallingTouchHotAreas(parcel, property); + property->SetAccessTokenId(parcel.ReadUint32()); + UnmarshallingTransform(parcel, property); + UnmarshallingWindowSizeLimits(parcel, property); + Transform zoomTrans; + zoomTrans.Unmarshalling(parcel); + property->SetZoomTransform(zoomTrans); + property->SetDisplayZoomState(parcel.ReadBool()); + AbilityInfo info = { parcel.ReadString(), parcel.ReadString(), parcel.ReadInt32() }; + property->SetAbilityInfo(info); + return property; +} + +bool WindowProperty::Write(Parcel& parcel, PropertyChangeAction action) +{ + bool ret = parcel.WriteUint32(static_cast(windowId_)); + switch (action) { + case PropertyChangeAction::ACTION_UPDATE_RECT: + ret = ret && parcel.WriteBool(decoStatus_) && parcel.WriteUint32(static_cast(dragType_)) && + parcel.WriteInt32(originRect_.posX_) && parcel.WriteInt32(originRect_.posY_) && + parcel.WriteUint32(originRect_.width_) && parcel.WriteUint32(originRect_.height_) && + parcel.WriteInt32(requestRect_.posX_) && parcel.WriteInt32(requestRect_.posY_) && + parcel.WriteUint32(requestRect_.width_) && parcel.WriteUint32(requestRect_.height_) && + parcel.WriteUint32(static_cast(windowSizeChangeReason_)); + break; + case PropertyChangeAction::ACTION_UPDATE_MODE: + ret = ret && parcel.WriteUint32(static_cast(mode_)); + break; + case PropertyChangeAction::ACTION_UPDATE_FLAGS: + ret = ret && parcel.WriteUint32(flags_); + break; + case PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS: + ret = ret && MapMarshalling(parcel); + break; + case PropertyChangeAction::ACTION_UPDATE_FOCUSABLE: + ret = ret && parcel.WriteBool(focusable_); + break; + case PropertyChangeAction::ACTION_UPDATE_TOUCHABLE: + ret = ret && parcel.WriteBool(touchable_); + break; + case PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW: + ret = ret && parcel.WriteUint32(callingWindow_); + break; + case PropertyChangeAction::ACTION_UPDATE_ORIENTATION: + ret = ret && parcel.WriteUint32(static_cast(requestedOrientation_)); + break; + case PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON: + ret = ret && parcel.WriteBool(turnScreenOn_); + break; + case PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON: + ret = ret && parcel.WriteBool(keepScreenOn_); + break; + case PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS: + ret = ret && parcel.WriteFloat(brightness_); + break; + case PropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO: + ret = ret && parcel.WriteUint32(modeSupportInfo_); + break; + case PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA: + ret = ret && MarshallingTouchHotAreas(parcel); + break; + case PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY: + ret = ret && MarshallingTransform(parcel); + break; + case PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG: + ret = ret && parcel.WriteUint32(animationFlag_); + break; + case PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE: + ret = ret && parcel.WriteBool(isPrivacyMode_); + break; + default: + break; + } + return ret; +} + +void WindowProperty::Read(Parcel& parcel, PropertyChangeAction action) +{ + SetWindowId(parcel.ReadUint32()); + switch (action) { + case PropertyChangeAction::ACTION_UPDATE_RECT: + SetDecoStatus(parcel.ReadBool()); + SetDragType(static_cast(parcel.ReadUint32())); + SetOriginRect(Rect { parcel.ReadInt32(), parcel.ReadInt32(), parcel.ReadUint32(), parcel.ReadUint32() }); + SetRequestRect(Rect { parcel.ReadInt32(), parcel.ReadInt32(), parcel.ReadUint32(), parcel.ReadUint32() }); + SetWindowSizeChangeReason(static_cast(parcel.ReadUint32())); + break; + case PropertyChangeAction::ACTION_UPDATE_MODE: + SetWindowMode(static_cast(parcel.ReadUint32())); + break; + case PropertyChangeAction::ACTION_UPDATE_FLAGS: + SetWindowFlags(parcel.ReadUint32()); + break; + case PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS: + MapUnmarshalling(parcel, this); + break; + case PropertyChangeAction::ACTION_UPDATE_FOCUSABLE: + SetFocusable(parcel.ReadBool()); + break; + case PropertyChangeAction::ACTION_UPDATE_TOUCHABLE: + SetTouchable(parcel.ReadBool()); + break; + case PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW: + SetCallingWindow(parcel.ReadUint32()); + break; + case PropertyChangeAction::ACTION_UPDATE_ORIENTATION: + SetRequestedOrientation(static_cast(parcel.ReadUint32())); + break; + case PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON: + SetTurnScreenOn(parcel.ReadBool()); + break; + case PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON: + SetKeepScreenOn(parcel.ReadBool()); + break; + case PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS: + SetBrightness(parcel.ReadFloat()); + break; + case PropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO: + SetModeSupportInfo(parcel.ReadUint32()); + break; + case PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA: + UnmarshallingTouchHotAreas(parcel, this); + break; + case PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY: + UnmarshallingTransform(parcel, this); + break; + case PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG: { + SetAnimationFlag(parcel.ReadUint32()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE: + SetPrivacyMode(parcel.ReadBool()); + break; + default: + break; + } +} + +void WindowProperty::CopyFrom(const sptr& property) +{ + windowName_ = property->windowName_; + windowRect_ = property->windowRect_; + requestRect_ = property->requestRect_; + decoStatus_ = property->decoStatus_; + type_ = property->type_; + mode_ = property->mode_; + lastMode_ = property->lastMode_; + flags_ = property->flags_; + isFullScreen_ = property->isFullScreen_; + focusable_ = property->focusable_; + touchable_ = property->touchable_; + isPrivacyMode_ = property->isPrivacyMode_; + isTransparent_ = property->isTransparent_; + alpha_ = property->alpha_; + brightness_ = property->brightness_; + displayId_ = property->displayId_; + windowId_ = property->windowId_; + parentId_ = property->parentId_; + hitOffset_ = property->hitOffset_; + animationFlag_ = property->animationFlag_; + windowSizeChangeReason_ = property->windowSizeChangeReason_; + sysBarPropMap_ = property->sysBarPropMap_; + isDecorEnable_ = property->isDecorEnable_; + tokenState_ = property->tokenState_; + callingWindow_ = property->callingWindow_; + requestedOrientation_ = property->requestedOrientation_; + turnScreenOn_ = property->turnScreenOn_; + keepScreenOn_ = property->keepScreenOn_; + modeSupportInfo_ = property->modeSupportInfo_; + requestModeSupportInfo_ = property->requestModeSupportInfo_; + dragType_ = property->dragType_; + originRect_ = property->originRect_; + isStretchable_ = property->isStretchable_; + touchHotAreas_ = property->touchHotAreas_; + accessTokenId_ = property->accessTokenId_; + trans_ = property->trans_; + sizeLimits_ = property->sizeLimits_; + zoomTrans_ = property->zoomTrans_; + isDisplayZoomOn_ = property->isDisplayZoomOn_; + reCalcuZoomTransformMat_ = true; + abilityInfo_ = property->abilityInfo_; +} +} +} diff --git a/window_manager/utils/src/window_transition_info.cpp b/window_manager/utils/src/window_transition_info.cpp new file mode 100644 index 0000000..0de4ad5 --- /dev/null +++ b/window_manager/utils/src/window_transition_info.cpp @@ -0,0 +1,250 @@ +/* + * 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 "window_transition_info.h" + +namespace OHOS { +namespace Rosen { +WindowTransitionInfo::WindowTransitionInfo(sptr info) +{ + bundleName_ = info->bundleName_; + abilityName_ = info->abilityName_; + mode_ = static_cast(info->mode_); + abilityToken_ = info->abilityToken_; + displayId_ = info->displayId_; + isShowWhenLocked_ = info->isShowWhenLocked_; + isRecent_ = info->isRecent_; + missionId_ = info->missionId_; + if (info->windowModes_.empty()) { + supportWindowModes_ = { + AppExecFwk::SupportWindowMode::FULLSCREEN, + AppExecFwk::SupportWindowMode::SPLIT, + AppExecFwk::SupportWindowMode::FLOATING + }; + } else { + supportWindowModes_.assign(info->windowModes_.begin(), info->windowModes_.end()); + } + + sizeLimits_.maxRatio_ = static_cast(info->maxWindowRatio_); + sizeLimits_.minRatio_ = static_cast(info->minWindowRatio_); + sizeLimits_.maxWidth_ = info->maxWindowWidth_; + sizeLimits_.minWidth_ = info->minWindowWidth_; + sizeLimits_.maxHeight_ = info->maxWindowHeight_; + sizeLimits_.minHeight_ = info->minWindowHeight_; + reason_ = static_cast(info->reason_); +} + +void WindowTransitionInfo::SetBundleName(std::string name) +{ + bundleName_ = name; +} + +std::string WindowTransitionInfo::GetBundleName() +{ + return bundleName_; +} + +void WindowTransitionInfo::SetAbilityName(std::string name) +{ + abilityName_ = name; +} + +std::string WindowTransitionInfo::GetAbilityName() +{ + return abilityName_; +} + +void WindowTransitionInfo::SetWindowMode(WindowMode mode) +{ + mode_ = mode; +} + +WindowMode WindowTransitionInfo::GetWindowMode() +{ + return mode_; +} + +void WindowTransitionInfo::SetWindowRect(Rect rect) +{ + windowRect_ = rect; +} + +Rect WindowTransitionInfo::GetWindowRect() +{ + return windowRect_; +} + +void WindowTransitionInfo::SetAbilityToken(sptr abilityToken) +{ + abilityToken_ = abilityToken; +} + +sptr WindowTransitionInfo::GetAbilityToken() +{ + return abilityToken_; +} + +void WindowTransitionInfo::SetDisplayId(DisplayId displayId) +{ + displayId_ = displayId; +} + +DisplayId WindowTransitionInfo::GetDisplayId() +{ + return displayId_; +} + +void WindowTransitionInfo::SetWindowType(WindowType windowType) +{ + windowType_ = windowType; +} + +WindowType WindowTransitionInfo::GetWindowType() +{ + return windowType_; +} + +void WindowTransitionInfo::SetShowFlagWhenLocked(bool isShow) +{ + isShowWhenLocked_ = isShow; +} + +void WindowTransitionInfo::SetWindowSupportModes(const std::vector supportModes) +{ + supportWindowModes_.assign(supportModes.begin(), supportModes.end()); +} + +std::vector WindowTransitionInfo::GetWindowSupportModes() +{ + return supportWindowModes_; +} + +WindowSizeLimits WindowTransitionInfo::GetWindowSizeLimits() const +{ + return sizeLimits_; +} + +bool WindowTransitionInfo::GetShowFlagWhenLocked() +{ + return isShowWhenLocked_; +} + +void WindowTransitionInfo::SetTransitionReason(TransitionReason reason) +{ + reason_ = reason; +} + +TransitionReason WindowTransitionInfo::GetTransitionReason() +{ + return reason_; +} + +void WindowTransitionInfo::SetIsRecent(bool isRecent) +{ + isRecent_ = isRecent; +} + +bool WindowTransitionInfo::GetIsRecent() const +{ + return isRecent_; +} + +void WindowTransitionInfo::SetMissionId(int32_t missionId) +{ + missionId_ = missionId; +} + +int32_t WindowTransitionInfo::GetMissionId() const +{ + return missionId_; +} + +bool WindowTransitionInfo::Marshalling(Parcel& parcel) const +{ + if (!parcel.WriteString(bundleName_) || !parcel.WriteString(abilityName_)) { + return false; + } + + if (!parcel.WriteUint32(static_cast(mode_))) { + return false; + } + + if (!(parcel.WriteInt32(windowRect_.posX_) && parcel.WriteInt32(windowRect_.posY_) && + parcel.WriteUint32(windowRect_.width_) && parcel.WriteUint32(windowRect_.height_))) { + return false; + } + + if (!abilityToken_) { + if (!parcel.WriteBool(false)) { + return false; + } + } else { + if (!parcel.WriteBool(true) || !parcel.WriteObject(abilityToken_)) { + return false; + } + } + + if (!parcel.WriteUint64(displayId_)) { + return false; + } + + if (!parcel.WriteUint32(static_cast(windowType_))) { + return false; + } + + if (!parcel.WriteBool(isShowWhenLocked_)) { + return false; + } + + if (!parcel.WriteBool(isRecent_)) { + return false; + } + + if (!parcel.WriteUint32(static_cast(reason_))) { + return false; + } + + if (!parcel.WriteInt32(missionId_)) { + return false; + } + return true; +} + +WindowTransitionInfo* WindowTransitionInfo::Unmarshalling(Parcel& parcel) +{ + auto windowTransitionInfo = new(std::nothrow) WindowTransitionInfo(); + if (windowTransitionInfo == nullptr) { + return nullptr; + } + windowTransitionInfo->bundleName_ = parcel.ReadString(); + windowTransitionInfo->abilityName_ = parcel.ReadString(); + windowTransitionInfo->mode_ = static_cast(parcel.ReadUint32()); + windowTransitionInfo->windowRect_.posX_ = parcel.ReadInt32(); + windowTransitionInfo->windowRect_.posY_ = parcel.ReadInt32(); + windowTransitionInfo->windowRect_.width_ = parcel.ReadUint32(); + windowTransitionInfo->windowRect_.height_ = parcel.ReadUint32(); + if (parcel.ReadBool()) { + windowTransitionInfo->abilityToken_ = parcel.ReadObject(); + } + windowTransitionInfo->displayId_ = parcel.ReadUint64(); + windowTransitionInfo->windowType_ = static_cast(parcel.ReadUint32()); + windowTransitionInfo->isShowWhenLocked_ = parcel.ReadBool(); + windowTransitionInfo->isRecent_ = parcel.ReadBool(); + windowTransitionInfo->reason_ = static_cast(parcel.ReadUint32()); + windowTransitionInfo->missionId_ = parcel.ReadInt32(); + return windowTransitionInfo; +} +} // Rosen +} // OHOS diff --git a/window_manager/utils/src/wm_math.cpp b/window_manager/utils/src/wm_math.cpp new file mode 100644 index 0000000..878c3b0 --- /dev/null +++ b/window_manager/utils/src/wm_math.cpp @@ -0,0 +1,360 @@ +/* + * 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 "wm_math.h" +#include + +namespace OHOS::Rosen { +namespace TransformHelper { +const Matrix3 Matrix3::Identity = { { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, +} }; +const Matrix4 Matrix4::Identity = { { + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 }, +} }; + +Matrix3 operator*(const Matrix3& left, const Matrix3& right) +{ + return { { + // row 0 + { left.mat_[0][0] * right.mat_[0][0] + left.mat_[0][1] * right.mat_[1][0] + left.mat_[0][2] * right.mat_[2][0], + left.mat_[0][0] * right.mat_[0][1] + left.mat_[0][1] * right.mat_[1][1] + left.mat_[0][2] * right.mat_[2][1], + left.mat_[0][0] * right.mat_[0][2] + left.mat_[0][1] * right.mat_[1][2] + left.mat_[0][2] * right.mat_[2][2] }, + + // row 1 + { left.mat_[1][0] * right.mat_[0][0] + left.mat_[1][1] * right.mat_[1][0] + left.mat_[1][2] * right.mat_[2][0], + left.mat_[1][0] * right.mat_[0][1] + left.mat_[1][1] * right.mat_[1][1] + left.mat_[1][2] * right.mat_[2][1], + left.mat_[1][0] * right.mat_[0][2] + left.mat_[1][1] * right.mat_[1][2] + left.mat_[1][2] * right.mat_[2][2] }, + + // row 2 + { left.mat_[2][0] * right.mat_[0][0] + left.mat_[2][1] * right.mat_[1][0] + left.mat_[2][2] * right.mat_[2][0], + left.mat_[2][0] * right.mat_[0][1] + left.mat_[2][1] * right.mat_[1][1] + left.mat_[2][2] * right.mat_[2][1], + left.mat_[2][0] * right.mat_[0][2] + left.mat_[2][1] * right.mat_[1][2] + left.mat_[2][2] * right.mat_[2][2] } + } }; +} + +Matrix3& Matrix3::operator*=(const Matrix3& right) +{ + *this = *this * right; + return *this; +} + +Matrix4 operator*(const Matrix4& left, const Matrix4& right) +{ + return { { + // row 0 + { left.mat_[0][0] * right.mat_[0][0] + left.mat_[0][1] * right.mat_[1][0] + + left.mat_[0][2] * right.mat_[2][0] + left.mat_[0][3] * right.mat_[3][0], + left.mat_[0][0] * right.mat_[0][1] + left.mat_[0][1] * right.mat_[1][1] + + left.mat_[0][2] * right.mat_[2][1] + left.mat_[0][3] * right.mat_[3][1], + left.mat_[0][0] * right.mat_[0][2] + left.mat_[0][1] * right.mat_[1][2] + + left.mat_[0][2] * right.mat_[2][2] + left.mat_[0][3] * right.mat_[3][2], + left.mat_[0][0] * right.mat_[0][3] + left.mat_[0][1] * right.mat_[1][3] + + left.mat_[0][2] * right.mat_[2][3] + left.mat_[0][3] * right.mat_[3][3] }, + + // row 1 + { left.mat_[1][0] * right.mat_[0][0] + left.mat_[1][1] * right.mat_[1][0] + + left.mat_[1][2] * right.mat_[2][0] + left.mat_[1][3] * right.mat_[3][0], + left.mat_[1][0] * right.mat_[0][1] + left.mat_[1][1] * right.mat_[1][1] + + left.mat_[1][2] * right.mat_[2][1] + left.mat_[1][3] * right.mat_[3][1], + left.mat_[1][0] * right.mat_[0][2] + left.mat_[1][1] * right.mat_[1][2] + + left.mat_[1][2] * right.mat_[2][2] + left.mat_[1][3] * right.mat_[3][2], + left.mat_[1][0] * right.mat_[0][3] + left.mat_[1][1] * right.mat_[1][3] + + left.mat_[1][2] * right.mat_[2][3] + left.mat_[1][3] * right.mat_[3][3] }, + + // row 2 + { left.mat_[2][0] * right.mat_[0][0] + left.mat_[2][1] * right.mat_[1][0] + + left.mat_[2][2] * right.mat_[2][0] + left.mat_[2][3] * right.mat_[3][0], + left.mat_[2][0] * right.mat_[0][1] + left.mat_[2][1] * right.mat_[1][1] + + left.mat_[2][2] * right.mat_[2][1] + left.mat_[2][3] * right.mat_[3][1], + left.mat_[2][0] * right.mat_[0][2] + left.mat_[2][1] * right.mat_[1][2] + + left.mat_[2][2] * right.mat_[2][2] + left.mat_[2][3] * right.mat_[3][2], + left.mat_[2][0] * right.mat_[0][3] + left.mat_[2][1] * right.mat_[1][3] + + left.mat_[2][2] * right.mat_[2][3] + left.mat_[2][3] * right.mat_[3][3] }, + + // row 3 + { left.mat_[3][0] * right.mat_[0][0] + left.mat_[3][1] * right.mat_[1][0] + + left.mat_[3][2] * right.mat_[2][0] + left.mat_[3][3] * right.mat_[3][0], + left.mat_[3][0] * right.mat_[0][1] + left.mat_[3][1] * right.mat_[1][1] + + left.mat_[3][2] * right.mat_[2][1] + left.mat_[3][3] * right.mat_[3][1], + left.mat_[3][0] * right.mat_[0][2] + left.mat_[3][1] * right.mat_[1][2] + + left.mat_[3][2] * right.mat_[2][2] + left.mat_[3][3] * right.mat_[3][2], + left.mat_[3][0] * right.mat_[0][3] + left.mat_[3][1] * right.mat_[1][3] + + left.mat_[3][2] * right.mat_[2][3] + left.mat_[3][3] * right.mat_[3][3] } + } }; +} + +Matrix4& Matrix4::operator*=(const Matrix4& right) +{ + *this = *this * right; + return *this; +} + +void Matrix4::SwapRow(int row1, int row2) +{ + float *p = mat_[row1]; + float *q = mat_[row2]; + float tmp = p[0]; + p[0] = q[0]; + q[0] = tmp; + + tmp = p[1]; + p[1] = q[1]; + q[1] = tmp; + + tmp = p[2]; + p[2] = q[2]; + q[2] = tmp; + + tmp = p[3]; + p[3] = q[3]; + q[3] = tmp; +} + +void Matrix4::Invert() +{ + // Inverse matrix with Gauss-Jordan method + Matrix4 tmp = Matrix4::Identity; + int i, j, k; + for (k = 0; k < MAT_SIZE; k++) { + float t = mat_[k][k]; + if (t < MathHelper::POS_ZERO && t > MathHelper::NAG_ZERO) { + for (i = k + 1; i < MAT_SIZE; i++) { + if (mat_[i][k] < MathHelper::NAG_ZERO || mat_[i][k] > MathHelper::POS_ZERO) { + SwapRow(k, i); + tmp.SwapRow(k, i); + break; + } + } + t = mat_[k][k]; + } + for (j = 0; j <= k; j++) { + tmp.mat_[k][j] /= t; + } + for (; j < MAT_SIZE; j++) { + mat_[k][j] /= t; + tmp.mat_[k][j] /= t; + } + for (i = 0; i < MAT_SIZE; i++) { + if (i == k) { + continue; + } + float u = mat_[i][k]; + for (j = 0; j <= k; j++) { + tmp.mat_[i][j] -= tmp.mat_[k][j] * u; + } + for (; j < MAT_SIZE; j++) { + mat_[i][j] -= mat_[k][j] * u; + tmp.mat_[i][j] -= tmp.mat_[k][j] * u; + } + } + } + *this = tmp; +} + +Vector3 Matrix4::GetScale() const +{ + Vector3 retVal; + retVal.x_ = Vector3(mat_[0][0], mat_[0][1], mat_[0][2]).Length(); + retVal.y_ = Vector3(mat_[1][0], mat_[1][1], mat_[1][2]).Length(); + retVal.z_ = Vector3(mat_[2][0], mat_[2][1], mat_[2][2]).Length(); + return retVal; +} + +Vector3 Matrix4::GetTranslation() const +{ + return Vector3(mat_[3][0], mat_[3][1], mat_[3][2]); +} + +// Create a scale matrix with x and y scales +Matrix3 CreateScale(float xScale, float yScale) +{ + return { { + { xScale, 0.0f, 0.0f }, + { 0.0f, yScale, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + } }; +} + +// Create a rotation matrix about the Z axis +// theta is in radians +Matrix3 CreateRotation(float theta) +{ + return { { + { std::cos(theta), std::sin(theta), 0.0f }, + { -std::sin(theta), std::cos(theta), 0.0f }, + { 0.0f, 0.0f, 1.0f }, + } }; +} + +// Create a translation matrix (on the xy-plane) +Matrix3 CreateTranslation(const Vector2& trans) +{ + return { { + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { trans.x_, trans.y_, 1.0f }, + } }; +} + +// Create a scale matrix with x, y, and z scales +Matrix4 CreateScale(float xScale, float yScale, float zScale) +{ + return { { + { xScale, 0.0f, 0.0f, 0.0f }, + { 0.0f, yScale, 0.0f, 0.0f }, + { 0.0f, 0.0f, zScale, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + } }; +} + +// Create a rotation matrix about X axis +// theta is in radians +Matrix4 CreateRotationX(float theta) +{ + return { { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, std::cos(theta), std::sin(theta), 0.0f }, + { 0.0f, -std::sin(theta), std::cos(theta), 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + } }; +} + +// Create a rotation matrix about Y axis +// theta is in radians +Matrix4 CreateRotationY(float theta) +{ + return { { + { std::cos(theta), 0.0f, -std::sin(theta), 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { std::sin(theta), 0.0f, std::cos(theta), 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + } }; +} + +// Create a rotation matrix about Z axis +// theta is in radians +Matrix4 CreateRotationZ(float theta) +{ + return { { + { std::cos(theta), std::sin(theta), 0.0f, 0.0f }, + { -std::sin(theta), std::cos(theta), 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, + } }; +} + +// Create a 3D translation matrix +Matrix4 CreateTranslation(const Vector3& trans) +{ + return { { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { trans.x_, trans.y_, trans.z_, 1.0f }, + } }; +} + +Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up) +{ + Vector3 zaxis = Vector3::Normalize(target - eye); + Vector3 xaxis = Vector3::Normalize(Vector3::Cross(up, zaxis)); + Vector3 yaxis = Vector3::Normalize(Vector3::Cross(zaxis, xaxis)); + Vector3 trans; + trans.x_ = -Vector3::Dot(xaxis, eye); + trans.y_ = -Vector3::Dot(yaxis, eye); + trans.z_ = -Vector3::Dot(zaxis, eye); + + return { { + { xaxis.x_, yaxis.x_, zaxis.x_, 0.0f }, + { xaxis.y_, yaxis.y_, zaxis.y_, 0.0f }, + { xaxis.z_, yaxis.z_, zaxis.z_, 0.0f }, + { trans.x_, trans.y_, trans.z_, 1.0f } + } }; +} + +Matrix4 CreatePerspective(const Vector3& camera) +{ + return { { + { std::abs(camera.z_), 0.0f, 0.0f, 0.0f }, + { 0.0f, std::abs(camera.z_), 0.0f, 0.0f }, + { camera.x_, camera.y_, 0.0f, 1.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + } }; +} + +// Transform a Vector2 in xy-plane by matrix3 +Vector2 Transform(const Vector2& vec, const Matrix3& mat) +{ + Vector2 retVal; + retVal.x_ = vec.x_ * mat.mat_[0][0] + vec.y_ * mat.mat_[1][0] + mat.mat_[2][0]; + retVal.y_ = vec.x_ * mat.mat_[0][1] + vec.y_ * mat.mat_[1][1] + mat.mat_[2][1]; + return retVal; +} + +// Transform a Vector3 in 3D world by matrix4 +Vector3 Transform(const Vector3& vec, const Matrix4& mat) +{ + Vector3 retVal; + retVal.x_ = vec.x_ * mat.mat_[0][0] + vec.y_ * mat.mat_[1][0] + + vec.z_ * mat.mat_[2][0] + mat.mat_[3][0]; // 2: row2, 3: row3 + retVal.y_ = vec.x_ * mat.mat_[0][1] + vec.y_ * mat.mat_[1][1] + + vec.z_ * mat.mat_[2][1] + mat.mat_[3][1]; + retVal.z_ = vec.x_ * mat.mat_[0][2] + vec.y_ * mat.mat_[1][2] + + vec.z_ * mat.mat_[2][2] + mat.mat_[3][2]; + return retVal; +} + +// Transform the vector and renormalize the w component +Vector3 TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w) +{ + Vector3 retVal; + retVal.x_ = vec.x_ * mat.mat_[0][0] + vec.y_ * mat.mat_[1][0] + + vec.z_ * mat.mat_[2][0] + w * mat.mat_[3][0]; // 2: row2, 3: row3 + retVal.y_ = vec.x_ * mat.mat_[0][1] + vec.y_ * mat.mat_[1][1] + + vec.z_ * mat.mat_[2][1] + w * mat.mat_[3][1]; // 2: row2, 3: row3 + retVal.z_ = vec.x_ * mat.mat_[0][2] + vec.y_ * mat.mat_[1][2] + + vec.z_ * mat.mat_[2][2] + w * mat.mat_[3][2]; // 2: row2, 3: row3 + float transformedW = vec.x_ * mat.mat_[0][3] + vec.y_ * mat.mat_[1][3] + + vec.z_ * mat.mat_[2][3] + w * mat.mat_[3][3]; // 2: row2, 3: row3 + if (!MathHelper::NearZero(transformedW)) { + transformedW = 1.0f / transformedW; + retVal *= transformedW; + } + return retVal; +} + +// Given a screen point, unprojects it into origin position at screen, +// based on the current transform matrix +Vector2 GetOriginScreenPoint(const Vector2& p, const Matrix4& mat) +{ + Matrix4 invertMat = mat; + invertMat.Invert(); + // Get start point + Vector3 screenPoint(p.x_, p.y_, 0.1f); + Vector3 start = TransformWithPerspDiv(screenPoint, invertMat); + // Get end point + screenPoint.z_ = 0.9f; + Vector3 end = TransformWithPerspDiv(screenPoint, invertMat); + // Get the intersection point of line start-end and xy plane + float t = end.z_ / (end.z_ - start.z_); + return Vector2(t * start.x_ + (1 - t) * end.x_, t * start.y_ + (1 - t) * end.y_); +} +} // namespace TransformHelper +} // namespace OHOS::Rosen diff --git a/window_manager/utils/src/wm_occlusion_region.cpp b/window_manager/utils/src/wm_occlusion_region.cpp new file mode 100644 index 0000000..068d50b --- /dev/null +++ b/window_manager/utils/src/wm_occlusion_region.cpp @@ -0,0 +1,324 @@ +/* + * 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 "wm_occlusion_region.h" + +#include +#include + +namespace OHOS::Rosen::WmOcclusion { +static Rect _s_empty_rect_ { 0, 0, 0, 0 }; +static Rect _s_invalid_rect_ { 0, 0, -1, -1 }; +bool Region::_s_so_loaded_ = false; + +std::ostream& operator<<(std::ostream& os, const Rect& r) +{ + os << "{" << r.left_ << "," << r.top_ << "," << r.right_ << "," << r.bottom_ << "}"; + return os; +} + +bool EventSortByY(const Event& e1, const Event& e2) +{ + if (e1.y_ == e2.y_) { + return e1.type_ < e2.type_; + } + return e1.y_ < e2.y_; +} + +void Node::Update(int updateStart, int updateEnd, Event::Type type) +{ + if (updateStart >= updateEnd) { + return; + } + if (updateStart == start_ && updateEnd == end_) { + if (type == Event::Type::OPEN || type == Event::Type::CLOSE) { + positive_count_ += type; + } else { + negative_count_ += type; + } + } else { + if (left_ == nullptr) { + left_ = new Node { start_, mid_ }; + } + if (right_ == nullptr) { + right_ = new Node { mid_, end_ }; + } + left_->Update(updateStart, mid_ < updateEnd ? mid_ : updateEnd, type); + right_->Update(mid_ > updateStart ? mid_ : updateStart, updateEnd, type); + } +} + +void Node::GetAndRange(std::vector& res, bool isParentNodePos = false, bool isParentNodeNeg = false) +{ + bool isPos = isParentNodePos || (positive_count_ > 0); + bool isNeg = isParentNodeNeg || (negative_count_ > 0); + if (isPos && isNeg) { + PushRange(res); + } else { + if (left_ != nullptr) { + left_->GetAndRange(res, isPos, isNeg); + } + if (right_ != nullptr) { + right_->GetAndRange(res, isPos, isNeg); + } + } +} + +void Node::GetOrRange(std::vector& res, bool isParentNodePos = false, bool isParentNodeNeg = false) +{ + bool isPos = isParentNodePos || (positive_count_ > 0); + bool isNeg = isParentNodeNeg || (negative_count_ > 0); + if (isPos || isNeg) { + PushRange(res); + } else { + if (left_ != nullptr) { + left_->GetOrRange(res, isPos, isNeg); + } + if (right_ != nullptr) { + right_->GetOrRange(res, isPos, isNeg); + } + } +} + +void Node::GetXOrRange(std::vector& res, bool isParentNodePos = false, bool isParentNodeNeg = false) +{ + bool isPos = isParentNodePos || (positive_count_ > 0); + bool isNeg = isParentNodeNeg || (negative_count_ > 0); + if (((isPos && !isNeg) || (!isPos && isNeg)) && IsLeaf()) { + PushRange(res); + } else if (isPos && isNeg) { + return; + } else { + if (left_ != nullptr) { + left_->GetXOrRange(res, isPos, isNeg); + } + if (right_ != nullptr) { + right_->GetXOrRange(res, isPos, isNeg); + } + } +} + +void Node::GetSubRange(std::vector& res, bool isParentNodePos = false, bool isParentNodeNeg = false) +{ + bool isPos = isParentNodePos || (positive_count_ > 0); + bool isNeg = isParentNodeNeg || (negative_count_ > 0); + if (IsLeaf() && isPos && !isNeg) { + PushRange(res); + } else if (isNeg) { + return; + } else { + if (left_ != nullptr) { + left_->GetSubRange(res, isPos, isNeg); + } + if (right_ != nullptr) { + right_->GetSubRange(res, isPos, isNeg); + } + } +} + +void MakeEnumerate(std::set& ys, std::map& indexOf, std::vector& indexAt) +{ + auto it = ys.begin(); + int index = 0; + while (it != ys.end()) { + indexOf[*it] = index++; + indexAt.push_back(*it); + ++it; + } + return; +} + +void Region::getRange(std::vector& ranges, Node& node, Region::OP op) +{ + switch (op) { + case Region::OP::AND: + node.GetAndRange(ranges); + break; + case Region::OP::OR: + node.GetOrRange(ranges); + break; + case Region::OP::XOR: + node.GetXOrRange(ranges); + break; + case Region::OP::SUB: + node.GetSubRange(ranges); + break; + default: + break; + } + return; +} + +void Region::UpdateRects(Rects& r, std::vector& ranges, std::vector& indexAt, Region& res) +{ + uint32_t i = 0; + uint32_t j = 0; + while (i < r.preRects.size() && j < ranges.size()) { + if (r.preRects[i].left_ == indexAt[ranges[j].start_] && r.preRects[i].right_ == indexAt[ranges[j].end_]) { + r.curRects.emplace_back(Rect { r.preRects[i].left_, r.preRects[i].top_, r.preRects[i].right_, r.curY }); + i++; + j++; + } else if (r.preRects[i].right_ < indexAt[ranges[j].end_]) { + res.GetRegionRects().push_back(r.preRects[i]); + i++; + } else { + r.curRects.emplace_back(Rect { indexAt[ranges[j].start_], r.preY, indexAt[ranges[j].end_], r.curY }); + j++; + } + } + for (; j < ranges.size(); j++) { + r.curRects.emplace_back(Rect { indexAt[ranges[j].start_], r.preY, indexAt[ranges[j].end_], r.curY }); + } + for (; i < r.preRects.size(); i++) { + res.GetRegionRects().push_back(r.preRects[i]); + } + r.preRects.clear(); + r.preRects.swap(r.curRects); + return; +} + +void Region::MakeBound() +{ + if (rects_.size()) { + bound_ = rects_[0]; + for (const auto& r : rects_) { + bound_.left_ = std::min(r.left_, bound_.left_); + bound_.top_ = std::min(r.top_, bound_.top_); + bound_.right_ = std::max(r.right_, bound_.right_); + bound_.bottom_ = std::max(r.bottom_, bound_.bottom_); + } + } +} + +void Region::RegionOp(Region& r1, Region& r2, Region& res, Region::OP op) +{ + RegionOpLocal(r1, r2, res, op); +} + +void Region::RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op) +{ + r1.MakeBound(); + r2.MakeBound(); + res.GetRegionRects().clear(); + std::vector events; + std::set xs; + + for (auto& r : r1.GetRegionRects()) { + events.emplace_back(Event { r.top_, Event::Type::OPEN, r.left_, r.right_ }); + events.emplace_back(Event { r.bottom_, Event::Type::CLOSE, r.left_, r.right_ }); + xs.insert(r.left_); + xs.insert(r.right_); + } + for (auto& r : r2.GetRegionRects()) { + events.emplace_back(Event { r.top_, Event::Type::VOID_OPEN, r.left_, r.right_ }); + events.emplace_back(Event { r.bottom_, Event::Type::VOID_CLOSE, r.left_, r.right_ }); + xs.insert(r.left_); + xs.insert(r.right_); + } + + if (events.size() == 0) { + return; + } + + std::map indexOf; + std::vector indexAt; + MakeEnumerate(xs, indexOf, indexAt); + sort(events.begin(), events.end(), EventSortByY); + + Node rootNode { 0, static_cast(indexOf.size() - 1) }; + + std::vector ranges; + Rects r; + r.preY = events[0].y_; + r.curY = events[0].y_; + for (auto& e : events) { + r.curY = e.y_; + ranges.clear(); + getRange(ranges, rootNode, op); + if (r.curY > r.preY) { + UpdateRects(r, ranges, indexAt, res); + } + rootNode.Update(indexOf[e.left_], indexOf[e.right_], e.type_); + r.preY = r.curY; + } + copy(r.preRects.begin(), r.preRects.end(), back_inserter(res.GetRegionRects())); + res.MakeBound(); +} + +Region& Region::OperationSelf(Region& r, Region::OP op) +{ + Region r1(*this); + RegionOp(r1, r, *this, op); + return *this; +} + +Region& Region::AndSelf(Region& r) +{ + return OperationSelf(r, Region::OP::AND); +} + +Region& Region::OrSelf(Region& r) +{ + return OperationSelf(r, Region::OP::OR); +} + +Region& Region::XOrSelf(Region& r) +{ + return OperationSelf(r, Region::OP::XOR); +} + +Region& Region::SubSelf(Region& r) +{ + return OperationSelf(r, Region::OP::SUB); +} + +Region Region::And(Region& r) +{ + Region res; + RegionOp(*this, r, res, Region::OP::AND); + return res; +} + +Region Region::Or(Region& r) +{ + Region res; + RegionOp(*this, r, res, Region::OP::OR); + return res; +} + +Region Region::Xor(Region& r) +{ + Region res; + RegionOp(*this, r, res, Region::OP::XOR); + return res; +} + +Region Region::Sub(Region& r) +{ + Region res; + RegionOp(*this, r, res, Region::OP::SUB); + return res; +} + +std::ostream& operator<<(std::ostream& os, const Region& r) +{ + os << "{"; + os << r.GetSize() << ": "; + for (const Rect& rect : r.GetRegionRects()) { + os << rect; + } + os << "}" << std::endl; + return os; +} +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/src/xml_config_base.cpp b/window_manager/utils/src/xml_config_base.cpp new file mode 100644 index 0000000..ac9bd9f --- /dev/null +++ b/window_manager/utils/src/xml_config_base.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "xml_config_base.h" + +namespace OHOS { +namespace Rosen { +std::recursive_mutex XmlConfigBase::mutex_; +const XmlConfigBase::ConfigItem XmlConfigBase::ConfigItem::DEFAULT; +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/BUILD.gn b/window_manager/utils/test/BUILD.gn new file mode 100644 index 0000000..a29ddb1 --- /dev/null +++ b/window_manager/utils/test/BUILD.gn @@ -0,0 +1,17 @@ +# 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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/utils/test/unittest/BUILD.gn b/window_manager/utils/test/unittest/BUILD.gn new file mode 100644 index 0000000..fbcaf19 --- /dev/null +++ b/window_manager/utils/test/unittest/BUILD.gn @@ -0,0 +1,210 @@ +# 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. + +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") +module_out_path = "window_manager/utils" + +group("unittest") { + testonly = true + + deps = [ + ":utils_all_test", + ":utils_cutout_info_test", + ":utils_display_info_test", + ":utils_perform_reporter_test", + ":utils_screen_group_info_test", + ":utils_screen_info_test", + ":utils_string_test", + ":utils_window_helper_test", + ":utils_window_property_test", + ":utils_window_transition_info_test", + ":utils_wm_math_test", + ":utils_wm_occlusion_region_test", + ] +} + +ohos_unittest("utils_display_info_test") { + module_out_path = module_out_path + + sources = [ "display_info_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_screen_info_test") { + module_out_path = module_out_path + + sources = [ "screen_info_test.cpp" ] + + deps = [ ":utils_unittest_common" ] + + external_deps = [ "graphic_standard:surface" ] +} + +ohos_unittest("utils_screen_group_info_test") { + module_out_path = module_out_path + + sources = [ "screen_group_info_test.cpp" ] + + deps = [ ":utils_unittest_common" ] + + external_deps = [ "graphic_standard:surface" ] +} + +ohos_unittest("utils_string_test") { + module_out_path = module_out_path + + sources = [ "string_util_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_window_property_test") { + module_out_path = module_out_path + + sources = [ "window_property_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_wm_math_test") { + module_out_path = module_out_path + + sources = [ "wm_math_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_surface_draw_test") { + module_out_path = module_out_path + + sources = [ "surface_draw_test.cpp" ] + + deps = [ ":utils_unittest_common" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ace_engine:ace_uicontent", + "input:libmmi-client", + "ipc:ipc_core", + ] +} + +ohos_unittest("utils_window_helper_test") { + module_out_path = module_out_path + + sources = [ "window_helper_test.cpp" ] + + deps = [ ":utils_unittest_common" ] + + external_deps = [ + "ability_runtime:ability_manager", + "bundle_framework:appexecfwk_base", + ] +} + +ohos_unittest("utils_perform_reporter_test") { + module_out_path = module_out_path + + sources = [ "perform_reporter_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_cutout_info_test") { + module_out_path = module_out_path + + sources = [ "cutout_info_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_all_test") { + module_out_path = module_out_path + + sources = [ "utils_all_test.cpp" ] + + deps = [ ":utils_unittest_common" ] + + external_deps = [ + "ability_runtime:ability_manager", + "ipc:ipc_core", + ] +} + +ohos_unittest("utils_wm_occlusion_region_test") { + module_out_path = module_out_path + + sources = [ "wm_occlusion_region_test.cpp" ] + + deps = [ ":utils_unittest_common" ] +} + +ohos_unittest("utils_window_transition_info_test") { + module_out_path = module_out_path + + sources = [ "window_transition_info_test.cpp" ] + + deps = [ ":utils_unittest_common" ] + + external_deps = [ + "ability_runtime:ability_manager", + "ipc:ipc_core", + ] +} + +## Build dm_unittest_common.a {{{ +config("utils_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/dmserver/include", + "//foundation/window/window_manager/test/common/mock", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/dm/include", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_base/include", + ] +} + +ohos_static_library("utils_unittest_common") { + visibility = [ ":*" ] + testonly = true + + public_configs = [ + ":utils_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//commonlibrary/c_utils/base:utils", + "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_base:librender_service_base", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + subsystem_name = "window" + part_name = "window_manager" +} +## Build wm_unittest_common.a }}} diff --git a/window_manager/utils/test/unittest/cutout_info_test.cpp b/window_manager/utils/test/unittest/cutout_info_test.cpp new file mode 100644 index 0000000..fa63984 --- /dev/null +++ b/window_manager/utils/test/unittest/cutout_info_test.cpp @@ -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. + */ + +#include +#include "cutout_info.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class CutoutInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void CutoutInfoTest::SetUpTestCase() +{ +} + +void CutoutInfoTest::TearDownTestCase() +{ +} + +void CutoutInfoTest::SetUp() +{ +} + +void CutoutInfoTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WriteBoundingRectsVector + * @tc.desc: WriteBoundingRectsVector test + * @tc.type: FUNC + */ +HWTEST_F(CutoutInfoTest, WriteBoundingRectsVector, Function | SmallTest | Level2) +{ + sptr info = new CutoutInfo(); + DMRect rect = {0, 0, 0, 0}; + std::vector boundingRects; + boundingRects.emplace_back(rect); + Parcel parcel; + bool ret = info->WriteBoundingRectsVector(boundingRects, parcel); + ASSERT_TRUE(ret); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/display_info_test.cpp b/window_manager/utils/test/unittest/display_info_test.cpp new file mode 100644 index 0000000..809bab9 --- /dev/null +++ b/window_manager/utils/test/unittest/display_info_test.cpp @@ -0,0 +1,69 @@ +/* + * 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 "display_info.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DisplayInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void DisplayInfoTest::SetUpTestCase() +{ +} + +void DisplayInfoTest::TearDownTestCase() +{ +} + +void DisplayInfoTest::SetUp() +{ +} + +void DisplayInfoTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: MarshallingUnmarshalling + * @tc.desc: Marshalling Unmarshalling test + * @tc.type: FUNC + */ +HWTEST_F(DisplayInfoTest, MarshallingUnmarshalling, Function | SmallTest | Level2) +{ + DisplayInfo displayInfoSrc; + displayInfoSrc.SetDisplayId(1); + + Parcel parcel; + displayInfoSrc.Marshalling(parcel); + DisplayInfo* displayInfoDst = displayInfoSrc.Unmarshalling(parcel); + + ASSERT_EQ(displayInfoDst->GetDisplayId(), 1); + delete displayInfoDst; +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/perform_reporter_test.cpp b/window_manager/utils/test/unittest/perform_reporter_test.cpp new file mode 100644 index 0000000..374c35f --- /dev/null +++ b/window_manager/utils/test/unittest/perform_reporter_test.cpp @@ -0,0 +1,136 @@ +/* + * 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 "perform_reporter.h" +#include "window_manager_hilog.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "PerformReporterTest"}; +} +class PerformReporterTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + void SimuReportProcess(PerformReporter& pr, const std::vector& durations); + bool PerformDataCmp(const PerformReporter& pr, const uint32_t totalCount, const std::vector& splitCount); +}; + +void PerformReporterTest::SetUpTestCase() +{ +} + +void PerformReporterTest::TearDownTestCase() +{ +} + +void PerformReporterTest::SetUp() +{ +} + +void PerformReporterTest::TearDown() +{ +} + +void PerformReporterTest::SimuReportProcess(PerformReporter& pr, const std::vector& durations) +{ + for (auto duration : durations) { + pr.start(); + std::this_thread::sleep_for(std::chrono::milliseconds(duration)); + pr.end(); + } +} + +bool PerformReporterTest::PerformDataCmp(const PerformReporter& pr, + const uint32_t totalCount, const std::vector& splitCount) +{ + if (pr.totalCount_ != totalCount) { + WLOGFE("pr.totalCount_=%{public}u, expect=%{public}u", pr.totalCount_.load(), totalCount); + return false; + } + + size_t i = 0; + for (auto& iter: pr.timeSplitCount_) { + if (iter.second != splitCount[i]) { + std::ostringstream oss; + oss << "pr.timeSplitCount_[" << iter.first << "]=" << iter.second << ", but expect=" << splitCount[i]; + WLOGFI("%{public}s", oss.str().c_str()); + return false; + } + i++; + } + + return true; +} + +namespace { +/** + * @tc.name: StartEnd + * @tc.desc: StartEnd test + * @tc.type: FUNC + */ +HWTEST_F(PerformReporterTest, StartEnd, Function | SmallTest | Level2) +{ + PerformReporter pr = PerformReporter("TestTag", {100, 200, 300}, 10); + SimuReportProcess(pr, {50, 150, 250, 350, 450}); + ASSERT_EQ(true, PerformDataCmp(pr, 5, {1, 1, 1, 2})); +} + +/** + * @tc.name: StartEndClear + * @tc.desc: StartEndClear test + * @tc.type: FUNC + */ +HWTEST_F(PerformReporterTest, StartEndClear, Function | SmallTest | Level2) +{ + PerformReporter pr = PerformReporter("TestTag", {100, 200, 300}, 3); + SimuReportProcess(pr, {50, 150, 250}); +} + +/** + * @tc.name: StartEndInvSeq + * @tc.desc: StartEndInvSeq test + * @tc.type: FUNC + */ +HWTEST_F(PerformReporterTest, StartEndInvSeq, Function | SmallTest | Level2) +{ + PerformReporter pr = PerformReporter("TestTag", {100, 200, 300}, 4); + SimuReportProcess(pr, {250, 150, 50}); +} + +/** + * @tc.name: PrivateClear + * @tc.desc: PrivateClear test + * @tc.type: FUNC + */ +HWTEST_F(PerformReporterTest, PrivateClear, Function | SmallTest | Level2) +{ + PerformReporter pr = PerformReporter("TestTag", {100, 200, 300}, 10); + SimuReportProcess(pr, {50, 150, 250, 350, 450}); + + pr.clear(); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/screen_group_info_test.cpp b/window_manager/utils/test/unittest/screen_group_info_test.cpp new file mode 100644 index 0000000..035d6c0 --- /dev/null +++ b/window_manager/utils/test/unittest/screen_group_info_test.cpp @@ -0,0 +1,77 @@ +/* + * 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 "screen_group_info.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class ScreenGroupInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void ScreenGroupInfoTest::SetUpTestCase() +{ +} + +void ScreenGroupInfoTest::TearDownTestCase() +{ +} + +void ScreenGroupInfoTest::SetUp() +{ +} + +void ScreenGroupInfoTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: MarshallingUnmarshalling + * @tc.desc: Marshalling Unmarshalling test + * @tc.type: FUNC + */ +HWTEST_F(ScreenGroupInfoTest, MarshallingUnmarshalling, Function | SmallTest | Level1) +{ + std::vector screenIds; + screenIds.push_back(1); + screenIds.push_back(2); + screenIds.push_back(3); + ScreenGroupInfo screenGroupInfoSrc; + screenGroupInfoSrc.SetChildren(screenIds); + + Parcel parcel; + screenGroupInfoSrc.Marshalling(parcel); + ScreenGroupInfo* screenGroupInfoDst = screenGroupInfoSrc.Unmarshalling(parcel); + + std::vector screenIdsDst = screenGroupInfoDst->GetChildren(); + ASSERT_EQ(screenIdsDst.size(), 3); + ASSERT_EQ(screenIdsDst[0], 1); + ASSERT_EQ(screenIdsDst[1], 2); + ASSERT_EQ(screenIdsDst[2], 3); + delete screenGroupInfoDst; +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/screen_info_test.cpp b/window_manager/utils/test/unittest/screen_info_test.cpp new file mode 100644 index 0000000..2160daa --- /dev/null +++ b/window_manager/utils/test/unittest/screen_info_test.cpp @@ -0,0 +1,69 @@ +/* + * 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 "screen_info.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class ScreenInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void ScreenInfoTest::SetUpTestCase() +{ +} + +void ScreenInfoTest::TearDownTestCase() +{ +} + +void ScreenInfoTest::SetUp() +{ +} + +void ScreenInfoTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: MarshallingUnmarshalling + * @tc.desc: Marshalling Unmarshalling test + * @tc.type: FUNC + */ +HWTEST_F(ScreenInfoTest, MarshallingUnmarshalling, Function | SmallTest | Level2) +{ + ScreenInfo screenInfoSrc; + screenInfoSrc.SetScreenId(1); + + Parcel parcel; + screenInfoSrc.Marshalling(parcel); + ScreenInfo* screenInfoDst = screenInfoSrc.Unmarshalling(parcel); + + ASSERT_EQ(screenInfoDst->GetScreenId(), 1); + delete screenInfoDst; +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/string_util_test.cpp b/window_manager/utils/test/unittest/string_util_test.cpp new file mode 100644 index 0000000..10e8c84 --- /dev/null +++ b/window_manager/utils/test/unittest/string_util_test.cpp @@ -0,0 +1,65 @@ +/* + * 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 "string_util.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class StringUtilTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void StringUtilTest::SetUpTestCase() +{ +} + +void StringUtilTest::TearDownTestCase() +{ +} + +void StringUtilTest::SetUp() +{ +} + +void StringUtilTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: StringUtil Trim + * @tc.desc: test trim + * @tc.type: FUNC + * @tc.require: issueI5M2SK + */ +HWTEST_F(StringUtilTest, Trim, Function | SmallTest | Level1) +{ + ASSERT_EQ("", StringUtil::Trim("")); + ASSERT_EQ("", StringUtil::Trim(" ")); + ASSERT_EQ("123", StringUtil::Trim(" 123 ")); + ASSERT_EQ("12 3", StringUtil::Trim(" 12 3 ")); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/surface_draw_test.cpp b/window_manager/utils/test/unittest/surface_draw_test.cpp new file mode 100644 index 0000000..25e2811 --- /dev/null +++ b/window_manager/utils/test/unittest/surface_draw_test.cpp @@ -0,0 +1,217 @@ +/* + * 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 "surface_draw.h" +#include "display.h" +#include "display_info.h" +#include "display_manager.h" +#include "window_impl.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + const std::string IMAGE_PLACE_HOLDER_PNG_PATH = "/etc/window/resources/bg_place_holder.png"; + const int WAIT_FOR_SYNC_US = 1000 * 500; // 500ms +} +class SurfaceDrawTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + +public: + struct WindowTestInfo { + std::string name; + Rect rect; + WindowType type; + WindowMode mode; + bool needAvoid; + bool parentLimit; + bool forbidSplitMove {false}; + bool showWhenLocked; + uint32_t parentId; + }; + sptr CreateTestWindow(const std::string& name); + + static inline DisplayId displayId_; + static inline int32_t displayWidth_; + static inline int32_t displayHeight_; + WindowTestInfo windowInfo_; +}; + +void SurfaceDrawTest::SetUpTestCase() +{ + displayId_ = DisplayManager::GetInstance().GetDefaultDisplayId(); + sptr display = DisplayManager::GetInstance().GetDefaultDisplay(); + if (display == nullptr) { + return; + } + displayWidth_ = display->GetWidth(); + displayHeight_ = display->GetHeight(); +} + +void SurfaceDrawTest::TearDownTestCase() +{ +} + +void SurfaceDrawTest::SetUp() +{ + windowInfo_ = { + .name = "main", + .rect = {100, 100, 250, 300}, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = true, + .parentLimit = false, + .parentId = INVALID_WINDOW_ID, + }; +} + +void SurfaceDrawTest::TearDown() +{ +} + +sptr SurfaceDrawTest::CreateTestWindow(const std::string& name) +{ + sptr option = new WindowOption(); + option->SetDisplayId(displayId_); + option->SetWindowType(windowInfo_.type); + option->SetWindowRect(windowInfo_.rect); + option->SetWindowMode(windowInfo_.mode); + option->SetWindowName(name); + sptr window = Window::Create(option->GetWindowName(), option); + window->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + return window; +} + +namespace { +/** + * @tc.name: DrawImage + * @tc.desc: SurfaceDraw::DrawImage test + * @tc.type: FUNC + */ +HWTEST_F(SurfaceDrawTest, DrawImage01, Function | SmallTest | Level1) +{ + ASSERT_FALSE(SurfaceDraw::DrawImage(nullptr, 0, 0, "")); + sptr window = CreateTestWindow("testDrawImage"); + window->Show(); + usleep(WAIT_FOR_SYNC_US / 20); // wait for rect updated + + auto surfaceNode = window->GetSurfaceNode(); + ASSERT_NE(surfaceNode, nullptr); + usleep(WAIT_FOR_SYNC_US / 20); // wait for rect updated + uint32_t width = window->GetRect().width_; + uint32_t height = window->GetRect().height_; + ASSERT_TRUE(SurfaceDraw::DrawImage(surfaceNode, width, height, IMAGE_PLACE_HOLDER_PNG_PATH)); + ASSERT_FALSE(SurfaceDraw::DrawImage(surfaceNode, -1, -1, IMAGE_PLACE_HOLDER_PNG_PATH)); + window->Destroy(); +} +/** + * @tc.name: DecodeImageToPixelMap + * @tc.desc: SurfaceDraw::DecodeImageToPixelMap test + * @tc.type: FUNC + */ +HWTEST_F(SurfaceDrawTest, DecodeImageToPixelMap01, Function | SmallTest | Level1) +{ + ASSERT_EQ(SurfaceDraw::DecodeImageToPixelMap(""), nullptr); + ASSERT_NE(SurfaceDraw::DecodeImageToPixelMap(IMAGE_PLACE_HOLDER_PNG_PATH), nullptr); +} +/** + * @tc.name: DrawMasking + * @tc.desc: SurfaceDraw::DrawMasking test + * @tc.type: FUNC + */ +HWTEST_F(SurfaceDrawTest, DrawMasking01, Function | SmallTest | Level1) +{ + OHOS::Rosen::Rect screenRect = {0, 0, 0, 0}; + OHOS::Rosen::Rect transRect = {0, 0, 0, 0}; + ASSERT_FALSE(SurfaceDraw::DrawMasking(nullptr, screenRect, transRect)); + + sptr window = CreateTestWindow("testDrawMasking"); + window->Show(); + usleep(WAIT_FOR_SYNC_US / 20); // wait for rect updated + + auto surfaceNode = window->GetSurfaceNode(); + ASSERT_NE(surfaceNode, nullptr); + ASSERT_FALSE(SurfaceDraw::DrawMasking(surfaceNode, screenRect, transRect)); + + screenRect.width_ = displayWidth_; + screenRect.height_ = displayHeight_; + transRect.width_ = displayWidth_; + transRect.height_ = displayHeight_; + ASSERT_TRUE(SurfaceDraw::DrawMasking(surfaceNode, screenRect, transRect)); + window->Destroy(); +} +/** + * @tc.name: DoDrawImageRect + * @tc.desc: SurfaceDraw::DoDrawImageRect test + * @tc.type: FUNC + */ +HWTEST_F(SurfaceDrawTest, DoDrawImageRect01, Function | SmallTest | Level1) +{ + sptr window = CreateTestWindow("testDoDrawImageRect"); + ASSERT_NE(window, nullptr); + window->Show(); + usleep(WAIT_FOR_SYNC_US / 20); // wait for rect updated + + OHOS::Rosen::Rect rect = window->GetRect(); + uint32_t color = 0x00660000; + + auto surfaceNode = window->GetSurfaceNode(); + ASSERT_NE(surfaceNode, nullptr); + sptr layer = SurfaceDraw::GetLayer(surfaceNode); + ASSERT_NE(layer, nullptr); + sptr buffer = SurfaceDraw::GetSurfaceBuffer(layer, rect.width_, rect.height_); + ASSERT_NE(buffer, nullptr); + + ASSERT_FALSE(SurfaceDraw::DoDrawImageRect(buffer, rect, nullptr, color, false)); + + std::shared_ptr pixelMap = SurfaceDraw::DecodeImageToPixelMap(IMAGE_PLACE_HOLDER_PNG_PATH); + ASSERT_NE(pixelMap, nullptr); + + ASSERT_TRUE(SurfaceDraw::DoDrawImageRect(buffer, rect, pixelMap, color, false)); + window->Destroy(); +} +/** + * @tc.name: GetSurfaceSnapshot + * @tc.desc: SurfaceDraw::GetSurfaceSnapshot test + * @tc.type: FUNC + */ +HWTEST_F(SurfaceDrawTest, GetSurfaceSnapshot01, Function | SmallTest | Level1) +{ + sptr window = CreateTestWindow("testDoDrawImageRect"); + ASSERT_NE(window, nullptr); + window->Show(); + usleep(WAIT_FOR_SYNC_US / 20); // wait for rect updated + + auto surfaceNode = window->GetSurfaceNode(); + ASSERT_NE(surfaceNode, nullptr); + + std::shared_ptr pixelMap = SurfaceDraw::DecodeImageToPixelMap(IMAGE_PLACE_HOLDER_PNG_PATH); + ASSERT_NE(pixelMap, nullptr); + + ASSERT_FALSE(SurfaceDraw::GetSurfaceSnapshot(nullptr, pixelMap, 0, 0, 0)); + ASSERT_FALSE(SurfaceDraw::GetSurfaceSnapshot(surfaceNode, pixelMap, 0, 0, 0)); + window->Destroy(); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/utils_all_test.cpp b/window_manager/utils/test/unittest/utils_all_test.cpp new file mode 100644 index 0000000..79994f5 --- /dev/null +++ b/window_manager/utils/test/unittest/utils_all_test.cpp @@ -0,0 +1,211 @@ +/* + * 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 "agent_death_recipient.h" +#include "iremote_object_mocker.h" +#include "singleton_container.h" +#include "perform_reporter.h" +#include "surface_reader_handler_impl.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class TestClass { +public: + std::string name = "testClass"; +}; + +class UtilsAllTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + std::map oldStringMap_; + std::map oldSingletonMap_; + std::map> oldDependencySetMap_; +}; + +void UtilsAllTest::SetUpTestCase() +{ +} + +void UtilsAllTest::TearDownTestCase() +{ +} + +void UtilsAllTest::SetUp() +{ +} + +void UtilsAllTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: ADROnRemoteDied01 + * @tc.desc: test AgentDeathRecipient::OnRemoteDied + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, ADROnRemoteDied01, Function | SmallTest | Level2) +{ + sptr deathRecipient = new AgentDeathRecipient(nullptr); + + deathRecipient->OnRemoteDied(nullptr); + + sptr remoteObj = new MockIRemoteObject(); + deathRecipient->OnRemoteDied(remoteObj); + ASSERT_EQ(0, remoteObj->count_); + + deathRecipient->callback_ = [&remoteObj](sptr& remote) { + remoteObj->count_ = 1; + }; + deathRecipient->OnRemoteDied(remoteObj); + ASSERT_EQ(1, remoteObj->count_); +} +/** + * @tc.name: PRCount01 + * @tc.desc: test PerformReporter::count + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, PRCount01, Function | SmallTest | Level2) +{ + std::vector timeSpiltsMs = {0, 1, 2}; + PerformReporter reporter = PerformReporter("test", timeSpiltsMs); + + reporter.count(0); + ASSERT_EQ(1, reporter.totalCount_); + reporter.timeSplitCount_.clear(); + ASSERT_EQ(1, reporter.totalCount_); +} +/** + * @tc.name: SCAddSingleton01 + * @tc.desc: test SingletonContainer::AddSingleton + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, SCAddSingleton01, Function | SmallTest | Level2) +{ + auto& singletonContainer = SingletonContainer::GetInstance(); + + singletonContainer.AddSingleton("test", nullptr); + auto testId = singletonContainer.stringMap["test"]; + singletonContainer.AddSingleton("test", nullptr); + ASSERT_EQ(testId, singletonContainer.stringMap["test"]); + singletonContainer.AddSingleton("test2", nullptr); + ASSERT_EQ(testId + 1, singletonContainer.stringMap["test2"]); + + auto testId2 = singletonContainer.stringMap["test2"]; + singletonContainer.singletonMap.erase(testId); + singletonContainer.singletonMap.erase(testId2); + singletonContainer.stringMap.erase("test"); + singletonContainer.stringMap.erase("test2"); +} + +/** + * @tc.name: SCSetSingleton01 + * @tc.desc: test SingletonContainer::AddSingleton + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, SCSetSingleton01, Function | SmallTest | Level2) +{ + auto& singletonContainer = SingletonContainer::GetInstance(); + + TestClass* testObj = new TestClass(); + + singletonContainer.SetSingleton("test", testObj); + auto testId = singletonContainer.stringMap["test"]; + auto instance = singletonContainer.GetSingleton("test2"); + ASSERT_EQ(instance, nullptr); + + instance = singletonContainer.GetSingleton("test"); + ASSERT_NE(instance, nullptr); + ASSERT_EQ(static_cast(instance)->name, "testClass"); + + singletonContainer.SetSingleton("test", nullptr); + instance = singletonContainer.GetSingleton("test"); + ASSERT_EQ(instance, nullptr); + + singletonContainer.singletonMap.erase(testId); + singletonContainer.stringMap.erase("test"); + delete testObj; +} +/** + * @tc.name: SCDependOn01 + * @tc.desc: test SingletonContainer::DependOn + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, SCDependOn01, Function | SmallTest | Level2) +{ + auto& singletonContainer = SingletonContainer::GetInstance(); + + singletonContainer.AddSingleton("test", nullptr); + + ASSERT_EQ(nullptr, singletonContainer.DependOn("test", "test")); + + auto id = singletonContainer.stringMap["test"]; + auto& testSet = singletonContainer.dependencySetMap[id]; + ASSERT_EQ(1, testSet.size()); + + ASSERT_EQ(nullptr, singletonContainer.DependOn("test", "test")); + id = singletonContainer.stringMap["test"]; + auto& testSet2 = singletonContainer.dependencySetMap[id]; + ASSERT_EQ(1, testSet2.size()); + + singletonContainer.singletonMap.erase(id); + singletonContainer.stringMap.erase("test"); + id = singletonContainer.dependencySetMap.erase(id); +} +/** + * @tc.name: SRHOnImageAvailable01 + * @tc.desc: test SurfaceReaderHandlerImpl::OnImageAvailable + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, SRHOnImageAvailable, Function | SmallTest | Level2) +{ + sptr surfaceReaderHandlerImpl = new (std::nothrow)SurfaceReaderHandlerImpl(); + surfaceReaderHandlerImpl->flag_ = false; + surfaceReaderHandlerImpl->OnImageAvailable(nullptr); + ASSERT_EQ(true, surfaceReaderHandlerImpl->flag_); + surfaceReaderHandlerImpl->flag_ = true; + surfaceReaderHandlerImpl->OnImageAvailable(nullptr); + ASSERT_EQ(true, surfaceReaderHandlerImpl->flag_); +} +/** + * @tc.name: SRHOnImageAvailable01 + * @tc.desc: test SurfaceReaderHandlerImpl::OnImageAvailable + * @tc.type: FUNC + */ +HWTEST_F(UtilsAllTest, SRHResetFlag, Function | SmallTest | Level2) +{ + sptr surfaceReaderHandlerImpl = new (std::nothrow)SurfaceReaderHandlerImpl(); + surfaceReaderHandlerImpl->flag_ = false; + surfaceReaderHandlerImpl->ResetFlag(); + ASSERT_EQ(false, surfaceReaderHandlerImpl->flag_); + surfaceReaderHandlerImpl->flag_ = true; + surfaceReaderHandlerImpl->ResetFlag(); + ASSERT_EQ(false, surfaceReaderHandlerImpl->flag_); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/window_helper_test.cpp b/window_manager/utils/test/unittest/window_helper_test.cpp new file mode 100644 index 0000000..a247d28 --- /dev/null +++ b/window_manager/utils/test/unittest/window_helper_test.cpp @@ -0,0 +1,259 @@ +/* + * 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 "window_helper.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowHelperTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowHelperTest::SetUpTestCase() +{ +} + +void WindowHelperTest::TearDownTestCase() +{ +} + +void WindowHelperTest::SetUp() +{ +} + +void WindowHelperTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowTypeWindowMode + * @tc.desc: window type/mode test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, WindowTypeWindowMode, Function | SmallTest | Level1) +{ + ASSERT_EQ(true, WindowHelper::IsMainFullScreenWindow(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN)); + ASSERT_EQ(false, WindowHelper::IsMainFullScreenWindow(WindowType::WINDOW_TYPE_APP_SUB_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN)); + ASSERT_EQ(false, WindowHelper::IsMainFullScreenWindow(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_SPLIT_PRIMARY)); + + ASSERT_EQ(true, WindowHelper::IsFloatingWindow(WindowMode::WINDOW_MODE_FLOATING)); + ASSERT_EQ(false, WindowHelper::IsFloatingWindow(WindowMode::WINDOW_MODE_FULLSCREEN)); + + ASSERT_EQ(true, WindowHelper::IsFullScreenWindow(WindowMode::WINDOW_MODE_FULLSCREEN)); + ASSERT_EQ(false, WindowHelper::IsFullScreenWindow(WindowMode::WINDOW_MODE_FLOATING)); +} + +/** + * @tc.name: WindowModeSupport + * @tc.desc: window mode supported test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, WindowModeSupport, Function | SmallTest | Level1) +{ + ASSERT_EQ(true, WindowHelper::IsWindowModeSupported(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, + WindowMode::WINDOW_MODE_FULLSCREEN)); + ASSERT_EQ(true, WindowHelper::IsWindowModeSupported(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, + WindowMode::WINDOW_MODE_FLOATING)); + ASSERT_EQ(true, WindowHelper::IsWindowModeSupported(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, + WindowMode::WINDOW_MODE_SPLIT_PRIMARY)); + ASSERT_EQ(true, WindowHelper::IsWindowModeSupported(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, + WindowMode::WINDOW_MODE_SPLIT_SECONDARY)); + ASSERT_EQ(true, WindowHelper::IsWindowModeSupported(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, + WindowMode::WINDOW_MODE_PIP)); + ASSERT_EQ(true, WindowHelper::IsWindowModeSupported(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, + WindowMode::WINDOW_MODE_UNDEFINED)); +} + +/** + * @tc.name: WindowRect + * @tc.desc: rect test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, WindowRect, Function | SmallTest | Level1) +{ + Rect rect0 = {0, 0, 0, 0}; + ASSERT_EQ(true, WindowHelper::IsEmptyRect(rect0)); + + Rect rect1 = {0, 0, 1, 1}; + ASSERT_EQ(false, WindowHelper::IsEmptyRect(rect1)); +} + +/** + * @tc.name: WindowStringUtil + * @tc.desc: string test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, WindowStringUtil, Function | SmallTest | Level1) +{ + ASSERT_EQ(true, WindowHelper::IsNumber("123")); + ASSERT_EQ(false, WindowHelper::IsNumber("1a3")); + ASSERT_EQ(false, WindowHelper::IsNumber("")); + + ASSERT_EQ(true, WindowHelper::IsFloatingNumber("1.23")); + ASSERT_EQ(true, WindowHelper::IsFloatingNumber(".123")); + ASSERT_EQ(false, WindowHelper::IsFloatingNumber("1a3")); + ASSERT_EQ(false, WindowHelper::IsFloatingNumber("123..")); + + std::vector vec = WindowHelper::Split("123a123a123", "a"); + for (size_t i = 0; i < vec.size(); i++) { + if (vec[i].compare("123")) { + ASSERT_TRUE(false); + } + } + ASSERT_TRUE(true); +} + +/** + * @tc.name: CalculateOriginPosition + * @tc.desc: CalculateOriginPosition test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, CalculateOriginPosition, Function | SmallTest | Level1) +{ + Rect rect1 { 0, 0, 10, 10 }, rect2 { 100, 100, 200, 200 }; + PointInfo point = WindowHelper::CalculateOriginPosition(rect1, rect2, PointInfo { 200, 200 }); + PointInfo expectPoint { 5, 5 }; + ASSERT_EQ(true, point.x == expectPoint.x); + ASSERT_EQ(true, point.y == expectPoint.y); + + Transform transform; + transform.scaleX_ = 0.66f; + transform.scaleY_ = 1.5f; + transform.rotationY_ = 30; + transform.translateX_ = 100; + transform.translateY_ = 200; + transform.translateZ_ = 50; + Rect rect { 50, 50, 240, 320 }; + TransformHelper::Vector3 pivotPos = { rect.posX_ + transform.pivotX_ * rect.width_, + rect.posY_ + transform.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 mat = TransformHelper::CreateTranslation(-pivotPos); + mat *= WindowHelper::ComputeWorldTransformMat4(transform); + mat *= TransformHelper::CreateTranslation(pivotPos); + + TransformHelper::Vector3 expectOriginPoint(0, 0, 0); + TransformHelper::Vector3 tranformedPoint = TransformHelper::Transform(expectOriginPoint, mat); + PointInfo actialOriginPoint = WindowHelper::CalculateOriginPosition(mat, + { static_cast(tranformedPoint.x_), static_cast(tranformedPoint.y_) }); + const float errorRange = 2.f; + ASSERT_LT(std::abs(expectOriginPoint.x_ - actialOriginPoint.x), errorRange); + ASSERT_LT(std::abs(expectOriginPoint.y_ - actialOriginPoint.y), errorRange); +} + +/** + * @tc.name: TransformRect + * @tc.desc: TransformRect test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, TransformRect, Function | SmallTest | Level1) +{ + Transform transform; + Rect rect { 0, 0, 10, 20 }; + transform.scaleX_ = transform.scaleY_ = 2.0f; + TransformHelper::Vector3 pivotPos = { rect.posX_ + transform.pivotX_ * rect.width_, + rect.posY_ + transform.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 mat = TransformHelper::CreateTranslation(-pivotPos); + mat *= WindowHelper::ComputeWorldTransformMat4(transform); + mat *= TransformHelper::CreateTranslation(pivotPos); + Rect transformRect = WindowHelper::TransformRect(mat, rect); + ASSERT_EQ(rect.width_ * transform.scaleX_, transformRect.width_); + ASSERT_EQ(rect.height_ * transform.scaleY_, transformRect.height_); +} + +/** + * @tc.name: CalculateHotZoneScale + * @tc.desc: CalculateHotZoneScale test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, CalculateHotZoneScale, Function | SmallTest | Level1) +{ + Transform transform; + transform.scaleX_ = 0.66f; + transform.scaleY_ = 1.5f; + transform.pivotX_ = transform.pivotY_ = 0.5f; + Rect rect { -1, -2, 2, 4 }; + TransformHelper::Vector3 pivotPos = { rect.posX_ + transform.pivotX_ * rect.width_, + rect.posY_ + transform.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 mat = TransformHelper::CreateTranslation(-pivotPos); + mat *= WindowHelper::ComputeWorldTransformMat4(transform); + mat *= TransformHelper::CreateTranslation(pivotPos); + + const float errorRange = 0.01f; + TransformHelper::Vector2 hotZoneScale = WindowHelper::CalculateHotZoneScale(mat); + ASSERT_LT(std::abs(transform.scaleX_ - hotZoneScale.x_), errorRange); + ASSERT_LT(std::abs(transform.scaleY_ - hotZoneScale.y_), errorRange); +} + +/** + * @tc.name: WindowType + * @tc.desc: Window Type test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, WindowType, Function | SmallTest | Level1) +{ + ASSERT_EQ(true, WindowHelper::IsSystemWindow(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW)); + ASSERT_EQ(true, WindowHelper::IsSystemSubWindow(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW)); + ASSERT_EQ(false, WindowHelper::IsSystemSubWindow(WindowType::WINDOW_TYPE_APP_SUB_WINDOW)); + ASSERT_EQ(false, WindowHelper::IsSystemSubWindow(WindowType::WINDOW_TYPE_FLOAT)); +} + +/** + * @tc.name: GetTransformFromWorldMat4 + * @tc.desc: GetTransformFromWorldMat4 test + * @tc.type: FUNC + */ +HWTEST_F(WindowHelperTest, GetTransformFromWorldMat4, Function | SmallTest | Level1) +{ + Transform transform1; + transform1.scaleX_ = 0.66f; + transform1.scaleY_ = 1.5f; + transform1.translateX_ = 12.f; + transform1.translateY_ = 45.f; + Rect rect1 { 0, 0, 300, 400 }; + TransformHelper::Vector3 pivotPos1 = { rect1.posX_ + transform1.pivotX_ * rect1.width_, + rect1.posY_ + transform1.pivotY_ * rect1.height_, 0 }; + TransformHelper::Matrix4 mat1 = TransformHelper::CreateTranslation(-pivotPos1); + mat1 *= WindowHelper::ComputeWorldTransformMat4(transform1); + mat1 *= TransformHelper::CreateTranslation(pivotPos1); + + Rect rect2 = WindowHelper::TransformRect(mat1, rect1); + Transform transform2; + WindowHelper::GetTransformFromWorldMat4(mat1, rect2, transform2); + TransformHelper::Vector3 pivotPos2 = { rect2.posX_ + transform2.pivotX_ * rect2.width_, + rect2.posY_ + transform2.pivotY_ * rect2.height_, 0 }; + TransformHelper::Matrix4 mat2 = TransformHelper::CreateTranslation(-pivotPos2); + mat2 *= WindowHelper::ComputeWorldTransformMat4(transform2); + mat2 *= TransformHelper::CreateTranslation(pivotPos2); + for (int i = 0; i < TransformHelper::Matrix4::MAT_SIZE; i++) { + for (int j = 0; j < TransformHelper::Matrix4::MAT_SIZE; j++) { + ASSERT_EQ(true, MathHelper::NearZero(mat1.mat_[i][j] - mat2.mat_[i][j])); + } + } +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/window_property_test.cpp b/window_manager/utils/test/unittest/window_property_test.cpp new file mode 100644 index 0000000..0484b76 --- /dev/null +++ b/window_manager/utils/test/unittest/window_property_test.cpp @@ -0,0 +1,198 @@ +/* + * 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 "window_property.h" +#include "wm_common_inner.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowPropertyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowPropertyTest::SetUpTestCase() +{ +} + +void WindowPropertyTest::TearDownTestCase() +{ +} + +void WindowPropertyTest::SetUp() +{ +} + +void WindowPropertyTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: MarshallingUnmarshalling + * @tc.desc: Marshalling Unmarshalling test + * @tc.type: FUNC + */ +HWTEST_F(WindowPropertyTest, MarshallingUnmarshalling, Function | SmallTest | Level2) +{ + WindowProperty winPropSrc; + winPropSrc.SetPrivacyMode(true); + winPropSrc.SetTransparent(true); + winPropSrc.SetTransform(Transform::Identity()); + + Parcel parcel; + winPropSrc.Marshalling(parcel); + WindowProperty* winPropDst = winPropSrc.Unmarshalling(parcel); + + ASSERT_EQ(winPropDst->GetPrivacyMode(), true); + ASSERT_EQ(winPropDst->GetTransparent(), true); + ASSERT_EQ(winPropDst->GetTransform(), Transform::Identity()); + delete winPropDst; +} + +/** + * @tc.name: CopyFrom + * @tc.desc: CopyFrom test + * @tc.type: FUNC + */ +HWTEST_F(WindowPropertyTest, CopyFrom, Function | SmallTest | Level2) +{ + const sptr winPropSrc = new(std::nothrow) WindowProperty(); + winPropSrc->SetPrivacyMode(true); + winPropSrc->SetTransparent(true); + winPropSrc->SetTransform(Transform::Identity()); + + WindowProperty winPropDst(winPropSrc); // winPropDst.CopyFrom(winPropSrc); + + ASSERT_EQ(winPropSrc->GetPrivacyMode(), winPropDst.GetPrivacyMode()); + ASSERT_EQ(winPropSrc->GetTransparent(), winPropDst.GetTransparent()); + ASSERT_EQ(winPropSrc->GetTransform(), winPropDst.GetTransform()); +} + +/** + * @tc.name: Read + * @tc.desc: Read test + * @tc.type: FUNC + */ +HWTEST_F(WindowPropertyTest, Read, Function | SmallTest | Level2) +{ + WindowProperty winPropSrc; + winPropSrc.SetPrivacyMode(true); + winPropSrc.SetTransparent(true); + + Parcel parcel; + winPropSrc.Marshalling(parcel); + + WindowProperty winPropDst; + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_RECT); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_MODE); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_FLAGS); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_FOCUSABLE); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_TOUCHABLE); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_ORIENTATION); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG); + winPropDst.Read(parcel, PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE); + + ASSERT_EQ(true, winPropDst.GetPrivacyMode()); + ASSERT_EQ(false, winPropDst.GetTransparent()); +} + +/** + * @tc.name: Write + * @tc.desc: Write test + * @tc.type: FUNC + */ +HWTEST_F(WindowPropertyTest, Write, Function | SmallTest | Level2) +{ + Parcel parcel; + WindowProperty winPropDst; + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_RECT)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_MODE)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_FLAGS)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_FOCUSABLE)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_TOUCHABLE)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_ORIENTATION)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY)); + ASSERT_EQ(true, winPropDst.Write(parcel, PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG)); +} + +/** + * @tc.name: SetAbilityInfo + * @tc.desc: Test SetAbilityInfo and GetAbilityInfo + * @tc.type: FUNC + */ +HWTEST_F(WindowPropertyTest, SetAbilityInfo, Function | SmallTest | Level2) +{ + WindowProperty winPropDst; + AbilityInfo info; + info.bundleName_ = "testBundleName"; + info.abilityName_ = "testAbilityName"; + winPropDst.SetAbilityInfo(info); + ASSERT_EQ("testBundleName", winPropDst.GetAbilityInfo().bundleName_); + ASSERT_EQ("testAbilityName", winPropDst.GetAbilityInfo().abilityName_); +} + +/** + * @tc.name: ResumeLastWindowMode + * @tc.desc: Test ResumeLastWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowPropertyTest, ResumeLastWindowMode, Function | SmallTest | Level2) +{ + WindowProperty winPropDst; + winPropDst.modeSupportInfo_ = WindowModeSupport::WINDOW_MODE_SUPPORT_PIP; + winPropDst.lastMode_ = WindowMode::WINDOW_MODE_PIP; + winPropDst.mode_ = WindowMode::WINDOW_MODE_UNDEFINED; + winPropDst.ResumeLastWindowMode(); + ASSERT_EQ(WindowMode::WINDOW_MODE_PIP, winPropDst.mode_); + + winPropDst.modeSupportInfo_ = WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY; + winPropDst.lastMode_ = WindowMode::WINDOW_MODE_PIP; + winPropDst.mode_ = WindowMode::WINDOW_MODE_UNDEFINED; + winPropDst.ResumeLastWindowMode(); + ASSERT_EQ(WindowMode::WINDOW_MODE_UNDEFINED, winPropDst.mode_); + + winPropDst.modeSupportInfo_ = WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING; + winPropDst.lastMode_ = WindowMode::WINDOW_MODE_PIP; + winPropDst.mode_ = WindowMode::WINDOW_MODE_UNDEFINED; + winPropDst.ResumeLastWindowMode(); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, winPropDst.mode_); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/window_transition_info_test.cpp b/window_manager/utils/test/unittest/window_transition_info_test.cpp new file mode 100644 index 0000000..75f67bb --- /dev/null +++ b/window_manager/utils/test/unittest/window_transition_info_test.cpp @@ -0,0 +1,117 @@ +/* + * 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 "window_transition_info.h" +#include "iremote_object_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using RemoteMocker = IRemoteObjectMocker; +class WindowTransitionInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void SetTransitionInfo(sptr info); +}; + +void WindowTransitionInfoTest::SetUpTestCase() +{ +} + +void WindowTransitionInfoTest::TearDownTestCase() +{ +} + +void WindowTransitionInfoTest::SetUp() +{ +} + +void WindowTransitionInfoTest::TearDown() +{ +} + +void WindowTransitionInfoTest::SetTransitionInfo(sptr info) +{ + info->bundleName_ = "bundleName"; + info->abilityName_ = "abilityName"; + info->mode_ = WindowMode::WINDOW_MODE_FULLSCREEN; + info->windowRect_ = { 10, 10, 10, 10 }; + info->displayId_ = 0; +} + +namespace { +/** + * @tc.name: WindowTransitionInfo01 + * @tc.desc: WindowTransitionInfo::WindowTransitionInfo test + * @tc.type: FUNC + */ +HWTEST_F(WindowTransitionInfoTest, WindowTransitionInfo01, Function | SmallTest | Level2) +{ + sptr info = new AAFwk::AbilityTransitionInfo(); + ASSERT_NE(nullptr, info); + info->bundleName_ = "TestAbilityTransitionInfo1"; + sptr winTransitionInfo1 = new WindowTransitionInfo(info); + ASSERT_NE(nullptr, winTransitionInfo1); + ASSERT_EQ(info->bundleName_, winTransitionInfo1->bundleName_); + ASSERT_EQ(3, winTransitionInfo1->supportWindowModes_.size()); + ASSERT_EQ(AppExecFwk::SupportWindowMode::FULLSCREEN, winTransitionInfo1->supportWindowModes_[0]); + ASSERT_EQ(AppExecFwk::SupportWindowMode::SPLIT, winTransitionInfo1->supportWindowModes_[1]); + ASSERT_EQ(AppExecFwk::SupportWindowMode::FLOATING, winTransitionInfo1->supportWindowModes_[2]); + + info->bundleName_ = "TestAbilityTransitionInfo2"; + info->windowModes_.emplace_back(AppExecFwk::SupportWindowMode::SPLIT); + sptr winTransitionInfo2 = new WindowTransitionInfo(info); + ASSERT_EQ(info->bundleName_, winTransitionInfo2->bundleName_); + ASSERT_EQ(1, winTransitionInfo2->supportWindowModes_.size()); + ASSERT_EQ(AppExecFwk::SupportWindowMode::SPLIT, winTransitionInfo2->supportWindowModes_[0]); +} +/** + * @tc.name: Marshalling + * @tc.desc: WindowTransitionInfo::Marshalling test + * @tc.type: FUNC + */ +HWTEST_F(WindowTransitionInfoTest, Marshalling01, Function | SmallTest | Level2) +{ + sptr info = new AAFwk::AbilityTransitionInfo(); + ASSERT_NE(nullptr, info); + + Parcel parcel; + sptr winTransitionInfo = new WindowTransitionInfo(info); + ASSERT_NE(nullptr, winTransitionInfo); + + winTransitionInfo->bundleName_ = "bundleNameValue"; + winTransitionInfo->abilityName_ = "abilityNameValue"; + + bool result = winTransitionInfo->Marshalling(parcel); + ASSERT_EQ(true, result); + + sptr romote = new RemoteMocker(); + winTransitionInfo->abilityToken_ = romote; + result = winTransitionInfo->Marshalling(parcel); + ASSERT_EQ(true, result); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/wm_math_test.cpp b/window_manager/utils/test/unittest/wm_math_test.cpp new file mode 100644 index 0000000..b627e79 --- /dev/null +++ b/window_manager/utils/test/unittest/wm_math_test.cpp @@ -0,0 +1,138 @@ +/* + * 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 "wm_math.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using namespace TransformHelper; +class WmMathTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WmMathTest::SetUpTestCase() +{ +} + +void WmMathTest::TearDownTestCase() +{ +} + +void WmMathTest::SetUp() +{ +} + +void WmMathTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: MathHalper + * @tc.desc: MathHalper test + * @tc.type: FUNC + */ +HWTEST_F(WmMathTest, MathHalper, Function | SmallTest | Level2) +{ + { + const float t = 0.5f; + ASSERT_EQ(true, MathHelper::NearZero(0)); + ASSERT_EQ(true, MathHelper::NearZero(t * MathHelper::NAG_ZERO)); + ASSERT_EQ(true, MathHelper::NearZero(t * MathHelper::POS_ZERO)); + } + { + float radians = MathHelper::PI, degrees = 180.f; + ASSERT_EQ(true, MathHelper::NearZero(MathHelper::ToDegrees(radians) - degrees)); + ASSERT_EQ(true, MathHelper::NearZero(MathHelper::ToRadians(degrees) - radians)); + } + { + int a = 1, b = 2, c = 3, d = 4; + ASSERT_EQ(true, MathHelper::Max(a, b, c) == c); + ASSERT_EQ(true, MathHelper::Min(a, b, c) == a); + ASSERT_EQ(true, MathHelper::Max(a, b, c, d) == d); + ASSERT_EQ(true, MathHelper::Min(a, b, c, d) == a); + ASSERT_EQ(true, MathHelper::Clamp(a, b, c) == b); + ASSERT_EQ(true, MathHelper::Clamp(b, a, c) == b); + ASSERT_EQ(true, MathHelper::Clamp(c, a, b) == b); + } +} + +/** + * @tc.name: TransformMatrix + * @tc.desc: Create transform matrix + * Get scale component from transform matrix + * Get translation component from transform matrix + * @tc.type: FUNC + */ +HWTEST_F(WmMathTest, TransformMatrix, Function | SmallTest | Level2) +{ + Vector3 scale(1.5f, 0.7f, 2.2f), translation(100.f, 132.f, 20.f); + Matrix4 transformMat = CreateScale(scale.x_, scale.y_, scale.z_); + float theta = 2.34f; + transformMat *= CreateRotationY(theta); + transformMat *= CreateTranslation(translation); + Vector3 scaleComp = transformMat.GetScale(); + Vector3 translationComp = transformMat.GetTranslation(); + ASSERT_EQ(true, MathHelper::NearZero((scale - scaleComp).Length())); + ASSERT_EQ(true, MathHelper::NearZero((translation - translationComp).Length())); +} +/** + * @tc.name: TransformWithPerspDiv + * @tc.desc: Create transform matrix + * Get scale component from transform matrix + * Get translation component from transform matrix + * @tc.type: FUNC + */ +HWTEST_F(WmMathTest, TransformWithPerspDiv, Function | SmallTest | Level2) +{ + Vector3 vec(1.0, 1.0, 1.0); + Matrix4 mat = Matrix4::Identity; + auto result = TransformWithPerspDiv(vec, mat, 0.5); + auto expect = vec * 2; + ASSERT_EQ(expect.x_, result.x_); + ASSERT_EQ(expect.y_, result.y_); + ASSERT_EQ(expect.z_, result.z_); + + result = TransformWithPerspDiv(vec, mat, 0); + ASSERT_EQ(vec.x_, result.x_); + ASSERT_EQ(vec.y_, result.y_); + ASSERT_EQ(vec.z_, result.z_); +} + +/** + * @tc.name: Invert + * @tc.desc: + * @tc.type: FUNC + */ +HWTEST_F(WmMathTest, Invert, Function | SmallTest | Level2) +{ + Matrix4 mat; + mat.mat_[0][0] = 0.f; + mat.mat_[1][0] = -1.0f; + mat.Invert(); + ASSERT_EQ(false, MathHelper::NearZero(0.f - mat.mat_[1][0])); +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/utils/test/unittest/wm_occlusion_region_test.cpp b/window_manager/utils/test/unittest/wm_occlusion_region_test.cpp new file mode 100644 index 0000000..c3e78f6 --- /dev/null +++ b/window_manager/utils/test/unittest/wm_occlusion_region_test.cpp @@ -0,0 +1,425 @@ +/* + * 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 "wm_occlusion_region.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace WmOcclusion { +class WmOcclusionRegionTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void WmOcclusionRegionTest::SetUpTestCase() +{ +} + +void WmOcclusionRegionTest::TearDownTestCase() +{ +} + +void WmOcclusionRegionTest::SetUp() +{ +} + +void WmOcclusionRegionTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: EventSortByY01 + * @tc.desc: test WmOcclusion::EventSortByY + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, EventSortByY, Function | SmallTest | Level2) +{ + Event event1{ 0, Event::Type::OPEN, 0, 0 }; + Event event2{ 0, Event::Type::OPEN, 0, 0 }; + bool result = true; + + event1.y_ = 1; + event1.type_ = Event::Type::CLOSE; + event2.y_ = 1; + event2.type_ = Event::Type::OPEN; + result = EventSortByY(event1, event2); + ASSERT_EQ(true, result); + + event1.y_ = 1; + event1.type_ = Event::Type::OPEN; + event2.y_ = 1; + event2.type_ = Event::Type::CLOSE; + result = EventSortByY(event1, event2); + ASSERT_EQ(false, result); + + event1.y_ = 1; + event2.y_ = 2; + result = EventSortByY(event1, event2); + ASSERT_EQ(true, result); + + event1.y_ = 2; + event2.y_ = 1; + result = EventSortByY(event1, event2); + ASSERT_EQ(false, result); +} + +/** + * @tc.name: Node::Update01 + * @tc.desc: test WmOcclusion::Node::Update + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, Update01, Function | SmallTest | Level2) +{ + Node* rootNode = new Node(0, 2); + ASSERT_NE(rootNode, nullptr); + rootNode->positive_count_ = Event::Type::CLOSE; + rootNode->Update(0, 0, Event::Type::OPEN); + ASSERT_EQ(Event::Type::CLOSE, rootNode->positive_count_); + + rootNode->positive_count_ = Event::Type::CLOSE; + rootNode->Update(0, 2, Event::Type::OPEN); + ASSERT_EQ(0, rootNode->positive_count_); + + rootNode->positive_count_ = Event::Type::CLOSE; + rootNode->Update(0, 2, Event::Type::CLOSE); + ASSERT_EQ(-2, rootNode->positive_count_); + + rootNode->negative_count_ = Event::Type::VOID_CLOSE; + rootNode->Update(0, 2, Event::Type::VOID_OPEN); + ASSERT_EQ(0, rootNode->negative_count_); + + rootNode->negative_count_ = Event::Type::VOID_CLOSE; + rootNode->Update(0, 2, Event::Type::VOID_CLOSE); + ASSERT_EQ(-4, rootNode->negative_count_); + + rootNode->positive_count_ = Event::Type::CLOSE; + rootNode->Update(0, 1, Event::Type::OPEN); + + ASSERT_NE(nullptr, rootNode->left_); + ASSERT_NE(nullptr, rootNode->right_); + ASSERT_EQ(1, rootNode->left_->positive_count_); + ASSERT_EQ(0, rootNode->right_->positive_count_); + + rootNode->Update(1, 2, Event::Type::CLOSE); + ASSERT_EQ(1, rootNode->left_->positive_count_); + ASSERT_EQ(-1, rootNode->right_->positive_count_); + + delete rootNode; +} +/** + * @tc.name: Node::GetAndRange01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Node::GetAndRange + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, GetAndRange01, Function | SmallTest | Level2) +{ + Node* rootNode = new Node(0, 2); + ASSERT_NE(rootNode, nullptr); + rootNode->positive_count_ = 0; + rootNode->negative_count_ = 0; + std::vector res; + rootNode->GetAndRange(res, false, false); + ASSERT_EQ(0, res.size()); + rootNode->GetAndRange(res, true, true); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + rootNode->left_ = new Node { 0, 1 }; + rootNode->left_->positive_count_ = 1; + rootNode->GetAndRange(res, false, true); + ASSERT_EQ(2, res.size()); + ASSERT_EQ(0, res[1].start_); + ASSERT_EQ(1, res[1].end_); + + rootNode->right_ = new Node { 1, 3 }; + rootNode->right_->negative_count_ = 1; + rootNode->GetAndRange(res, true, false); + ASSERT_EQ(2, res.size()); + ASSERT_EQ(0, res[1].start_); + ASSERT_EQ(3, res[1].end_); + + delete rootNode->right_; + rootNode->right_ = new Node { 1, 4 }; + rootNode->right_->positive_count_ = 1; + rootNode->right_->negative_count_ = 1; + rootNode->GetAndRange(res, false, false); + ASSERT_EQ(3, res.size()); + ASSERT_EQ(1, res[2].start_); + ASSERT_EQ(4, res[2].end_); + + delete rootNode; +} +/** + * @tc.name: Node::GetOrRange01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Node::GetOrRange + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, GetOrRange01, Function | SmallTest | Level2) +{ + std::vector res; + Node* rootNode = new Node(0, 2); + ASSERT_NE(rootNode, nullptr); + rootNode->positive_count_ = 0; + rootNode->negative_count_ = 0; + rootNode->GetOrRange(res, true, true); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + res.clear(); + rootNode->GetOrRange(res, true, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + res.clear(); + rootNode->GetOrRange(res, false, true); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + res.clear(); + rootNode->GetOrRange(res, false, false); + ASSERT_EQ(0, res.size()); + + rootNode->left_ = new Node { 0, 1 }; + rootNode->left_->positive_count_ = 0; + rootNode->left_->negative_count_ = 1; + rootNode->GetOrRange(res, false, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res[0].start_); + ASSERT_EQ(1, res[0].end_); + delete rootNode->left_; + rootNode->left_ = nullptr; + + res.clear(); + rootNode->right_ = new Node { 1, 3 }; + rootNode->right_->positive_count_ = 0; + rootNode->right_->negative_count_ = 1; + rootNode->GetOrRange(res, false, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(1, res[0].start_); + ASSERT_EQ(3, res[0].end_); + + delete rootNode; +} +/** + * @tc.name: Node::GetXOrRange01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Node::GetXOrRange + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, GetXOrRange01, Function | SmallTest | Level2) +{ + std::vector res; + Node* rootNode = new Node(0, 2); + ASSERT_NE(rootNode, nullptr); + rootNode->positive_count_ = 0; + rootNode->negative_count_ = 0; + rootNode->GetXOrRange(res, true, true); + ASSERT_EQ(0, res.size()); + + rootNode->GetXOrRange(res, true, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + res.clear(); + rootNode->GetXOrRange(res, false, true); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + res.clear(); + rootNode->GetXOrRange(res, false, false); + ASSERT_EQ(0, res.size()); + + rootNode->left_ = new Node { 0, 1 }; + rootNode->left_->positive_count_ = 0; + rootNode->left_->negative_count_ = 1; + rootNode->GetXOrRange(res, false, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res[0].start_); + ASSERT_EQ(1, res[0].end_); + + delete rootNode->left_; + rootNode->left_ = nullptr; + + res.clear(); + rootNode->right_ = new Node { 1, 3 }; + rootNode->right_->positive_count_ = 0; + rootNode->right_->negative_count_ = 1; + rootNode->GetXOrRange(res, false, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(1, res[0].start_); + ASSERT_EQ(3, res[0].end_); + + delete rootNode; +} +/** + * @tc.name: Node::GetSubRange01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Node::GetSubRange + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, GetSubRange01, Function | SmallTest | Level2) +{ + std::vector res; + Node* rootNode = new Node(0, 2); + ASSERT_NE(rootNode, nullptr); + rootNode->positive_count_ = 0; + rootNode->negative_count_ = 0; + rootNode->GetSubRange(res, true, true); + ASSERT_EQ(0, res.size()); + + rootNode->GetSubRange(res, true, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res.at(0).start_); + ASSERT_EQ(2, res.at(0).end_); + + res.clear(); + rootNode->GetSubRange(res, false, true); + ASSERT_EQ(0, res.size()); + + rootNode->GetSubRange(res, false, false); + ASSERT_EQ(0, res.size()); + + rootNode->left_ = new Node { 0, 1 }; + rootNode->left_->positive_count_ = 1; + rootNode->left_->negative_count_ = 0; + rootNode->GetSubRange(res, false, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(0, res[0].start_); + ASSERT_EQ(1, res[0].end_); + + delete rootNode->left_; + rootNode->left_ = nullptr; + + res.clear(); + rootNode->right_ = new Node { 1, 3 }; + rootNode->right_->positive_count_ = 1; + rootNode->right_->negative_count_ = 0; + rootNode->GetSubRange(res, false, false); + ASSERT_EQ(1, res.size()); + ASSERT_EQ(1, res[0].start_); + ASSERT_EQ(3, res[0].end_); + + delete rootNode; +} +/** + * @tc.name: Region::UpdateRects01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Region::UpdateRects + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, UpdateRects01, Function | SmallTest | Level2) +{ + Region* region = new Region(); + ASSERT_NE(region, nullptr); + Region::Rects rects; + rects.preRects = { + Rect{0, 10, 1, 10}, + Rect{3, 10, 1, 10}, + Rect{1, 10, 3, 10}, + }; + std::vector ranges = { + Range{0, 1}, + Range{1, 2}, + Range{3, 4}, + }; + std::vector indexAt = { + 0, 1, 2, 2, 3 + }; + Region regionRes; + region->UpdateRects(rects, ranges, indexAt, regionRes); + + std::vector resultPreRectsLeft = { 0, 1, 2, 10 }; + ASSERT_EQ(3, rects.preRects.size()); + for (uint32_t i = 0; i < rects.preRects.size(); ++i) { + ASSERT_EQ(resultPreRectsLeft[i], rects.preRects[i].left_); + } + ASSERT_EQ(2, regionRes.GetRegionRects().size()); + auto regionRects = regionRes.GetRegionRects(); + std::vector resultRegionRectsLeft = { 3, 1, 10, }; + for (uint32_t i = 0; i < regionRects.size(); ++i) { + ASSERT_EQ(resultRegionRectsLeft[i], regionRects[i].left_); + } + delete region; +} +/** + * @tc.name: Region::MakeBound01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Region::MakeBound + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, MakeBound01, Function | SmallTest | Level2) +{ + Region* region = new Region(); + ASSERT_NE(region, nullptr); + region->bound_ = { 10, 10, 10, 10 }; + region->rects_.clear(); + region->MakeBound(); + ASSERT_EQ(10, region->bound_.left_); + ASSERT_EQ(10, region->bound_.top_); + ASSERT_EQ(10, region->bound_.right_); + ASSERT_EQ(10, region->bound_.bottom_); + + region->rects_ = { + Rect{5, 5, 5, 5}, + Rect{6, 4, 6, 6}, + Rect{7, 6, 2, 8}, + Rect{8, 7, 7, 3}, + }; + region->MakeBound(); + ASSERT_EQ(5, region->bound_.left_); + ASSERT_EQ(4, region->bound_.top_); + ASSERT_EQ(7, region->bound_.right_); + ASSERT_EQ(8, region->bound_.bottom_); + + delete region; +} +/** + * @tc.name: Region::RegionOpLocal01 + * @tc.desc: test WmOcclusionRegion WmOcclusion::Region::RegionOpLocal + * @tc.type: FUNC + */ +HWTEST_F(WmOcclusionRegionTest, RegionOpLocal01, Function | SmallTest | Level2) +{ + Region regionBase; + Region region1; + Region region2; + Region regionRes; + Region::OP op = Region::OP::SUB; + regionRes.rects_.emplace_back(Rect{ 10, 10, 10, 10 }); + regionBase.RegionOpLocal(region1, region2, regionRes, op); + ASSERT_EQ(0, regionRes.GetRegionRects().size()); + + region1.rects_.emplace_back(Rect{ 6, 7, 8, 9, }); + region1.rects_.emplace_back(Rect{ 10, 9, 8, 7, }); + region1.rects_.emplace_back(Rect{ 5, 6, 7, 8, }); + region1.rects_.emplace_back(Rect{ 11, 10, 9, 8, }); + regionBase.RegionOpLocal(region1, region2, regionRes, op); + ASSERT_EQ(3, regionRes.GetRegionRects().size()); +} +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/windowmanager_aafwk.gni b/window_manager/windowmanager_aafwk.gni new file mode 100644 index 0000000..ff4753a --- /dev/null +++ b/window_manager/windowmanager_aafwk.gni @@ -0,0 +1,31 @@ +# 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. + +ability_runtime_path = "//foundation/ability/ability_runtime" +ability_runtime_inner_api_path = "${ability_runtime_path}/interfaces/inner_api" +ability_runtime_kits_path = "${ability_runtime_path}/frameworks/kits" +ability_runtime_services_path = "${ability_runtime_path}/services" +ability_runtime_napi_path = "${ability_runtime_path}/frameworks/js/napi" + +declare_args() { + efficiency_manager_enable = true + window_manager_feature_subscribe_motion = false + + if (defined(global_parts_info) && + !defined(global_parts_info.resourceschedule_efficiency_manager)) { + efficiency_manager_enable = false + } +} + +print( + "window_manager_feature_subscribe_motion = ${window_manager_feature_subscribe_motion}") diff --git a/window_manager/wm/BUILD.gn b/window_manager/wm/BUILD.gn new file mode 100644 index 0000000..b7ef383 --- /dev/null +++ b/window_manager/wm/BUILD.gn @@ -0,0 +1,134 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") + +config("libwm_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "../wmserver/include", + "//foundation/arkui/napi", # because of ability_context.h + ] +} + +config("libwm_public_config") { + include_dirs = [ + "../interfaces/innerkits/wm", + "../utils/include", + ] +} + +## Build libwm.so +ohos_shared_library("libwm") { + + sources = [ + "../wmserver/src/zidl/window_manager_proxy.cpp", + "src/color_parser.cpp", + "src/input_transfer_station.cpp", + "src/static_call.cpp", + "src/vsync_station.cpp", + "src/window.cpp", + "src/window_accessibility_controller.cpp", + "src/window_adapter.cpp", + "src/window_agent.cpp", + "src/window_frame_trace_impl.cpp", + "src/window_impl.cpp", + "src/window_input_channel.cpp", + "src/window_manager.cpp", + "src/window_manager_agent.cpp", + "src/window_option.cpp", + "src/window_scene.cpp", + "src/zidl/window_manager_agent_stub.cpp", + "src/zidl/window_stub.cpp", + ] + + configs = [ + ":libwm_private_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + public_configs = [ ":libwm_public_config" ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/utils:libwmutil", + ] + + external_deps = [ + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ace_engine:ace_uicontent", + "c_utils:utils", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "input:libmmi-client", + "ipc:ipc_core", + "multimedia_image_framework:image_native", + "samgr:samgr_proxy", + ] + + defines = [] + if (efficiency_manager_enable) { + external_deps += [ "efficiency_manager:suspend_manager_client" ] + defines += [ "EFFICIENCY_MANAGER_ENABLE" ] + } + + if (defined(global_parts_info)) { + if (defined(global_parts_info.resourceschedule_frame_aware_sched) || + defined(global_parts_info.hmosresourceschedule_resourceschedule_frame_aware_sched_override)) { + defines += [ "FRAME_TRACE_ENABLE" ] + deps += [ "//foundation/resourceschedule/frame_aware_sched/interfaces/innerkits/frameintf:frame_trace_intf" ] + include_dirs = [ "//foundation/resourceschedule/frame_aware_sched/interfaces/innerkits/frameintf" ] + } + } + + if (!defined(global_parts_info) || + defined(global_parts_info.resourceschedule_resource_schedule_service)) { + soc_perf_enable = true + } else { + soc_perf_enable = false + } + print("soc_perf_enable: ", soc_perf_enable) + + if (soc_perf_enable == true) { + external_deps += [ "resource_schedule_service:ressched_client" ] + defines += [ "SOC_PERF_ENABLE" ] + } + + if (!defined(global_parts_info) || + defined(global_parts_info.inputmethod_imf)) { + imf_enable = true + } else { + imf_enable = false + } + print("imf_enable: ", imf_enable) + + if (imf_enable == true) { + external_deps += [ "imf:inputmethod_client" ] + defines += [ "IMF_ENABLE" ] + } + + part_name = "window_manager" + subsystem_name = "window" +} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/wm/include/README.md b/window_manager/wm/include/README.md new file mode 100644 index 0000000..f0321dc --- /dev/null +++ b/window_manager/wm/include/README.md @@ -0,0 +1 @@ +Store code of window client inner header files diff --git a/window_manager/wm/include/color_parser.h b/window_manager/wm/include/color_parser.h new file mode 100644 index 0000000..4f2b4b0 --- /dev/null +++ b/window_manager/wm/include/color_parser.h @@ -0,0 +1,35 @@ +/* + * 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_ROSEN_COLOR_PARSER_H +#define OHOS_ROSEN_COLOR_PARSER_H + +#include + +namespace OHOS { +namespace Rosen { +class ColorParser { +public: + static bool Parse(const std::string& colorStr, uint32_t& colorValue); + +private: + static bool IsValidHexString(const std::string& colorStr); + + ColorParser() = default; + ~ColorParser() = default; +}; +} +} +#endif // OHOS_ROSEN_COLOR_PARSER_H diff --git a/window_manager/wm/include/input_transfer_station.h b/window_manager/wm/include/input_transfer_station.h new file mode 100644 index 0000000..fa64191 --- /dev/null +++ b/window_manager/wm/include/input_transfer_station.h @@ -0,0 +1,58 @@ +/* + * 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_INPUT_TRANSFER_STATION_H +#define OHOS_INPUT_TRANSFER_STATION_H + +#include "input_manager.h" +#include "pointer_event.h" +#include "window.h" +#include "window_input_channel.h" +#include "wm_single_instance.h" +#include "vsync_station.h" + +namespace OHOS { +namespace Rosen { +class InputEventListener; + +class InputTransferStation { +WM_DECLARE_SINGLE_INSTANCE(InputTransferStation); +friend class InputEventListener; +public: + void AddInputWindow(const sptr& window); + void RemoveInputWindow(uint32_t windowId); + +private: + sptr GetInputChannel(uint32_t windowId); + + std::mutex mtx_; + std::unordered_map> windowInputChannels_; + std::shared_ptr inputListener_ = nullptr; + std::shared_ptr eventHandler_ = nullptr; + const std::string INPUT_AND_VSYNC_THREAD = "InputAndVsyncThread"; +}; + +class InputEventListener : public MMI::IInputEventConsumer { +public: + InputEventListener() = default; + void OnInputEvent(std::shared_ptr pointerEvent) const override; + void OnInputEvent(std::shared_ptr keyEvent) const override; + void OnInputEvent(std::shared_ptr axisEvent) const override; +}; +} // namespace Rosen +} // namespace OHOS + + +#endif // OHOS_INPUT_TRANSFER_STATION_H diff --git a/window_manager/wm/include/ressched_report.h b/window_manager/wm/include/ressched_report.h new file mode 100644 index 0000000..6efe691 --- /dev/null +++ b/window_manager/wm/include/ressched_report.h @@ -0,0 +1,156 @@ +/* + * 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_ROSEN_RESSCHED_REPORT_H +#define OHOS_ROSEN_RESSCHED_REPORT_H + +#ifdef SOC_PERF_ENABLE +#include "event_handler.h" +#include "res_sched_client.h" +#endif +#include "window_helper.h" +#include "wm_common.h" +#include "wm_single_instance.h" + +namespace OHOS { +namespace Rosen { +#ifdef SOC_PERF_ENABLE +namespace { + constexpr int64_t PERF_TIME_OUT = 200; + constexpr int64_t SLIDE_PERF_TIME_OUT = 1000; + constexpr int32_t PERF_CLICK_NORMAL_CODE = 9; + constexpr int32_t PERF_DRAG_CODE = 31; + constexpr int32_t PERF_MOVE_CODE = 32; + constexpr int32_t PERF_SLIDE_CODE = 34; + const std::string TASK_NAME = "SlideOff"; +} +#endif + +class ResSchedReport { + WM_DECLARE_SINGLE_INSTANCE(ResSchedReport); + public: + void StopPerfIfNeed() + { +#ifdef SOC_PERF_ENABLE + if (windowDragBoost_) { + ClosePerf(PERF_DRAG_CODE); + windowDragBoost_ = false; + } + if (windowMovingBoost_) { + ClosePerf(PERF_MOVE_CODE); + windowMovingBoost_ = false; + } +#endif + } + + void TrigClick() + { +#ifdef SOC_PERF_ENABLE + std::unordered_map mapPayload; + // 2 means click event. + OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(PERF_CLICK_NORMAL_CODE, 2, mapPayload); +#endif + } + + void RequestPerfIfNeed(WindowSizeChangeReason reason, WindowType type, WindowMode mode) + { +#ifdef SOC_PERF_ENABLE + if (WindowHelper::IsMainFloatingWindow(type, mode) || WindowHelper::IsSplitWindowMode(mode)) { + switch (reason) { + case WindowSizeChangeReason::DRAG_END: { + if (windowDragBoost_) { + ClosePerf(PERF_DRAG_CODE); + windowDragBoost_ = false; + } + break; + } + case WindowSizeChangeReason::DRAG_START: + [[fallthrough]]; + case WindowSizeChangeReason::DRAG: { + RequestPerf(PERF_DRAG_CODE, PERF_TIME_OUT); + windowDragBoost_ = true; + break; + } + case WindowSizeChangeReason::MOVE: { + RequestPerf(PERF_MOVE_CODE, PERF_TIME_OUT); + windowMovingBoost_ = true; + break; + } + default: { + // doing nothing + } + } + } +#endif + } + + void TrigSlide(WindowType type, bool isOn) + { +#ifdef SOC_PERF_ENABLE + if (type != WindowType::WINDOW_TYPE_STATUS_BAR) { + return; + } + static auto lastRequestPerfTime = std::chrono::steady_clock::now(); + static auto eventRunner = AppExecFwk::EventRunner::GetMainEventRunner(); + static auto handler = std::make_shared(eventRunner); + static auto task = []() { + std::unordered_map mapPayload; + OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(PERF_SLIDE_CODE, 1, mapPayload); + }; + auto current = std::chrono::steady_clock::now(); + bool isTimeOut = std::chrono::duration_cast(current - lastRequestPerfTime). + count() > SLIDE_PERF_TIME_OUT; + if (isTimeOut && isOn) { + handler->RemoveTask(TASK_NAME); + lastRequestPerfTime = current; + std::unordered_map mapPayload; + OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(PERF_SLIDE_CODE, 0, mapPayload); + } + if (!isTimeOut && !isOn) { + // 500 is the animation duration. + handler->PostTask(task, TASK_NAME, 500, AppExecFwk::EventQueue::Priority::HIGH); + } +#endif + } +private: +#ifdef SOC_PERF_ENABLE + void RequestPerf(int32_t code, int64_t timeOut) + { + auto currentTime = std::chrono::steady_clock::now(); + bool isTimeOut = std::chrono::duration_cast(currentTime - lastRequestPerfTime_). + count() > timeOut; + if (isTimeOut) { + std::unordered_map mapPayload; + // 0 means doing action. + OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(code, 0, mapPayload); + lastRequestPerfTime_ = currentTime; + } + } + + void ClosePerf(int32_t code) + { + std::unordered_map mapPayload; + // 1 means stop action. + OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(code, 1, mapPayload); + } + + std::chrono::steady_clock::time_point lastRequestPerfTime_ = std::chrono::steady_clock::now(); + bool windowMovingBoost_ = false; + bool windowDragBoost_ = false; +#endif +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_RESSCHED_REPORT_H diff --git a/window_manager/wm/include/static_call.h b/window_manager/wm/include/static_call.h new file mode 100644 index 0000000..1e27d9d --- /dev/null +++ b/window_manager/wm/include/static_call.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-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_STATIC_CALL_H +#define OHOS_STATIC_CALL_H + +#include +#include "singleton_delegator.h" +#include "wm_single_instance.h" +#include "window.h" +#include "window_option.h" +namespace OHOS { +namespace Rosen { +class StaticCall { +WM_DECLARE_SINGLE_INSTANCE_BASE(StaticCall); +public: + virtual sptr CreateWindow(const std::string& windowName, + sptr& option, std::shared_ptr context = nullptr); + virtual std::vector> GetSubWindow(uint32_t parentId); +protected: + StaticCall() = default; +private: + static inline SingletonDelegator delegator_; +}; +} // namespace ROSEN +} // namespace OHOS + +#endif // FRAMEWORKS_WM_TEST_UT_STATIC_CALL_H \ No newline at end of file diff --git a/window_manager/wm/include/vsync_station.h b/window_manager/wm/include/vsync_station.h new file mode 100644 index 0000000..6d9f556 --- /dev/null +++ b/window_manager/wm/include/vsync_station.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021-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_VSYNC_STATION_H +#define OHOS_VSYNC_STATION_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "wm_common.h" +#include "wm_single_instance.h" + +namespace OHOS { +namespace Rosen { +class VsyncStation { +WM_DECLARE_SINGLE_INSTANCE_BASE(VsyncStation); +public: + ~VsyncStation() = default; + void RequestVsync(const std::shared_ptr& vsyncCallback); + void RemoveCallback(); + void SetIsMainHandlerAvailable(bool available) + { + isMainHandlerAvailable_ = available; + } + + void SetVsyncEventHandler(const std::shared_ptr& eventHandler) + { + vsyncHandler_ = eventHandler; + } + +private: + VsyncStation() = default; + static void OnVsync(int64_t nanoTimestamp, void* client); + void VsyncCallbackInner(int64_t nanoTimestamp); + void OnVsyncTimeOut(); + + std::mutex mtx_; + bool hasRequestedVsync_ = false; + bool hasInitVsyncReceiver_ = false; + bool isMainHandlerAvailable_ = true; + const std::string VSYNC_THREAD_ID = "VsyncThread"; + std::shared_ptr receiver_ = nullptr; + std::unordered_set> vsyncCallbacks_; + VSyncReceiver::FrameCallback frameCallback_ = { + .userData_ = this, + .callback_ = OnVsync, + }; + std::shared_ptr vsyncHandler_ = nullptr; + AppExecFwk::EventHandler::Callback vsyncTimeoutCallback_ = std::bind(&VsyncStation::OnVsyncTimeOut, this); +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_VSYNC_STATION_H \ No newline at end of file diff --git a/window_manager/wm/include/window_adapter.h b/window_manager/wm/include/window_adapter.h new file mode 100644 index 0000000..a6836d8 --- /dev/null +++ b/window_manager/wm/include/window_adapter.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021-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_WINDOW_ADAPTER_H +#define OHOS_WINDOW_ADAPTER_H + +#include +#include + +#include "window.h" +#include "zidl/window_interface.h" +#include "singleton_delegator.h" +#include "window_property.h" +#include "wm_single_instance.h" +#include "zidl/window_manager_interface.h" +namespace OHOS { +namespace Rosen { +class WMSDeathRecipient : public IRemoteObject::DeathRecipient { +public: + virtual void OnRemoteDied(const wptr& wptrDeath) override; +}; + +class WindowAdapter { +WM_DECLARE_SINGLE_INSTANCE(WindowAdapter); +public: + virtual WMError CreateWindow(sptr& window, sptr& windowProperty, + std::shared_ptr surfaceNode, uint32_t& windowId, const sptr& token); + virtual WMError AddWindow(sptr& windowProperty); + virtual WMError RemoveWindow(uint32_t windowId); + virtual WMError DestroyWindow(uint32_t windowId); + virtual WMError RequestFocus(uint32_t windowId); + virtual WMError GetAvoidAreaByType(uint32_t windowId, AvoidAreaType type, AvoidArea& avoidRect); + virtual WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId); + virtual void NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty); + virtual void ProcessPointDown(uint32_t windowId, bool isPointDown = true); + virtual void ProcessPointUp(uint32_t windowId); + virtual void MinimizeAllAppWindows(DisplayId displayId); + virtual WMError ToggleShownStateForAllAppWindows(); + virtual WMError SetWindowLayoutMode(WindowLayoutMode mode); + virtual WMError UpdateProperty(sptr& windowProperty, PropertyChangeAction action); + virtual WMError GetSystemConfig(SystemConfig& systemConfig); + virtual WMError GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones); + virtual WMError UpdateRsTree(uint32_t windowId, bool isAdd); + virtual WMError BindDialogTarget(uint32_t& windowId, sptr targetToken); + virtual bool RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent); + virtual bool UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent); + + virtual WMError SetWindowAnimationController(const sptr& controller); + virtual WMError NotifyWindowTransition(sptr from, sptr to); + virtual WMError UpdateAvoidAreaListener(uint32_t windowId, bool haveListener); + virtual void ClearWindowAdapter(); + + virtual WMError GetAccessibilityWindowInfo(std::vector>& infos); + virtual WMError GetVisibilityWindowInfo(std::vector>& infos); + virtual void MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback); + virtual void SetAnchorAndScale(int32_t x, int32_t y, float scale); + virtual void SetAnchorOffset(int32_t deltaX, int32_t deltaY); + virtual void OffWindowZoom(); + virtual std::shared_ptr GetSnapshot(int32_t windowId); + virtual void NotifyDumpInfoResult(const std::vector& info); +private: + static inline SingletonDelegator delegator; + bool InitWMSProxy(); + + std::recursive_mutex mutex_; + sptr windowManagerServiceProxy_ = nullptr; + sptr wmsDeath_ = nullptr; + bool isProxyValid_ { false }; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_ADAPTER_H diff --git a/window_manager/wm/include/window_agent.h b/window_manager/wm/include/window_agent.h new file mode 100644 index 0000000..74e872d --- /dev/null +++ b/window_manager/wm/include/window_agent.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-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_WINDOW_AGENT_H +#define OHOS_WINDOW_AGENT_H + +#include "zidl/window_stub.h" +#include "window_impl.h" +#include "window_property.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowAgent : public WindowStub { +public: + explicit WindowAgent(sptr& window); + ~WindowAgent() = default; + WMError UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) override; + WMError UpdateWindowMode(WindowMode mode) override; + WMError UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) override; + WMError UpdateFocusStatus(bool focused) override; + WMError UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) override; + WMError UpdateWindowState(WindowState state) override; + WMError UpdateWindowDragInfo(const PointInfo& point, DragEvent event) override; + WMError UpdateDisplayId(DisplayId from, DisplayId to) override; + WMError UpdateOccupiedAreaChangeInfo(const sptr& info) override; + WMError UpdateActiveStatus(bool isActive) override; + sptr GetWindowProperty() override; + WMError NotifyTouchOutside() override; + WMError NotifyScreenshot() override; + WMError DumpInfo(const std::vector& params) override; + WMError NotifyDestroy(void) override; + WMError NotifyForeground(void) override; + WMError NotifyBackground(void) override; + WMError NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) override; + WMError UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) override; + WMError RestoreSplitWindowMode(uint32_t mode) override; +private: + sptr window_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_AGENT_H diff --git a/window_manager/wm/include/window_frame_trace.h b/window_manager/wm/include/window_frame_trace.h new file mode 100644 index 0000000..bf59318 --- /dev/null +++ b/window_manager/wm/include/window_frame_trace.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021-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_WINDOW_FRAME_TRACE_H +#define OHOS_WINDOW_FRAME_TRACE_H + +#include +namespace FRAME_TRACE { + +struct TraceHandle; + +class WindowFrameTrace { +public: + WindowFrameTrace() = default; + virtual ~WindowFrameTrace() = default; + virtual void VsyncStartFrameTrace() {} + virtual void VsyncStopFrameTrace() {} +}; + +class WindowFrameTraceImpl : public WindowFrameTrace { +public: + WindowFrameTraceImpl() = default; + ~WindowFrameTraceImpl() override = default; + static WindowFrameTraceImpl* GetInstance(); +#ifdef FRAME_TRACE_ENABLE + void VsyncStartFrameTrace() override; + void VsyncStopFrameTrace() override; + +private: + bool judgeFrameTrace_ = false; + bool accessFrameTrace_ = false; + struct TraceHandle* handleUI_ = nullptr; + std::string intervalName_ = "ui"; + + bool AccessFrameTrace(); +#endif +}; +} // namespace FRAME_TRACE +#endif // OHOS_WINDOW_FRAME_TRACE_H diff --git a/window_manager/wm/include/window_impl.h b/window_manager/wm/include/window_impl.h new file mode 100644 index 0000000..6f1f55f --- /dev/null +++ b/window_manager/wm/include/window_impl.h @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_IMPL_H +#define OHOS_ROSEN_WINDOW_IMPL_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "input_transfer_station.h" +#include "vsync_station.h" +#include "window.h" +#include "window_property.h" +#include "window_transition_info.h" +#include "wm_common_inner.h" +#include "wm_common.h" + +using OHOS::AppExecFwk::DisplayOrientation; + +namespace OHOS { +namespace Rosen { +union ColorParam { +#if BIG_ENDIANNESS + struct { + uint8_t alpha; + uint8_t red; + uint8_t green; + uint8_t blue; + } argb; +#else + struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + } argb; +#endif + uint32_t value; +}; + +const std::map ABILITY_TO_WMS_ORIENTATION_MAP { + {DisplayOrientation::UNSPECIFIED, Orientation::UNSPECIFIED }, + {DisplayOrientation::LANDSCAPE, Orientation::HORIZONTAL }, + {DisplayOrientation::PORTRAIT, Orientation::VERTICAL }, + {DisplayOrientation::FOLLOWRECENT, Orientation::UNSPECIFIED }, + {DisplayOrientation::LANDSCAPE_INVERTED, Orientation::REVERSE_HORIZONTAL }, + {DisplayOrientation::PORTRAIT_INVERTED, Orientation::REVERSE_VERTICAL }, + {DisplayOrientation::AUTO_ROTATION, Orientation::SENSOR }, + {DisplayOrientation::AUTO_ROTATION_LANDSCAPE, Orientation::SENSOR_HORIZONTAL }, + {DisplayOrientation::AUTO_ROTATION_PORTRAIT, Orientation::SENSOR_VERTICAL }, + {DisplayOrientation::AUTO_ROTATION_RESTRICTED, Orientation::AUTO_ROTATION_RESTRICTED }, + {DisplayOrientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED, Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED }, + {DisplayOrientation::AUTO_ROTATION_PORTRAIT_RESTRICTED, Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED }, + {DisplayOrientation::LOCKED, Orientation::LOCKED }, +}; + +class WindowImpl : public Window { +#define CALL_LIFECYCLE_LISTENER(windowLifecycleCb, listeners) \ + do { \ + for (auto& listener : (listeners)) { \ + if (listener.GetRefPtr() != nullptr) { \ + listener.GetRefPtr()->windowLifecycleCb(); \ + } \ + } \ + } while (0) + +#define CALL_LIFECYCLE_LISTENER_WITH_PARAM(windowLifecycleCb, listeners, param) \ + do { \ + for (auto& listener : (listeners)) { \ + if (listener.GetRefPtr() != nullptr) { \ + listener.GetRefPtr()->windowLifecycleCb(param); \ + } \ + } \ + } while (0) + +#define CALL_UI_CONTENT(uiContentCb) \ + do { \ + if (uiContent_ != nullptr) { \ + uiContent_->uiContentCb(); \ + } \ + } while (0) + +public: + explicit WindowImpl(const sptr& option); + ~WindowImpl(); + + static sptr Find(const std::string& id); + static sptr GetTopWindowWithContext(const std::shared_ptr& context = nullptr); + static sptr GetTopWindowWithId(uint32_t mainWinId); + static std::vector> GetSubWindow(uint32_t parantId); + static void UpdateConfigurationForAll(const std::shared_ptr& configuration); + virtual std::shared_ptr GetSurfaceNode() const override; + virtual Rect GetRect() const override; + virtual Rect GetRequestRect() const override; + virtual WindowType GetType() const override; + virtual WindowMode GetMode() const override; + virtual float GetAlpha() const override; + virtual WindowState GetWindowState() const override; + virtual WMError SetFocusable(bool isFocusable) override; + virtual bool GetFocusable() const override; + virtual WMError SetTouchable(bool isTouchable) override; + virtual bool GetTouchable() const override; + virtual const std::string& GetWindowName() const override; + virtual uint32_t GetWindowId() const override; + virtual uint32_t GetWindowFlags() const override; + uint32_t GetRequestModeSupportInfo() const override; + bool IsMainHandlerAvailable() const override; + inline NotifyNativeWinDestroyFunc GetNativeDestroyCallback() + { + return notifyNativefunc_; + } + virtual SystemBarProperty GetSystemBarPropertyByType(WindowType type) const override; + virtual bool IsFullScreen() const override; + virtual bool IsLayoutFullScreen() const override; + virtual WMError SetWindowType(WindowType type) override; + virtual WMError SetWindowMode(WindowMode mode) override; + virtual void SetAlpha(float alpha) override; + virtual void SetTransform(const Transform& trans) override; + virtual WMError AddWindowFlag(WindowFlag flag) override; + virtual WMError RemoveWindowFlag(WindowFlag flag) override; + virtual WMError SetWindowFlags(uint32_t flags) override; + virtual WMError SetSystemBarProperty(WindowType type, const SystemBarProperty& property) override; + virtual WMError UpdateSystemBarProperty(bool status); + virtual WMError SetLayoutFullScreen(bool status) override; + virtual WMError SetFullScreen(bool status) override; + virtual const Transform& GetTransform() const override; + virtual const Transform& GetZoomTransform() const; + virtual WMError UpdateSurfaceNodeAfterCustomAnimation(bool isAdd) override; + inline void SetWindowState(WindowState state) + { + state_ = state; + } + virtual WMError GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea) override; + + WMError Create(uint32_t parentId, + const std::shared_ptr& context = nullptr); + virtual WMError Destroy() override; + virtual WMError Show(uint32_t reason = 0, bool withAnimation = false) override; + virtual WMError Hide(uint32_t reason = 0, bool withAnimation = false) override; + virtual WMError MoveTo(int32_t x, int32_t y) override; + virtual WMError Resize(uint32_t width, uint32_t height) override; + virtual WMError SetKeepScreenOn(bool keepScreenOn) override; + virtual bool IsKeepScreenOn() const override; + virtual WMError SetTurnScreenOn(bool turnScreenOn) override; + virtual bool IsTurnScreenOn() const override; + virtual WMError SetBackgroundColor(const std::string& color) override; + virtual WMError SetTransparent(bool isTransparent) override; + virtual bool IsTransparent() const override; + virtual WMError SetBrightness(float brightness) override; + virtual float GetBrightness() const override; + virtual WMError SetCallingWindow(uint32_t windowId) override; + virtual void SetPrivacyMode(bool isPrivacyMode) override; + virtual bool IsPrivacyMode() const override; + virtual void SetSystemPrivacyMode(bool isSystemPrivacyMode) override; + virtual void DisableAppWindowDecor() override; + virtual WMError BindDialogTarget(sptr targetToken) override; + virtual void SetSnapshotSkip(bool isSkip) override; + + // window effect + virtual WMError SetCornerRadius(float cornerRadius) override; + virtual WMError SetShadowRadius(float radius) override; + virtual WMError SetShadowColor(std::string color) override; + virtual void SetShadowOffsetX(float offsetX) override; + virtual void SetShadowOffsetY(float offsetY) override; + virtual WMError SetBlur(float radius) override; + virtual WMError SetBackdropBlur(float radius) override; + virtual WMError SetBackdropBlurStyle(WindowBlurStyle blurStyle) override; + + virtual bool IsDecorEnable() const override; + virtual WMError Maximize() override; + virtual WMError Minimize() override; + virtual WMError Recover() override; + virtual WMError Close() override; + virtual void StartMove() override; + + virtual WMError RequestFocus() const override; + virtual void SetInputEventConsumer(const std::shared_ptr& inputEventConsumer) override; + + virtual bool RegisterLifeCycleListener(const sptr& listener) override; + virtual bool RegisterWindowChangeListener(const sptr& listener) override; + virtual bool UnregisterLifeCycleListener(const sptr& listener) override; + virtual bool UnregisterWindowChangeListener(const sptr& listener) override; + virtual bool RegisterAvoidAreaChangeListener(sptr& listener) override; + virtual bool UnregisterAvoidAreaChangeListener(sptr& listener) override; + virtual bool RegisterDragListener(const sptr& listener) override; + virtual bool UnregisterDragListener(const sptr& listener) override; + virtual bool RegisterDisplayMoveListener(sptr& listener) override; + virtual bool UnregisterDisplayMoveListener(sptr& listener) override; + virtual void RegisterWindowDestroyedListener(const NotifyNativeWinDestroyFunc& func) override; + virtual bool RegisterOccupiedAreaChangeListener(const sptr& listener) override; + virtual bool UnregisterOccupiedAreaChangeListener(const sptr& listener) override; + virtual bool RegisterTouchOutsideListener(const sptr& listener) override; + virtual bool UnregisterTouchOutsideListener(const sptr& listener) override; + virtual bool RegisterAnimationTransitionController(const sptr& listener) override; + virtual bool RegisterScreenshotListener(const sptr& listener) override; + virtual bool UnregisterScreenshotListener(const sptr& listener) override; + virtual bool RegisterDialogTargetTouchListener(const sptr& listener) override; + virtual bool UnregisterDialogTargetTouchListener(const sptr& listener) override; + virtual void RegisterDialogDeathRecipientListener(const sptr& listener) override; + virtual void UnregisterDialogDeathRecipientListener(const sptr& listener) override; + virtual void SetAceAbilityHandler(const sptr& handler) override; + virtual void SetRequestModeSupportInfo(uint32_t modeSupportInfo) override; + void UpdateRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason); + void UpdateMode(WindowMode mode); + void UpdateModeSupportInfo(uint32_t modeSupportInfo); + virtual void ConsumeKeyEvent(std::shared_ptr& inputEvent) override; + virtual void ConsumePointerEvent(const std::shared_ptr& inputEvent) override; + virtual void RequestVsync(const std::shared_ptr& vsyncCallback) override; + void UpdateFocusStatus(bool focused); + virtual bool IsFocused() const override; + virtual void UpdateConfiguration(const std::shared_ptr& configuration) override; + void UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type); + void UpdateWindowState(WindowState state); + sptr GetWindowProperty(); + void UpdateDragEvent(const PointInfo& point, DragEvent event); + void UpdateDisplayId(DisplayId from, DisplayId to); + void UpdateOccupiedAreaChangeInfo(const sptr& info); + void UpdateActiveStatus(bool isActive); + void NotifyTouchOutside(); + void NotifyScreenshot(); + void NotifyTouchDialogTarget() override; + void NotifyDestroy(); + void NotifyForeground(); + void NotifyBackground(); + void UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn); + + virtual WMError SetUIContent(const std::string& contentInfo, NativeEngine* engine, + NativeValue* storage, bool isdistributed, AppExecFwk::Ability* ability) override; + virtual std::string GetContentInfo() override; + virtual const std::shared_ptr GetContext() const override; + virtual Ace::UIContent* GetUIContent() const override; + virtual void OnNewWant(const AAFwk::Want& want) override; + virtual void SetRequestedOrientation(Orientation) override; + virtual Orientation GetRequestedOrientation() override; + virtual void SetNeedRemoveWindowInputChannel(bool needRemoveWindowInputChannel) override; + virtual WMError SetTouchHotAreas(const std::vector& rects) override; + virtual void GetRequestedTouchHotAreas(std::vector& rects) const override; + virtual WMError SetAPPWindowLabel(const std::string& label) override; + virtual WMError SetAPPWindowIcon(const std::shared_ptr& icon) override; + + // colorspace, gamut + virtual bool IsSupportWideGamut() override; + virtual void SetColorSpace(ColorSpace colorSpace) override; + virtual ColorSpace GetColorSpace() override; + + virtual void DumpInfo(const std::vector& params, std::vector& info) override; + virtual std::shared_ptr Snapshot() override; + virtual WMError NotifyMemoryLevel(int32_t level) const override; + virtual bool IsAllowHaveSystemSubWindow() override; + void RestoreSplitWindowMode(uint32_t mode); +private: + template + using EnableIfSame = typename std::enable_if, Ret>::type; + template bool RegisterListener(std::vector>& holder, const sptr& listener); + template bool UnregisterListener(std::vector>& holder, const sptr& listener); + template void ClearUselessListeners(std::map& listeners, uint32_t winId) + { + listeners.erase(winId); + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> lifecycleListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : lifecycleListeners_[GetWindowId()]) { + lifecycleListeners.push_back(listener); + } + } + return lifecycleListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> windowChangeListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : windowChangeListeners_[GetWindowId()]) { + windowChangeListeners.push_back(listener); + } + } + return windowChangeListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> avoidAreaChangeListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : avoidAreaChangeListeners_[GetWindowId()]) { + avoidAreaChangeListeners.push_back(listener); + } + } + return avoidAreaChangeListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> displayMoveListeners; + { + std::lock_guard lock(mutex_); + for (auto& listener : displayMoveListeners_) { + displayMoveListeners.push_back(listener); + } + } + return displayMoveListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> screenshotListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : screenshotListeners_[GetWindowId()]) { + screenshotListeners.push_back(listener); + } + } + return screenshotListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> touchOutsideListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : touchOutsideListeners_[GetWindowId()]) { + touchOutsideListeners.push_back(listener); + } + } + return touchOutsideListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> dialogTargetTouchListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : dialogTargetTouchListeners_[GetWindowId()]) { + dialogTargetTouchListeners.push_back(listener); + } + } + return dialogTargetTouchListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> windowDragListeners; + { + std::lock_guard lock(mutex_); + for (auto& listener : windowDragListeners_) { + windowDragListeners.push_back(listener); + } + } + return windowDragListeners; + } + template + inline EnableIfSame>> GetListeners() + { + std::vector> occupiedAreaChangeListeners; + { + std::lock_guard lock(globalMutex_); + for (auto& listener : occupiedAreaChangeListeners_[GetWindowId()]) { + occupiedAreaChangeListeners.push_back(listener); + } + } + return occupiedAreaChangeListeners; + } + template + inline EnableIfSame> GetListener() + { + std::lock_guard lock(globalMutex_); + return dialogDeathRecipientListener_[GetWindowId()]; + } + inline void NotifyAfterForeground(bool needNotifyUiContent = true) + { + auto lifecycleListeners = GetListeners(); + CALL_LIFECYCLE_LISTENER(AfterForeground, lifecycleListeners); + if (needNotifyUiContent) { + CALL_UI_CONTENT(Foreground); + } + } + inline void NotifyAfterBackground() + { + auto lifecycleListeners = GetListeners(); + CALL_LIFECYCLE_LISTENER(AfterBackground, lifecycleListeners); + CALL_UI_CONTENT(Background); + } + inline void NotifyAfterFocused() + { + auto lifecycleListeners = GetListeners(); + CALL_LIFECYCLE_LISTENER(AfterFocused, lifecycleListeners); + CALL_UI_CONTENT(Focus); + } + inline void NotifyAfterUnfocused(bool needNotifyUiContent = true) + { + auto lifecycleListeners = GetListeners(); + // use needNotifyUinContent to separate ui content callbacks + CALL_LIFECYCLE_LISTENER(AfterUnfocused, lifecycleListeners); + if (needNotifyUiContent) { + CALL_UI_CONTENT(UnFocus); + } + } + inline void NotifyBeforeDestroy(std::string windowName) + { + std::lock_guard lock(mutex_); + if (uiContent_ != nullptr) { + auto uiContent = std::move(uiContent_); + uiContent_ = nullptr; + uiContent->Destroy(); + } + if (notifyNativefunc_) { + notifyNativefunc_(windowName); + } + } + inline void NotifyBeforeSubWindowDestroy(sptr window) + { + auto uiContent = window->GetUIContent(); + if (uiContent != nullptr) { + uiContent->Destroy(); + } + if (window->GetNativeDestroyCallback()) { + window->GetNativeDestroyCallback()(window->GetWindowName()); + } + } + inline void NotifyAfterActive() + { + auto lifecycleListeners = GetListeners(); + CALL_LIFECYCLE_LISTENER(AfterActive, lifecycleListeners); + } + inline void NotifyAfterInactive() + { + auto lifecycleListeners = GetListeners(); + CALL_LIFECYCLE_LISTENER(AfterInactive, lifecycleListeners); + } + inline void NotifyForegroundFailed(WMError ret) + { + auto lifecycleListeners = GetListeners(); + CALL_LIFECYCLE_LISTENER_WITH_PARAM(ForegroundFailed, lifecycleListeners, static_cast(ret)); + } + inline bool IsStretchableReason(WindowSizeChangeReason reason) + { + return reason == WindowSizeChangeReason::DRAG || reason == WindowSizeChangeReason::DRAG_END || + reason == WindowSizeChangeReason::DRAG_START || reason == WindowSizeChangeReason::RECOVER || + reason == WindowSizeChangeReason::MOVE || reason == WindowSizeChangeReason::UNDEFINED; + } + void ClearListenersById(uint32_t winId); + void NotifySizeChange(Rect rect, WindowSizeChangeReason reason); + void NotifyAvoidAreaChange(const sptr& avoidArea, AvoidAreaType type); + void NotifyDisplayMoveChange(DisplayId from, DisplayId to); + void NotifyOccupiedAreaChange(const sptr& info); + void NotifyModeChange(WindowMode mode); + void NotifyDragEvent(const PointInfo& point, DragEvent event); + void DestroyDialogWindow(); + void DestroyFloatingWindow(); + void DestroySubWindow(); + void SetDefaultOption(); // for api7 + bool IsWindowValid() const; + static sptr FindTopWindow(uint32_t topWinId); + void TransferPointerEvent(const std::shared_ptr& pointerEvent); + void ConsumeMoveOrDragEvent(const std::shared_ptr& pointerEvent); + void ReadyToMoveOrDragWindow(const std::shared_ptr& pointerEvent, + const MMI::PointerEvent::PointerItem& pointerItem); + void EndMoveOrDragWindow(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); + void ResetMoveOrDragState(); + bool IsPointerEventConsumed(); + bool IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY); + void AdjustWindowAnimationFlag(bool withAnimation = false); + void MapFloatingWindowToAppIfNeeded(); + void MapDialogWindowToAppIfNeeded(); + WMError UpdateProperty(PropertyChangeAction action); + WMError Destroy(bool needNotifyServer, bool needClearListener = true); + WMError SetBackgroundColor(uint32_t color); + uint32_t GetBackgroundColor() const; + void InitAbilityInfo(); + std::shared_ptr GetOriginalAbilityInfo() const; + void RecordLifeCycleExceptionEvent(LifeCycleEvent event, WMError errCode) const; + std::string TransferLifeCycleEventToString(LifeCycleEvent type) const; + Rect GetSystemAlarmWindowDefaultSize(Rect defaultRect); + void HandleModeChangeHotZones(int32_t posX, int32_t posY); + WMError NotifyWindowTransition(TransitionReason reason); + void UpdatePointerEventForStretchableWindow(const std::shared_ptr& pointerEvent); + void UpdateDragType(int32_t startPointPosX, int32_t startPointPosY); + void HandleBackKeyPressedEvent(const std::shared_ptr& keyEvent); + bool CheckCameraFloatingWindowMultiCreated(WindowType type); + void GetConfigurationFromAbilityInfo(); + void UpdateTitleButtonVisibility(); + void SetModeSupportInfo(uint32_t modeSupportInfo); + uint32_t GetModeSupportInfo() const; + WMError PreProcessShow(uint32_t reason, bool withAnimation); + bool NeedToStopShowing(); + void CalculateStartRectExceptHotZone(float virtualPixelRatio); + void SetSystemConfig(); + void TransformSurfaceNode(const Transform& trans); + bool IsAppMainOrSunOrFloatingWindow(); + void SetWindowCornerRadiusAccordingToSystemConfig(); + bool IsAppMainOrSubOrFloatingWindow(); + void UpdateWindowShadowAccordingToSystemConfig(); + bool WindowCreateCheck(uint32_t parentId); + uint32_t CalculatePointerDirection(int32_t pointerX, int32_t pointerY); + void HandlePointerStyle(const std::shared_ptr& pointerEvent); + RSSurfaceNode::SharedPtr CreateSurfaceNode(std::string name, WindowType type); + void UpdateWindowStateUnfrozen(); + void UpdateViewportConfig(const Rect& rect, const sptr& display, WindowSizeChangeReason reason); + + // colorspace, gamut + using ColorSpaceConvertMap = struct { + ColorSpace colorSpace; + ColorGamut surfaceColorGamut; + }; + static const ColorSpaceConvertMap colorSpaceConvertMap[]; + static ColorSpace GetColorSpaceFromSurfaceGamut(ColorGamut ColorGamut); + static ColorGamut GetSurfaceGamutFromColorSpace(ColorSpace colorSpace); + + static std::map>> windowMap_; + static std::map>> subWindowMap_; + static std::map>> appFloatingWindowMap_; + static std::map>> appDialogWindowMap_; + sptr property_; + WindowState state_ { WindowState::STATE_INITIAL }; + WindowTag windowTag_; + sptr aceAbilityHandler_; + static std::map>> screenshotListeners_; + static std::map>> touchOutsideListeners_; + static std::map>> dialogTargetTouchListeners_; + static std::map>> lifecycleListeners_; + static std::map>> windowChangeListeners_; + static std::map>> avoidAreaChangeListeners_; + std::vector> windowDragListeners_; + std::vector> displayMoveListeners_; + static std::map>> occupiedAreaChangeListeners_; + static std::map> dialogDeathRecipientListener_; + std::shared_ptr inputEventConsumer_; + sptr animationTransitionController_; + NotifyNativeWinDestroyFunc notifyNativefunc_; + std::shared_ptr surfaceNode_; + std::string name_; + std::unique_ptr uiContent_; + std::shared_ptr context_; + std::recursive_mutex mutex_; + static std::recursive_mutex globalMutex_; + const float SYSTEM_ALARM_WINDOW_WIDTH_RATIO = 0.8; + const float SYSTEM_ALARM_WINDOW_HEIGHT_RATIO = 0.3; + WindowSizeChangeReason lastSizeChangeReason_ = WindowSizeChangeReason::END; + + sptr moveDragProperty_; + bool isAppDecorEnable_ = true; + SystemConfig windowSystemConfig_ ; + bool isOriginRectSet_ = false; + bool needRemoveWindowInputChannel_ = false; + bool isMainHandlerAvailable_ = true; + bool isAppFloatingWindow_ = false; + bool isFocused_ = false; + uint32_t mouseStyleID_ = 0; + bool isPointerStyleChanged_ = false; + const std::map STYLEID_MAP = { + {DragType::DRAG_UNDEFINED, MMI::MOUSE_ICON::DEFAULT}, + {DragType::DRAG_BOTTOM_OR_TOP, MMI::MOUSE_ICON::NORTH_SOUTH}, + {DragType::DRAG_LEFT_OR_RIGHT, MMI::MOUSE_ICON::WEST_EAST}, + {DragType::DRAG_LEFT_TOP_CORNER, MMI::MOUSE_ICON::NORTH_WEST_SOUTH_EAST}, + {DragType::DRAG_RIGHT_TOP_CORNER, MMI::MOUSE_ICON::NORTH_EAST_SOUTH_WEST} + }; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_IMPL_H diff --git a/window_manager/wm/include/window_input_channel.h b/window_manager/wm/include/window_input_channel.h new file mode 100644 index 0000000..ed085e9 --- /dev/null +++ b/window_manager/wm/include/window_input_channel.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-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_WINDOW_INPUT_CHANNEL_H +#define OHOS_WINDOW_INPUT_CHANNEL_H + +#include +#include +#include "refbase.h" +#include "vsync_station.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +class WindowInputChannel final: public RefBase { +public: + explicit WindowInputChannel(const sptr& window); + virtual ~WindowInputChannel(); + void HandlePointerEvent(std::shared_ptr& pointerEvent); + void HandleKeyEvent(std::shared_ptr& keyEvent); + void Destroy(); +private: + bool IsKeyboardEvent(const std::shared_ptr& keyEvent) const; + std::mutex mtx_; + sptr window_; + bool isAvailable_; + static const int32_t MAX_INPUT_NUM = 100; +}; +} +} + + +#endif // OHOS_WINDOW_INPUT_CHANNEL_H diff --git a/window_manager/wm/include/window_manager_agent.h b/window_manager/wm/include/window_manager_agent.h new file mode 100644 index 0000000..2f6f782 --- /dev/null +++ b/window_manager/wm/include/window_manager_agent.h @@ -0,0 +1,38 @@ +/* + * 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_WINDOW_MANAGER_AGENT_H +#define OHOS_WINDOW_MANAGER_AGENT_H + +#include "window_manager.h" +#include "zidl/window_manager_agent_stub.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerAgent : public WindowManagerAgentStub { +public: + WindowManagerAgent() = default; + ~WindowManagerAgent() = default; + + void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) override; + void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& props) override; + void NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) override; + void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) override; + void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) override; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_MANAGER_AGENT_H diff --git a/window_manager/wm/include/zidl/window_interface.h b/window_manager/wm/include/zidl/window_interface.h new file mode 100644 index 0000000..98ff001 --- /dev/null +++ b/window_manager/wm/include/zidl/window_interface.h @@ -0,0 +1,77 @@ +/* + * 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_WINDOW_INTERFACE_H +#define OHOS_WINDOW_INTERFACE_H + +#include "iremote_broker.h" +#include "window.h" +#include "window_property.h" +#include "wm_common.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +class IWindow : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.IWindow"); + + enum class WindowMessage : uint32_t { + TRANS_ID_UPDATE_WINDOW_RECT, + TRANS_ID_UPDATE_WINDOW_MODE, + TRANS_ID_UPDATE_MODE_SUPPORT_INFO, + TRANS_ID_UPDATE_FOCUS_STATUS, + TRANS_ID_UPDATE_AVOID_AREA, + TRANS_ID_UPDATE_WINDOW_STATE, + TRANS_ID_UPDATE_DRAG_EVENT, + TRANS_ID_UPDATE_DISPLAY_ID, + TRANS_ID_UPDATE_OCCUPIED_AREA, + TRANS_ID_UPDATE_ACTIVE_STATUS, + TRANS_ID_GET_WINDOW_PROPERTY, + TRANS_ID_NOTIFY_OUTSIDE_PRESSED, + TRANS_ID_NOTIFY_SCREEN_SHOT, + TRANS_ID_DUMP_INFO, + TRANS_ID_NOTIFY_DESTROY, + TRANS_ID_NOTIFY_FOREGROUND, + TRANS_ID_NOTIFY_BACKGROUND, + TRANS_ID_NOTIFY_CLIENT_POINT_UP, + TRANS_ID_UPDATE_ZOOM_TRANSFORM, + TRANS_ID_RESTORE_SPLIT_WINDOW_MODE, + }; + + virtual WMError UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) = 0; + virtual WMError UpdateWindowMode(WindowMode mode) = 0; + virtual WMError UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) = 0; + virtual WMError UpdateFocusStatus(bool focused) = 0; + virtual WMError UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) = 0; + virtual WMError UpdateWindowState(WindowState state) = 0; + virtual WMError UpdateWindowDragInfo(const PointInfo& point, DragEvent event) = 0; + virtual WMError UpdateDisplayId(DisplayId from, DisplayId to) = 0; + virtual WMError UpdateOccupiedAreaChangeInfo(const sptr& info) = 0; + virtual WMError UpdateActiveStatus(bool isActive) = 0; + virtual sptr GetWindowProperty() = 0; + virtual WMError NotifyTouchOutside() = 0; + virtual WMError NotifyScreenshot() = 0; + virtual WMError DumpInfo(const std::vector& params) = 0; + virtual WMError NotifyDestroy(void) = 0; + virtual WMError NotifyForeground(void) = 0; + virtual WMError NotifyBackground(void) = 0; + virtual WMError NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) = 0; + virtual WMError UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) = 0; + virtual WMError RestoreSplitWindowMode(uint32_t mode) = 0; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_INTERFACE_H diff --git a/window_manager/wm/include/zidl/window_manager_agent_interface.h b/window_manager/wm/include/zidl/window_manager_agent_interface.h new file mode 100644 index 0000000..17fa35b --- /dev/null +++ b/window_manager/wm/include/zidl/window_manager_agent_interface.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-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_WINDOW_MANAGER_AGENT_INTERFACE_H +#define OHOS_WINDOW_MANAGER_AGENT_INTERFACE_H + +#include +#include "wm_common.h" +#include "window_manager.h" + +namespace OHOS { +namespace Rosen { +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, + WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT, +}; + +class IWindowManagerAgent : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.IWindowManagerAgent"); + + enum class WindowManagerAgentMsg : uint32_t { + TRANS_ID_UPDATE_FOCUS = 1, + TRANS_ID_UPDATE_SYSTEM_BAR_PROPS, + TRANS_ID_UPDATE_WINDOW_STATUS, + TRANS_ID_UPDATE_WINDOW_VISIBILITY, + TRANS_ID_UPDATE_CAMERA_FLOAT, + }; + + virtual void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) = 0; + virtual void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) = 0; + virtual void NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) = 0; + virtual void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) = 0; + virtual void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) = 0; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_MANAGER_AGENT_INTERFACE_H diff --git a/window_manager/wm/include/zidl/window_manager_agent_proxy.h b/window_manager/wm/include/zidl/window_manager_agent_proxy.h new file mode 100644 index 0000000..3584ba5 --- /dev/null +++ b/window_manager/wm/include/zidl/window_manager_agent_proxy.h @@ -0,0 +1,42 @@ +/* + * 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_WINDOW_MANAGER_AGENT_PROXY_H +#define OHOS_WINDOW_MANAGER_AGENT_PROXY_H + +#include "window_manager_agent_interface.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerAgentProxy : public IRemoteProxy { +public: + explicit WindowManagerAgentProxy(const sptr& impl) : IRemoteProxy(impl) {}; + + ~WindowManagerAgentProxy() {}; + + void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) override; + void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) override; + void NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) override; + void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) override; + void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_MANAGER_PROXY_H diff --git a/window_manager/wm/include/zidl/window_manager_agent_stub.h b/window_manager/wm/include/zidl/window_manager_agent_stub.h new file mode 100644 index 0000000..b463e67 --- /dev/null +++ b/window_manager/wm/include/zidl/window_manager_agent_stub.h @@ -0,0 +1,34 @@ +/* + * 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_WINDOW_MANAGER_AGENT_STUB_H +#define OHOS_WINDOW_MANAGER_AGENT_STUB_H + +#include "window_manager_agent_interface.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerAgentStub : public IRemoteStub { +public: + WindowManagerAgentStub() = default; + ~WindowManagerAgentStub() = default; + + virtual int OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption& option) override; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_MANAGER_AGENT_STUB_H diff --git a/window_manager/wm/include/zidl/window_proxy.h b/window_manager/wm/include/zidl/window_proxy.h new file mode 100644 index 0000000..49f100e --- /dev/null +++ b/window_manager/wm/include/zidl/window_proxy.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021-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_WINDOW_PROXY_H +#define OHOS_WINDOW_PROXY_H + +#include "window_interface.h" +#include "iremote_proxy.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowProxy : public IRemoteProxy { +public: + explicit WindowProxy(const sptr& impl) : IRemoteProxy(impl) {}; + + ~WindowProxy() {}; + + WMError UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) override; + WMError UpdateWindowMode(WindowMode mode) override; + WMError UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) override; + WMError UpdateFocusStatus(bool focused) override; + WMError UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) override; + WMError UpdateWindowState(WindowState state) override; + WMError UpdateWindowDragInfo(const PointInfo& point, DragEvent event) override; + WMError UpdateDisplayId(DisplayId from, DisplayId to) override; + WMError UpdateOccupiedAreaChangeInfo(const sptr& info) override; + WMError UpdateActiveStatus(bool isActive) override; + sptr GetWindowProperty() override; + WMError NotifyTouchOutside() override; + WMError NotifyScreenshot() override; + WMError DumpInfo(const std::vector& params) override; + WMError NotifyDestroy(void) override; + WMError NotifyForeground(void) override; + WMError NotifyBackground(void) override; + WMError NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) override; + WMError UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) override; + WMError RestoreSplitWindowMode(uint32_t mode) override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_PROXY_H diff --git a/window_manager/wm/include/zidl/window_stub.h b/window_manager/wm/include/zidl/window_stub.h new file mode 100644 index 0000000..45964f5 --- /dev/null +++ b/window_manager/wm/include/zidl/window_stub.h @@ -0,0 +1,49 @@ +/* + * 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_WINDOW_STUB_H +#define OHOS_WINDOW_STUB_H + +#include "window_interface.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace Rosen { +class WindowStub : public IRemoteStub { +public: + WindowStub() = default; + ~WindowStub() = default; + + virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) override; +private: + static inline const class StaticDestroyMonitor { + public: + StaticDestroyMonitor() : destroyed_(false) {} + ~StaticDestroyMonitor() + { + destroyed_ = true; + } + bool IsDestroyed() const + { + return destroyed_; + } + private: + bool destroyed_; + } staticDestroyMonitor_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_STUB_H diff --git a/window_manager/wm/src/README.md b/window_manager/wm/src/README.md new file mode 100644 index 0000000..2a99b4a --- /dev/null +++ b/window_manager/wm/src/README.md @@ -0,0 +1 @@ +Store code of window client source files diff --git a/window_manager/wm/src/color_parser.cpp b/window_manager/wm/src/color_parser.cpp new file mode 100644 index 0000000..ce1a727 --- /dev/null +++ b/window_manager/wm/src/color_parser.cpp @@ -0,0 +1,67 @@ +/* + * 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 "color_parser.h" +#include + +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "ColorParser"}; +} + +bool ColorParser::Parse(const std::string& colorStr, uint32_t& colorValue) +{ + if (colorStr.empty()) { + WLOGFE("color string is empty"); + return false; + } + + if (colorStr[0] == '#') { // start with '#' + std::string color = colorStr.substr(1); + if (!IsValidHexString(color)) { + return false; + } + char* ptr; + colorValue = std::strtoul(color.c_str(), &ptr, 16); // convert hex string to number + if (colorStr.size() == 7) { // #RRGGBB: RRGGBB -> AARRGGBB + colorValue |= 0xff000000; + return true; + } else if (colorStr.size() == 9) { // #AARRGGBB + return true; + } else { + // do nothing + } + } + return false; +} + +bool ColorParser::IsValidHexString(const std::string& colorStr) +{ + if (colorStr.empty()) { + return false; + } + for (char ch : colorStr) { + if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) { + continue; + } + return false; + } + return true; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wm/src/input_transfer_station.cpp b/window_manager/wm/src/input_transfer_station.cpp new file mode 100644 index 0000000..95bbda5 --- /dev/null +++ b/window_manager/wm/src/input_transfer_station.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021-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 "input_transfer_station.h" + +#include +#include +#include "vsync_station.h" +#include "window_manager_hilog.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputTransferStation"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(InputTransferStation) + +void InputEventListener::OnInputEvent(std::shared_ptr keyEvent) const +{ + if (keyEvent == nullptr) { + WLOGFE("KeyEvent is nullptr"); + return; + } + uint32_t windowId = static_cast(keyEvent->GetAgentWindowId()); + WLOGFD("Receive keyEvent, windowId: %{public}u", windowId); + auto channel = InputTransferStation::GetInstance().GetInputChannel(windowId); + if (channel == nullptr) { + WLOGFE("WindowInputChannel is nullptr"); + return; + } + channel->HandleKeyEvent(keyEvent); +} + +void InputEventListener::OnInputEvent(std::shared_ptr axisEvent) const +{ + if (axisEvent == nullptr) { + WLOGFE("AxisEvent is nullptr"); + return; + } + WLOGFD("Receive axisEvent, windowId: %{public}d", axisEvent->GetAgentWindowId()); + axisEvent->MarkProcessed(); +} + +void InputEventListener::OnInputEvent(std::shared_ptr pointerEvent) const +{ + if (pointerEvent == nullptr) { + WLOGFE("PointerEvent is nullptr"); + return; + } + // If handling input event at server, client will receive pointEvent that the winId is -1, intercept log error + uint32_t invalidId = static_cast(-1); + uint32_t windowId = static_cast(pointerEvent->GetAgentWindowId()); + WLOGFD("Receive pointerEvent, windowId: %{public}u", windowId); + auto channel = InputTransferStation::GetInstance().GetInputChannel(windowId); + if (channel == nullptr) { + if (windowId != invalidId) { + WLOGFE("WindowInputChannel is nullptr"); + } + pointerEvent->MarkProcessed(); + return; + } + channel->HandlePointerEvent(pointerEvent); +} + +void InputTransferStation::AddInputWindow(const sptr& window) +{ + uint32_t windowId = window->GetWindowId(); + WLOGFD("Add input window, windowId: %{public}u", windowId); + + // INPUT_WINDOW_TYPE_SKIPPED should not set input consumer + if (INPUT_WINDOW_TYPE_SKIPPED.find(window->GetType()) != INPUT_WINDOW_TYPE_SKIPPED.end()) { + WLOGFW("skip window for InputConsumer [id:%{public}u, type:%{public}d]", windowId, window->GetType()); + return; + } + sptr inputChannel = new WindowInputChannel(window); + std::lock_guard lock(mtx_); + windowInputChannels_.insert(std::make_pair(windowId, inputChannel)); + if (inputListener_ == nullptr) { + WLOGFD("Init input listener, IsMainHandlerAvailable: %{public}u", window->IsMainHandlerAvailable()); + std::shared_ptr listener = std::make_shared(InputEventListener()); + auto mainEventRunner = AppExecFwk::EventRunner::GetMainEventRunner(); + if (mainEventRunner != nullptr && window->IsMainHandlerAvailable()) { + WLOGFD("MainEventRunner is available"); + eventHandler_ = std::make_shared(mainEventRunner); + } else { + WLOGFD("MainEventRunner is not available"); + eventHandler_ = AppExecFwk::EventHandler::Current(); + auto curThreadId = std::this_thread::get_id(); + if (!eventHandler_ || (mainEventRunner != nullptr && + mainEventRunner->GetThreadId() == *(reinterpret_cast(&curThreadId)))) { + eventHandler_ = std::make_shared( + AppExecFwk::EventRunner::Create(INPUT_AND_VSYNC_THREAD)); + } + VsyncStation::GetInstance().SetIsMainHandlerAvailable(false); + VsyncStation::GetInstance().SetVsyncEventHandler(eventHandler_); + } + MMI::InputManager::GetInstance()->SetWindowInputEventConsumer(listener, eventHandler_); + inputListener_ = listener; + } +} + +void InputTransferStation::RemoveInputWindow(uint32_t windowId) +{ + WLOGFD("Remove input window, windowId: %{public}u", windowId); + sptr inputChannel = nullptr; + { + std::lock_guard lock(mtx_); + auto iter = windowInputChannels_.find(windowId); + if (iter != windowInputChannels_.end()) { + inputChannel = iter->second; + windowInputChannels_.erase(windowId); + } + } + if (inputChannel != nullptr) { + inputChannel->Destroy(); + } else { + WLOGFE("Can not find windowId: %{public}u", windowId); + } +} + +sptr InputTransferStation::GetInputChannel(uint32_t windowId) +{ + std::lock_guard lock(mtx_); + auto iter = windowInputChannels_.find(windowId); + if (iter == windowInputChannels_.end()) { + return nullptr; + } + return iter->second; +} +} +} diff --git a/window_manager/wm/src/static_call.cpp b/window_manager/wm/src/static_call.cpp new file mode 100644 index 0000000..b92fe6d --- /dev/null +++ b/window_manager/wm/src/static_call.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021-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 "static_call.h" + +namespace OHOS { +namespace Rosen { +WM_IMPLEMENT_SINGLE_INSTANCE(StaticCall) + +sptr StaticCall::CreateWindow(const std::string& windowName, + sptr& option, std::shared_ptr context) +{ + return Window::Create(windowName, option, context); +} + +std::vector> StaticCall::GetSubWindow(uint32_t parentId) +{ + return Window::GetSubWindow(parentId); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wm/src/vsync_station.cpp b/window_manager/wm/src/vsync_station.cpp new file mode 100644 index 0000000..53bdd8f --- /dev/null +++ b/window_manager/wm/src/vsync_station.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021-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 "vsync_station.h" +#include "window_frame_trace.h" +#include "transaction/rs_interfaces.h" +#include "window_manager_hilog.h" + +using namespace FRAME_TRACE; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "VsyncStation"}; + const std::string VSYNC_TIME_OUT_TASK = "vsync_time_out_task"; + constexpr int64_t VSYNC_TIME_OUT_MILLISECONDS = 600; +} +WM_IMPLEMENT_SINGLE_INSTANCE(VsyncStation) + +void VsyncStation::RequestVsync(const std::shared_ptr& vsyncCallback) +{ + { + std::lock_guard lock(mtx_); + vsyncCallbacks_.insert(vsyncCallback); + + if (!hasInitVsyncReceiver_ || !vsyncHandler_) { + auto mainEventRunner = AppExecFwk::EventRunner::GetMainEventRunner(); + if (mainEventRunner != nullptr && isMainHandlerAvailable_) { + WLOGFI("MainEventRunner is available"); + vsyncHandler_ = std::make_shared(mainEventRunner); + } else { + WLOGFI("MainEventRunner is not available"); + if (!vsyncHandler_) { + vsyncHandler_ = std::make_shared( + AppExecFwk::EventRunner::Create(VSYNC_THREAD_ID)); + } + } + auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance(); + while (receiver_ == nullptr) { + receiver_ = rsClient.CreateVSyncReceiver("WM_" + std::to_string(::getpid()), vsyncHandler_); + } + receiver_->Init(); + hasInitVsyncReceiver_ = true; + } + if (hasRequestedVsync_) { + return; + } + hasRequestedVsync_ = true; + if (vsyncHandler_) { + vsyncHandler_->RemoveTask(VSYNC_TIME_OUT_TASK); + vsyncHandler_->PostTask(vsyncTimeoutCallback_, VSYNC_TIME_OUT_TASK, VSYNC_TIME_OUT_MILLISECONDS); + } + } + WindowFrameTraceImpl::GetInstance()->VsyncStartFrameTrace(); + receiver_->RequestNextVSync(frameCallback_); +} + +void VsyncStation::RemoveCallback() +{ + std::lock_guard lock(mtx_); + WLOGFI("[WM] Remove Vsync callback"); + vsyncCallbacks_.clear(); +} + +void VsyncStation::VsyncCallbackInner(int64_t timestamp) +{ + std::unordered_set> vsyncCallbacks; + { + std::lock_guard lock(mtx_); + hasRequestedVsync_ = false; + vsyncCallbacks = vsyncCallbacks_; + vsyncCallbacks_.clear(); + vsyncHandler_->RemoveTask(VSYNC_TIME_OUT_TASK); + } + for (const auto& callback: vsyncCallbacks) { + callback->onCallback(timestamp); + } +} + +void VsyncStation::OnVsync(int64_t timestamp, void* client) +{ + auto vsyncClient = static_cast(client); + if (vsyncClient) { + vsyncClient->VsyncCallbackInner(timestamp); + WindowFrameTraceImpl::GetInstance()->VsyncStopFrameTrace(); + } else { + WLOGFE("VsyncClient is null"); + } +} + +void VsyncStation::OnVsyncTimeOut() +{ + std::lock_guard lock(mtx_); + WLOGFI("[WM] Vsync time out"); + hasRequestedVsync_ = false; +} +} +} diff --git a/window_manager/wm/src/window.cpp b/window_manager/wm/src/window.cpp new file mode 100644 index 0000000..467cda7 --- /dev/null +++ b/window_manager/wm/src/window.cpp @@ -0,0 +1,106 @@ +/* + * 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 "window.h" +#include "window_helper.h" +#include "window_impl.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowImpl"}; +} +sptr Window::Create(const std::string& windowName, sptr& option, + const std::shared_ptr& context) +{ + if (windowName.empty()) { + WLOGFE("window name is empty"); + return nullptr; + } + if (option == nullptr) { + option = new(std::nothrow) WindowOption(); + if (option == nullptr) { + WLOGFE("malloc option failed"); + return nullptr; + } + } + WindowType type = option->GetWindowType(); + if (!(WindowHelper::IsAppWindow(type) || WindowHelper::IsSystemWindow(type))) { + WLOGFE("window type is invalid %{public}d", type); + return nullptr; + } + option->SetWindowName(windowName); + sptr windowImpl = new(std::nothrow) WindowImpl(option); + if (windowImpl == nullptr) { + WLOGFE("malloc windowImpl failed"); + return nullptr; + } + WMError error = windowImpl->Create(option->GetParentId(), context); + if (error != WMError::WM_OK) { + return nullptr; + } + return windowImpl; +} + +sptr Window::Find(const std::string& windowName) +{ + return WindowImpl::Find(windowName); +} + +sptr Window::GetTopWindowWithContext(const std::shared_ptr& context) +{ + return WindowImpl::GetTopWindowWithContext(context); +} + +sptr Window::GetTopWindowWithId(uint32_t mainWinId) +{ + return WindowImpl::GetTopWindowWithId(mainWinId); +} + +std::vector> Window::GetSubWindow(uint32_t parentId) +{ + return WindowImpl::GetSubWindow(parentId); +} + +void Window::UpdateConfigurationForAll(const std::shared_ptr& configuration) +{ + return WindowImpl::UpdateConfigurationForAll(configuration); +} + +bool OccupiedAreaChangeInfo::Marshalling(Parcel& parcel) const +{ + return parcel.WriteInt32(rect_.posX_) && parcel.WriteInt32(rect_.posY_) && + parcel.WriteUint32(rect_.width_) && parcel.WriteUint32(rect_.height_) && + parcel.WriteUint32(static_cast(type_)); +} + +OccupiedAreaChangeInfo* OccupiedAreaChangeInfo::Unmarshalling(Parcel& parcel) +{ + OccupiedAreaChangeInfo* occupiedAreaChangeInfo = new OccupiedAreaChangeInfo(); + bool res = parcel.ReadInt32(occupiedAreaChangeInfo->rect_.posX_) && + parcel.ReadInt32(occupiedAreaChangeInfo->rect_.posY_) && + parcel.ReadUint32(occupiedAreaChangeInfo->rect_.width_) && + parcel.ReadUint32(occupiedAreaChangeInfo->rect_.height_); + if (!res) { + delete occupiedAreaChangeInfo; + return nullptr; + } + occupiedAreaChangeInfo->type_ = static_cast(parcel.ReadUint32()); + return occupiedAreaChangeInfo; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/window_accessibility_controller.cpp b/window_manager/wm/src/window_accessibility_controller.cpp new file mode 100644 index 0000000..1420351 --- /dev/null +++ b/window_manager/wm/src/window_accessibility_controller.cpp @@ -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. + */ + +#include "window_accessibility_controller.h" +#include "window_adapter.h" + +namespace OHOS::Rosen { +WM_IMPLEMENT_SINGLE_INSTANCE(WindowAccessibilityController) +WindowAccessibilityController::WindowAccessibilityController() +{ +} + +void WindowAccessibilityController::SetAnchorAndScale(int32_t x, int32_t y, float scale) +{ + SingletonContainer::Get().SetAnchorAndScale(x, y, scale); +} + +void WindowAccessibilityController::SetAnchorOffset(int32_t deltaX, int32_t deltaY) +{ + SingletonContainer::Get().SetAnchorOffset(deltaX, deltaY); +} + +void WindowAccessibilityController::OffWindowZoom() +{ + SingletonContainer::Get().OffWindowZoom(); +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/wm/src/window_adapter.cpp b/window_manager/wm/src/window_adapter.cpp new file mode 100644 index 0000000..23232c6 --- /dev/null +++ b/window_manager/wm/src/window_adapter.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2021-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 "window_adapter.h" +#include +#include +#include "window_manager.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowAdapter"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(WindowAdapter) + +#define INIT_PROXY_CHECK_RETURN(ret) \ + do { \ + if (!InitWMSProxy()) { \ + WLOGFE("InitWMSProxy failed!"); \ + return ret; \ + } \ + } while (false) + +WMError WindowAdapter::CreateWindow(sptr& window, sptr& windowProperty, + std::shared_ptr surfaceNode, uint32_t& windowId, const sptr& token) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->CreateWindow(window, windowProperty, surfaceNode, windowId, token); +} + +WMError WindowAdapter::AddWindow(sptr& windowProperty) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->AddWindow(windowProperty); +} + +WMError WindowAdapter::RemoveWindow(uint32_t windowId) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->RemoveWindow(windowId); +} + +WMError WindowAdapter::DestroyWindow(uint32_t windowId) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->DestroyWindow(windowId); +} + +WMError WindowAdapter::RequestFocus(uint32_t windowId) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->RequestFocus(windowId); +} + +bool WindowAdapter::RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + INIT_PROXY_CHECK_RETURN(false); + + return windowManagerServiceProxy_->RegisterWindowManagerAgent(type, windowManagerAgent); +} + +bool WindowAdapter::UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + INIT_PROXY_CHECK_RETURN(false); + + return windowManagerServiceProxy_->UnregisterWindowManagerAgent(type, windowManagerAgent); +} + +WMError WindowAdapter::GetAccessibilityWindowInfo(std::vector>& infos) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->GetAccessibilityWindowInfo(infos); +} + +WMError WindowAdapter::GetVisibilityWindowInfo(std::vector>& infos) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->GetVisibilityWindowInfo(infos); +} + +WMError WindowAdapter::SetWindowAnimationController(const sptr& controller) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + return windowManagerServiceProxy_->SetWindowAnimationController(controller); +} + +WMError WindowAdapter::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType type, AvoidArea& avoidArea) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + avoidArea = windowManagerServiceProxy_->GetAvoidAreaByType(windowId, type); + return WMError::WM_OK; +} + +void WindowAdapter::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) +{ + INIT_PROXY_CHECK_RETURN(); + + return windowManagerServiceProxy_->NotifyServerReadyToMoveOrDrag(windowId, windowProperty, moveDragProperty); +} + +void WindowAdapter::ProcessPointDown(uint32_t windowId, bool isPointDown) +{ + INIT_PROXY_CHECK_RETURN(); + + return windowManagerServiceProxy_->ProcessPointDown(windowId, isPointDown); +} + +void WindowAdapter::ProcessPointUp(uint32_t windowId) +{ + INIT_PROXY_CHECK_RETURN(); + + return windowManagerServiceProxy_->ProcessPointUp(windowId); +} + +void WindowAdapter::MinimizeAllAppWindows(DisplayId displayId) +{ + INIT_PROXY_CHECK_RETURN(); + + windowManagerServiceProxy_->MinimizeAllAppWindows(displayId); +} + +WMError WindowAdapter::ToggleShownStateForAllAppWindows() +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->ToggleShownStateForAllAppWindows(); +} + +WMError WindowAdapter::GetSystemConfig(SystemConfig& systemConfig) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->GetSystemConfig(systemConfig); +} + +WMError WindowAdapter::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->GetModeChangeHotZones(displayId, hotZones); +} + +bool WindowAdapter::InitWMSProxy() +{ + std::lock_guard lock(mutex_); + if (!isProxyValid_) { + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + WLOGFE("Failed to get system ability mgr."); + return false; + } + + sptr remoteObject = systemAbilityManager->GetSystemAbility(WINDOW_MANAGER_SERVICE_ID); + if (!remoteObject) { + WLOGFE("Failed to get window manager service."); + return false; + } + + windowManagerServiceProxy_ = iface_cast(remoteObject); + if ((!windowManagerServiceProxy_) || (!windowManagerServiceProxy_->AsObject())) { + WLOGFE("Failed to get system window manager services"); + return false; + } + + wmsDeath_ = new WMSDeathRecipient(); + if (!wmsDeath_) { + WLOGFE("Failed to create death Recipient ptr WMSDeathRecipient"); + return false; + } + if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(wmsDeath_)) { + WLOGFE("Failed to add death recipient"); + return false; + } + isProxyValid_ = true; + } + return true; +} + +void WindowAdapter::ClearWindowAdapter() +{ + if ((windowManagerServiceProxy_ != nullptr) && (windowManagerServiceProxy_->AsObject() != nullptr)) { + windowManagerServiceProxy_->AsObject()->RemoveDeathRecipient(wmsDeath_); + } + std::lock_guard lock(mutex_); + isProxyValid_ = false; +} + +void WMSDeathRecipient::OnRemoteDied(const wptr& wptrDeath) +{ + if (wptrDeath == nullptr) { + WLOGFE("wptrDeath is null"); + return; + } + + sptr object = wptrDeath.promote(); + if (!object) { + WLOGFE("object is null"); + return; + } + WLOGFI("wms OnRemoteDied"); + SingletonContainer::Get().ClearWindowAdapter(); + SingletonContainer::Get().OnRemoteDied(); +} + +WMError WindowAdapter::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->GetTopWindowId(mainWinId, topWinId); +} + +WMError WindowAdapter::SetWindowLayoutMode(WindowLayoutMode mode) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->SetWindowLayoutMode(mode); +} + +WMError WindowAdapter::UpdateProperty(sptr& windowProperty, PropertyChangeAction action) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + return windowManagerServiceProxy_->UpdateProperty(windowProperty, action); +} + +WMError WindowAdapter::NotifyWindowTransition(sptr from, sptr to) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + + return windowManagerServiceProxy_->NotifyWindowTransition(from, to, true); +} + +void WindowAdapter::MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback) +{ + INIT_PROXY_CHECK_RETURN(); + windowManagerServiceProxy_->MinimizeWindowsByLauncher(windowIds, isAnimated, finishCallback); + return; +} + +WMError WindowAdapter::UpdateAvoidAreaListener(uint32_t windowId, bool haveListener) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + return windowManagerServiceProxy_->UpdateAvoidAreaListener(windowId, haveListener); +} + +WMError WindowAdapter::UpdateRsTree(uint32_t windowId, bool isAdd) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + return windowManagerServiceProxy_->UpdateRsTree(windowId, isAdd); +} + +WMError WindowAdapter::BindDialogTarget(uint32_t& windowId, sptr targetToken) +{ + INIT_PROXY_CHECK_RETURN(WMError::WM_ERROR_SAMGR); + return windowManagerServiceProxy_->BindDialogTarget(windowId, targetToken); +} + +void WindowAdapter::SetAnchorAndScale(int32_t x, int32_t y, float scale) +{ + INIT_PROXY_CHECK_RETURN(); + windowManagerServiceProxy_->SetAnchorAndScale(x, y, scale); +} + +void WindowAdapter::SetAnchorOffset(int32_t deltaX, int32_t deltaY) +{ + INIT_PROXY_CHECK_RETURN(); + windowManagerServiceProxy_->SetAnchorOffset(deltaX, deltaY); +} + +void WindowAdapter::OffWindowZoom() +{ + INIT_PROXY_CHECK_RETURN(); + windowManagerServiceProxy_->OffWindowZoom(); +} + +std::shared_ptr WindowAdapter::GetSnapshot(int32_t windowId) +{ + INIT_PROXY_CHECK_RETURN(nullptr); + return windowManagerServiceProxy_->GetSnapshot(windowId); +} + +void WindowAdapter::NotifyDumpInfoResult(const std::vector& info) +{ + INIT_PROXY_CHECK_RETURN(); + windowManagerServiceProxy_->NotifyDumpInfoResult(info); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wm/src/window_agent.cpp b/window_manager/wm/src/window_agent.cpp new file mode 100644 index 0000000..3bc8765 --- /dev/null +++ b/window_manager/wm/src/window_agent.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2021-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 "window_agent.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowAgent"}; +} + +WindowAgent::WindowAgent(sptr& windowImpl) +{ + window_ = windowImpl; +} + +WMError WindowAgent::UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateRect(rect, decoStatus, reason); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateWindowMode(WindowMode mode) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateMode(mode); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateModeSupportInfo(modeSupportInfo); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateFocusStatus(bool focused) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateFocusStatus(focused); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) +{ + if (window_ == nullptr || avoidArea == nullptr) { + WLOGFE("window_ or avoidArea is nullptr."); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateAvoidArea(avoidArea, type); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateWindowState(WindowState state) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateWindowState(state); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateWindowDragInfo(const PointInfo& point, DragEvent event) +{ + if (window_ == nullptr) { + WLOGFE("window is null"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateDragEvent(point, event); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateDisplayId(DisplayId from, DisplayId to) +{ + if (window_ == nullptr) { + WLOGFE("window is null"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateDisplayId(from, to); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateOccupiedAreaChangeInfo(const sptr& info) +{ + if (window_ == nullptr) { + WLOGFE("window is null"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateOccupiedAreaChangeInfo(info); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateActiveStatus(bool isActive) +{ + if (window_ == nullptr) { + WLOGFE("window is null"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateActiveStatus(isActive); + return WMError::WM_OK; +} + +sptr WindowAgent::GetWindowProperty() +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return nullptr; + } + return window_->GetWindowProperty(); +} + +WMError WindowAgent::RestoreSplitWindowMode(uint32_t mode) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->RestoreSplitWindowMode(mode); + return WMError::WM_OK; +} + +WMError WindowAgent::NotifyTouchOutside() +{ + if (window_ == nullptr) { + WLOGFI("window is null"); + return WMError::WM_ERROR_NULLPTR; + } + WLOGFD("called"); + window_->NotifyTouchOutside(); + return WMError::WM_OK; +} + +WMError WindowAgent::NotifyScreenshot() +{ + if (window_ == nullptr) { + WLOGFE("notify screenshot failed: window is null."); + return WMError::WM_ERROR_NULLPTR; + } + WLOGFI("called"); + window_->NotifyScreenshot(); + return WMError::WM_OK; +} + +WMError WindowAgent::DumpInfo(const std::vector& params) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + std::vector info; + window_->DumpInfo(params, info); + return WMError::WM_OK; +} + +WMError WindowAgent::UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->UpdateZoomTransform(trans, isDisplayZoomOn); + return WMError::WM_OK; +} + +WMError WindowAgent::NotifyDestroy(void) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->NotifyDestroy(); + return WMError::WM_OK; +} + +WMError WindowAgent::NotifyForeground(void) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->NotifyForeground(); + return WMError::WM_OK; +} + +WMError WindowAgent::NotifyBackground(void) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->NotifyBackground(); + return WMError::WM_OK; +} + +WMError WindowAgent::NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) +{ + if (window_ == nullptr) { + WLOGFE("window_ is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + window_->ConsumePointerEvent(pointerEvent); + return WMError::WM_OK; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/window_frame_trace_impl.cpp b/window_manager/wm/src/window_frame_trace_impl.cpp new file mode 100644 index 0000000..c3cda74 --- /dev/null +++ b/window_manager/wm/src/window_frame_trace_impl.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021-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 "window_frame_trace.h" +#include +#ifdef FRAME_TRACE_ENABLE +#include "frame_trace.h" +#endif + +namespace FRAME_TRACE { + +#ifdef __aarch64__ +const char* FRAME_TRACE_SO_PATH = "/system/lib64/libframe_trace_intf.z.so"; +#else +const char* FRAME_TRACE_SO_PATH = "/system/lib/libframe_trace_intf.z.so"; +#endif + +WindowFrameTraceImpl* WindowFrameTraceImpl::GetInstance() +{ + static WindowFrameTraceImpl ftWindow; + return &ftWindow; +} +#ifdef FRAME_TRACE_ENABLE +bool WindowFrameTraceImpl::AccessFrameTrace() +{ + if (!judgeFrameTrace_) { + judgeFrameTrace_ = true; + accessFrameTrace_ = access(FRAME_TRACE_SO_PATH, F_OK) ? false : true; + } + return accessFrameTrace_; +} + +void WindowFrameTraceImpl::VsyncStartFrameTrace() +{ + if (!AccessFrameTrace()) { + return; + } + if (FrameAwareTraceEnable(intervalName_)) { + if (handleUI_ == nullptr) { + handleUI_ = CreateTraceTag(intervalName_); + } + if (handleUI_ != nullptr) { + EnableTraceForThread(handleUI_); + StartFrameTrace(handleUI_); + } + } +} + +void WindowFrameTraceImpl::VsyncStopFrameTrace() +{ + if (!AccessFrameTrace()) { + return; + } + if (FrameAwareTraceEnable(intervalName_)) { + if (handleUI_ != nullptr) { + StopFrameTrace(handleUI_); + } + } +} +#endif +} // namespace FRAME_TRACE diff --git a/window_manager/wm/src/window_impl.cpp b/window_manager/wm/src/window_impl.cpp new file mode 100755 index 0000000..416b1f3 --- /dev/null +++ b/window_manager/wm/src/window_impl.cpp @@ -0,0 +1,3225 @@ +/* + * Copyright (c) 2021-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 "window_impl.h" + + +#include +#include +#include +#include +#include +#include + +#include "permission.h" +#include "color_parser.h" +#include "display_manager.h" +#include "display_info.h" +#include "ressched_report.h" +#include "singleton_container.h" +#include "surface_capture_future.h" +#include "sys_cap_util.h" +#include "window_adapter.h" +#include "window_agent.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#include "wm_common_inner.h" +#include "wm_math.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowImpl"}; + const std::string PARAM_DUMP_HELP = "-h"; +} + +WM_IMPLEMENT_SINGLE_INSTANCE(ResSchedReport); + +const WindowImpl::ColorSpaceConvertMap WindowImpl::colorSpaceConvertMap[] = { + { ColorSpace::COLOR_SPACE_DEFAULT, ColorGamut::COLOR_GAMUT_SRGB }, + { ColorSpace::COLOR_SPACE_WIDE_GAMUT, ColorGamut::COLOR_GAMUT_DCI_P3 }, +}; + +std::map>> WindowImpl::windowMap_; +std::map>> WindowImpl::subWindowMap_; +std::map>> WindowImpl::appFloatingWindowMap_; +std::map>> WindowImpl::appDialogWindowMap_; +std::map>> WindowImpl::screenshotListeners_; +std::map>> WindowImpl::touchOutsideListeners_; +std::map>> WindowImpl::dialogTargetTouchListeners_; +std::map>> WindowImpl::lifecycleListeners_; +std::map>> WindowImpl::windowChangeListeners_; +std::map>> WindowImpl::avoidAreaChangeListeners_; +std::map>> WindowImpl::occupiedAreaChangeListeners_; +std::map> WindowImpl::dialogDeathRecipientListener_; +std::recursive_mutex WindowImpl::globalMutex_; +int constructorCnt = 0; +int deConstructorCnt = 0; +WindowImpl::WindowImpl(const sptr& option) +{ + property_ = new (std::nothrow) WindowProperty(); + property_->SetWindowName(option->GetWindowName()); + property_->SetRequestRect(option->GetWindowRect()); + property_->SetWindowType(option->GetWindowType()); + property_->SetWindowMode(option->GetWindowMode()); + property_->SetFullScreen(option->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN); + property_->SetFocusable(option->GetFocusable()); + property_->SetTouchable(option->GetTouchable()); + property_->SetDisplayId(option->GetDisplayId()); + property_->SetCallingWindow(option->GetCallingWindow()); + property_->SetWindowFlags(option->GetWindowFlags()); + property_->SetHitOffset(option->GetHitOffset()); + property_->SetRequestedOrientation(option->GetRequestedOrientation()); + windowTag_ = option->GetWindowTag(); + isMainHandlerAvailable_ = option->GetMainHandlerAvailable(); + property_->SetTurnScreenOn(option->IsTurnScreenOn()); + property_->SetKeepScreenOn(option->IsKeepScreenOn()); + property_->SetBrightness(option->GetBrightness()); + AdjustWindowAnimationFlag(); + auto& sysBarPropMap = option->GetSystemBarProperty(); + for (auto it : sysBarPropMap) { + property_->SetSystemBarProperty(it.first, it.second); + } + name_ = option->GetWindowName(); + + surfaceNode_ = CreateSurfaceNode(property_->GetWindowName(), option->GetWindowType()); + + moveDragProperty_ = new (std::nothrow) MoveDragProperty(); + WLOGFD("WindowImpl constructorCnt: %{public}d name: %{public}s", + ++constructorCnt, property_->GetWindowName().c_str()); +} + +RSSurfaceNode::SharedPtr WindowImpl::CreateSurfaceNode(std::string name, WindowType type) +{ + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = name; + RSSurfaceNodeType rsSurfaceNodeType = RSSurfaceNodeType::DEFAULT; + switch (type) { + case WindowType::WINDOW_TYPE_BOOT_ANIMATION: + case WindowType::WINDOW_TYPE_POINTER: + rsSurfaceNodeType = RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE; + break; + default: + rsSurfaceNodeType = RSSurfaceNodeType::DEFAULT; + break; + } + return RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType); +} + +WindowImpl::~WindowImpl() +{ + WLOGFD("windowName: %{public}s, windowId: %{public}d, deConstructorCnt: %{public}d, surfaceNode:%{public}d", + GetWindowName().c_str(), GetWindowId(), ++deConstructorCnt, static_cast(surfaceNode_.use_count())); + Destroy(true, false); +} + +sptr WindowImpl::Find(const std::string& name) +{ + auto iter = windowMap_.find(name); + if (iter == windowMap_.end()) { + return nullptr; + } + return iter->second.second; +} + +const std::shared_ptr WindowImpl::GetContext() const +{ + return context_; +} + +sptr WindowImpl::FindTopWindow(uint32_t topWinId) +{ + if (windowMap_.empty()) { + WLOGFE("Please create mainWindow First!"); + return nullptr; + } + for (auto iter = windowMap_.begin(); iter != windowMap_.end(); iter++) { + if (topWinId == iter->second.first) { + WLOGFD("FindTopWindow id: %{public}u", topWinId); + return iter->second.second; + } + } + WLOGFE("Cannot find topWindow!"); + return nullptr; +} + +sptr WindowImpl::GetTopWindowWithId(uint32_t mainWinId) +{ + uint32_t topWinId = INVALID_WINDOW_ID; + WMError ret = SingletonContainer::Get().GetTopWindowId(mainWinId, topWinId); + if (ret != WMError::WM_OK) { + WLOGFE("GetTopWindowId failed with errCode:%{public}d", static_cast(ret)); + return nullptr; + } + return FindTopWindow(topWinId); +} + +sptr WindowImpl::GetTopWindowWithContext(const std::shared_ptr& context) +{ + if (windowMap_.empty()) { + WLOGFE("Please create mainWindow First!"); + return nullptr; + } + uint32_t mainWinId = INVALID_WINDOW_ID; + for (auto iter = windowMap_.begin(); iter != windowMap_.end(); iter++) { + auto win = iter->second.second; + if (context.get() == win->GetContext().get() && WindowHelper::IsMainWindow(win->GetType())) { + mainWinId = win->GetWindowId(); + WLOGFD("GetTopWindow Find MainWinId:%{public}u.", mainWinId); + break; + } + } + WLOGFD("GetTopWindowfinal MainWinId:%{public}u!", mainWinId); + if (mainWinId == INVALID_WINDOW_ID) { + WLOGFE("Cannot find topWindow!"); + return nullptr; + } + uint32_t topWinId = INVALID_WINDOW_ID; + WMError ret = SingletonContainer::Get().GetTopWindowId(mainWinId, topWinId); + if (ret != WMError::WM_OK) { + WLOGFE("GetTopWindowId failed with errCode:%{public}d", static_cast(ret)); + return nullptr; + } + return FindTopWindow(topWinId); +} + +std::vector> WindowImpl::GetSubWindow(uint32_t parentId) +{ + if (subWindowMap_.find(parentId) == subWindowMap_.end()) { + WLOGFE("Cannot parentWindow with id: %{public}u!", parentId); + return std::vector>(); + } + return std::vector>(subWindowMap_[parentId].begin(), subWindowMap_[parentId].end()); +} + +void WindowImpl::UpdateConfigurationForAll(const std::shared_ptr& configuration) +{ + for (const auto& winPair : windowMap_) { + auto window = winPair.second.second; + window->UpdateConfiguration(configuration); + } +} + +std::shared_ptr WindowImpl::GetSurfaceNode() const +{ + return surfaceNode_; +} + +Rect WindowImpl::GetRect() const +{ + return property_->GetWindowRect(); +} + +Rect WindowImpl::GetRequestRect() const +{ + return property_->GetRequestRect(); +} + +WindowType WindowImpl::GetType() const +{ + return property_->GetWindowType(); +} + +WindowMode WindowImpl::GetMode() const +{ + return property_->GetWindowMode(); +} + +float WindowImpl::GetAlpha() const +{ + return property_->GetAlpha(); +} + +WindowState WindowImpl::GetWindowState() const +{ + return state_; +} + +WMError WindowImpl::SetFocusable(bool isFocusable) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + property_->SetFocusable(isFocusable); + if (state_ == WindowState::STATE_SHOWN) { + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_FOCUSABLE); + } + return WMError::WM_OK; +} + +bool WindowImpl::GetFocusable() const +{ + return property_->GetFocusable(); +} + +WMError WindowImpl::SetTouchable(bool isTouchable) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + property_->SetTouchable(isTouchable); + if (state_ == WindowState::STATE_SHOWN) { + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_TOUCHABLE); + } + return WMError::WM_OK; +} + +bool WindowImpl::GetTouchable() const +{ + return property_->GetTouchable(); +} + +const std::string& WindowImpl::GetWindowName() const +{ + return name_; +} + +uint32_t WindowImpl::GetWindowId() const +{ + return property_->GetWindowId(); +} + +uint32_t WindowImpl::GetWindowFlags() const +{ + return property_->GetWindowFlags(); +} + +uint32_t WindowImpl::GetRequestModeSupportInfo() const +{ + return property_->GetRequestModeSupportInfo(); +} + +uint32_t WindowImpl::GetModeSupportInfo() const +{ + return property_->GetModeSupportInfo(); +} + +bool WindowImpl::IsMainHandlerAvailable() const +{ + return isMainHandlerAvailable_; +} + +SystemBarProperty WindowImpl::GetSystemBarPropertyByType(WindowType type) const +{ + auto curProperties = property_->GetSystemBarProperty(); + return curProperties[type]; +} + +WMError WindowImpl::GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea) +{ + WLOGFD("GetAvoidAreaByType Search Type: %{public}u", static_cast(type)); + uint32_t windowId = property_->GetWindowId(); + WMError ret = SingletonContainer::Get().GetAvoidAreaByType(windowId, type, avoidArea); + if (ret != WMError::WM_OK) { + WLOGFE("GetAvoidAreaByType errCode:%{public}d winId:%{public}u Type is :%{public}u.", + static_cast(ret), property_->GetWindowId(), static_cast(type)); + } + return ret; +} + +WMError WindowImpl::SetWindowType(WindowType type) +{ + WLOGFD("window id: %{public}u, type:%{public}u.", property_->GetWindowId(), static_cast(type)); + if (type != WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW && !Permission::IsSystemCalling()) { + WLOGFE("set window type permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (state_ == WindowState::STATE_CREATED) { + if (!(WindowHelper::IsAppWindow(type) || WindowHelper::IsSystemWindow(type))) { + WLOGFE("window type is invalid %{public}u.", type); + return WMError::WM_ERROR_INVALID_PARAM; + } + property_->SetWindowType(type); + if (isAppDecorEnable_ && windowSystemConfig_.isSystemDecorEnable_) { + property_->SetDecorEnable(WindowHelper::IsMainWindow(property_->GetWindowType())); + } + AdjustWindowAnimationFlag(); + return WMError::WM_OK; + } + if (property_->GetWindowType() != type) { + return WMError::WM_ERROR_INVALID_PARAM; + } + return WMError::WM_OK; +} + +WMError WindowImpl::SetWindowMode(WindowMode mode) +{ + WLOGFD("[Client] Window %{public}u mode %{public}u", property_->GetWindowId(), static_cast(mode)); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (!WindowHelper::IsWindowModeSupported(GetModeSupportInfo(), mode)) { + WLOGFD("window %{public}u do not support window mode: %{public}u", + property_->GetWindowId(), static_cast(mode)); + return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE; + } + if (state_ == WindowState::STATE_CREATED || state_ == WindowState::STATE_HIDDEN) { + UpdateMode(mode); + } else if (state_ == WindowState::STATE_SHOWN) { + WindowMode lastMode = property_->GetWindowMode(); + property_->SetWindowMode(mode); + WMError ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_MODE); + if (ret != WMError::WM_OK) { + property_->SetWindowMode(lastMode); + return ret; + } + // set client window mode if success. + UpdateMode(mode); + } + if (property_->GetWindowMode() != mode) { + WLOGFE("set window mode filed! id: %{public}u.", property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_PARAM; + } + return WMError::WM_OK; +} + +void WindowImpl::SetAlpha(float alpha) +{ + WLOGFD("[Client] Window %{public}u alpha %{public}f", property_->GetWindowId(), alpha); + if (!Permission::IsSystemCalling()) { + WLOGFE("set alpha permission denied!"); + return; + } + if (!IsWindowValid()) { + return; + } + property_->SetAlpha(alpha); + surfaceNode_->SetAlpha(alpha); + RSTransaction::FlushImplicitTransaction(); +} + +void WindowImpl::SetTransform(const Transform& trans) +{ + WLOGFD("[Client] Window %{public}u SetTransform", property_->GetWindowId()); + if (!IsWindowValid()) { + return; + } + Transform oriTrans = property_->GetTransform(); + property_->SetTransform(trans); + WMError ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY); + if (ret != WMError::WM_OK) { + WLOGFE("SetTransform errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + property_->SetTransform(oriTrans); // reset to ori transform when update failed + } + if (property_->IsDisplayZoomOn()) { + TransformSurfaceNode(property_->GetZoomTransform()); + } else { + TransformSurfaceNode(trans); + } +} + +const Transform& WindowImpl::GetTransform() const +{ + return property_->GetTransform(); +} + +const Transform& WindowImpl::GetZoomTransform() const +{ + return property_->GetZoomTransform(); +} + +WMError WindowImpl::AddWindowFlag(WindowFlag flag) +{ + if (flag == WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED && state_ != WindowState::STATE_CREATED) { + WLOGFE("Only support add show when locked when window create, id: %{public}u", property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW; + } + + uint32_t updateFlags = property_->GetWindowFlags() | (static_cast(flag)); + return SetWindowFlags(updateFlags); +} + +WMError WindowImpl::RemoveWindowFlag(WindowFlag flag) +{ + if (flag == WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED && state_ != WindowState::STATE_CREATED) { + WLOGFE("Only support remove show when locked when window create, id: %{public}u", property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW; + } + + uint32_t updateFlags = property_->GetWindowFlags() & (~(static_cast(flag))); + return SetWindowFlags(updateFlags); +} + +WMError WindowImpl::SetWindowFlags(uint32_t flags) +{ + WLOGFD("[Client] Window %{public}u flags %{public}u", property_->GetWindowId(), flags); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (property_->GetWindowFlags() == flags) { + return WMError::WM_OK; + } + auto oriFlags = property_->GetWindowFlags(); + property_->SetWindowFlags(flags); + if (state_ == WindowState::STATE_CREATED || state_ == WindowState::STATE_HIDDEN) { + return WMError::WM_OK; + } + WMError ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_FLAGS); + if (ret != WMError::WM_OK) { + WLOGFE("SetWindowFlags errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + property_->SetWindowFlags(oriFlags); + } + return ret; +} + +void WindowImpl::OnNewWant(const AAFwk::Want& want) +{ + WLOGFD("[Client] Window [name:%{public}s, id:%{public}u] OnNewWant", name_.c_str(), property_->GetWindowId()); + if (uiContent_ != nullptr) { + uiContent_->OnNewWant(want); + } +} + +WMError WindowImpl::SetUIContent(const std::string& contentInfo, + NativeEngine* engine, NativeValue* storage, bool isdistributed, AppExecFwk::Ability* ability) +{ + WLOGFD("SetUIContent contentInfo: %{public}s", contentInfo.c_str()); + if (uiContent_) { + uiContent_->Destroy(); + } + std::unique_ptr uiContent; + if (ability != nullptr) { + uiContent = Ace::UIContent::Create(ability); + } else { + uiContent = Ace::UIContent::Create(context_.get(), engine); + } + if (uiContent == nullptr) { + WLOGFE("fail to SetUIContent id: %{public}u", property_->GetWindowId()); + return WMError::WM_ERROR_NULLPTR; + } + if (!isAppDecorEnable_ || !windowSystemConfig_.isSystemDecorEnable_) { + WLOGFD("app set decor enable false"); + property_->SetDecorEnable(false); + } + if (isdistributed) { + uiContent->Restore(this, contentInfo, storage); + } else { + uiContent->Initialize(this, contentInfo, storage); + } + // make uiContent available after Initialize/Restore + uiContent_ = std::move(uiContent); + + if (state_ == WindowState::STATE_SHOWN) { + // UIContent may be nullptr when show window, need to notify again when window is shown + uiContent_->Foreground(); + UpdateTitleButtonVisibility(); + Ace::ViewportConfig config; + Rect rect = GetRect(); + config.SetSize(rect.width_, rect.height_); + config.SetPosition(rect.posX_, rect.posY_); + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); + if (display == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return WMError::WM_ERROR_NULLPTR; + } + float virtualPixelRatio = display->GetVirtualPixelRatio(); + config.SetDensity(virtualPixelRatio); + uiContent_->UpdateViewportConfig(config, WindowSizeChangeReason::UNDEFINED); + WLOGFD("notify uiContent window size change end"); + } + return WMError::WM_OK; +} + +Ace::UIContent* WindowImpl::GetUIContent() const +{ + return uiContent_.get(); +} + +std::string WindowImpl::GetContentInfo() +{ + WLOGFD("GetContentInfo"); + if (uiContent_ == nullptr) { + WLOGFE("fail to GetContentInfo id: %{public}u", property_->GetWindowId()); + return ""; + } + return uiContent_->GetContentInfo(); +} + +ColorSpace WindowImpl::GetColorSpaceFromSurfaceGamut(ColorGamut ColorGamut) +{ + for (auto item: colorSpaceConvertMap) { + if (item.surfaceColorGamut == ColorGamut) { + return item.colorSpace; + } + } + return ColorSpace::COLOR_SPACE_DEFAULT; +} + +ColorGamut WindowImpl::GetSurfaceGamutFromColorSpace(ColorSpace colorSpace) +{ + for (auto item: colorSpaceConvertMap) { + if (item.colorSpace == colorSpace) { + return item.surfaceColorGamut; + } + } + return ColorGamut::COLOR_GAMUT_SRGB; +} + +bool WindowImpl::IsSupportWideGamut() +{ + return true; +} + +void WindowImpl::SetColorSpace(ColorSpace colorSpace) +{ + auto surfaceGamut = GetSurfaceGamutFromColorSpace(colorSpace); + surfaceNode_->SetColorSpace(surfaceGamut); +} + +ColorSpace WindowImpl::GetColorSpace() +{ + auto surfaceGamut = surfaceNode_->GetColorSpace(); + return GetColorSpaceFromSurfaceGamut(surfaceGamut); +} + +std::shared_ptr WindowImpl::Snapshot() +{ + WLOGFD("WMS-Client Snapshot"); + std::shared_ptr callback = std::make_shared(); + auto isSucceeded = RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode_, callback); + std::shared_ptr pixelMap; + if (isSucceeded) { + pixelMap = callback->GetResult(2000); // wait for <= 2000ms + } else { + pixelMap = SingletonContainer::Get().GetSnapshot(property_->GetWindowId()); + } + if (pixelMap != nullptr) { + WLOGFD("WMS-Client Save WxH = %{public}dx%{public}d", pixelMap->GetWidth(), pixelMap->GetHeight()); + } else { + WLOGFE("Failed to get pixelmap, return nullptr!"); + } + return pixelMap; +} + +void WindowImpl::DumpInfo(const std::vector& params, std::vector& info) +{ + if (params.size() == 1 && params[0] == PARAM_DUMP_HELP) { // 1: params num + WLOGFD("Dump ArkUI help Info"); + Ace::UIContent::ShowDumpHelp(info); + return; + } + WLOGFD("ArkUI:DumpInfo"); + if (uiContent_ != nullptr) { + uiContent_->DumpInfo(params, info); + } + SingletonContainer::Get().NotifyDumpInfoResult(info); +} + +WMError WindowImpl::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) +{ + WLOGFD("[Client] Window %{public}u SetSystemBarProperty type %{public}u " \ + "enable:%{public}u, backgroundColor:%{public}x, contentColor:%{public}x ", + property_->GetWindowId(), static_cast(type), property.enable_, + property.backgroundColor_, property.contentColor_); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (GetSystemBarPropertyByType(type) == property) { + return WMError::WM_OK; + } + property_->SetSystemBarProperty(type, property); + if (state_ == WindowState::STATE_CREATED || state_ == WindowState::STATE_HIDDEN) { + return WMError::WM_OK; + } + WMError ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS); + if (ret != WMError::WM_OK) { + WLOGFE("SetSystemBarProperty errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + } + return ret; +} + +WMError WindowImpl::UpdateSystemBarProperty(bool status) +{ + if (!IsWindowValid()) { + WLOGFE("PutSystemBarProperty errCode:%{public}d winId:%{public}u", + static_cast(WMError::WM_ERROR_INVALID_WINDOW), property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW; + } + + SystemBarProperty statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR); + SystemBarProperty naviProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + if (status) { + statusProperty.enable_ = false; + naviProperty.enable_ = false; + } else { + statusProperty.enable_ = true; + naviProperty.enable_ = true; + } + + if ((GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR) == statusProperty) && + (GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR) == naviProperty)) { + return WMError::WM_OK; + } + if (!(GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR) == statusProperty)) { + property_->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusProperty); + } + if (!(GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR) == naviProperty)) { + property_->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, naviProperty); + } + if (state_ == WindowState::STATE_CREATED || state_ == WindowState::STATE_HIDDEN) { + return WMError::WM_OK; + } + + WMError ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS); + if (ret != WMError::WM_OK) { + WLOGFE("SetSystemBarProperty errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + } + return ret; +} + +WMError WindowImpl::SetLayoutFullScreen(bool status) +{ + WLOGFD("[Client] Window %{public}u SetLayoutFullScreen: %{public}u", property_->GetWindowId(), status); + if (!IsWindowValid() || + !WindowHelper::IsWindowModeSupported(GetModeSupportInfo(), WindowMode::WINDOW_MODE_FULLSCREEN)) { + WLOGFE("invalid window or fullscreen mode is not be supported, winId:%{public}u", property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW; + } + WMError ret = SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + if (ret != WMError::WM_OK) { + WLOGFE("SetWindowMode errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + return ret; + } + if (status) { + ret = RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + if (ret != WMError::WM_OK) { + WLOGFE("RemoveWindowFlag errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + return ret; + } + } else { + ret = AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + if (ret != WMError::WM_OK) { + WLOGFE("AddWindowFlag errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + return ret; + } + } + return ret; +} + +WMError WindowImpl::SetFullScreen(bool status) +{ + WLOGFD("[Client] Window %{public}u SetFullScreen: %{public}d", property_->GetWindowId(), status); + if (!IsWindowValid() || + !WindowHelper::IsWindowModeSupported(GetModeSupportInfo(), WindowMode::WINDOW_MODE_FULLSCREEN)) { + WLOGFE("invalid window or fullscreen mode is not be supported, winId:%{public}u", property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW; + } + WMError ret = UpdateSystemBarProperty(status); + if (ret != WMError::WM_OK) { + WLOGFE("UpdateSystemBarProperty errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + } + ret = SetLayoutFullScreen(status); + if (ret != WMError::WM_OK) { + WLOGFE("SetLayoutFullScreen errCode:%{public}d winId:%{public}u", + static_cast(ret), property_->GetWindowId()); + } + return ret; +} + +void WindowImpl::MapFloatingWindowToAppIfNeeded() +{ + if (!WindowHelper::IsAppFloatingWindow(GetType()) || context_.get() == nullptr) { + return; + } + + for (const auto& winPair : windowMap_) { + auto win = winPair.second.second; + if (win->GetType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && + context_.get() == win->GetContext().get()) { + sptr selfImpl(this); + appFloatingWindowMap_[win->GetWindowId()].push_back(selfImpl); + WLOGFD("Map FloatingWindow %{public}u to AppMainWindow %{public}u, type is %{public}u", + GetWindowId(), win->GetWindowId(), GetType()); + return; + } + } +} + +void WindowImpl::MapDialogWindowToAppIfNeeded() +{ + if (GetType() != WindowType::WINDOW_TYPE_DIALOG) { + return; + } + + for (const auto& winPair : windowMap_) { + auto win = winPair.second.second; + if (win->GetType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && + context_.get() == win->GetContext().get()) { + sptr selfImpl(this); + appDialogWindowMap_[win->GetWindowId()].push_back(selfImpl); + WLOGFD("Map DialogWindow %{public}u to AppMainWindow %{public}u", GetWindowId(), win->GetWindowId()); + return; + } + } +} + +WMError WindowImpl::UpdateProperty(PropertyChangeAction action) +{ + return SingletonContainer::Get().UpdateProperty(property_, action); +} + +void WindowImpl::GetConfigurationFromAbilityInfo() +{ + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + if (abilityContext == nullptr) { + WLOGFE("id:%{public}u is not ability Window", property_->GetWindowId()); + return; + } + auto abilityInfo = abilityContext->GetAbilityInfo(); + if (abilityInfo == nullptr) { + WLOGFE("id:%{public}u Ability window get ability info failed", property_->GetWindowId()); + return; + } + + // get support modes configuration + uint32_t modeSupportInfo = WindowHelper::ConvertSupportModesToSupportInfo(abilityInfo->windowModes); + if (modeSupportInfo == 0) { + WLOGFD("mode config param is 0, all modes is supported"); + modeSupportInfo = WindowModeSupport::WINDOW_MODE_SUPPORT_ALL; + } + WLOGFD("winId: %{public}u, modeSupportInfo: %{public}u", GetWindowId(), modeSupportInfo); + SetRequestModeSupportInfo(modeSupportInfo); + + // get window size limits configuration + WindowSizeLimits sizeLimits; + sizeLimits.maxWidth_ = abilityInfo->maxWindowWidth; + sizeLimits.maxHeight_ = abilityInfo->maxWindowHeight; + sizeLimits.minWidth_ = abilityInfo->minWindowWidth; + sizeLimits.minHeight_ = abilityInfo->minWindowHeight; + sizeLimits.maxRatio_ = static_cast(abilityInfo->maxWindowRatio); + sizeLimits.minRatio_ = static_cast(abilityInfo->minWindowRatio); + property_->SetSizeLimits(sizeLimits); + + // get orientation configuration + DisplayOrientation displayOrientation = static_cast( + static_cast(abilityInfo->orientation)); + if (ABILITY_TO_WMS_ORIENTATION_MAP.count(displayOrientation) == 0) { + WLOGFE("id:%{public}u Do not support this Orientation type", property_->GetWindowId()); + return; + } + Orientation orientation = ABILITY_TO_WMS_ORIENTATION_MAP.at(displayOrientation); + if (orientation < Orientation::BEGIN || orientation > Orientation::END) { + WLOGFE("Set orientation from ability failed"); + return; + } + property_->SetRequestedOrientation(orientation); +} + +void WindowImpl::UpdateTitleButtonVisibility() +{ + WLOGFD("[Client] UpdateTitleButtonVisibility"); + if (uiContent_ == nullptr || !isAppDecorEnable_) { + return; + } + auto modeSupportInfo = GetModeSupportInfo(); + bool hideSplitButton = !(modeSupportInfo & WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY); + // not support fullscreen in split and floating mode, or not support float in fullscreen mode + bool hideMaximizeButton = (!(modeSupportInfo & WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN) && + (GetMode() == WindowMode::WINDOW_MODE_FLOATING || WindowHelper::IsSplitWindowMode(GetMode()))) || + (!(modeSupportInfo & WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING) && + GetMode() == WindowMode::WINDOW_MODE_FULLSCREEN); + WLOGFD("[Client] [hideSplit, hideMaximize]: [%{public}d, %{public}d]", hideSplitButton, hideMaximizeButton); + uiContent_->HideWindowTitleButton(hideSplitButton, hideMaximizeButton, false); +} + +bool WindowImpl::IsAppMainOrSubOrFloatingWindow() +{ + // App main window need decor config, stretchable config and effect config + // App sub window and float window need effect config + if (WindowHelper::IsAppWindow(GetType())) { + return true; + } + + if (WindowHelper::IsAppFloatingWindow(GetType())) { + for (const auto& winPair : windowMap_) { + auto win = winPair.second.second; + if (win != nullptr && win->GetType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && + context_.get() == win->GetContext().get()) { + isAppFloatingWindow_ = true; + return true; + } + } + } + return false; +} + +void WindowImpl::SetWindowCornerRadiusAccordingToSystemConfig() +{ + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); + if (display == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return; + } + auto vpr = display->GetVirtualPixelRatio(); + auto fullscreenRadius = windowSystemConfig_.effectConfig_.fullScreenCornerRadius_ * vpr; + auto splitRadius = windowSystemConfig_.effectConfig_.splitCornerRadius_ * vpr; + auto floatRadius = windowSystemConfig_.effectConfig_.floatCornerRadius_ * vpr; + + WLOGFD("[WEffect] [name:%{public}s] mode: %{public}u, vpr: %{public}f, [%{public}f, %{public}f, %{public}f]", + name_.c_str(), GetMode(), vpr, fullscreenRadius, splitRadius, floatRadius); + + if (WindowHelper::IsFullScreenWindow(GetMode()) && MathHelper::GreatNotEqual(fullscreenRadius, 0.0)) { + SetCornerRadius(fullscreenRadius); + } else if (WindowHelper::IsSplitWindowMode(GetMode()) && MathHelper::GreatNotEqual(splitRadius, 0.0)) { + SetCornerRadius(splitRadius); + } else if (WindowHelper::IsFloatingWindow(GetMode()) && MathHelper::GreatNotEqual(floatRadius, 0.0)) { + SetCornerRadius(floatRadius); + } +} + +void WindowImpl::UpdateWindowShadowAccordingToSystemConfig() +{ + if (!WindowHelper::IsAppWindow(GetType()) && !isAppFloatingWindow_) { + return; + } + + auto& shadow = isFocused_ ? windowSystemConfig_.effectConfig_.focusedShadow_ : + windowSystemConfig_.effectConfig_.unfocusedShadow_; + + if (MathHelper::NearZero(shadow.elevation_)) { + return; + } + + if (!WindowHelper::IsFloatingWindow(GetMode())) { + surfaceNode_->SetShadowElevation(0.f); + WLOGFD("[WEffect][%{public}s]close shadow", name_.c_str()); + return; + } + + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); + if (display == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return; + } + auto vpr = display->GetVirtualPixelRatio(); + + uint32_t colorValue; + if (!ColorParser::Parse(shadow.color_, colorValue)) { + WLOGFE("[WEffect]invalid color string: %{public}s", shadow.color_.c_str()); + return; + } + + WLOGFD("[WEffect][%{public}s]focused: %{public}u, [%{public}f, %{public}s, %{public}f, %{public}f, %{public}f]", + name_.c_str(), isFocused_, shadow.elevation_, shadow.color_.c_str(), + shadow.offsetX_, shadow.offsetY_, shadow.alpha_); + + surfaceNode_->SetShadowElevation(shadow.elevation_ * vpr); + surfaceNode_->SetShadowColor(colorValue); + surfaceNode_->SetShadowOffsetX(shadow.offsetX_); + surfaceNode_->SetShadowOffsetY(shadow.offsetY_); + surfaceNode_->SetShadowAlpha(shadow.alpha_); + RSTransaction::FlushImplicitTransaction(); +} + +void WindowImpl::SetSystemConfig() +{ + if (!IsAppMainOrSubOrFloatingWindow()) { + return; + } + if (SingletonContainer::Get().GetSystemConfig(windowSystemConfig_) == WMError::WM_OK) { + if (WindowHelper::IsMainWindow(property_->GetWindowType())) { + WLOGFD("get system decor enable:%{public}d", windowSystemConfig_.isSystemDecorEnable_); + property_->SetDecorEnable(windowSystemConfig_.isSystemDecorEnable_); + WLOGFD("get stretchable enable:%{public}d", windowSystemConfig_.isStretchable_); + property_->SetStretchable(windowSystemConfig_.isStretchable_); + // if window mode is undefined, set it from configuration + if (property_->GetWindowMode() == WindowMode::WINDOW_MODE_UNDEFINED) { + WLOGFD("get default window mode:%{public}u", windowSystemConfig_.defaultWindowMode_); + property_->SetWindowMode(windowSystemConfig_.defaultWindowMode_); + } + if (property_->GetLastWindowMode() == WindowMode::WINDOW_MODE_UNDEFINED) { + property_->SetLastWindowMode(windowSystemConfig_.defaultWindowMode_); + } + } + SetWindowCornerRadiusAccordingToSystemConfig(); + } + UpdateWindowShadowAccordingToSystemConfig(); +} + +bool WindowImpl::WindowCreateCheck(uint32_t parentId) +{ + // check window name, same window names are forbidden + if (windowMap_.find(name_) != windowMap_.end()) { + WLOGFE("WindowName(%{public}s) already exists.", name_.c_str()); + return false; + } + if (CheckCameraFloatingWindowMultiCreated(property_->GetWindowType())) { + WLOGFE("Camera Floating Window already exists."); + return false; + } + if (parentId == INVALID_WINDOW_ID) { + if (WindowHelper::IsSystemSubWindow(property_->GetWindowType()) || + WindowHelper::IsSubWindow(property_->GetWindowType())) { + return false; + } + return true; + } + + if (property_->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) { + property_->SetParentId(parentId); + } else { + sptr parentWindow = nullptr; + for (const auto& winPair : windowMap_) { + if (winPair.second.first == parentId) { + property_->SetParentId(parentId); + parentWindow = winPair.second.second; + break; + } + } + if (WindowHelper::IsSystemSubWindow(property_->GetWindowType())) { + if (parentWindow == nullptr) { + return false; + } + if (!parentWindow->IsAllowHaveSystemSubWindow()) { + return false; + } + } + } + if (property_->GetParentId() != parentId) { + WLOGFE("Parent Window does not exist. ParentId is %{public}u", parentId); + return false; + } + + return true; +} + +WMError WindowImpl::Create(uint32_t parentId, const std::shared_ptr& context) +{ + WLOGFD("[Client] Window [name:%{public}s] Create", name_.c_str()); + if (!WindowCreateCheck(parentId)) { + return WMError::WM_ERROR_INVALID_PARAM; + } + + context_ = context; + sptr window(this); + sptr windowAgent(new WindowAgent(window)); + static std::atomic tempWindowId = 0; + uint32_t windowId = tempWindowId++; // for test + sptr token = nullptr; + if (context_ != nullptr) { + token = context_->GetToken(); + if (token != nullptr) { + property_->SetTokenState(true); + } + } + InitAbilityInfo(); + SetSystemConfig(); + + if (WindowHelper::IsMainWindow(property_->GetWindowType())) { + GetConfigurationFromAbilityInfo(); + } else if (property_->GetWindowMode() == WindowMode::WINDOW_MODE_UNDEFINED) { + property_->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + } + + if (property_->GetWindowType() == WindowType::WINDOW_TYPE_VOLUME_OVERLAY) { + surfaceNode_->SetFrameGravity(Gravity::TOP_LEFT); + } + + WMError ret = SingletonContainer::Get().CreateWindow(windowAgent, property_, surfaceNode_, + windowId, token); + RecordLifeCycleExceptionEvent(LifeCycleEvent::CREATE_EVENT, ret); + if (ret != WMError::WM_OK) { + WLOGFE("create window failed with errCode:%{public}d", static_cast(ret)); + return ret; + } + property_->SetWindowId(windowId); + if (surfaceNode_) { + surfaceNode_->SetWindowId(windowId); + } + sptr self(this); + windowMap_.insert(std::make_pair(name_, std::pair>(windowId, self))); + if (parentId != INVALID_WINDOW_ID) { + subWindowMap_[property_->GetParentId()].push_back(window); + } + + MapFloatingWindowToAppIfNeeded(); + MapDialogWindowToAppIfNeeded(); + + state_ = WindowState::STATE_CREATED; + InputTransferStation::GetInstance().AddInputWindow(self); + needRemoveWindowInputChannel_ = true; + return ret; +} + +void WindowImpl::InitAbilityInfo() +{ + AbilityInfo info; + info.bundleName_ = SysCapUtil::GetBundleName(); + auto originalAbilityInfo = GetOriginalAbilityInfo(); + if (originalAbilityInfo != nullptr) { + info.abilityName_ = originalAbilityInfo->name; + } else { + WLOGFD("original ability info is null %{public}s", name_.c_str()); + } + property_->SetAbilityInfo(info); +} + +std::shared_ptr WindowImpl::GetOriginalAbilityInfo() const +{ + if (context_ == nullptr) { + WLOGFD("context is null %{public}s", name_.c_str()); + return nullptr; + } + + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + if (abilityContext == nullptr) { + WLOGFD("abilityContext is null %{public}s", name_.c_str()); + return nullptr; + } + return abilityContext->GetAbilityInfo(); +} + +WMError WindowImpl::BindDialogTarget(sptr targetToken) +{ + uint32_t windowId = property_->GetWindowId(); + WMError ret = SingletonContainer::Get().BindDialogTarget(windowId, targetToken); + if (ret != WMError::WM_OK) { + WLOGFE("bind window failed with errCode:%{public}d", static_cast(ret)); + } + + return ret; +} + +void WindowImpl::DestroyDialogWindow() +{ + // remove from appDialogWindowMap_ + for (auto& dialogWindows: appDialogWindowMap_) { + for (auto iter = dialogWindows.second.begin(); iter != dialogWindows.second.end(); ++iter) { + if ((*iter) == nullptr) { + continue; + } + if ((*iter)->GetWindowId() == GetWindowId()) { + dialogWindows.second.erase(iter); + break; + } + } + } + + // Destroy app dialog window if exist + if (appDialogWindowMap_.count(GetWindowId()) > 0) { + auto& dialogWindows = appDialogWindowMap_.at(GetWindowId()); + for (auto iter = dialogWindows.begin(); iter != dialogWindows.end(); iter = dialogWindows.begin()) { + if ((*iter) == nullptr) { + dialogWindows.erase(iter); + continue; + } + (*iter)->Destroy(false); + } + appDialogWindowMap_.erase(GetWindowId()); + } +} + +void WindowImpl::DestroyFloatingWindow() +{ + // remove from appFloatingWindowMap_ + for (auto& floatingWindows: appFloatingWindowMap_) { + for (auto iter = floatingWindows.second.begin(); iter != floatingWindows.second.end(); ++iter) { + if ((*iter) == nullptr) { + continue; + } + if ((*iter)->GetWindowId() == GetWindowId()) { + floatingWindows.second.erase(iter); + break; + } + } + } + + // Destroy app floating window if exist + if (appFloatingWindowMap_.count(GetWindowId()) > 0) { + auto& floatingWindows = appFloatingWindowMap_.at(GetWindowId()); + for (auto iter = floatingWindows.begin(); iter != floatingWindows.end(); iter = floatingWindows.begin()) { + if ((*iter) == nullptr) { + floatingWindows.erase(iter); + continue; + } + (*iter)->Destroy(); + } + appFloatingWindowMap_.erase(GetWindowId()); + } +} + +void WindowImpl::DestroySubWindow() +{ + if (subWindowMap_.count(property_->GetParentId()) > 0) { // remove from subWindowMap_ + std::vector>& subWindows = subWindowMap_.at(property_->GetParentId()); + for (auto iter = subWindows.begin(); iter < subWindows.end(); ++iter) { + if ((*iter) == nullptr) { + continue; + } + if ((*iter)->GetWindowId() == GetWindowId()) { + subWindows.erase(iter); + break; + } + } + } + + if (subWindowMap_.count(GetWindowId()) > 0) { // remove from subWindowMap_ and windowMap_ + auto& subWindows = subWindowMap_.at(GetWindowId()); + for (auto iter = subWindows.begin(); iter != subWindows.end(); iter = subWindows.begin()) { + if ((*iter) == nullptr) { + subWindows.erase(iter); + continue; + } + (*iter)->Destroy(false); + } + subWindowMap_[GetWindowId()].clear(); + subWindowMap_.erase(GetWindowId()); + } +} + +WMError WindowImpl::Destroy() +{ + return Destroy(true); +} + +WMError WindowImpl::Destroy(bool needNotifyServer, bool needClearListener) +{ + if (!IsWindowValid()) { + return WMError::WM_OK; + } + + WLOGFD("[Client] Window %{public}u Destroy", property_->GetWindowId()); + WMError ret = WMError::WM_OK; + if (needNotifyServer) { + NotifyBeforeDestroy(GetWindowName()); + if (subWindowMap_.count(GetWindowId()) > 0) { + for (auto& subWindow : subWindowMap_.at(GetWindowId())) { + NotifyBeforeSubWindowDestroy(subWindow); + } + } + ret = SingletonContainer::Get().DestroyWindow(property_->GetWindowId()); + RecordLifeCycleExceptionEvent(LifeCycleEvent::DESTROY_EVENT, ret); + if (ret != WMError::WM_OK) { + WLOGFE("destroy window failed with errCode:%{public}d", static_cast(ret)); + if (GetType() != WindowType::WINDOW_TYPE_DIALOG) { + return ret; + } + } + } else { + WLOGFD("Do not need to notify server to destroy window"); + } + + if (needRemoveWindowInputChannel_) { + InputTransferStation::GetInstance().RemoveInputWindow(property_->GetWindowId()); + } + windowMap_.erase(GetWindowName()); + if (needClearListener) { + ClearListenersById(GetWindowId()); + } + DestroySubWindow(); + DestroyFloatingWindow(); + DestroyDialogWindow(); + { + std::lock_guard lock(mutex_); + state_ = WindowState::STATE_DESTROYED; + } + return ret; +} + +bool WindowImpl::NeedToStopShowing() +{ + if (!WindowHelper::IsMainWindow(property_->GetWindowType())) { + return false; + } + // show failed when current mode is not support or window only supports split mode and can show when locked + bool isShowWhenLocked = GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + if (!WindowHelper::IsWindowModeSupported(GetModeSupportInfo(), GetMode()) || + WindowHelper::IsOnlySupportSplitAndShowWhenLocked(isShowWhenLocked, GetModeSupportInfo())) { + WLOGFE("current mode is not supported, windowId: %{public}u, modeSupportInfo: %{public}u, winMode: %{public}u", + property_->GetWindowId(), GetModeSupportInfo(), GetMode()); + return true; + } + return false; +} + +WMError WindowImpl::UpdateSurfaceNodeAfterCustomAnimation(bool isAdd) +{ + WLOGFD("[Client] Window [name:%{public}s, id:%{public}u] UpdateRsTree, isAdd:%{public}u", + name_.c_str(), property_->GetWindowId(), isAdd); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (!WindowHelper::IsSystemWindow(property_->GetWindowType())) { + WLOGFE("only system window can set"); + return WMError::WM_ERROR_INVALID_OPERATION; + } + AdjustWindowAnimationFlag(false); // false means update rs tree with default option + // need time out check + WMError ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG); + if (ret != WMError::WM_OK) { + WLOGFE("UpdateProperty failed with errCode:%{public}d", static_cast(ret)); + return ret; + } + ret = SingletonContainer::Get().UpdateRsTree(property_->GetWindowId(), isAdd); + if (ret != WMError::WM_OK) { + WLOGFE("UpdateRsTree failed with errCode:%{public}d", static_cast(ret)); + return ret; + } + return WMError::WM_OK; +} + +void WindowImpl::AdjustWindowAnimationFlag(bool withAnimation) +{ + // when show/hide with animation + // use custom animation when transitionController exists; else use default animation + WindowType winType = property_->GetWindowType(); + bool isAppWindow = WindowHelper::IsAppWindow(winType); + if (withAnimation && !isAppWindow && animationTransitionController_) { + // use custom animation + property_->SetAnimationFlag(static_cast(WindowAnimation::CUSTOM)); + } else if (isAppWindow || (withAnimation && !animationTransitionController_)) { + // use default animation + property_->SetAnimationFlag(static_cast(WindowAnimation::DEFAULT)); + } else if (winType == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + property_->SetAnimationFlag(static_cast(WindowAnimation::INPUTE)); + } else { + // with no animation + property_->SetAnimationFlag(static_cast(WindowAnimation::NONE)); + } +} + +WMError WindowImpl::PreProcessShow(uint32_t reason, bool withAnimation) +{ + if (state_ == WindowState::STATE_FROZEN) { + WLOGFE("window is frozen, can not be shown, windowId: %{public}u", property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + SetDefaultOption(); + SetModeSupportInfo(GetRequestModeSupportInfo()); + AdjustWindowAnimationFlag(withAnimation); + + if (NeedToStopShowing()) { // true means stop showing + return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE; + } + + // update title button visibility when show + UpdateTitleButtonVisibility(); + return WMError::WM_OK; +} + +WMError WindowImpl::Show(uint32_t reason, bool withAnimation) +{ + WLOGFD("[Client] Window Show [name:%{public}s, id:%{public}u, mode: %{public}u], reason:%{public}u, " + "withAnimation:%{public}d", name_.c_str(), property_->GetWindowId(), GetMode(), reason, withAnimation); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + WindowStateChangeReason stateChangeReason = static_cast(reason); + if (stateChangeReason == WindowStateChangeReason::KEYGUARD || + stateChangeReason == WindowStateChangeReason::TOGGLING) { + state_ = WindowState::STATE_SHOWN; + NotifyAfterForeground(); + return WMError::WM_OK; + } + if (state_ == WindowState::STATE_SHOWN) { + if (property_->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + WLOGFD("desktop window [id:%{public}u] is shown, minimize all app windows", property_->GetWindowId()); + SingletonContainer::Get().MinimizeAllAppWindows(property_->GetDisplayId()); + } else { + WLOGFD("window is already shown id: %{public}u, raise to top", property_->GetWindowId()); + SingletonContainer::Get().ProcessPointDown(property_->GetWindowId(), false); + } + NotifyAfterForeground(false); + return WMError::WM_OK; + } + WMError ret = PreProcessShow(reason, withAnimation); + if (ret != WMError::WM_OK) { + NotifyForegroundFailed(ret); + return ret; + } + + ret = SingletonContainer::Get().AddWindow(property_); + RecordLifeCycleExceptionEvent(LifeCycleEvent::SHOW_EVENT, ret); + if (ret == WMError::WM_OK) { + state_ = WindowState::STATE_SHOWN; + NotifyAfterForeground(); + } else { + NotifyForegroundFailed(ret); + WLOGFE("show window id:%{public}u errCode:%{public}d", property_->GetWindowId(), static_cast(ret)); + } + return ret; +} + +WMError WindowImpl::Hide(uint32_t reason, bool withAnimation) +{ + WLOGFD("[Client] Window [name:%{public}s, id:%{public}u] Hide, reason:%{public}u, withAnimation:%{public}d", + name_.c_str(), property_->GetWindowId(), reason, withAnimation); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + WindowStateChangeReason stateChangeReason = static_cast(reason); + if (stateChangeReason == WindowStateChangeReason::KEYGUARD || + stateChangeReason == WindowStateChangeReason::TOGGLING) { + state_ = stateChangeReason == WindowStateChangeReason::KEYGUARD ? + WindowState::STATE_FROZEN : WindowState::STATE_HIDDEN; + NotifyAfterBackground(); + return WMError::WM_OK; + } + if (state_ == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) { + WLOGFD("window is already hidden id: %{public}u", property_->GetWindowId()); + return WMError::WM_OK; + } + WMError ret = WMError::WM_OK; + if (WindowHelper::IsSystemWindow(property_->GetWindowType())) { + AdjustWindowAnimationFlag(withAnimation); + // when show(true) with default, hide() with None, to adjust animationFlag to disabled default animation + ret = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG); + if (ret != WMError::WM_OK) { + WLOGFE("UpdateProperty failed with errCode:%{public}d", static_cast(ret)); + return ret; + } + } + ret = SingletonContainer::Get().RemoveWindow(property_->GetWindowId()); + RecordLifeCycleExceptionEvent(LifeCycleEvent::HIDE_EVENT, ret); + if (ret != WMError::WM_OK) { + WLOGFE("hide errCode:%{public}d for winId:%{public}u", static_cast(ret), property_->GetWindowId()); + return ret; + } + state_ = WindowState::STATE_HIDDEN; + NotifyAfterBackground(); + uint32_t animationFlag = property_->GetAnimationFlag(); + if (animationFlag == static_cast(WindowAnimation::CUSTOM)) { + animationTransitionController_->AnimationForHidden(); + } + ResetMoveOrDragState(); + return ret; +} + +WMError WindowImpl::MoveTo(int32_t x, int32_t y) +{ + WLOGFD("[Client] Window [name:%{public}s, id:%{public}d] MoveTo %{public}d %{public}d", + name_.c_str(), property_->GetWindowId(), x, y); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + + Rect rect = (WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) ? + GetRect() : property_->GetRequestRect(); + Rect moveRect = { x, y, rect.width_, rect.height_ }; // must keep w/h, which may maintain stashed resize info + property_->SetRequestRect(moveRect); + if (state_ == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) { + WLOGFD("window is hidden or created! id: %{public}u, oriPos: [%{public}d, %{public}d, " + "movePos: [%{public}d, %{public}d]", property_->GetWindowId(), rect.posX_, rect.posY_, x, y); + return WMError::WM_OK; + } + + if (GetMode() != WindowMode::WINDOW_MODE_FLOATING) { + WLOGFE("fullscreen window could not resize, winId: %{public}u", GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + property_->SetWindowSizeChangeReason(WindowSizeChangeReason::MOVE); + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_RECT); +} + +WMError WindowImpl::Resize(uint32_t width, uint32_t height) +{ + WLOGFD("[Client] Window [name:%{public}s, id:%{public}d] Resize %{public}u %{public}u", + name_.c_str(), property_->GetWindowId(), width, height); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + + Rect rect = (WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) ? + GetRect() : property_->GetRequestRect(); + Rect resizeRect = { rect.posX_, rect.posY_, width, height }; + property_->SetRequestRect(resizeRect); + property_->SetDecoStatus(false); + if (state_ == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) { + WLOGFD("window is hidden or created! id: %{public}u, oriRect: [%{public}u, %{public}u], " + "resizeRect: [%{public}u, %{public}u]", property_->GetWindowId(), rect.width_, + rect.height_, width, height); + return WMError::WM_OK; + } + + if (GetMode() != WindowMode::WINDOW_MODE_FLOATING) { + WLOGFE("fullscreen window could not resize, winId: %{public}u", GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + property_->SetWindowSizeChangeReason(WindowSizeChangeReason::RESIZE); + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_RECT); +} + +WMError WindowImpl::SetKeepScreenOn(bool keepScreenOn) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + property_->SetKeepScreenOn(keepScreenOn); + if (state_ == WindowState::STATE_SHOWN) { + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON); + } + return WMError::WM_OK; +} + +bool WindowImpl::IsKeepScreenOn() const +{ + return property_->IsKeepScreenOn(); +} + +WMError WindowImpl::SetTurnScreenOn(bool turnScreenOn) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + property_->SetTurnScreenOn(turnScreenOn); + if (state_ == WindowState::STATE_SHOWN) { + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON); + } + return WMError::WM_OK; +} + +bool WindowImpl::IsTurnScreenOn() const +{ + return property_->IsTurnScreenOn(); +} + +WMError WindowImpl::SetBackgroundColor(uint32_t color) +{ + if (uiContent_ != nullptr) { + uiContent_->SetBackgroundColor(color); + return WMError::WM_OK; + } + WLOGFD("uiContent is nullptr, windowId: %{public}u, use FA mode", GetWindowId()); + if (aceAbilityHandler_ != nullptr) { + aceAbilityHandler_->SetBackgroundColor(color); + return WMError::WM_OK; + } + WLOGFE("FA mode could not set background color: %{public}u", GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; +} + +uint32_t WindowImpl::GetBackgroundColor() const +{ + if (uiContent_ != nullptr) { + return uiContent_->GetBackgroundColor(); + } + WLOGFD("uiContent is nullptr, windowId: %{public}u, use FA mode", GetWindowId()); + if (aceAbilityHandler_ != nullptr) { + return aceAbilityHandler_->GetBackgroundColor(); + } + WLOGFE("FA mode does not get background color: %{public}u", GetWindowId()); + return 0xffffffff; // means no background color been set, default color is white +} + +WMError WindowImpl::SetBackgroundColor(const std::string& color) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + uint32_t colorValue; + if (ColorParser::Parse(color, colorValue)) { + WLOGFD("SetBackgroundColor: window: %{public}s, value: [%{public}s, %{public}u]", + name_.c_str(), color.c_str(), colorValue); + return SetBackgroundColor(colorValue); + } + WLOGFE("invalid color string: %{public}s", color.c_str()); + return WMError::WM_ERROR_INVALID_PARAM; +} + +WMError WindowImpl::SetTransparent(bool isTransparent) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + ColorParam backgroundColor; + backgroundColor.value = GetBackgroundColor(); + if (isTransparent) { + backgroundColor.argb.alpha = 0x00; // 0x00: completely transparent + return SetBackgroundColor(backgroundColor.value); + } else { + backgroundColor.value = GetBackgroundColor(); + if (backgroundColor.argb.alpha == 0x00) { + backgroundColor.argb.alpha = 0xff; // 0xff: completely opaque + return SetBackgroundColor(backgroundColor.value); + } + } + return WMError::WM_OK; +} + +bool WindowImpl::IsTransparent() const +{ + ColorParam backgroundColor; + backgroundColor.value = GetBackgroundColor(); + WLOGFD("color: %{public}u, alpha: %{public}u", backgroundColor.value, backgroundColor.argb.alpha); + return backgroundColor.argb.alpha == 0x00; // 0x00: completely transparent +} + +WMError WindowImpl::SetBrightness(float brightness) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (brightness < MINIMUM_BRIGHTNESS || brightness > MAXIMUM_BRIGHTNESS) { + WLOGFE("invalid brightness value: %{public}f", brightness); + return WMError::WM_ERROR_INVALID_PARAM; + } + if (!WindowHelper::IsAppWindow(GetType())) { + WLOGFE("non app window does not support set brightness, type: %{public}u", GetType()); + return WMError::WM_ERROR_INVALID_TYPE; + } + property_->SetBrightness(brightness); + if (state_ == WindowState::STATE_SHOWN) { + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS); + } + return WMError::WM_OK; +} + +float WindowImpl::GetBrightness() const +{ + return property_->GetBrightness(); +} + +WMError WindowImpl::SetCallingWindow(uint32_t windowId) +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + property_->SetCallingWindow(windowId); + return UpdateProperty(PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW); +} + +void WindowImpl::RecordLifeCycleExceptionEvent(LifeCycleEvent event, WMError errCode) const +{ + if (!(errCode > WMError::WM_ERROR_NEED_REPORT_BASE && errCode < WMError::WM_ERROR_NEED_REPORT_END)) { + return; + } + std::ostringstream oss; + oss << "life cycle is abnormal: " << "window_name: " << name_ + << ", id:" << GetWindowId() << ", event: " << TransferLifeCycleEventToString(event) + << ", errCode: " << static_cast(errCode) << ";"; + std::string info = oss.str(); + WLOGFD("window life cycle exception: %{public}s", info.c_str()); + int32_t ret = OHOS::HiviewDFX::HiSysEvent::Write( + OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, + "WINDOW_LIFE_CYCLE_EXCEPTION", + OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, + "PID", getpid(), + "UID", getuid(), + "MSG", info); + if (ret != 0) { + WLOGFE("Write HiSysEvent error, ret:%{public}d", ret); + } +} + +std::string WindowImpl::TransferLifeCycleEventToString(LifeCycleEvent type) const +{ + std::string event; + switch (type) { + case LifeCycleEvent::CREATE_EVENT: + event = "CREATE"; + break; + case LifeCycleEvent::SHOW_EVENT: + event = "SHOW"; + break; + case LifeCycleEvent::HIDE_EVENT: + event = "HIDE"; + break; + case LifeCycleEvent::DESTROY_EVENT: + event = "DESTROY"; + break; + default: + event = "UNDEFINE"; + break; + } + return event; +} + +void WindowImpl::SetPrivacyMode(bool isPrivacyMode) +{ + property_->SetPrivacyMode(isPrivacyMode); + surfaceNode_->SetSecurityLayer(isPrivacyMode || property_->GetSystemPrivacyMode()); + UpdateProperty(PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE); +} + +bool WindowImpl::IsPrivacyMode() const +{ + return property_->GetPrivacyMode(); +} + +void WindowImpl::SetSystemPrivacyMode(bool isSystemPrivacyMode) +{ + property_->SetSystemPrivacyMode(isSystemPrivacyMode); + surfaceNode_->SetSecurityLayer(isSystemPrivacyMode || property_->GetPrivacyMode()); +} + +void WindowImpl::SetSnapshotSkip(bool isSkip) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set snapshot skip permission denied!"); + return; + } + surfaceNode_->SetSecurityLayer(isSkip || property_->GetSystemPrivacyMode()); +} + +void WindowImpl::DisableAppWindowDecor() +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("disable app window decor permission denied!"); + return; + } + if (!WindowHelper::IsMainWindow(property_->GetWindowType())) { + WLOGFE("window decoration is invalid on sub window"); + return; + } + WLOGFD("disable app window decoration."); + isAppDecorEnable_ = false; +} + +bool WindowImpl::IsDecorEnable() const +{ + WLOGFD("get decor enable %{public}d", property_->GetDecorEnable()); + return property_->GetDecorEnable(); +} + +WMError WindowImpl::Maximize() +{ + WLOGFD("[Client] Window %{public}u Maximize", property_->GetWindowId()); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (WindowHelper::IsMainWindow(property_->GetWindowType())) { + return SetFullScreen(true); + } else { + WLOGFD("Maximize Window failed. The window is not main window"); + return WMError::WM_ERROR_INVALID_PARAM; + } +} + +WMError WindowImpl::NotifyWindowTransition(TransitionReason reason) +{ + sptr fromInfo = new(std::nothrow) WindowTransitionInfo(); + sptr toInfo = new(std::nothrow) WindowTransitionInfo(); + if (fromInfo == nullptr || toInfo == nullptr) { + WLOGFE("client new windowTransitionInfo failed"); + return WMError::WM_ERROR_NO_MEM; + } + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + if (abilityContext == nullptr) { + WLOGFE("id:%{public}d is not ability Window", property_->GetWindowId()); + return WMError::WM_ERROR_NO_MEM; + } + auto abilityInfo = abilityContext->GetAbilityInfo(); + if (abilityInfo == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + fromInfo->SetBundleName(context_->GetBundleName()); + fromInfo->SetAbilityName(abilityInfo->name); + fromInfo->SetWindowMode(property_->GetWindowMode()); + fromInfo->SetWindowRect(property_->GetWindowRect()); + fromInfo->SetAbilityToken(context_->GetToken()); + fromInfo->SetWindowType(property_->GetWindowType()); + fromInfo->SetDisplayId(property_->GetDisplayId()); + fromInfo->SetTransitionReason(reason); + return SingletonContainer::Get().NotifyWindowTransition(fromInfo, toInfo); +} + +WMError WindowImpl::Minimize() +{ + WLOGFD("[Client] Window %{public}u Minimize", property_->GetWindowId()); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (WindowHelper::IsMainWindow(property_->GetWindowType())) { + if (context_ != nullptr) { + WMError ret = NotifyWindowTransition(TransitionReason::MINIMIZE); + if (ret != WMError::WM_OK) { + WLOGFD("[Client] Window %{public}u Minimize without remote animation ret:%{public}u", + property_->GetWindowId(), static_cast(ret)); + AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(context_->GetToken(), true); + } + } else { + Hide(); + } + } + return WMError::WM_OK; +} + +WMError WindowImpl::Recover() +{ + WLOGFD("[Client] Window %{public}u Normalize", property_->GetWindowId()); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (WindowHelper::IsMainWindow(property_->GetWindowType())) { + SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + } + return WMError::WM_OK; +} + +WMError WindowImpl::Close() +{ + WLOGFD("[Client] Window %{public}u Close", property_->GetWindowId()); + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (WindowHelper::IsMainWindow(property_->GetWindowType())) { + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + if (abilityContext != nullptr) { + WMError ret = NotifyWindowTransition(TransitionReason::CLOSE); + if (ret != WMError::WM_OK) { + WLOGFD("[Client] Window %{public}u Close without remote animation ret:%{public}u", + property_->GetWindowId(), static_cast(ret)); + abilityContext->CloseAbility(); + } + } else { + Destroy(); + } + } + return WMError::WM_OK; +} + +WMError WindowImpl::RequestFocus() const +{ + if (!IsWindowValid()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + return SingletonContainer::Get().RequestFocus(property_->GetWindowId()); +} + +void WindowImpl::SetInputEventConsumer(const std::shared_ptr& inputEventConsumer) +{ + std::lock_guard lock(mutex_); + inputEventConsumer_ = inputEventConsumer; +} + +bool WindowImpl::RegisterLifeCycleListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return RegisterListener(lifecycleListeners_[GetWindowId()], listener); +} + +bool WindowImpl::UnregisterLifeCycleListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + return UnregisterListener(lifecycleListeners_[GetWindowId()], listener); +} + +bool WindowImpl::RegisterWindowChangeListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return RegisterListener(windowChangeListeners_[GetWindowId()], listener); +} + +bool WindowImpl::UnregisterWindowChangeListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return UnregisterListener(windowChangeListeners_[GetWindowId()], listener); +} + +bool WindowImpl::RegisterAvoidAreaChangeListener(sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + bool ret = RegisterListener(avoidAreaChangeListeners_[GetWindowId()], listener); + if (avoidAreaChangeListeners_[GetWindowId()].size() == 1) { + SingletonContainer::Get().UpdateAvoidAreaListener(property_->GetWindowId(), true); + } + return ret; +} + +bool WindowImpl::UnregisterAvoidAreaChangeListener(sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + bool ret = UnregisterListener(avoidAreaChangeListeners_[GetWindowId()], listener); + if (avoidAreaChangeListeners_[GetWindowId()].empty()) { + SingletonContainer::Get().UpdateAvoidAreaListener(property_->GetWindowId(), false); + } + return ret; +} + +bool WindowImpl::RegisterDragListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(mutex_); + return RegisterListener(windowDragListeners_, listener); +} + +bool WindowImpl::UnregisterDragListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(mutex_); + return UnregisterListener(windowDragListeners_, listener); +} + +bool WindowImpl::RegisterDisplayMoveListener(sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(mutex_); + return RegisterListener(displayMoveListeners_, listener); +} + +bool WindowImpl::UnregisterDisplayMoveListener(sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(mutex_); + return UnregisterListener(displayMoveListeners_, listener); +} + +void WindowImpl::RegisterWindowDestroyedListener(const NotifyNativeWinDestroyFunc& func) +{ + WLOGFD("Start register"); + notifyNativefunc_ = std::move(func); +} + +bool WindowImpl::RegisterOccupiedAreaChangeListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return RegisterListener(occupiedAreaChangeListeners_[GetWindowId()], listener); +} + +bool WindowImpl::UnregisterOccupiedAreaChangeListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + return UnregisterListener(occupiedAreaChangeListeners_[GetWindowId()], listener); +} + +bool WindowImpl::RegisterTouchOutsideListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return RegisterListener(touchOutsideListeners_[GetWindowId()], listener); +} + +bool WindowImpl::UnregisterTouchOutsideListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + return UnregisterListener(touchOutsideListeners_[GetWindowId()], listener); +} + +bool WindowImpl::RegisterAnimationTransitionController(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener is nullptr"); + return false; + } + animationTransitionController_ = listener; + wptr propertyToken(property_); + wptr animationTransitionControllerToken(animationTransitionController_); + if (uiContent_) { + uiContent_->SetNextFrameLayoutCallback([propertyToken, animationTransitionControllerToken]() { + auto property = propertyToken.promote(); + auto animationTransitionController = animationTransitionControllerToken.promote(); + if (!property || !animationTransitionController) { + return; + } + uint32_t animationFlag = property->GetAnimationFlag(); + if (animationFlag == static_cast(WindowAnimation::CUSTOM)) { + // CustomAnimation is enabled when animationTransitionController_ exists + animationTransitionController->AnimationForShown(); + } + }); + } + return true; +} + +bool WindowImpl::RegisterScreenshotListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return RegisterListener(screenshotListeners_[GetWindowId()], listener); +} + +bool WindowImpl::UnregisterScreenshotListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + return UnregisterListener(screenshotListeners_[GetWindowId()], listener); +} + +bool WindowImpl::RegisterDialogTargetTouchListener(const sptr& listener) +{ + WLOGFD("Start register"); + std::lock_guard lock(globalMutex_); + return RegisterListener(dialogTargetTouchListeners_[GetWindowId()], listener); +} + +bool WindowImpl::UnregisterDialogTargetTouchListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + return UnregisterListener(dialogTargetTouchListeners_[GetWindowId()], listener); +} + +void WindowImpl::RegisterDialogDeathRecipientListener(const sptr& listener) +{ + WLOGFD("Start register"); + if (listener == nullptr) { + WLOGFE("listener is nullptr"); + return; + } + std::lock_guard lock(globalMutex_); + dialogDeathRecipientListener_[GetWindowId()] = listener; +} + +void WindowImpl::UnregisterDialogDeathRecipientListener(const sptr& listener) +{ + WLOGFD("Start unregister"); + std::lock_guard lock(globalMutex_); + dialogDeathRecipientListener_[GetWindowId()] = nullptr; +} + +template +bool WindowImpl::RegisterListener(std::vector>& holder, const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener is nullptr"); + return false; + } + if (std::find(holder.begin(), holder.end(), listener) != holder.end()) { + WLOGFE("Listener already registered"); + return true; + } + holder.emplace_back(listener); + return true; +} + +template +bool WindowImpl::UnregisterListener(std::vector>& holder, const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + holder.erase(std::remove_if(holder.begin(), holder.end(), + [listener](sptr registeredListener) { + return registeredListener == listener; + }), holder.end()); + return true; +} + +void WindowImpl::SetAceAbilityHandler(const sptr& handler) +{ + if (handler == nullptr) { + WLOGFD("ace ability handler is nullptr"); + } + std::lock_guard lock(mutex_); + aceAbilityHandler_ = handler; +} + +void WindowImpl::SetRequestModeSupportInfo(uint32_t modeSupportInfo) +{ + property_->SetRequestModeSupportInfo(modeSupportInfo); + SetModeSupportInfo(modeSupportInfo); +} + +void WindowImpl::SetModeSupportInfo(uint32_t modeSupportInfo) +{ + property_->SetModeSupportInfo(modeSupportInfo); +} + +void WindowImpl::UpdateRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) +{ + if (state_ == WindowState::STATE_DESTROYED) { + WLOGFW("invalid window state"); + return; + } + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); + if (display == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return; + } + Rect lastOriRect = property_->GetWindowRect(); + + property_->SetDecoStatus(decoStatus); + if (reason == WindowSizeChangeReason::HIDE) { + property_->SetRequestRect(rect); + return; + } + property_->SetWindowRect(rect); + + // update originRect when floating window show for the first time. + if (!isOriginRectSet_ && WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) { + property_->SetOriginRect(rect); + isOriginRectSet_ = true; + } + WLOGFD("winId:%{public}u, rect[%{public}d, %{public}d, %{public}u, %{public}u], reason:%{public}u", + property_->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_, reason); + Rect rectToAce = rect; + // update rectToAce for stretchable window + if (windowSystemConfig_.isStretchable_ && WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) { + if (IsStretchableReason(reason)) { + rectToAce = property_->GetOriginRect(); + } else { + property_->SetOriginRect(rect); + } + } + ResSchedReport::GetInstance().RequestPerfIfNeed(reason, GetType(), GetMode()); + if ((rectToAce != lastOriRect) || (reason != lastSizeChangeReason_)) { + NotifySizeChange(rectToAce, reason); + lastSizeChangeReason_ = reason; + } + UpdateViewportConfig(rectToAce, display, reason); +} + +void WindowImpl::UpdateMode(WindowMode mode) +{ + WLOGI("UpdateMode %{public}u", mode); + property_->SetWindowMode(mode); + UpdateTitleButtonVisibility(); + NotifyModeChange(mode); + if (uiContent_ != nullptr) { + uiContent_->UpdateWindowMode(mode); + WLOGFD("notify uiContent window mode change end"); + } + // different modes have different corner radius settings + SetWindowCornerRadiusAccordingToSystemConfig(); + // fullscreen and split have no shadow, float has shadow + UpdateWindowShadowAccordingToSystemConfig(); +} + +void WindowImpl::UpdateModeSupportInfo(uint32_t modeSupportInfo) +{ + WLOGI("modeSupportInfo: %{public}u, winId: %{public}u", modeSupportInfo, GetWindowId()); + SetModeSupportInfo(modeSupportInfo); + UpdateTitleButtonVisibility(); +} + +void WindowImpl::HandleBackKeyPressedEvent(const std::shared_ptr& keyEvent) +{ + std::shared_ptr inputEventConsumer; + { + std::lock_guard lock(mutex_); + inputEventConsumer = inputEventConsumer_; + } + bool isConsumed = false; + if (inputEventConsumer != nullptr) { + WLOGFD("Transfer back key event to inputEventConsumer"); + isConsumed = inputEventConsumer->OnInputEvent(keyEvent); + } else if (uiContent_ != nullptr) { + WLOGFD("Transfer back key event to uiContent"); + isConsumed = uiContent_->ProcessBackPressed(); + } else { + WLOGFE("There is no back key event consumer"); + } + if (isConsumed || !WindowHelper::IsMainWindow(property_->GetWindowType())) { + WLOGFD("Back key event is consumed or it is not a main window"); + return; + } + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + if (abilityContext == nullptr) { + WLOGFE("abilityContext is null"); + return; + } + // TerminateAbility will invoke last ability, CloseAbility will not. + bool shouldTerminateAbility = WindowHelper::IsFullScreenWindow(property_->GetWindowMode()); + if (shouldTerminateAbility) { + abilityContext->TerminateSelf(); + } else { + WMError ret = NotifyWindowTransition(TransitionReason::CLOSE); + if (ret != WMError::WM_OK) { + abilityContext->CloseAbility(); + } + } + WLOGFD("Window %{public}u will be closed, shouldTerminateAbility: %{public}u", + property_->GetWindowId(), static_cast(shouldTerminateAbility)); +} + +void WindowImpl::ConsumeKeyEvent(std::shared_ptr& keyEvent) +{ + int32_t keyCode = keyEvent->GetKeyCode(); + int32_t keyAction = keyEvent->GetKeyAction(); + WLOGFD("KeyCode: %{public}d, action: %{public}d", keyCode, keyAction); + if (keyCode == MMI::KeyEvent::KEYCODE_BACK && keyAction == MMI::KeyEvent::KEY_ACTION_UP) { + HandleBackKeyPressedEvent(keyEvent); + } else { + std::shared_ptr inputEventConsumer; + { + std::lock_guard lock(mutex_); + inputEventConsumer = inputEventConsumer_; + } + if (inputEventConsumer != nullptr) { + WLOGFD("Transfer key event to inputEventConsumer"); + (void)inputEventConsumer->OnInputEvent(keyEvent); + } else if (uiContent_ != nullptr) { + WLOGFD("Transfer key event to uiContent"); + (void)uiContent_->ProcessKeyEvent(keyEvent); + } else { + WLOGFE("There is no key event consumer"); + } + } +} + +void WindowImpl::HandleModeChangeHotZones(int32_t posX, int32_t posY) +{ + if (!WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) { + return; + } + + ModeChangeHotZones hotZones; + auto res = SingletonContainer::Get().GetModeChangeHotZones(property_->GetDisplayId(), hotZones); + WLOGFD("[HotZone] Window %{public}u, Pointer[%{public}d, %{public}d]", GetWindowId(), posX, posY); + if (res == WMError::WM_OK) { + WLOGFD("[HotZone] Fullscreen [%{public}d, %{public}d, %{public}u, %{public}u]", hotZones.fullscreen_.posX_, + hotZones.fullscreen_.posY_, hotZones.fullscreen_.width_, hotZones.fullscreen_.height_); + WLOGFD("[HotZone] Primary [%{public}d, %{public}d, %{public}u, %{public}u]", hotZones.primary_.posX_, + hotZones.primary_.posY_, hotZones.primary_.width_, hotZones.primary_.height_); + WLOGFD("[HotZone] Secondary [%{public}d, %{public}d, %{public}u, %{public}u]", hotZones.secondary_.posX_, + hotZones.secondary_.posY_, hotZones.secondary_.width_, hotZones.secondary_.height_); + + if (WindowHelper::IsPointInTargetRectWithBound(posX, posY, hotZones.fullscreen_)) { + SetFullScreen(true); + } else if (WindowHelper::IsPointInTargetRectWithBound(posX, posY, hotZones.primary_)) { + SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + } else if (WindowHelper::IsPointInTargetRectWithBound(posX, posY, hotZones.secondary_)) { + SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + } + } +} + +void WindowImpl::UpdatePointerEventForStretchableWindow(const std::shared_ptr& pointerEvent) +{ + MMI::PointerEvent::PointerItem pointerItem; + if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + WLOGFW("Point item is invalid"); + return; + } + const Rect& originRect = property_->GetOriginRect(); + PointInfo originPos = + WindowHelper::CalculateOriginPosition(originRect, GetRect(), + { pointerItem.GetDisplayX(), pointerItem.GetDisplayY() }); + pointerItem.SetDisplayX(originPos.x); + pointerItem.SetDisplayY(originPos.y); + pointerItem.SetWindowX(originPos.x - originRect.posX_); + pointerItem.SetWindowY(originPos.y - originRect.posY_); + pointerEvent->UpdatePointerItem(pointerEvent->GetPointerId(), pointerItem); +} + +void WindowImpl::UpdateDragType(int32_t startPointPosX, int32_t startPointPosY) +{ + const auto& startRectExceptCorner = moveDragProperty_->startRectExceptCorner_; + if (startPointPosX > startRectExceptCorner.posX_ && + (startPointPosX < startRectExceptCorner.posX_ + + static_cast(startRectExceptCorner.width_))) { + moveDragProperty_->dragType_ = DragType::DRAG_BOTTOM_OR_TOP; + } else if (startPointPosY > startRectExceptCorner.posY_ && + (startPointPosY < startRectExceptCorner.posY_ + + static_cast(startRectExceptCorner.height_))) { + moveDragProperty_->dragType_ = DragType::DRAG_LEFT_OR_RIGHT; + } else if ((startPointPosX <= startRectExceptCorner.posX_ && startPointPosY <= startRectExceptCorner.posY_) || + (startPointPosX >= startRectExceptCorner.posX_ + static_cast(startRectExceptCorner.width_) && + startPointPosY >= startRectExceptCorner.posY_ + static_cast(startRectExceptCorner.height_))) { + moveDragProperty_->dragType_ = DragType::DRAG_LEFT_TOP_CORNER; + } else { + moveDragProperty_->dragType_ = DragType::DRAG_RIGHT_TOP_CORNER; + } +} + +void WindowImpl::CalculateStartRectExceptHotZone(float vpr) +{ + TransformHelper::Vector2 hotZoneScale(1, 1); + if (property_->isNeedComputerTransform()) { + property_->ComputeTransform(); + hotZoneScale = WindowHelper::CalculateHotZoneScale(property_->GetTransformMat()); + } + + const auto& startPointRect = GetRect(); + auto& startRectExceptFrame = moveDragProperty_->startRectExceptFrame_; + startRectExceptFrame.posX_ = startPointRect.posX_ + + static_cast(WINDOW_FRAME_WIDTH * vpr / hotZoneScale.x_); + startRectExceptFrame.posY_ = startPointRect.posY_ + + static_cast(WINDOW_FRAME_WIDTH * vpr / hotZoneScale.y_); + startRectExceptFrame.width_ = startPointRect.width_ - + static_cast((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr / hotZoneScale.x_); + startRectExceptFrame.height_ = startPointRect.height_ - + static_cast((WINDOW_FRAME_WIDTH + WINDOW_FRAME_WIDTH) * vpr / hotZoneScale.y_); + + auto& startRectExceptCorner = moveDragProperty_->startRectExceptCorner_; + startRectExceptCorner.posX_ = startPointRect.posX_ + + static_cast(WINDOW_FRAME_CORNER_WIDTH * vpr / hotZoneScale.x_); + startRectExceptCorner.posY_ = startPointRect.posY_ + + static_cast(WINDOW_FRAME_CORNER_WIDTH * vpr / hotZoneScale.y_); + startRectExceptCorner.width_ = startPointRect.width_ - + static_cast((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr / hotZoneScale.x_); + startRectExceptCorner.height_ = startPointRect.height_ - + static_cast((WINDOW_FRAME_CORNER_WIDTH + WINDOW_FRAME_CORNER_WIDTH) * vpr / hotZoneScale.y_); +} + +bool WindowImpl::IsPointInDragHotZone(int32_t startPointPosX, int32_t startPointPosY) +{ + if (!WindowHelper::IsPointInTargetRect(startPointPosX, + startPointPosY, moveDragProperty_->startRectExceptFrame_) || + (!WindowHelper::IsPointInWindowExceptCorner(startPointPosX, + startPointPosY, moveDragProperty_->startRectExceptCorner_))) { + return true; + } + return false; +} + +void WindowImpl::StartMove() +{ + if (!WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) { + WLOGFE("[StartMove] current window can not be moved, windowId %{public}u", GetWindowId()); + return; + } + if (!moveDragProperty_->pointEventStarted_ || moveDragProperty_->startDragFlag_) { + WLOGFE("[StartMove] pointerEvent has not been started, or is dragging now"); + return; + } + moveDragProperty_->startMoveFlag_ = true; + SingletonContainer::Get().NotifyServerReadyToMoveOrDrag(property_->GetWindowId(), + property_, moveDragProperty_); + WLOGFD("[StartMove] windowId %{public}u", GetWindowId()); +} + +void WindowImpl::ResetMoveOrDragState() +{ + if (!WindowHelper::IsMainWindow(GetType())) { + return; + } + moveDragProperty_->pointEventStarted_ = false; + moveDragProperty_->startDragFlag_ = false; + moveDragProperty_->startMoveFlag_ = false; + UpdateRect(GetRect(), property_->GetDecoStatus(), WindowSizeChangeReason::DRAG_END); +} + +void WindowImpl::ReadyToMoveOrDragWindow(const std::shared_ptr& pointerEvent, + const MMI::PointerEvent::PointerItem& pointerItem) +{ + if (moveDragProperty_->pointEventStarted_) { + return; + } + + moveDragProperty_->startPointRect_ = GetRect(); + moveDragProperty_->startPointPosX_ = pointerItem.GetDisplayX(); + moveDragProperty_->startPointPosY_ = pointerItem.GetDisplayY(); + moveDragProperty_->startPointerId_ = pointerEvent->GetPointerId(); + moveDragProperty_->targetDisplayId_ = pointerEvent->GetTargetDisplayId(); + moveDragProperty_->sourceType_ = pointerEvent->GetSourceType(); + moveDragProperty_->pointEventStarted_ = true; + + // calculate window inner rect except frame + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(moveDragProperty_->targetDisplayId_); + if (display == nullptr || display->GetDisplayInfo() == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return; + } + float vpr = display->GetVirtualPixelRatio(); + int32_t startPointPosX = moveDragProperty_->startPointPosX_ + display->GetDisplayInfo()->GetOffsetX(); + int32_t startPointPosY = moveDragProperty_->startPointPosY_ + display->GetDisplayInfo()->GetOffsetY(); + + CalculateStartRectExceptHotZone(vpr); + + if (GetType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + moveDragProperty_->startMoveFlag_ = true; + SingletonContainer::Get().NotifyServerReadyToMoveOrDrag(property_->GetWindowId(), + property_, moveDragProperty_); + } else if (IsPointInDragHotZone(startPointPosX, startPointPosY)) { + moveDragProperty_->startDragFlag_ = true; + UpdateDragType(startPointPosX, startPointPosY); + SingletonContainer::Get().NotifyServerReadyToMoveOrDrag(property_->GetWindowId(), + property_, moveDragProperty_); + } + return; +} + +void WindowImpl::EndMoveOrDragWindow(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType) +{ + if (pointId != moveDragProperty_->startPointerId_ || sourceType != moveDragProperty_->sourceType_) { + return; + } + + if (moveDragProperty_->startDragFlag_) { + SingletonContainer::Get().ProcessPointUp(GetWindowId()); + moveDragProperty_->startDragFlag_ = false; + } + + if (moveDragProperty_->startMoveFlag_) { + SingletonContainer::Get().ProcessPointUp(GetWindowId()); + moveDragProperty_->startMoveFlag_ = false; + HandleModeChangeHotZones(posX, posY); + } + moveDragProperty_->pointEventStarted_ = false; + ResSchedReport::GetInstance().StopPerfIfNeed(); +} + +void WindowImpl::ConsumeMoveOrDragEvent(const std::shared_ptr& pointerEvent) +{ + MMI::PointerEvent::PointerItem pointerItem; + int32_t pointId = pointerEvent->GetPointerId(); + int32_t sourceType = pointerEvent->GetSourceType(); + if (!pointerEvent->GetPointerItem(pointId, pointerItem) || + (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE && + pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT)) { + WLOGFW("invalid pointerEvent"); + return; + } + int32_t pointDisplayX = pointerItem.GetDisplayX(); + int32_t pointDisplayY = pointerItem.GetDisplayY(); + int32_t action = pointerEvent->GetPointerAction(); + int32_t targetDisplayId = pointerEvent->GetTargetDisplayId(); + switch (action) { + // Ready to move or drag + case MMI::PointerEvent::POINTER_ACTION_DOWN: + case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN: { + const auto& rect = GetRect(); + ReadyToMoveOrDragWindow(pointerEvent, pointerItem); + if (IsPointerEventConsumed()) { + ResSchedReport::GetInstance().TrigClick(); + } + WLOGFD("[Client Point Down]: windowId: %{public}u, pointId: %{public}d, sourceType: %{public}d, " + "hasPointStarted: %{public}d, startMove: %{public}d, startDrag: %{public}d, targetDisplayId: " + "%{public}d, pointPos: [%{public}d, %{public}d], winRect: [%{public}d, %{public}d, %{public}u, " + "%{public}u]", GetWindowId(), pointId, sourceType, moveDragProperty_->pointEventStarted_, + moveDragProperty_->startMoveFlag_, moveDragProperty_->startDragFlag_, targetDisplayId, + pointDisplayX, pointDisplayY, rect.posX_, rect.posY_, rect.width_, rect.height_); + break; + } + // End move or drag + case MMI::PointerEvent::POINTER_ACTION_UP: + case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP: + case MMI::PointerEvent::POINTER_ACTION_CANCEL: { + EndMoveOrDragWindow(pointDisplayX, pointDisplayY, pointId, sourceType); + WLOGFD("[Client Point Up/Cancel]: windowId: %{public}u, action: %{public}d, sourceType: %{public}d, " + "startMove: %{public}d, startDrag: %{public}d", GetWindowId(), action, sourceType, + moveDragProperty_->startMoveFlag_, moveDragProperty_->startDragFlag_); + break; + } + default: + break; + } +} + +bool WindowImpl::IsPointerEventConsumed() +{ + return moveDragProperty_->startDragFlag_ || moveDragProperty_->startMoveFlag_; +} + +void WindowImpl::TransferPointerEvent(const std::shared_ptr& pointerEvent) +{ + if (windowSystemConfig_.isStretchable_ && GetMode() == WindowMode::WINDOW_MODE_FLOATING) { + UpdatePointerEventForStretchableWindow(pointerEvent); + } + std::shared_ptr inputEventConsumer; + { + std::lock_guard lock(mutex_); + inputEventConsumer = inputEventConsumer_; + } + if (inputEventConsumer != nullptr) { + WLOGFD("Transfer pointer event to inputEventConsumer"); + (void)inputEventConsumer->OnInputEvent(pointerEvent); + } else if (uiContent_ != nullptr) { + WLOGFD("Transfer pointer event to uiContent"); + (void)uiContent_->ProcessPointerEvent(pointerEvent); + } else { + WLOGE("pointerEvent is not consumed, windowId: %{public}u", GetWindowId()); + pointerEvent->MarkProcessed(); + } +} + +uint32_t WindowImpl::CalculatePointerDirection(int32_t pointerX, int32_t pointerY) +{ + UpdateDragType(pointerX, pointerY); + return STYLEID_MAP.at(moveDragProperty_->dragType_); +} + +void WindowImpl::HandlePointerStyle(const std::shared_ptr& pointerEvent) +{ + MMI::PointerEvent::PointerItem pointerItem; + if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + WLOGFE("Get pointeritem failed"); + pointerEvent->MarkProcessed(); + return; + } + auto action = pointerEvent->GetPointerAction(); + if (WindowHelper::IsMainFloatingWindow(GetType(), GetMode())) { + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(moveDragProperty_->targetDisplayId_); + if (display == nullptr || display->GetDisplayInfo() == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", + property_->GetDisplayId(), property_->GetWindowId()); + return; + } + float vpr = display->GetVirtualPixelRatio(); + CalculateStartRectExceptHotZone(vpr); + if (IsPointInDragHotZone(pointerItem.GetDisplayX(), pointerItem.GetDisplayY())) { + uint32_t tempStyleID = mouseStyleID_; + // calculate pointer style + mouseStyleID_ = CalculatePointerDirection(pointerItem.GetDisplayX(), pointerItem.GetDisplayY()); + if (tempStyleID != mouseStyleID_) { + MMI::InputManager::GetInstance()->SetPointerStyle( + static_cast(pointerEvent->GetAgentWindowId()), mouseStyleID_); + } + isPointerStyleChanged_ = true; + } else if (action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP) { + MMI::InputManager::GetInstance()->SetPointerStyle( + static_cast(pointerEvent->GetAgentWindowId()), MMI::MOUSE_ICON::DEFAULT); + } + } else if (GetType() == WindowType::WINDOW_TYPE_DOCK_SLICE && isPointerStyleChanged_ == false) { + uint32_t mouseStyle = (GetRect().width_ > GetRect().height_) ? + MMI::MOUSE_ICON::NORTH_SOUTH : MMI::MOUSE_ICON::WEST_EAST; + MMI::InputManager::GetInstance()->SetPointerStyle( + static_cast(pointerEvent->GetAgentWindowId()), mouseStyle); + isPointerStyleChanged_ = true; + } + if (isPointerStyleChanged_ && (action == MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW || + !IsPointInDragHotZone(pointerItem.GetDisplayX(), pointerItem.GetDisplayY()))) { + MMI::InputManager::GetInstance()->SetPointerStyle(static_cast(pointerEvent->GetAgentWindowId()), + MMI::MOUSE_ICON::DEFAULT); + isPointerStyleChanged_ = false; + mouseStyleID_ = 0; + } +} + +void WindowImpl::ConsumePointerEvent(const std::shared_ptr& pointerEvent) +{ + // If windowRect transformed, transform event back to its origin position + if (property_) { + property_->UpdatePointerEvent(pointerEvent); + } + int32_t action = pointerEvent->GetPointerAction(); + if (action == MMI::PointerEvent::POINTER_ACTION_MOVE || action == MMI::PointerEvent::POINTER_ACTION_DOWN || + action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) { + ResSchedReport::GetInstance().TrigSlide(GetType(), true); + } + if (action == MMI::PointerEvent::POINTER_ACTION_UP || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP || + action == MMI::PointerEvent::POINTER_ACTION_CANCEL) { + ResSchedReport::GetInstance().TrigSlide(GetType(), false); + } + if ((action == MMI::PointerEvent::POINTER_ACTION_MOVE || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP) && + pointerEvent->GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_MOUSE) { + HandlePointerStyle(pointerEvent); + } + if (action == MMI::PointerEvent::POINTER_ACTION_DOWN || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) { + WLOGFD("WMS process point down, window: [name:%{public}s, id:%{public}u], action: %{public}d", + name_.c_str(), GetWindowId(), action); + if (GetType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT) { + MMI::PointerEvent::PointerItem pointerItem; + if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { + WLOGFW("Point item is invalid"); + pointerEvent->MarkProcessed(); + return; + } + if (!WindowHelper::IsPointInTargetRect(pointerItem.GetDisplayX(), pointerItem.GetDisplayY(), GetRect())) { + NotifyAfterUnfocused(false); + pointerEvent->MarkProcessed(); + return; + } + } + if (property_ != nullptr) { + SingletonContainer::Get().ProcessPointDown(property_->GetWindowId()); + } + } + + // If point event type is up, should reset start move flag + if (WindowHelper::IsMainFloatingWindow(GetType(), GetMode()) || GetType() == WindowType::WINDOW_TYPE_DOCK_SLICE || + (action == MMI::PointerEvent::POINTER_ACTION_UP || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP || + action == MMI::PointerEvent::POINTER_ACTION_CANCEL)) { + ConsumeMoveOrDragEvent(pointerEvent); + } + + if (IsPointerEventConsumed()) { + pointerEvent->MarkProcessed(); + return; + } + + TransferPointerEvent(pointerEvent); +} + +void WindowImpl::RequestVsync(const std::shared_ptr& vsyncCallback) +{ + std::lock_guard lock(mutex_); + if (state_ == WindowState::STATE_DESTROYED) { + WLOGFE("[WM] Receive Vsync Request failed, window is destroyed"); + return; + } + if (!SingletonContainer::IsDestroyed()) { + VsyncStation::GetInstance().RequestVsync(vsyncCallback); + } +} + +void WindowImpl::UpdateFocusStatus(bool focused) +{ + WLOGFD("window focus status: %{public}d, id: %{public}u", focused, property_->GetWindowId()); + if (focused) { + NotifyAfterFocused(); + } else { + NotifyAfterUnfocused(); + } + isFocused_ = focused; + UpdateWindowShadowAccordingToSystemConfig(); +} + +bool WindowImpl::IsFocused() const +{ + return isFocused_; +} + +void WindowImpl::UpdateConfiguration(const std::shared_ptr& configuration) +{ + if (uiContent_ != nullptr) { + WLOGFD("notify ace winId:%{public}u", GetWindowId()); + uiContent_->UpdateConfiguration(configuration); + } + if (subWindowMap_.count(GetWindowId()) == 0) { + return; + } + for (auto& subWindow : subWindowMap_.at(GetWindowId())) { + subWindow->UpdateConfiguration(configuration); + } +} + +void WindowImpl::UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) +{ + WLOGFD("Window Update AvoidArea, id: %{public}u", property_->GetWindowId()); + NotifyAvoidAreaChange(avoidArea, type); +} + +void WindowImpl::UpdateViewportConfig(const Rect& rect, const sptr& display, WindowSizeChangeReason reason) +{ + std::lock_guard lock(mutex_); + if (uiContent_ == nullptr) { + return; + } + Ace::ViewportConfig config; + config.SetSize(rect.width_, rect.height_); + config.SetPosition(rect.posX_, rect.posY_); + if (display) { + config.SetDensity(display->GetVirtualPixelRatio()); + } + uiContent_->UpdateViewportConfig(config, reason); + WLOGFD("UpdateViewportConfig Id:%{public}u, windowRect:[%{public}d, %{public}d, %{public}u, %{public}u]", + property_->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); +} + +void WindowImpl::UpdateWindowStateUnfrozen() +{ + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + if (abilityContext != nullptr && windowTag_ == WindowTag::MAIN_WINDOW) { + WLOGFD("DoAbilityForeground KEYGUARD, id: %{public}u", GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->DoAbilityForeground(abilityContext->GetToken(), + static_cast(WindowStateChangeReason::KEYGUARD)); + } else if (state_ != WindowState::STATE_SHOWN) { + state_ = WindowState::STATE_SHOWN; + NotifyAfterForeground(); + } +} + +void WindowImpl::UpdateWindowState(WindowState state) +{ + WLOGFD("[Client] Window %{public}u, %{public}s WindowState to set:%{public}u", GetWindowId(), name_.c_str(), state); + if (!IsWindowValid()) { + return; + } + auto abilityContext = AbilityRuntime::Context::ConvertTo(context_); + switch (state) { + case WindowState::STATE_FROZEN: { + if (abilityContext != nullptr && windowTag_ == WindowTag::MAIN_WINDOW) { + WLOGFD("DoAbilityBackground KEYGUARD, id: %{public}u", GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->DoAbilityBackground(abilityContext->GetToken(), + static_cast(WindowStateChangeReason::KEYGUARD)); + } else { + state_ = WindowState::STATE_FROZEN; + NotifyAfterBackground(); + } + break; + } + case WindowState::STATE_UNFROZEN: { + if (abilityContext != nullptr && windowTag_ == WindowTag::MAIN_WINDOW) { + WLOGFD("DoAbilityForeground KEYGUARD, id: %{public}u", GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->DoAbilityForeground(abilityContext->GetToken(), + static_cast(WindowStateChangeReason::KEYGUARD)); + } else { + state_ = WindowState::STATE_SHOWN; + NotifyAfterForeground(); + } + break; + } + case WindowState::STATE_SHOWN: { + if (abilityContext != nullptr && windowTag_ == WindowTag::MAIN_WINDOW) { + WLOGFD("WindowState::STATE_SHOWN, id: %{public}u", GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->DoAbilityForeground(abilityContext->GetToken(), + static_cast(WindowStateChangeReason::TOGGLING)); + } else { + state_ = WindowState::STATE_SHOWN; + NotifyAfterForeground(); + } + break; + } + case WindowState::STATE_HIDDEN: { + if (abilityContext != nullptr && windowTag_ == WindowTag::MAIN_WINDOW && + state_ == WindowState::STATE_SHOWN) { + WLOGFD("WindowState: STATE_SHOWN, id: %{public}u", GetWindowId()); + AAFwk::AbilityManagerClient::GetInstance()->DoAbilityBackground(abilityContext->GetToken(), + static_cast(WindowStateChangeReason::NORMAL)); + } else { + Hide(static_cast(WindowStateChangeReason::NORMAL), false); + } + break; + } + default: { + WLOGFE("windowState to set is invalid"); + break; + } + } +} + +sptr WindowImpl::GetWindowProperty() +{ + WLOGFD("[Client] Window %{public}u, %{public}s", GetWindowId(), name_.c_str()); + if (!IsWindowValid()) { + return nullptr; + } + return property_; +} + +void WindowImpl::RestoreSplitWindowMode(uint32_t mode) +{ + if (!IsWindowValid()) { + return; + } + auto windowMode = static_cast(mode); + if (windowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || windowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + UpdateMode(windowMode); + } +} + +void WindowImpl::UpdateDragEvent(const PointInfo& point, DragEvent event) +{ + NotifyDragEvent(point, event); +} + +void WindowImpl::NotifyDragEvent(const PointInfo& point, DragEvent event) +{ + auto windowDragListeners = GetListeners(); + Rect rect = GetRect(); + for (auto& listener : windowDragListeners) { + if (listener.GetRefPtr() != nullptr) { + listener.GetRefPtr()->OnDrag(point.x - rect.posX_, point.y - rect.posY_, event); + } + } +} + +void WindowImpl::UpdateDisplayId(DisplayId from, DisplayId to) +{ + WLOGFD("update displayId. win %{public}u", GetWindowId()); + NotifyDisplayMoveChange(from, to); + property_->SetDisplayId(to); +} + +void WindowImpl::UpdateOccupiedAreaChangeInfo(const sptr& info) +{ + WLOGFD("Window Update OccupiedArea, id: %{public}u", property_->GetWindowId()); + NotifyOccupiedAreaChange(info); +} + +void WindowImpl::UpdateActiveStatus(bool isActive) +{ + WLOGFD("window active status: %{public}d, id: %{public}u", isActive, property_->GetWindowId()); + if (isActive) { + NotifyAfterActive(); + } else { + NotifyAfterInactive(); + } +} + +void WindowImpl::NotifyScreenshot() +{ + auto screenshotListeners = GetListeners(); + for (auto& screenshotListener : screenshotListeners) { + if (screenshotListener.GetRefPtr() != nullptr) { + screenshotListener.GetRefPtr()->OnScreenshot(); + } + } +} + +void WindowImpl::NotifyTouchOutside() +{ + auto touchOutsideListeners = GetListeners(); + for (auto& touchOutsideListener : touchOutsideListeners) { + if (touchOutsideListener.GetRefPtr() != nullptr) { + touchOutsideListener.GetRefPtr()->OnTouchOutside(); + } + } +} + +void WindowImpl::NotifyTouchDialogTarget() +{ + SingletonContainer::Get().ProcessPointDown(property_->GetWindowId()); + auto dialogTargetTouchListeners = GetListeners(); + for (auto& dialogTargetTouchListener : dialogTargetTouchListeners) { + if (dialogTargetTouchListener.GetRefPtr() != nullptr) { + dialogTargetTouchListener.GetRefPtr()->OnDialogTargetTouch(); + } + } +} + +void WindowImpl::NotifyDestroy() +{ + auto dialogDeathRecipientListener = GetListener(); + if (dialogDeathRecipientListener.GetRefPtr() != nullptr) { + dialogDeathRecipientListener.GetRefPtr()->OnDialogDeathRecipient(); + } +} + +void WindowImpl::NotifyForeground() +{ + NotifyAfterForeground(); +} + +void WindowImpl::NotifyBackground() +{ + NotifyAfterBackground(); +} + +void WindowImpl::TransformSurfaceNode(const Transform& trans) +{ + if (surfaceNode_ == nullptr) { + return; + } + surfaceNode_->SetPivotX(trans.pivotX_); + surfaceNode_->SetPivotY(trans.pivotY_); + surfaceNode_->SetScaleX(trans.scaleX_); + surfaceNode_->SetScaleY(trans.scaleY_); + surfaceNode_->SetTranslateX(trans.translateX_); + surfaceNode_->SetTranslateY(trans.translateY_); + surfaceNode_->SetTranslateZ(trans.translateZ_); + surfaceNode_->SetRotationX(trans.rotationX_); + surfaceNode_->SetRotationY(trans.rotationY_); + surfaceNode_->SetRotation(trans.rotationZ_); +} + +void WindowImpl::UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) +{ + WLOGFD("%{public}s zoomTrans, pivotX:%{public}f, pivotY:%{public}f, scaleX:%{public}f, scaleY:%{public}f" + ", transX:%{public}f, transY:%{public}f, transZ:%{public}f, rotateX:%{public}f, rotateY:%{public}f " + "rotateZ:%{public}f", property_->GetWindowName().c_str(), trans.pivotX_, trans.pivotY_, trans.scaleX_, + trans.scaleY_, trans.translateX_, trans.translateY_, trans.translateZ_, trans.rotationX_, + trans.rotationY_, trans.rotationZ_); + property_->SetZoomTransform(trans); + property_->SetDisplayZoomState(isDisplayZoomOn); +} + +void WindowImpl::ClearListenersById(uint32_t winId) +{ + std::lock_guard lock(globalMutex_); + ClearUselessListeners(screenshotListeners_, winId); + ClearUselessListeners(touchOutsideListeners_, winId); + ClearUselessListeners(dialogTargetTouchListeners_, winId); + ClearUselessListeners(lifecycleListeners_, winId); + ClearUselessListeners(windowChangeListeners_, winId); + ClearUselessListeners(avoidAreaChangeListeners_, winId); + ClearUselessListeners(occupiedAreaChangeListeners_, winId); + ClearUselessListeners(dialogDeathRecipientListener_, winId); +} + +void WindowImpl::NotifySizeChange(Rect rect, WindowSizeChangeReason reason) +{ + auto windowChangeListeners = GetListeners(); + for (auto& listener : windowChangeListeners) { + if (listener.GetRefPtr() != nullptr) { + listener.GetRefPtr()->OnSizeChange(rect, reason); + } + } +} + +void WindowImpl::NotifyAvoidAreaChange(const sptr& avoidArea, AvoidAreaType type) +{ + auto avoidAreaChangeListeners = GetListeners(); + for (auto& listener : avoidAreaChangeListeners) { + if (listener.GetRefPtr() != nullptr) { + listener.GetRefPtr()->OnAvoidAreaChanged(*avoidArea, type); + } + } +} + +void WindowImpl::NotifyDisplayMoveChange(DisplayId from, DisplayId to) +{ + auto displayMoveListeners = GetListeners(); + for (auto& listener : displayMoveListeners) { + if (listener.GetRefPtr() != nullptr) { + listener.GetRefPtr()->OnDisplayMove(from, to); + } + } +} + +void WindowImpl::NotifyModeChange(WindowMode mode) +{ + auto windowChangeListeners = GetListeners(); + for (auto& listener : windowChangeListeners) { + if (listener.GetRefPtr() != nullptr) { + listener.GetRefPtr()->OnModeChange(mode); + } + } +} + +void WindowImpl::NotifyOccupiedAreaChange(const sptr& info) +{ + auto occupiedAreaChangeListeners = GetListeners(); + for (auto& listener : occupiedAreaChangeListeners) { + if (listener.GetRefPtr() != nullptr) { + listener.GetRefPtr()->OnSizeChange(info); + } + } +} + +void WindowImpl::SetNeedRemoveWindowInputChannel(bool needRemoveWindowInputChannel) +{ + needRemoveWindowInputChannel_ = needRemoveWindowInputChannel; +} + +Rect WindowImpl::GetSystemAlarmWindowDefaultSize(Rect defaultRect) +{ + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); + if (display == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return defaultRect; + } + uint32_t width = static_cast(display->GetWidth()); + uint32_t height = static_cast(display->GetHeight()); + WLOGFD("width:%{public}u, height:%{public}u, displayId:%{public}" PRIu64"", + width, height, property_->GetDisplayId()); + Rect rect; + uint32_t alarmWidth = static_cast((static_cast(width) * + SYSTEM_ALARM_WINDOW_WIDTH_RATIO)); + uint32_t alarmHeight = static_cast((static_cast(height) * + SYSTEM_ALARM_WINDOW_HEIGHT_RATIO)); + + rect = { static_cast((width - alarmWidth) / 2), static_cast((height - alarmHeight) / 2), + alarmWidth, alarmHeight }; // divided by 2 to middle the window + return rect; +} + +void WindowImpl::SetDefaultOption() +{ + switch (property_->GetWindowType()) { + case WindowType::WINDOW_TYPE_STATUS_BAR: + case WindowType::WINDOW_TYPE_NAVIGATION_BAR: + case WindowType::WINDOW_TYPE_VOLUME_OVERLAY: + case WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT: { + property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + property_->SetFocusable(false); + break; + } + case WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW: { + property_->SetRequestRect(GetSystemAlarmWindowDefaultSize(property_->GetRequestRect())); + property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + break; + } + case WindowType::WINDOW_TYPE_KEYGUARD: { + RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + property_->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + break; + } + case WindowType::WINDOW_TYPE_DRAGGING_EFFECT: { + property_->SetWindowFlags(0); + break; + } + case WindowType::WINDOW_TYPE_APP_COMPONENT: { + property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + property_->SetAnimationFlag(static_cast(WindowAnimation::NONE)); + break; + } + case WindowType::WINDOW_TYPE_TOAST: + case WindowType::WINDOW_TYPE_FLOAT: + case WindowType::WINDOW_TYPE_FLOAT_CAMERA: + case WindowType::WINDOW_TYPE_VOICE_INTERACTION: + case WindowType::WINDOW_TYPE_LAUNCHER_DOCK: + case WindowType::WINDOW_TYPE_SEARCHING_BAR: + case WindowType::WINDOW_TYPE_SCREENSHOT: + case WindowType::WINDOW_TYPE_DIALOG: { + property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + break; + } + case WindowType::WINDOW_TYPE_BOOT_ANIMATION: + case WindowType::WINDOW_TYPE_POINTER: { + property_->SetFocusable(false); + break; + } + case WindowType::WINDOW_TYPE_DOCK_SLICE: { + property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + property_->SetFocusable(false); + break; + } + default: + break; + } +} + +bool WindowImpl::IsWindowValid() const +{ + bool res = ((state_ > WindowState::STATE_INITIAL) && (state_ < WindowState::STATE_BOTTOM)); + if (!res) { + WLOGFD("window is already destroyed or not created! id: %{public}u", GetWindowId()); + } + return res; +} + +bool WindowImpl::IsLayoutFullScreen() const +{ + uint32_t flags = GetWindowFlags(); + auto mode = GetMode(); + bool needAvoid = (flags & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + return (mode == WindowMode::WINDOW_MODE_FULLSCREEN && !needAvoid); +} + +bool WindowImpl::IsFullScreen() const +{ + auto statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR); + auto naviProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + return (IsLayoutFullScreen() && !statusProperty.enable_ && !naviProperty.enable_); +} + +void WindowImpl::SetRequestedOrientation(Orientation orientation) +{ + if (property_->GetRequestedOrientation() == orientation) { + return; + } + property_->SetRequestedOrientation(orientation); + if (state_ == WindowState::STATE_SHOWN) { + UpdateProperty(PropertyChangeAction::ACTION_UPDATE_ORIENTATION); + } +} + +Orientation WindowImpl::GetRequestedOrientation() +{ + return property_->GetRequestedOrientation(); +} + +WMError WindowImpl::SetTouchHotAreas(const std::vector& rects) +{ + std::vector lastTouchHotAreas; + property_->GetTouchHotAreas(lastTouchHotAreas); + + property_->SetTouchHotAreas(rects); + WMError result = UpdateProperty(PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA); + if (result != WMError::WM_OK) { + property_->SetTouchHotAreas(lastTouchHotAreas); + } + return result; +} +void WindowImpl::GetRequestedTouchHotAreas(std::vector& rects) const +{ + property_->GetTouchHotAreas(rects); +} + +WMError WindowImpl::SetAPPWindowLabel(const std::string& label) +{ + if (uiContent_ == nullptr) { + WLOGFE("uicontent is empty"); + return WMError::WM_ERROR_NULLPTR; + } + uiContent_->SetAppWindowTitle(label); + return WMError::WM_OK; +} + +WMError WindowImpl::SetAPPWindowIcon(const std::shared_ptr& icon) +{ + if (icon == nullptr) { + WLOGFE("window icon is empty"); + return WMError::WM_ERROR_NULLPTR; + } + if (uiContent_ == nullptr) { + WLOGFE("uicontent is empty"); + return WMError::WM_ERROR_NULLPTR; + } + uiContent_->SetAppWindowIcon(icon); + return WMError::WM_OK; +} +bool WindowImpl::CheckCameraFloatingWindowMultiCreated(WindowType type) +{ + if (type != WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + return false; + } + + for (auto& winPair : windowMap_) { + if (winPair.second.second->GetType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + return true; + } + } + uint32_t accessTokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + property_->SetAccessTokenId(accessTokenId); + WLOGFD("Create camera float window, accessTokenId = %{public}u", accessTokenId); + return false; +} + +WMError WindowImpl::SetCornerRadius(float cornerRadius) +{ + WLOGFD("[Client] Window %{public}s set corner radius %{public}f", name_.c_str(), cornerRadius); + if (MathHelper::LessNotEqual(cornerRadius, 0.0)) { + return WMError::WM_ERROR_INVALID_PARAM; + } + surfaceNode_->SetCornerRadius(cornerRadius); + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +WMError WindowImpl::SetShadowRadius(float radius) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set shadow radius permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + WLOGFD("[Client] Window %{public}s set shadow radius %{public}f", name_.c_str(), radius); + if (MathHelper::LessNotEqual(radius, 0.0)) { + return WMError::WM_ERROR_INVALID_PARAM; + } + surfaceNode_->SetShadowRadius(radius); + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +WMError WindowImpl::SetShadowColor(std::string color) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set shadow color permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + WLOGFD("[Client] Window %{public}s set shadow color %{public}s", name_.c_str(), color.c_str()); + uint32_t colorValue; + if (!ColorParser::Parse(color, colorValue)) { + return WMError::WM_ERROR_INVALID_PARAM; + } + surfaceNode_->SetShadowColor(colorValue); + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +void WindowImpl::SetShadowOffsetX(float offsetX) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set shadow offset x permission denied!"); + return; + } + WLOGFD("[Client] Window %{public}s set shadow offsetX %{public}f", name_.c_str(), offsetX); + surfaceNode_->SetShadowOffsetX(offsetX); + RSTransaction::FlushImplicitTransaction(); +} + +void WindowImpl::SetShadowOffsetY(float offsetY) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set shadow offset y permission denied!"); + return; + } + WLOGFD("[Client] Window %{public}s set shadow offsetY %{public}f", name_.c_str(), offsetY); + surfaceNode_->SetShadowOffsetY(offsetY); + RSTransaction::FlushImplicitTransaction(); +} + +WMError WindowImpl::SetBlur(float radius) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set blur permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + WLOGFD("[Client] Window %{public}s set blur radius %{public}f", name_.c_str(), radius); + if (MathHelper::LessNotEqual(radius, 0.0)) { + return WMError::WM_ERROR_INVALID_PARAM; + } + surfaceNode_->SetFilter(RSFilter::CreateBlurFilter(radius, radius)); + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +WMError WindowImpl::SetBackdropBlur(float radius) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set backdrop blur permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + WLOGFD("[Client] Window %{public}s set backdrop blur radius %{public}f", name_.c_str(), radius); + if (MathHelper::LessNotEqual(radius, 0.0)) { + return WMError::WM_ERROR_INVALID_PARAM; + } + surfaceNode_->SetBackgroundFilter(RSFilter::CreateBlurFilter(radius, radius)); + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +WMError WindowImpl::SetBackdropBlurStyle(WindowBlurStyle blurStyle) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set backdrop blur style permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + WLOGFD("[Client] Window %{public}s set backdrop blur style %{public}u", name_.c_str(), blurStyle); + if (blurStyle < WindowBlurStyle::WINDOW_BLUR_OFF || blurStyle > WindowBlurStyle::WINDOW_BLUR_THICK) { + return WMError::WM_ERROR_INVALID_PARAM; + } + + if (blurStyle == WindowBlurStyle::WINDOW_BLUR_OFF) { + surfaceNode_->SetBackgroundFilter(nullptr); + } else { + auto display = SingletonContainer::IsDestroyed() ? nullptr : + SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); + if (display == nullptr) { + WLOGFE("get display failed displayId:%{public}" PRIu64", window id:%{public}u", property_->GetDisplayId(), + property_->GetWindowId()); + return WMError::WM_ERROR_INVALID_PARAM; + } + surfaceNode_->SetBackgroundFilter(RSFilter::CreateMaterialFilter(static_cast(blurStyle), + display->GetVirtualPixelRatio())); + } + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +WMError WindowImpl::NotifyMemoryLevel(int32_t level) const +{ + WLOGFD("[Client] Window id: %{public}u, notify memory level: %{public}d", property_->GetWindowId(), level); + if (uiContent_ == nullptr) { + WLOGFE("[Client] Window %{public}s notify memory level failed, because uicontent is null.", name_.c_str()); + return WMError::WM_ERROR_NULLPTR; + } + // notify memory level + uiContent_->NotifyMemoryLevel(level); + return WMError::WM_OK; +} + +bool WindowImpl::IsAllowHaveSystemSubWindow() +{ + auto windowType = property_->GetWindowType(); + if (WindowHelper::IsSystemSubWindow(windowType) || + WindowHelper::IsSubWindow(windowType) || + windowType == WindowType::WINDOW_TYPE_DIALOG) { + WLOGFD("the window of type %{public}u is limited to add a system sub window", windowType); + return false; + } + return true; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/window_input_channel.cpp b/window_manager/wm/src/window_input_channel.cpp new file mode 100644 index 0000000..b333f44 --- /dev/null +++ b/window_manager/wm/src/window_input_channel.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021-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 "window_input_channel.h" +#ifdef IMF_ENABLE +#include +#endif // IMF_ENABLE +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowInputChannel"}; +} +WindowInputChannel::WindowInputChannel(const sptr& window): window_(window), isAvailable_(true) +{ +} + +WindowInputChannel::~WindowInputChannel() +{ + WLOGFI("windowName: %{public}s, windowId: %{public}d", window_->GetWindowName().c_str(), window_->GetWindowId()); + window_->SetNeedRemoveWindowInputChannel(false); +} + +void WindowInputChannel::HandleKeyEvent(std::shared_ptr& keyEvent) +{ + if (keyEvent == nullptr) { + WLOGFE("keyEvent is nullptr"); + return; + } + WLOGFD("Receive key event, windowId: %{public}u, keyCode: %{public}d", + window_->GetWindowId(), keyEvent->GetKeyCode()); + if (window_->GetType() == WindowType::WINDOW_TYPE_DIALOG) { + if (keyEvent->GetAgentWindowId() != keyEvent->GetTargetWindowId()) { + window_->NotifyTouchDialogTarget(); + keyEvent->MarkProcessed(); + return; + } + if (keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_BACK) { + keyEvent->MarkProcessed(); + return; + } + } + + bool inputMethodHasProcessed = false; +#ifdef IMF_ENABLE + bool isKeyboardEvent = IsKeyboardEvent(keyEvent); + if (isKeyboardEvent) { + WLOGFI("dispatch keyEvent to input method"); + inputMethodHasProcessed = MiscServices::InputMethodController::GetInstance()->dispatchKeyEvent(keyEvent); + } +#endif // IMF_ENABLE + if (!inputMethodHasProcessed) { + WLOGFI("dispatch keyEvent to ACE"); + window_->ConsumeKeyEvent(keyEvent); + } +} + +void WindowInputChannel::HandlePointerEvent(std::shared_ptr& pointerEvent) +{ + if (pointerEvent == nullptr) { + WLOGFE("pointerEvent is nullptr"); + return; + } + WLOGFD("Receive pointer event, windowId: %{public}u, action: %{public}d", + window_->GetWindowId(), pointerEvent->GetPointerAction()); + if ((window_->GetType() == WindowType::WINDOW_TYPE_DIALOG) && + (pointerEvent->GetAgentWindowId() != pointerEvent->GetTargetWindowId())) { + if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN || + pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) { + window_->NotifyTouchDialogTarget(); + } + pointerEvent->MarkProcessed(); + return; + } + window_->ConsumePointerEvent(pointerEvent); +} + +void WindowInputChannel::Destroy() +{ + std::lock_guard lock(mtx_); + WLOGFI("Destroy WindowInputChannel, windowId:%{public}u", window_->GetWindowId()); + isAvailable_ = false; +} + +bool WindowInputChannel::IsKeyboardEvent(const std::shared_ptr& keyEvent) const +{ + int32_t keyCode = keyEvent->GetKeyCode(); + bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN); + bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK); + bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN); + WLOGFI("isKeyFN: %{public}d, isKeyboard: %{public}d", isKeyFN, isKeyboard); + return (isKeyFN || isKeyboard || isKeyBack); +} +} +} \ No newline at end of file diff --git a/window_manager/wm/src/window_manager.cpp b/window_manager/wm/src/window_manager.cpp new file mode 100644 index 0000000..916325f --- /dev/null +++ b/window_manager/wm/src/window_manager.cpp @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2021-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 "window_manager.h" + +#include +#include + +#include "marshalling_helper.h" +#include "window_adapter.h" +#include "window_manager_agent.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#ifdef EFFICIENCY_MANAGER_ENABLE +#include "suspend_manager_client.h" +#endif // EFFICIENCY_MANAGER_ENABLE + +namespace OHOS { +namespace Rosen { +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_) && + parcel.WriteUint32(static_cast(windowType_)); +} + +WindowVisibilityInfo* WindowVisibilityInfo::Unmarshalling(Parcel &parcel) +{ + auto windowVisibilityInfo = new (std::nothrow) WindowVisibilityInfo(); + if (windowVisibilityInfo == nullptr) { + WLOGFE("window visibility info is nullptr."); + return nullptr; + } + bool res = parcel.ReadUint32(windowVisibilityInfo->windowId_) && parcel.ReadInt32(windowVisibilityInfo->pid_) && + parcel.ReadInt32(windowVisibilityInfo->uid_) && parcel.ReadBool(windowVisibilityInfo->isVisible_); + if (!res) { + delete windowVisibilityInfo; + return nullptr; + } + windowVisibilityInfo->windowType_ = static_cast(parcel.ReadUint32()); + return windowVisibilityInfo; +} + +bool AccessibilityWindowInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteInt32(wid_) && parcel.WriteUint32(windowRect_.width_) && + parcel.WriteUint32(windowRect_.height_) && parcel.WriteInt32(windowRect_.posX_) && + parcel.WriteInt32(windowRect_.posY_) && parcel.WriteBool(focused_) && parcel.WriteBool(isDecorEnable_) && + parcel.WriteUint64(displayId_) && parcel.WriteUint32(layer_) && + parcel.WriteUint32(static_cast(mode_)) && parcel.WriteUint32(static_cast(type_)); +} + +AccessibilityWindowInfo* AccessibilityWindowInfo::Unmarshalling(Parcel &parcel) +{ + auto info = new (std::nothrow) AccessibilityWindowInfo(); + if (info == nullptr) { + WLOGFE("accessibility window info is nullptr."); + return nullptr; + } + bool res = parcel.ReadInt32(info->wid_) && parcel.ReadUint32(info->windowRect_.width_) && + parcel.ReadUint32(info->windowRect_.height_) && parcel.ReadInt32(info->windowRect_.posX_) && + parcel.ReadInt32(info->windowRect_.posY_) && parcel.ReadBool(info->focused_) && + parcel.ReadBool(info->isDecorEnable_) && parcel.ReadUint64(info->displayId_) && + parcel.ReadUint32(info->layer_); + if (!res) { + delete info; + return nullptr; + } + info->mode_ = static_cast(parcel.ReadUint32()); + info->type_ = static_cast(parcel.ReadUint32()); + return info; +} + +bool FocusChangeInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteUint32(windowId_) && parcel.WriteUint64(displayId_) && + parcel.WriteInt32(pid_) && parcel.WriteInt32(uid_) && + parcel.WriteUint32(static_cast(windowType_)); +} + +FocusChangeInfo* FocusChangeInfo::Unmarshalling(Parcel &parcel) +{ + auto focusChangeInfo = new FocusChangeInfo(); + bool res = parcel.ReadUint32(focusChangeInfo->windowId_) && parcel.ReadUint64(focusChangeInfo->displayId_) && + parcel.ReadInt32(focusChangeInfo->pid_) && parcel.ReadInt32(focusChangeInfo->uid_); + if (!res) { + delete focusChangeInfo; + return nullptr; + } + focusChangeInfo->windowType_ = static_cast(parcel.ReadUint32()); + return focusChangeInfo; +} + +WM_IMPLEMENT_SINGLE_INSTANCE(WindowManager) + +class WindowManager::Impl { +public: + void NotifyFocused(uint32_t windowId, const sptr& abilityToken, + WindowType windowType, DisplayId displayId); + void NotifyUnfocused(uint32_t windowId, const sptr& abilityToken, + WindowType windowType, DisplayId displayId); + void NotifyFocused(const sptr& focusChangeInfo); + void NotifyUnfocused(const sptr& focusChangeInfo); + void NotifySystemBarChanged(DisplayId displayId, const SystemBarRegionTints& tints); + void NotifyAccessibilityWindowInfo(const std::vector>& infos, WindowUpdateType type); + void NotifyWindowVisibilityInfoChanged(const std::vector>& windowVisibilityInfos); + void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing); + static inline SingletonDelegator delegator_; + + std::recursive_mutex mutex_; + std::vector> focusChangedListeners_; + sptr focusChangedListenerAgent_; + std::vector> systemBarChangedListeners_; + sptr systemBarChangedListenerAgent_; + std::vector> windowUpdateListeners_; + sptr windowUpdateListenerAgent_; + std::vector> windowVisibilityListeners_; + sptr windowVisibilityListenerAgent_; + std::vector> cameraFloatWindowChangedListeners_; + sptr cameraFloatWindowChangedListenerAgent_; +}; + +void WindowManager::Impl::NotifyFocused(const sptr& focusChangeInfo) +{ + WLOGFD("NotifyFocused [%{public}u; %{public}" PRIu64"; %{public}d; %{public}d; %{public}u; %{public}p]", + focusChangeInfo->windowId_, focusChangeInfo->displayId_, focusChangeInfo->pid_, focusChangeInfo->uid_, + static_cast(focusChangeInfo->windowType_), focusChangeInfo->abilityToken_.GetRefPtr()); + std::vector> focusChangeListeners; + { + std::lock_guard lock(mutex_); + focusChangeListeners = focusChangedListeners_; + } + for (auto& listener : focusChangeListeners) { + listener->OnFocused(focusChangeInfo); + } +} + +void WindowManager::Impl::NotifyUnfocused(const sptr& focusChangeInfo) +{ + WLOGFD("NotifyUnfocused [%{public}u; %{public}" PRIu64"; %{public}d; %{public}d; %{public}u; %{public}p]", + focusChangeInfo->windowId_, focusChangeInfo->displayId_, focusChangeInfo->pid_, focusChangeInfo->uid_, + static_cast(focusChangeInfo->windowType_), focusChangeInfo->abilityToken_.GetRefPtr()); + std::vector> focusChangeListeners; + { + std::lock_guard lock(mutex_); + focusChangeListeners = focusChangedListeners_; + } + for (auto& listener : focusChangeListeners) { + listener->OnUnfocused(focusChangeInfo); + } +} + +void WindowManager::Impl::NotifySystemBarChanged(DisplayId displayId, const SystemBarRegionTints& tints) +{ + for (auto tint : tints) { + WLOGFD("type:%{public}d, enable:%{public}d," \ + "backgroundColor:%{public}x, contentColor:%{public}x " \ + "region:[%{public}d, %{public}d, %{public}d, %{public}d]", + tint.type_, tint.prop_.enable_, tint.prop_.backgroundColor_, tint.prop_.contentColor_, + tint.region_.posX_, tint.region_.posY_, tint.region_.width_, tint.region_.height_); + } + std::vector> systemBarChangeListeners; + { + std::lock_guard lock(mutex_); + systemBarChangeListeners = systemBarChangedListeners_; + } + for (auto& listener : systemBarChangeListeners) { + listener->OnSystemBarPropertyChange(displayId, tints); + } +} + +void WindowManager::Impl::NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) +{ + if (infos.empty()) { + WLOGFE("infos is empty"); + return; + } + for (auto& info : infos) { + WLOGFD("NotifyAccessibilityWindowInfo: wid[%{public}u], rect[%{public}d %{public}d %{public}d %{public}d]," \ + "isFocused[%{public}d], isDecorEnable[%{public}d], displayId[%{public}" PRIu64"], layer[%{public}u]," \ + "mode[%{public}u], type[%{public}u, updateType[%{public}d]", + info->wid_, info->windowRect_.width_, info->windowRect_.height_, info->windowRect_.posX_, + info->windowRect_.posY_, info->focused_, info->isDecorEnable_, info->displayId_, info->layer_, + info->mode_, info->type_, type); + } + + std::vector> windowUpdateListeners; + { + std::lock_guard lock(mutex_); + windowUpdateListeners = windowUpdateListeners_; + } + for (auto& listener : windowUpdateListeners) { + listener->OnWindowUpdate(infos, type); + } +} + +void WindowManager::Impl::NotifyWindowVisibilityInfoChanged( + const std::vector>& windowVisibilityInfos) +{ + std::vector> visibilityChangeListeners; + { + std::lock_guard lock(mutex_); + visibilityChangeListeners = windowVisibilityListeners_; + } + for (auto& listener : visibilityChangeListeners) { + listener->OnWindowVisibilityChanged(windowVisibilityInfos); + } +} + +void WindowManager::Impl::UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) +{ + WLOGFD("Camera float window, accessTokenId = %{public}u, isShowing = %{public}u", accessTokenId, isShowing); + std::vector> cameraFloatWindowChangeListeners; + { + std::lock_guard lock(mutex_); + cameraFloatWindowChangeListeners = cameraFloatWindowChangedListeners_; + } + for (auto& listener : cameraFloatWindowChangeListeners) { + listener->OnCameraFloatWindowChange(accessTokenId, isShowing); + } +} + +WindowManager::WindowManager() : pImpl_(std::make_unique()) {} + +bool WindowManager::RegisterFocusChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + + std::lock_guard lock(pImpl_->mutex_); + bool ret = true; + if (pImpl_->focusChangedListenerAgent_ == nullptr) { + pImpl_->focusChangedListenerAgent_ = new WindowManagerAgent(); + ret = SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_FOCUS, pImpl_->focusChangedListenerAgent_); + } + if (!ret) { + WLOGFW("RegisterWindowManagerAgent failed !"); + pImpl_->focusChangedListenerAgent_ = nullptr; + } else { + auto iter = std::find(pImpl_->focusChangedListeners_.begin(), pImpl_->focusChangedListeners_.end(), listener); + if (iter != pImpl_->focusChangedListeners_.end()) { + WLOGFW("Listener is already registered."); + return true; + } + pImpl_->focusChangedListeners_.push_back(listener); + } + return ret; +} + +bool WindowManager::UnregisterFocusChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + + std::lock_guard lock(pImpl_->mutex_); + auto iter = std::find(pImpl_->focusChangedListeners_.begin(), pImpl_->focusChangedListeners_.end(), listener); + if (iter == pImpl_->focusChangedListeners_.end()) { + WLOGFE("could not find this listener"); + return true; + } + pImpl_->focusChangedListeners_.erase(iter); + bool ret = true; + if (pImpl_->focusChangedListeners_.empty() && pImpl_->focusChangedListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_FOCUS, pImpl_->focusChangedListenerAgent_); + pImpl_->focusChangedListenerAgent_ = nullptr; + } + return ret; +} + +bool WindowManager::RegisterSystemBarChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + + std::lock_guard lock(pImpl_->mutex_); + bool ret = true; + if (pImpl_->systemBarChangedListenerAgent_ == nullptr) { + pImpl_->systemBarChangedListenerAgent_ = new WindowManagerAgent(); + ret = SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR, pImpl_->systemBarChangedListenerAgent_); + } + if (!ret) { + WLOGFW("RegisterWindowManagerAgent failed !"); + pImpl_->systemBarChangedListenerAgent_ = nullptr; + } else { + auto iter = std::find(pImpl_->systemBarChangedListeners_.begin(), pImpl_->systemBarChangedListeners_.end(), + listener); + if (iter != pImpl_->systemBarChangedListeners_.end()) { + WLOGFW("Listener is already registered."); + return true; + } + pImpl_->systemBarChangedListeners_.push_back(listener); + } + return ret; +} + +bool WindowManager::UnregisterSystemBarChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + + std::lock_guard lock(pImpl_->mutex_); + auto iter = std::find(pImpl_->systemBarChangedListeners_.begin(), pImpl_->systemBarChangedListeners_.end(), + listener); + if (iter == pImpl_->systemBarChangedListeners_.end()) { + WLOGFE("could not find this listener"); + return true; + } + pImpl_->systemBarChangedListeners_.erase(iter); + bool ret = true; + if (pImpl_->systemBarChangedListeners_.empty() && pImpl_->systemBarChangedListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR, pImpl_->systemBarChangedListenerAgent_); + pImpl_->systemBarChangedListenerAgent_ = nullptr; + } + return ret; +} + +void WindowManager::MinimizeAllAppWindows(DisplayId displayId) +{ + WLOGFD("displayId %{public}" PRIu64"", displayId); + SingletonContainer::Get().MinimizeAllAppWindows(displayId); +} + +WMError WindowManager::ToggleShownStateForAllAppWindows() +{ + WLOGFD("ToggleShownStateForAllAppWindows"); + return SingletonContainer::Get().ToggleShownStateForAllAppWindows(); +} + +WMError WindowManager::SetWindowLayoutMode(WindowLayoutMode mode) +{ + WLOGFD("set window layout mode: %{public}u", mode); + WMError ret = SingletonContainer::Get().SetWindowLayoutMode(mode); + if (ret != WMError::WM_OK) { + WLOGFE("set layout mode failed"); + } + return ret; +} + +bool WindowManager::RegisterWindowUpdateListener(const sptr &listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + std::lock_guard lock(pImpl_->mutex_); + bool ret = true; + if (pImpl_->windowUpdateListenerAgent_ == nullptr) { + pImpl_->windowUpdateListenerAgent_ = new WindowManagerAgent(); + ret = SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_UPDATE, pImpl_->windowUpdateListenerAgent_); + } + if (!ret) { + WLOGFW("RegisterWindowManagerAgent failed !"); + pImpl_->windowUpdateListenerAgent_ = nullptr; + } else { + auto iter = std::find(pImpl_->windowUpdateListeners_.begin(), pImpl_->windowUpdateListeners_.end(), listener); + if (iter != pImpl_->windowUpdateListeners_.end()) { + WLOGFI("Listener is already registered."); + return true; + } + pImpl_->windowUpdateListeners_.emplace_back(listener); + } + return ret; +} + +bool WindowManager::UnregisterWindowUpdateListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + std::lock_guard lock(pImpl_->mutex_); + auto iter = std::find(pImpl_->windowUpdateListeners_.begin(), pImpl_->windowUpdateListeners_.end(), listener); + if (iter == pImpl_->windowUpdateListeners_.end()) { + WLOGFE("could not find this listener"); + return true; + } + pImpl_->windowUpdateListeners_.erase(iter); + bool ret = true; + if (pImpl_->windowUpdateListeners_.empty() && pImpl_->windowUpdateListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_UPDATE, pImpl_->windowUpdateListenerAgent_); + pImpl_->windowUpdateListenerAgent_ = nullptr; + } + return ret; +} + +bool WindowManager::RegisterVisibilityChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + std::lock_guard lock(pImpl_->mutex_); + bool ret = true; + if (pImpl_->windowVisibilityListenerAgent_ == nullptr) { + pImpl_->windowVisibilityListenerAgent_ = new WindowManagerAgent(); + ret = SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, + pImpl_->windowVisibilityListenerAgent_); + } + if (!ret) { + WLOGFW("RegisterWindowManagerAgent failed !"); + pImpl_->windowVisibilityListenerAgent_ = nullptr; + } else { + auto iter = std::find(pImpl_->windowVisibilityListeners_.begin(), pImpl_->windowVisibilityListeners_.end(), + listener); + if (iter != pImpl_->windowVisibilityListeners_.end()) { + WLOGFW("Listener is already registered."); + return true; + } + pImpl_->windowVisibilityListeners_.emplace_back(listener); + } + return ret; +} + +bool WindowManager::UnregisterVisibilityChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + 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()); + + bool ret = true; + if (pImpl_->windowVisibilityListeners_.empty() && pImpl_->windowVisibilityListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, + pImpl_->windowVisibilityListenerAgent_); + pImpl_->windowVisibilityListenerAgent_ = nullptr; + } + return ret; +} + +bool WindowManager::RegisterCameraFloatWindowChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + + std::lock_guard lock(pImpl_->mutex_); + bool ret = true; + if (pImpl_->cameraFloatWindowChangedListenerAgent_ == nullptr) { + pImpl_->cameraFloatWindowChangedListenerAgent_ = new WindowManagerAgent(); + ret = SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT, + pImpl_->cameraFloatWindowChangedListenerAgent_); + } + if (!ret) { + WLOGFW("RegisterWindowManagerAgent failed !"); + pImpl_->cameraFloatWindowChangedListenerAgent_ = nullptr; + } else { + auto iter = std::find(pImpl_->cameraFloatWindowChangedListeners_.begin(), + pImpl_->cameraFloatWindowChangedListeners_.end(), listener); + if (iter != pImpl_->cameraFloatWindowChangedListeners_.end()) { + WLOGFW("Listener is already registered."); + return true; + } + pImpl_->cameraFloatWindowChangedListeners_.push_back(listener); + } + return ret; +} + +bool WindowManager::UnregisterCameraFloatWindowChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return false; + } + + std::lock_guard lock(pImpl_->mutex_); + auto iter = std::find(pImpl_->cameraFloatWindowChangedListeners_.begin(), + pImpl_->cameraFloatWindowChangedListeners_.end(), listener); + if (iter == pImpl_->cameraFloatWindowChangedListeners_.end()) { + WLOGFE("could not find this listener"); + return true; + } + pImpl_->cameraFloatWindowChangedListeners_.erase(iter); + bool ret = true; + if (pImpl_->cameraFloatWindowChangedListeners_.empty() && + pImpl_->cameraFloatWindowChangedListenerAgent_ != nullptr) { + ret = SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT, + pImpl_->cameraFloatWindowChangedListenerAgent_); + pImpl_->cameraFloatWindowChangedListenerAgent_ = nullptr; + } + return ret; +} + +void WindowManager::UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) const +{ + if (focusChangeInfo == nullptr) { + WLOGFE("focusChangeInfo is nullptr."); + return; + } + WLOGFD("window focus change: %{public}d, id: %{public}u", focused, focusChangeInfo->windowId_); + if (focused) { +#ifdef EFFICIENCY_MANAGER_ENABLE + SuspendManager::SuspendManagerClient::GetInstance().ThawOneApplication(focusChangeInfo->uid_, + "", "THAW_BY_FOCUS_CHANGED"); +#endif // EFFICIENCY_MANAGER_ENABLE + pImpl_->NotifyFocused(focusChangeInfo); + } else { + pImpl_->NotifyUnfocused(focusChangeInfo); + } +} + +void WindowManager::UpdateSystemBarRegionTints(DisplayId displayId, + const SystemBarRegionTints& tints) const +{ + pImpl_->NotifySystemBarChanged(displayId, tints); +} + +void WindowManager::NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) const +{ + pImpl_->NotifyAccessibilityWindowInfo(infos, type); +} + +void WindowManager::UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) const +{ + pImpl_->NotifyWindowVisibilityInfoChanged(windowVisibilityInfos); +} + +WMError WindowManager::GetAccessibilityWindowInfo(std::vector>& infos) const +{ + WMError ret = SingletonContainer::Get().GetAccessibilityWindowInfo(infos); + if (ret != WMError::WM_OK) { + WLOGFE("get window info failed"); + } + return ret; +} + +WMError WindowManager::GetVisibilityWindowInfo(std::vector>& infos) const +{ + WMError ret = SingletonContainer::Get().GetVisibilityWindowInfo(infos); + if (ret != WMError::WM_OK) { + WLOGFE("get window visibility info failed"); + } + return ret; +} + +void WindowManager::UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) const +{ + pImpl_->UpdateCameraFloatWindowStatus(accessTokenId, isShowing); +} + +void WindowManager::OnRemoteDied() const +{ + WLOGFI("wms is died"); + std::lock_guard lock(pImpl_->mutex_); + pImpl_->focusChangedListenerAgent_ = nullptr; + pImpl_->systemBarChangedListenerAgent_ = nullptr; + pImpl_->windowUpdateListenerAgent_ = nullptr; + pImpl_->windowVisibilityListenerAgent_ = nullptr; + pImpl_->cameraFloatWindowChangedListenerAgent_ = nullptr; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/window_manager_agent.cpp b/window_manager/wm/src/window_manager_agent.cpp new file mode 100644 index 0000000..2595a11 --- /dev/null +++ b/window_manager/wm/src/window_manager_agent.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021-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 "window_manager_agent.h" +#include "foundation/window/window_manager/interfaces/innerkits/wm/window_manager.h" +#include "singleton_container.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +void WindowManagerAgent::UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) +{ + SingletonContainer::Get().UpdateFocusChangeInfo(focusChangeInfo, focused); +} + +void WindowManagerAgent::UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) +{ + SingletonContainer::Get().UpdateSystemBarRegionTints(displayId, tints); +} + +void WindowManagerAgent::NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) +{ + SingletonContainer::Get().NotifyAccessibilityWindowInfo(infos, type); +} + +void WindowManagerAgent::UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) +{ + SingletonContainer::Get().UpdateWindowVisibilityInfo(visibilityInfos); +} + +void WindowManagerAgent::UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) +{ + SingletonContainer::Get().UpdateCameraFloatWindowStatus(accessTokenId, isShowing); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/window_option.cpp b/window_manager/wm/src/window_option.cpp new file mode 100644 index 0000000..a738d74 --- /dev/null +++ b/window_manager/wm/src/window_option.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2021-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 "window_option.h" +#include "window_helper.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +WindowOption::WindowOption(): windowTag_(WindowTag::SYSTEM_WINDOW) +{ + AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); +} + +void WindowOption::SetWindowRect(const struct Rect& rect) +{ + windowRect_ = rect; +} + +void WindowOption::SetWindowType(WindowType type) +{ + type_ = type; +} + +void WindowOption::SetWindowMode(WindowMode mode) +{ + if (!WindowHelper::IsValidWindowMode(mode)) { + return; + } + mode_ = mode; +} + +void WindowOption::SetFocusable(bool isFocusable) +{ + focusable_ = isFocusable; +} + +void WindowOption::SetTouchable(bool isTouchable) +{ + touchable_ = isTouchable; +} + +void WindowOption::SetDisplayId(DisplayId displayId) +{ + displayId_ = displayId; +} + +void WindowOption::SetParentId(uint32_t parentId) +{ + parentId_ = parentId; +} + +void WindowOption::SetWindowName(const std::string& windowName) +{ + windowName_ = windowName; +} + +void WindowOption::AddWindowFlag(WindowFlag flag) +{ + flags_ |= static_cast(flag); +} + +void WindowOption::RemoveWindowFlag(WindowFlag flag) +{ + flags_ &= ~(static_cast(flag)); +} + +void WindowOption::SetWindowFlags(uint32_t flags) +{ + flags_ = flags; +} + +void WindowOption::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) +{ + if (type == WindowType::WINDOW_TYPE_STATUS_BAR || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR) { + sysBarPropMap_[type] = property; + } +} + +Rect WindowOption::GetWindowRect() const +{ + return windowRect_; +} + +WindowType WindowOption::GetWindowType() const +{ + return type_; +} + +WindowMode WindowOption::GetWindowMode() const +{ + return mode_; +} + +bool WindowOption::GetFocusable() const +{ + return focusable_; +} + +bool WindowOption::GetTouchable() const +{ + return touchable_; +} + +DisplayId WindowOption::GetDisplayId() const +{ + return displayId_; +} + +uint32_t WindowOption::GetParentId() const +{ + return parentId_; +} + +const std::string& WindowOption::GetWindowName() const +{ + return windowName_; +} + +uint32_t WindowOption::GetWindowFlags() const +{ + return flags_; +} + +void WindowOption::SetHitOffset(int32_t x, int32_t y) +{ + hitOffset_.x = x; + hitOffset_.y = y; +} + +void WindowOption::SetWindowTag(WindowTag windowTag) +{ + windowTag_ = windowTag; +} + +WindowTag WindowOption::GetWindowTag() const +{ + return windowTag_; +} + +void WindowOption::SetMainHandlerAvailable(bool isMainHandlerAvailable) +{ + isMainHandlerAvailable_ = isMainHandlerAvailable; +} + +bool WindowOption::GetMainHandlerAvailable() const +{ + return isMainHandlerAvailable_; +} + +const PointInfo& WindowOption::GetHitOffset() const +{ + return hitOffset_; +} + +const std::unordered_map& WindowOption::GetSystemBarProperty() const +{ + return sysBarPropMap_; +} + +void WindowOption::SetKeepScreenOn(bool keepScreenOn) +{ + keepScreenOn_ = keepScreenOn; +} + +bool WindowOption::IsKeepScreenOn() const +{ + return keepScreenOn_; +} + +void WindowOption::SetTurnScreenOn(bool turnScreenOn) +{ + turnScreenOn_ = turnScreenOn; +} + +bool WindowOption::IsTurnScreenOn() const +{ + return turnScreenOn_; +} + +void WindowOption::SetBrightness(float brightness) +{ + brightness_ = brightness; +} + +float WindowOption::GetBrightness() const +{ + return brightness_; +} + +void WindowOption::SetCallingWindow(uint32_t windowId) +{ + callingWindow_ = windowId; +} + +uint32_t WindowOption::GetCallingWindow() const +{ + return callingWindow_; +} + +Orientation WindowOption::GetRequestedOrientation() const +{ + return requestedOrientation_; +} + +void WindowOption::SetRequestedOrientation(Orientation orientation) +{ + requestedOrientation_ = orientation; +} +} // namespace Rosen +} // namespace OHOS + diff --git a/window_manager/wm/src/window_scene.cpp b/window_manager/wm/src/window_scene.cpp new file mode 100644 index 0000000..7948ce0 --- /dev/null +++ b/window_manager/wm/src/window_scene.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021-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 "window_scene.h" +#include +#include + +#include "static_call.h" +#include "window_impl.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowScene"}; +} + +const std::string WindowScene::MAIN_WINDOW_ID = "main window"; + +WindowScene::~WindowScene() +{ + WLOGFI("~WindowScene"); + if (mainWindow_ != nullptr) { + mainWindow_->Destroy(); + mainWindow_ = nullptr; + } +} + +WMError WindowScene::Init(DisplayId displayId, const std::shared_ptr& context, + sptr& listener, sptr option) +{ + displayId_ = displayId; + if (option == nullptr) { + option = new(std::nothrow) WindowOption(); + if (option == nullptr) { + WLOGFW("alloc WindowOption failed"); + return WMError::WM_ERROR_NULLPTR; + } + } + option->SetDisplayId(displayId); + option->SetWindowTag(WindowTag::MAIN_WINDOW); + + mainWindow_ = SingletonContainer::Get().CreateWindow( + GenerateMainWindowName(context), option, context); + if (mainWindow_ == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + mainWindow_->RegisterLifeCycleListener(listener); + + return WMError::WM_OK; +} + +std::string WindowScene::GenerateMainWindowName(const std::shared_ptr& context) const +{ + if (context == nullptr) { + return MAIN_WINDOW_ID + std::to_string(count++); + } else { + std::string windowName = context->GetBundleName() + std::to_string(count++); + std::size_t pos = windowName.find_last_of('.'); + return (pos == std::string::npos) ? windowName : windowName.substr(pos + 1); // skip '.' + } +} + +sptr WindowScene::CreateWindow(const std::string& windowName, sptr& option) const +{ + if (windowName.empty() || mainWindow_ == nullptr || option == nullptr) { + WLOGFE("WindowScene Name: %{public}s", windowName.c_str()); + return nullptr; + } + option->SetParentId(mainWindow_->GetWindowId()); + option->SetWindowTag(WindowTag::SUB_WINDOW); + return SingletonContainer::Get().CreateWindow(windowName, option, mainWindow_->GetContext()); +} + +const sptr& WindowScene::GetMainWindow() const +{ + return mainWindow_; +} + +std::vector> WindowScene::GetSubWindow() +{ + if (mainWindow_ == nullptr) { + WLOGFE("Get sub window failed, because main window is null"); + return std::vector>(); + } + uint32_t parentId = mainWindow_->GetWindowId(); + return SingletonContainer::Get().GetSubWindow(parentId); +} + +WMError WindowScene::GoForeground(uint32_t reason) +{ + WLOGFI("reason:%{public}u", reason); + if (mainWindow_ == nullptr) { + WLOGFE("Go foreground failed, because main window is null"); + return WMError::WM_ERROR_NULLPTR; + } + return mainWindow_->Show(reason); +} + +WMError WindowScene::GoBackground(uint32_t reason) +{ + WLOGFI("reason:%{public}u", reason); + if (mainWindow_ == nullptr) { + WLOGFE("Go background failed, because main window is null"); + return WMError::WM_ERROR_NULLPTR; + } + return mainWindow_->Hide(reason); +} + +WMError WindowScene::GoDestroy() +{ + if (mainWindow_ == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + + WMError ret = mainWindow_->Destroy(); + if (ret != WMError::WM_OK) { + WLOGFE("WindowScene go destroy failed name: %{public}s", mainWindow_->GetWindowName().c_str()); + return ret; + } + mainWindow_ = nullptr; + return WMError::WM_OK; +} + +WMError WindowScene::OnNewWant(const AAFwk::Want& want) +{ + if (mainWindow_ == nullptr) { + WLOGFE("On new want failed, because main window is null"); + return WMError::WM_ERROR_NULLPTR; + } + mainWindow_->OnNewWant(want); + return WMError::WM_OK; +} + +WMError WindowScene::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) const +{ + if (mainWindow_ == nullptr) { + WLOGFE("Set systembar property failed, because main window is null"); + return WMError::WM_ERROR_NULLPTR; + } + return mainWindow_->SetSystemBarProperty(type, property); +} + +WMError WindowScene::RequestFocus() const +{ + if (mainWindow_ == nullptr) { + WLOGFE("Request focus failed, because main window is null"); + return WMError::WM_ERROR_NULLPTR; + } + return mainWindow_->RequestFocus(); +} + +void WindowScene::UpdateConfiguration(const std::shared_ptr& configuration) +{ + if (mainWindow_ == nullptr) { + WLOGFE("Update configuration failed, because main window is null"); + return; + } + WLOGFI("notify mainWindow winId:%{public}u", mainWindow_->GetWindowId()); + mainWindow_->UpdateConfiguration(configuration); +} + +std::string WindowScene::GetContentInfo() const +{ + if (mainWindow_ == nullptr) { + WLOGFE("Get content info failed, because main window is null"); + return ""; + } + return mainWindow_->GetContentInfo(); +} + +WMError WindowScene::NotifyMemoryLevel(int32_t level) const +{ + WLOGFI("Notify memory level: %{public}d", level); + if (mainWindow_ == nullptr) { + WLOGFE("Notify memory level failed, because main window is null"); + return WMError::WM_ERROR_NULLPTR; + } + return mainWindow_->NotifyMemoryLevel(level); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/zidl/window_manager_agent_proxy.cpp b/window_manager/wm/src/zidl/window_manager_agent_proxy.cpp new file mode 100644 index 0000000..3d615dc --- /dev/null +++ b/window_manager/wm/src/zidl/window_manager_agent_proxy.cpp @@ -0,0 +1,175 @@ +/* + * 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 "zidl/window_manager_agent_proxy.h" +#include +#include "marshalling_helper.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerAgentProxy"}; +} + +void WindowManagerAgentProxy::UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (focusChangeInfo == nullptr) { + WLOGFE("Invalid focus change info"); + return; + } + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(focusChangeInfo)) { + WLOGFE("Write displayId failed"); + return; + } + + if (!data.WriteRemoteObject(focusChangeInfo->abilityToken_)) { + WLOGFI("Write abilityToken failed"); + } + + if (!data.WriteBool(focused)) { + WLOGFE("Write Focus failed"); + return; + } + + if (Remote()->SendRequest(static_cast(WindowManagerAgentMsg::TRANS_ID_UPDATE_FOCUS), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerAgentProxy::UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUint64(displayId)) { + WLOGFE("Write displayId failed"); + return; + } + bool res = MarshallingHelper::MarshallingVectorObj(data, tints, + [](Parcel& parcel, const SystemBarRegionTint& tint) { + return parcel.WriteUint32(static_cast(tint.type_)) && parcel.WriteBool(tint.prop_.enable_) && + parcel.WriteUint32(tint.prop_.backgroundColor_) && parcel.WriteUint32(tint.prop_.contentColor_) && + parcel.WriteInt32(tint.region_.posX_) && parcel.WriteInt32(tint.region_.posY_) && + parcel.WriteInt32(tint.region_.width_) && parcel.WriteInt32(tint.region_.height_); + } + ); + if (!res) { + WLOGFE("Write SystemBarRegionTint failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerAgentMsg::TRANS_ID_UPDATE_SYSTEM_BAR_PROPS), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerAgentProxy::NotifyAccessibilityWindowInfo(const std::vector>& infos, + WindowUpdateType type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!MarshallingHelper::MarshallingVectorParcelableObj(data, infos)) { + WLOGFE("Write accessibility window infos failed"); + return; + } + + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write windowUpdateType failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerAgentMsg::TRANS_ID_UPDATE_WINDOW_STATUS), + data, reply, option) != ERR_NONE) { + 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(static_cast(WindowManagerAgentMsg::TRANS_ID_UPDATE_WINDOW_VISIBILITY), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerAgentProxy::UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUint32(accessTokenId)) { + WLOGFE("Write accessTokenId failed"); + return; + } + + if (!data.WriteBool(isShowing)) { + WLOGFE("Write is showing status failed"); + return; + } + + if (Remote()->SendRequest(static_cast(WindowManagerAgentMsg::TRANS_ID_UPDATE_CAMERA_FLOAT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} +} // namespace Rosen +} // namespace OHOS + diff --git a/window_manager/wm/src/zidl/window_manager_agent_stub.cpp b/window_manager/wm/src/zidl/window_manager_agent_stub.cpp new file mode 100644 index 0000000..f3382e7 --- /dev/null +++ b/window_manager/wm/src/zidl/window_manager_agent_stub.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021-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 "zidl/window_manager_agent_stub.h" +#include "ipc_skeleton.h" +#include "marshalling_helper.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerAgentStub"}; +} + +int WindowManagerAgentStub::OnRemoteRequest(uint32_t code, MessageParcel& data, + MessageParcel& reply, MessageOption& option) +{ + WLOGFI("code is %{public}u", code); + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + WindowManagerAgentMsg msgId = static_cast(code); + switch (msgId) { + case WindowManagerAgentMsg::TRANS_ID_UPDATE_FOCUS: { + sptr info = data.ReadParcelable(); + if (info != nullptr) { + info->abilityToken_ = data.ReadRemoteObject(); + } + bool focused = data.ReadBool(); + UpdateFocusChangeInfo(info, focused); + break; + } + case WindowManagerAgentMsg::TRANS_ID_UPDATE_SYSTEM_BAR_PROPS: { + DisplayId displayId = data.ReadUint64(); + SystemBarRegionTints tints; + bool res = MarshallingHelper::UnmarshallingVectorObj(data, tints, + [](Parcel& parcel, SystemBarRegionTint& tint) { + uint32_t type; + SystemBarProperty prop; + Rect region; + bool res = parcel.ReadUint32(type) && parcel.ReadBool(prop.enable_) && + parcel.ReadUint32(prop.backgroundColor_) && parcel.ReadUint32(prop.contentColor_) && + parcel.ReadInt32(region.posX_) && parcel.ReadInt32(region.posY_) && + parcel.ReadUint32(region.width_) && parcel.ReadUint32(region.height_); + tint.type_ = static_cast(type); + tint.prop_ = prop; + tint.region_ = region; + return res; + } + ); + if (!res) { + WLOGFE("fail to read SystemBarRegionTints."); + break; + } + UpdateSystemBarRegionTints(displayId, tints); + break; + } + case WindowManagerAgentMsg::TRANS_ID_UPDATE_WINDOW_STATUS: { + std::vector> infos; + if (!MarshallingHelper::UnmarshallingVectorParcelableObj(data, infos)) { + WLOGFE("read accessibility window infos failed"); + return -1; + } + WindowUpdateType type = static_cast(data.ReadUint32()); + NotifyAccessibilityWindowInfo(infos, type); + break; + } + case WindowManagerAgentMsg::TRANS_ID_UPDATE_WINDOW_VISIBILITY: { + std::vector> infos; + if (!MarshallingHelper::UnmarshallingVectorParcelableObj(data, infos)) { + WLOGFE("fail to read WindowVisibilityInfo."); + break; + } + UpdateWindowVisibilityInfo(infos); + break; + } + case WindowManagerAgentMsg::TRANS_ID_UPDATE_CAMERA_FLOAT: { + uint32_t accessTokenId = data.ReadUint32(); + bool isShowing = data.ReadBool(); + UpdateCameraFloatWindowStatus(accessTokenId, isShowing); + break; + } + default: + break; + } + return 0; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/src/zidl/window_proxy.cpp b/window_manager/wm/src/zidl/window_proxy.cpp new file mode 100644 index 0000000..b52a404 --- /dev/null +++ b/window_manager/wm/src/zidl/window_proxy.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2021-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 "zidl/window_proxy.h" +#include +#include "pointer_event.h" +#include "message_option.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowProxy"}; +} + +WMError WindowProxy::UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!(data.WriteInt32(rect.posX_) && data.WriteInt32(rect.posY_) && + data.WriteUint32(rect.width_) && data.WriteUint32(rect.height_))) { + WLOGFE("Write WindowRect failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteBool(decoStatus)) { + WLOGFE("Write deco status failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(static_cast(reason))) { + WLOGFE("Write WindowSizeChangeReason failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_WINDOW_RECT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateWindowMode(WindowMode mode) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(static_cast(mode))) { + WLOGFE("Write WindowMode failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_WINDOW_MODE), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(modeSupportInfo)) { + WLOGFE("Write WindowMode failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_MODE_SUPPORT_INFO), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateFocusStatus(bool focused) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteBool(focused)) { + WLOGFE("Write Focus failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_FOCUS_STATUS), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteStrongParcelable(avoidArea)) { + WLOGFE("Write WindowRect failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write AvoidAreaType failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_AVOID_AREA), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateWindowState(WindowState state) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(static_cast(state))) { + WLOGFE("Write isStopped"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_WINDOW_STATE), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateWindowDragInfo(const PointInfo& point, DragEvent event) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!(data.WriteInt32(point.x) and data.WriteInt32(point.y))) { + WLOGFE("Write pos failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteInt32(static_cast(event))) { + WLOGFE("Write event failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_DRAG_EVENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest TRANS_ID_UPDATE_DRAG_EVENT failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateDisplayId(DisplayId from, DisplayId to) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!(data.WriteUint64(from) and data.WriteUint64(to))) { + WLOGFE("Write displayid failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_DISPLAY_ID), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest TRANS_ID_UPDATE_DISPLAY_ID failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateOccupiedAreaChangeInfo(const sptr& info) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteParcelable(info)) { + WLOGFE("Write OccupiedAreaChangeInfo failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_OCCUPIED_AREA), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateActiveStatus(bool isActive) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteBool(isActive)) { + WLOGFE("Write Focus failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_ACTIVE_STATUS), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +sptr WindowProxy::GetWindowProperty() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return nullptr; + } + uint32_t requestCode = static_cast(WindowMessage::TRANS_ID_GET_WINDOW_PROPERTY); + if (Remote()->SendRequest(requestCode, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return nullptr; + } + return reply.ReadParcelable(); +} + +WMError WindowProxy::NotifyTouchOutside() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_OUTSIDE_PRESSED), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::NotifyScreenshot() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_SCREEN_SHOT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::DumpInfo(const std::vector& params) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteStringVector(params)) { + WLOGFE("Write params failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_DUMP_INFO), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!trans.Marshalling(data)) { + WLOGFE("Write params failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteBool(isDisplayZoomOn)) { + WLOGFE("Write params failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_UPDATE_ZOOM_TRANSFORM), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::NotifyDestroy(void) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_DESTROY), + data, replay, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::NotifyForeground(void) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_FOREGROUND), + data, replay, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::NotifyBackground(void) +{ + MessageParcel data; + MessageParcel replay; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_BACKGROUND), + data, replay, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) +{ + if (!pointerEvent) { + WLOGFE("pointerEvent is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!pointerEvent->WriteToParcel(data)) { + WLOGFE("Failed to write point event"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowMessage::TRANS_ID_NOTIFY_CLIENT_POINT_UP), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} + +WMError WindowProxy::RestoreSplitWindowMode(uint32_t mode) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(mode)) { + WLOGFE("mode failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + uint32_t requestCode = static_cast(WindowMessage::TRANS_ID_RESTORE_SPLIT_WINDOW_MODE); + if (Remote()->SendRequest(requestCode, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return WMError::WM_OK; +} +} // namespace Rosen +} // namespace OHOS + diff --git a/window_manager/wm/src/zidl/window_stub.cpp b/window_manager/wm/src/zidl/window_stub.cpp new file mode 100644 index 0000000..dae2bd6 --- /dev/null +++ b/window_manager/wm/src/zidl/window_stub.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2021-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 "zidl/window_stub.h" +#include +#include "ipc_skeleton.h" +#include "pointer_event.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowStub"}; +} + +int WindowStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + if (staticDestroyMonitor_.IsDestroyed()) { + WLOGFE("Main thread finished, static data has been destroyed"); + return -1; + } + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + WindowMessage msgId = static_cast(code); + switch (msgId) { + case WindowMessage::TRANS_ID_UPDATE_WINDOW_RECT: { + struct Rect rect { data.ReadInt32(), data.ReadInt32(), data.ReadUint32(), data.ReadUint32() }; + bool decoStatus = data.ReadBool(); + WindowSizeChangeReason reason = static_cast(data.ReadUint32()); + UpdateWindowRect(rect, decoStatus, reason); + break; + } + case WindowMessage::TRANS_ID_UPDATE_WINDOW_MODE: { + WindowMode mode = static_cast(data.ReadUint32()); + UpdateWindowMode(mode); + break; + } + case WindowMessage::TRANS_ID_UPDATE_MODE_SUPPORT_INFO: { + uint32_t modeSupportInfo = data.ReadUint32(); + UpdateWindowModeSupportInfo(modeSupportInfo); + break; + } + case WindowMessage::TRANS_ID_UPDATE_FOCUS_STATUS: { + bool focused = data.ReadBool(); + UpdateFocusStatus(focused); + break; + } + case WindowMessage::TRANS_ID_UPDATE_AVOID_AREA: { + sptr avoidArea = data.ReadStrongParcelable(); + uint32_t type; + if (!data.ReadUint32(type)) { + return -1; + } + UpdateAvoidArea(avoidArea, static_cast(type)); + break; + } + case WindowMessage::TRANS_ID_UPDATE_WINDOW_STATE: { + UpdateWindowState(static_cast(data.ReadUint32())); + break; + } + case WindowMessage::TRANS_ID_UPDATE_DRAG_EVENT: { + PointInfo point; + point.x = data.ReadInt32(); + point.y = data.ReadInt32(); + DragEvent event = static_cast (data.ReadUint32()); + UpdateWindowDragInfo(point, event); + break; + } + case WindowMessage::TRANS_ID_UPDATE_DISPLAY_ID: { + UpdateDisplayId(data.ReadUint64(), data.ReadUint64()); + break; + } + case WindowMessage::TRANS_ID_UPDATE_OCCUPIED_AREA: { + sptr info = data.ReadParcelable(); + UpdateOccupiedAreaChangeInfo(info); + break; + } + case WindowMessage::TRANS_ID_UPDATE_ACTIVE_STATUS: { + bool isActive = data.ReadBool(); + UpdateActiveStatus(isActive); + break; + } + case WindowMessage::TRANS_ID_GET_WINDOW_PROPERTY: { + auto property = GetWindowProperty(); + reply.WriteParcelable(property.GetRefPtr()); + break; + } + case WindowMessage::TRANS_ID_NOTIFY_OUTSIDE_PRESSED: { + NotifyTouchOutside(); + break; + } + case WindowMessage::TRANS_ID_NOTIFY_SCREEN_SHOT: { + NotifyScreenshot(); + break; + } + case WindowMessage::TRANS_ID_NOTIFY_DESTROY: { + NotifyDestroy(); + break; + } + case WindowMessage::TRANS_ID_NOTIFY_FOREGROUND: { + NotifyForeground(); + break; + } + case WindowMessage::TRANS_ID_NOTIFY_BACKGROUND: { + NotifyBackground(); + break; + } + case WindowMessage::TRANS_ID_DUMP_INFO: { + std::vector params; + if (!data.ReadStringVector(¶ms)) { + WLOGFE("Fail to read params"); + return -1; + } + DumpInfo(params); + break; + } + case WindowMessage::TRANS_ID_NOTIFY_CLIENT_POINT_UP: { + auto pointerEvent = MMI::PointerEvent::Create(); + if (!pointerEvent->ReadFromParcel(data)) { + WLOGFE("Read Pointer Event failed"); + return -1; + } + NotifyWindowClientPointUp(pointerEvent); + break; + } + case WindowMessage::TRANS_ID_UPDATE_ZOOM_TRANSFORM: { + Transform trans; + trans.Unmarshalling(data); + bool isDisplayZoomOn = data.ReadBool(); + UpdateZoomTransform(trans, isDisplayZoomOn); + break; + } + case WindowMessage::TRANS_ID_RESTORE_SPLIT_WINDOW_MODE: { + RestoreSplitWindowMode(data.ReadUint32()); + break; + } + default: + break; + } + return 0; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/BUILD.gn b/window_manager/wm/test/BUILD.gn new file mode 100644 index 0000000..0abe745 --- /dev/null +++ b/window_manager/wm/test/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright (c) 2021-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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/wm/test/unittest/BUILD.gn b/window_manager/wm/test/unittest/BUILD.gn new file mode 100644 index 0000000..734c30d --- /dev/null +++ b/window_manager/wm/test/unittest/BUILD.gn @@ -0,0 +1,214 @@ +# Copyright (c) 2021-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. + +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") +module_out_path = "window_manager/wm" + +group("unittest") { + testonly = true + + deps = [ + ":wm_input_transfer_station_test", + ":wm_window_effect_test", + ":wm_window_impl_listener_test", + ":wm_window_impl_test", + ":wm_window_input_channel_test", + ":wm_window_manager_agent_proxy_test", + ":wm_window_manager_stub_proxy_test", + ":wm_window_manager_test", + ":wm_window_option_test", + ":wm_window_proxy_test", + ":wm_window_scene_test", + ":wm_window_stub_test", + ":wm_window_test", + ] +} + +ohos_unittest("wm_window_manager_test") { + module_out_path = module_out_path + + include_dirs = [ "//foundation/window/window_manager/wm/src" ] + sources = [ "window_manager_test.cpp" ] + + deps = [ ":wm_unittest_common" ] + + if (efficiency_manager_enable) { + external_deps = [ "efficiency_manager:suspend_manager_client" ] + defines = [ "EFFICIENCY_MANAGER_ENABLE" ] + } +} + +ohos_unittest("wm_window_impl_test") { + module_out_path = module_out_path + + sources = [ "window_impl_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_effect_test") { + module_out_path = module_out_path + + sources = [ "window_effect_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_input_transfer_station_test") { + module_out_path = module_out_path + + sources = [ "input_transfer_station_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_input_channel_test") { + module_out_path = module_out_path + + sources = [ "window_input_channel_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_option_test") { + module_out_path = module_out_path + + sources = [ "window_option_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_scene_test") { + module_out_path = module_out_path + + sources = [ "window_scene_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_test") { + module_out_path = module_out_path + + sources = [ "window_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_impl_listener_test") { + module_out_path = module_out_path + + sources = [ "window_impl_listener_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_proxy_test") { + module_out_path = module_out_path + + sources = [ "window_proxy_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_stub_test") { + module_out_path = module_out_path + + sources = [ "window_stub_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_manager_stub_proxy_test") { + module_out_path = module_out_path + + sources = [ "window_manager_agent_stub_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +ohos_unittest("wm_window_manager_agent_proxy_test") { + module_out_path = module_out_path + + sources = [ "window_manager_agent_proxy_test.cpp" ] + + deps = [ ":wm_unittest_common" ] +} + +## Build wm_unittest_common.a {{{ +config("wm_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/test/common/mock", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/wm/include/zidl", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/wmserver/include/window_snapshot", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/utils/include", + "//commonlibrary/c_utils/base/include", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", + "//third_party/googletest/googlemock/include", + + # for abilityContext + "${ability_runtime_path}/interfaces/kits/native/ability/ability_runtime", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/context", + "//base/global/resource_management/interfaces/inner_api/include", + "//third_party/node/deps/icu-small/source/common", + "${ability_runtime_inner_api_path}/ability_manager/include", + "//foundation/ability/ability_base/interfaces/kits/native/configuration/include/", + + # abilityContext end + ] +} + +ohos_static_library("wm_unittest_common") { + visibility = [ ":*" ] + testonly = true + + public_configs = [ + ":wm_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", + ] + + public_deps = [ + "//base/powermgr/power_manager/interfaces/innerkits:powermgr_client", + + # need delete it for abilitycontext + "${ability_runtime_inner_api_path}/ability_manager:ability_manager", + "//commonlibrary/c_utils/base:utils", + "//foundation/arkui/ace_engine/interfaces/inner_api/ace:ace_uicontent", + "//foundation/arkui/napi:ace_napi", + "//foundation/graphic/graphic_2d/rosen/modules/animation/window_animation:window_animation", + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/multimodalinput/input/frameworks/proxy:libmmi-client", + "//foundation/systemabilitymgr/safwk/interfaces/innerkits/safwk:system_ability_fwk", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//foundation/window/window_manager/wmserver:libwms", + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "ability_base:configuration", + "ability_base:want", + "ability_runtime:ability_context_native", + "bundle_framework:appexecfwk_base", + "ipc:ipc_core", + ] +} +## Build wm_unittest_common.a }}} diff --git a/window_manager/wm/test/unittest/input_transfer_station_test.cpp b/window_manager/wm/test/unittest/input_transfer_station_test.cpp new file mode 100644 index 0000000..61c7878 --- /dev/null +++ b/window_manager/wm/test/unittest/input_transfer_station_test.cpp @@ -0,0 +1,85 @@ +/* + * 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 "input_manager.h" +#include "input_transfer_station.h" +#include "window_impl.h" +#include "mock_window_adapter.h" +#include "singleton_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using WindowMocker = SingletonMocker; +class InputTransferStationTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + sptr window_; +}; +void InputTransferStationTest::SetUpTestCase() +{ +} + +void InputTransferStationTest::TearDownTestCase() +{ +} + +void InputTransferStationTest::SetUp() +{ + sptr option = new WindowOption(); + option->SetWindowName("inputwindow"); + window_ = new WindowImpl(option); + window_->Create(INVALID_WINDOW_ID); +} + +void InputTransferStationTest::TearDown() +{ + window_->Destroy(); + window_ = nullptr; +} + +namespace { +/** + * @tc.name: AddInputWindow + * @tc.desc: add input window in station. + * @tc.type: FUNC + * @tc.require: issueI5I5L4 + */ +HWTEST_F(InputTransferStationTest, AddInputWindow, Function | SmallTest | Level2) +{ + std::shared_ptr listener = std::make_shared(InputEventListener()); + MMI::InputManager::GetInstance()->SetWindowInputEventConsumer(listener); + InputTransferStation::GetInstance().AddInputWindow(window_); +} + +/** + * @tc.name: RemoveInputWindow + * @tc.desc: remove input window in station. + * @tc.type: FUNC + * @tc.require: issueI5I5L4 + */ +HWTEST_F(InputTransferStationTest, RemoveInputWindow, Function | SmallTest | Level2) +{ + InputTransferStation::GetInstance().RemoveInputWindow(window_->GetWindowId()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_effect_test.cpp b/window_manager/wm/test/unittest/window_effect_test.cpp new file mode 100644 index 0000000..5958900 --- /dev/null +++ b/window_manager/wm/test/unittest/window_effect_test.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2021-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 "mock_window_adapter.h" +#include "singleton_mocker.h" +#include "window_impl.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class WindowEffectTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; +void WindowEffectTest::SetUpTestCase() +{ +} + +void WindowEffectTest::TearDownTestCase() +{ +} + +void WindowEffectTest::SetUp() +{ +} + +void WindowEffectTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowEffect01 + * @tc.desc: set window corner radius + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_OK, window->SetCornerRadius(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetCornerRadius(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetCornerRadius(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetCornerRadius(-1.0)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect02 + * @tc.desc: set window shadow radius + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_OK, window->SetShadowRadius(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetShadowRadius(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetShadowRadius(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowRadius(-1.0)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect03 + * @tc.desc: set window shadow color + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect03, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_OK, window->SetShadowColor("#FF22EE44")); + ASSERT_EQ(WMError::WM_OK, window->SetShadowColor("#22EE44")); + ASSERT_EQ(WMError::WM_OK, window->SetShadowColor("#ff22ee44")); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("ff22ee44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("22ee44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ppEE44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#eepp44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ffeePP44")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ff22ee4422")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetShadowColor("#ff")); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect04 + * @tc.desc: set window shadow offset + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect04, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + window->SetShadowOffsetX(0.0); + window->SetShadowOffsetX(16.0); + window->SetShadowOffsetX(1000.0); + window->SetShadowOffsetX(-1.0); + + window->SetShadowOffsetY(0.0); + window->SetShadowOffsetY(16.0); + window->SetShadowOffsetY(1000.0); + window->SetShadowOffsetY(-1.0); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect05 + * @tc.desc: set window blur radius + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect05, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_OK, window->SetBlur(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBlur(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBlur(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBlur(-1.0)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect06 + * @tc.desc: set window backdrop blur radius + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect06, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlur(0.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlur(16.0)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlur(1000.0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackdropBlur(-1.0)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: WindowEffect07 + * @tc.desc: set window backdrop blur style + * @tc.type: FUNC + * @tc.require: issueI5IUGI + */ +HWTEST_F(WindowEffectTest, WindowEffect07, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_OFF)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_THIN)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_REGULAR)); + ASSERT_EQ(WMError::WM_OK, window->SetBackdropBlurStyle(WindowBlurStyle::WINDOW_BLUR_THICK)); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackdropBlurStyle(static_cast(-1))); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackdropBlurStyle(static_cast(5))); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_impl_listener_test.cpp b/window_manager/wm/test/unittest/window_impl_listener_test.cpp new file mode 100644 index 0000000..f0b03dd --- /dev/null +++ b/window_manager/wm/test/unittest/window_impl_listener_test.cpp @@ -0,0 +1,138 @@ +/* + * 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 "window_impl.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowImplListenerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + sptr window_; +}; + +void WindowImplListenerTest::SetUpTestCase() +{ +} + +void WindowImplListenerTest::TearDownTestCase() +{ +} + +void WindowImplListenerTest::SetUp() +{ + sptr option = new WindowOption(); + option->SetWindowName("WindowTestListener"); + window_ = new WindowImpl(option); +} + +void WindowImplListenerTest::TearDown() +{ + window_ = nullptr; +} + +namespace { +/** + * @tc.name: BasicRegisterUnregister + * @tc.desc: test the basic method of register/unregister + * @tc.type: FUNC + */ +HWTEST_F(WindowImplListenerTest, BasicRegisterUnregister, Function | SmallTest | Level2) +{ + std::vector> holder; + sptr listener = nullptr; + window_->RegisterListener(holder, listener); + ASSERT_EQ(holder.size(), 0); + + listener = new IWindowLifeCycle(); + window_->RegisterListener(holder, listener); + ASSERT_EQ(holder.size(), 1); + window_->RegisterListener(holder, listener); + ASSERT_EQ(holder.size(), 1); + window_->UnregisterListener(holder, listener); + ASSERT_EQ(holder.size(), 0); +} + +/** + * @tc.name: InterfacesRegisterUnregister + * @tc.desc: test all interfaces listener + * @tc.type: FUNC + */ +HWTEST_F(WindowImplListenerTest, InterfacesRegisterUnregister, Function | SmallTest | Level2) +{ + sptr windowLifeCycle = new IWindowLifeCycle(); + window_->RegisterLifeCycleListener(windowLifeCycle); + ASSERT_EQ(window_->lifecycleListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterLifeCycleListener(windowLifeCycle); + ASSERT_EQ(window_->lifecycleListeners_[window_->GetWindowId()].size(), 0); + + sptr windowChangeListener = new IWindowChangeListener(); + window_->RegisterWindowChangeListener(windowChangeListener); + ASSERT_EQ(window_->windowChangeListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterWindowChangeListener(windowChangeListener); + ASSERT_EQ(window_->windowChangeListeners_[window_->GetWindowId()].size(), 0); + + sptr avoidAreaChangedListener = new IAvoidAreaChangedListener(); + window_->RegisterAvoidAreaChangeListener(avoidAreaChangedListener); + ASSERT_EQ(window_->avoidAreaChangeListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterAvoidAreaChangeListener(avoidAreaChangedListener); + ASSERT_EQ(window_->avoidAreaChangeListeners_[window_->GetWindowId()].size(), 0); + + sptr windowDragListener = new IWindowDragListener(); + window_->RegisterDragListener(windowDragListener); + ASSERT_EQ(window_->windowDragListeners_.size(), 1); + window_->UnregisterDragListener(windowDragListener); + ASSERT_EQ(window_->windowDragListeners_.size(), 0); + + sptr displayMoveListener = new IDisplayMoveListener(); + window_->RegisterDisplayMoveListener(displayMoveListener); + ASSERT_EQ(window_->displayMoveListeners_.size(), 1); + window_->UnregisterDisplayMoveListener(displayMoveListener); + ASSERT_EQ(window_->displayMoveListeners_.size(), 0); + + sptr occupiedAreaChangeListener = new IOccupiedAreaChangeListener(); + window_->RegisterOccupiedAreaChangeListener(occupiedAreaChangeListener); + ASSERT_EQ(window_->occupiedAreaChangeListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterOccupiedAreaChangeListener(occupiedAreaChangeListener); + ASSERT_EQ(window_->occupiedAreaChangeListeners_[window_->GetWindowId()].size(), 0); + + sptr touchOutsideListener = new ITouchOutsideListener(); + window_->RegisterTouchOutsideListener(touchOutsideListener); + ASSERT_EQ(window_->touchOutsideListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterTouchOutsideListener(touchOutsideListener); + ASSERT_EQ(window_->touchOutsideListeners_[window_->GetWindowId()].size(), 0); + + sptr screenshotListener = new IScreenshotListener(); + window_->RegisterScreenshotListener(screenshotListener); + ASSERT_EQ(window_->screenshotListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterScreenshotListener(screenshotListener); + ASSERT_EQ(window_->screenshotListeners_[window_->GetWindowId()].size(), 0); + + sptr dialogTargetTouchListener = new IDialogTargetTouchListener(); + window_->RegisterDialogTargetTouchListener(dialogTargetTouchListener); + ASSERT_EQ(window_->dialogTargetTouchListeners_[window_->GetWindowId()].size(), 1); + window_->UnregisterDialogTargetTouchListener(dialogTargetTouchListener); + ASSERT_EQ(window_->dialogTargetTouchListeners_[window_->GetWindowId()].size(), 0); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_impl_test.cpp b/window_manager/wm/test/unittest/window_impl_test.cpp new file mode 100644 index 0000000..649cc44 --- /dev/null +++ b/window_manager/wm/test/unittest/window_impl_test.cpp @@ -0,0 +1,3038 @@ +/* + * Copyright (c) 2021-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 "ability_context_impl.h" +#include "mock_window_adapter.h" +#include "singleton_mocker.h" +#include "window_impl.h" +#include "mock_uicontent.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class MockAceAbilityHandler : public IAceAbilityHandler { +public: + MOCK_METHOD1(SetBackgroundColor, void(uint32_t color)); + MOCK_METHOD0(GetBackgroundColor, uint32_t()); +}; + +class MockAnimationTransitionController : public IAnimationTransitionController { +public: + MOCK_METHOD0(AnimationForShown, void()); + MOCK_METHOD0(AnimationForHidden, void()); +}; + +class MockDialogDeathRecipientListener : public IDialogDeathRecipientListener { +public: + MOCK_CONST_METHOD0(OnDialogDeathRecipient, void()); +}; + +class MockScreenshotListener : public IScreenshotListener { +public: + MOCK_METHOD0(OnScreenshot, void()); +}; + +class MockDialogTargetTouchListener : public IDialogTargetTouchListener { +public: + MOCK_CONST_METHOD0(OnDialogTargetTouch, void()); +}; + +class MockWindowChangeListener : public IWindowChangeListener { +public: + MOCK_METHOD2(OnSizeChange, void(Rect rect, WindowSizeChangeReason reason)); + MOCK_METHOD1(OnModeChange, void(WindowMode mode)); +}; + +class MockAvoidAreaChangedListener : public IAvoidAreaChangedListener { +public: + MOCK_METHOD2(OnAvoidAreaChanged, void(const AvoidArea avoidArea, AvoidAreaType type)); +}; + +class MockDisplayMoveListener : public IDisplayMoveListener { +public: + MOCK_METHOD2(OnDisplayMove, void(DisplayId from, DisplayId to)); +}; + +class MockInputEventConsumer : public IInputEventConsumer { +public: + MOCK_CONST_METHOD1(OnInputEvent, bool(const std::shared_ptr&)); + MOCK_CONST_METHOD1(OnInputEvent, bool(const std::shared_ptr&)); + MOCK_CONST_METHOD1(OnInputEvent, bool(const std::shared_ptr&)); +}; + +class MockKeyEvent : public MMI::KeyEvent { +public: + MockKeyEvent() : MMI::KeyEvent(0) {} +}; + +class MockPointerEvent : public MMI::PointerEvent { +public: + MockPointerEvent() : MMI::PointerEvent(0) {} +}; + +class WindowImplTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + void CreateStretchableWindow(sptr& window, const Rect& rect); + + static inline std::shared_ptr abilityContext_; + std::unique_ptr m = std::make_unique(); +}; +void WindowImplTest::SetUpTestCase() +{ +} + +void WindowImplTest::TearDownTestCase() +{ +} + +void WindowImplTest::SetUp() +{ +} + +void WindowImplTest::TearDown() +{ +} + +void WindowImplTest::CreateStretchableWindow(sptr& window, const Rect& rect) +{ + sptr option = new WindowOption(); + option->SetWindowName("StretchableWindowTest"); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowRect({ 1, 1, 1, 1 }); + window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->windowSystemConfig_.isStretchable_ = true; + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + window->UpdateRect(rect, true, WindowSizeChangeReason::UNDEFINED); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect); +} + +namespace { +/** + * @tc.name: CreateWindow01 + * @tc.desc: Create window with no parentId + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CreateWindow01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("CreateWindow01"); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: CreateWindow02 + * @tc.desc: Create window with no parentId and no abilityContext + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CreateWindow02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("CreateWindow02"); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + ASSERT_EQ(WMError::WM_ERROR_SAMGR, window->Create(INVALID_WINDOW_ID)); +} + +/** + * @tc.name: CreateWindow03 + * @tc.desc: Create window with illegal parentId + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CreateWindow03, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowName("CreateWindow03"); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->Create(1234)); +} + +/** + * @tc.name: CreateWindow04 + * @tc.desc: Create window with repeated windowName + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CreateWindow04, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("CreateWindow04"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(INVALID_WINDOW_ID); + + sptr option_other = new WindowOption(); + option_other->SetWindowName("CreateWindow04"); + sptr window_other = new WindowImpl(option_other); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window_other->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); + ASSERT_EQ(WMError::WM_OK, window_other->Destroy()); +} + +/** + * @tc.name: CreateWindow05 + * @tc.desc: Create window with exist parentId + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CreateWindow05, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("CreateWindow05_parent"); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + sptr option2 = new WindowOption(); + option2->SetWindowName("CreateWindow05"); + sptr window2 = new WindowImpl(option2); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window2->Create(window->GetWindowId())); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); + ASSERT_EQ(WMError::WM_OK, window2->Destroy()); +} + +/** + * @tc.name: CreateWindow06 + * @tc.desc: Create window with no default option, get and check Property + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CreateWindow06, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("CreateWindow06"); + struct Rect rect = {1, 2, 3u, 4u}; + option->SetWindowRect(rect); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(1, window->GetRequestRect().posX_); + ASSERT_EQ(2, window->GetRequestRect().posY_); + ASSERT_EQ(3u, window->GetRequestRect().width_); + ASSERT_EQ(4u, window->GetRequestRect().height_); + ASSERT_EQ(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, window->GetType()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + ASSERT_EQ("CreateWindow06", window->GetWindowName()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: FindWindow01 + * @tc.desc: Find one exit window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindWindow01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("FindWindow01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(INVALID_WINDOW_ID); + ASSERT_NE(nullptr, WindowImpl::Find("FindWindow01")); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: FindWindow02 + * @tc.desc: Add another window, find both two windows + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindWindow02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("FindWindow02"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + option->SetWindowName("FindWindow02_other"); + sptr window2 = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window2->Create(INVALID_WINDOW_ID)); + + ASSERT_NE(nullptr, WindowImpl::Find("FindWindow02_other")); + ASSERT_NE(nullptr, WindowImpl::Find("FindWindow02")); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window2->Destroy()); +} + +/** + * @tc.name: FindWindow03 + * @tc.desc: Find one no exit window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindWindow03, Function | SmallTest | Level2) +{ + ASSERT_EQ(nullptr, WindowImpl::Find("FindWindow03")); +} + +/** + * @tc.name: FindWindow04 + * @tc.desc: Find window with empty name + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindWindow04, Function | SmallTest | Level2) +{ + ASSERT_EQ(nullptr, WindowImpl::Find("")); +} + +/** + * @tc.name: FindWindow05 + * @tc.desc: Find one destroyed window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindWindow05, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("FindWindow05"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); + ASSERT_EQ(nullptr, WindowImpl::Find("FindWindow05")); +} + +/** + * @tc.name: FindTopWindow01 + * @tc.desc: Find one top window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindTopWindow01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("FindTopWindow01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_NE(nullptr, window->FindTopWindow(window->property_->GetWindowId())); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetWindowType01 + * @tc.desc: SetWindowType + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowType01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetWindowType01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WMError::WM_OK, window->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetWindowMode01 + * @tc.desc: SetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowMode01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetWindowType01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WMError::WM_OK, window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetWindowMode02 + * @tc.desc: Set window mode to split primary + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowMode02, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName(""); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + ASSERT_EQ(WMError::WM_OK, window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY)); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, window->GetMode()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetWindowMode03 + * @tc.desc: Set window mode to split secondary + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowMode03, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName(""); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + ASSERT_EQ(WMError::WM_OK, window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY)); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, window->GetMode()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetWindowMode04 + * @tc.desc: Set window mode to floating + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowMode04, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName(""); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + ASSERT_EQ(WMError::WM_OK, window->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING)); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, window->GetMode()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetWindowMode05 + * @tc.desc: Set window mode to pip + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowMode05, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName(""); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + ASSERT_EQ(WMError::WM_OK, window->SetWindowMode(WindowMode::WINDOW_MODE_PIP)); + ASSERT_EQ(WindowMode::WINDOW_MODE_PIP, window->GetMode()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHideWindow01 + * @tc.desc: Show and hide window with add and remove window ok + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHideWindow01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("ShowHideWindow01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + window->NotifyForeground(); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Hide()); + window->NotifyBackground(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHideWindow02 + * @tc.desc: Show window with add window WM_ERROR_SAMGR + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHideWindow02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("ShowHideWindow02"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + ASSERT_EQ(WMError::WM_ERROR_SAMGR, window->Show()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHideWindow03 + * @tc.desc: Show window with add window WM_ERROR_IPC_FAILED + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHideWindow03, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("ShowHideWindow03"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_IPC_FAILED)); + ASSERT_EQ(WMError::WM_ERROR_IPC_FAILED, window->Show()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHideWindow04 + * @tc.desc: Show window with add window OK & Hide window with remove window WM_ERROR_SAMGR + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHideWindow04, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("ShowHideWindow04"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + ASSERT_EQ(WMError::WM_ERROR_SAMGR, window->Hide()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHideWindow05 + * @tc.desc: Hide window with remove window WM_ERROR_IPC_FAILED + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHideWindow05, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("ShowHideWindow05"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_IPC_FAILED)); + ASSERT_EQ(WMError::WM_ERROR_IPC_FAILED, window->Hide()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHideWindow06 + * @tc.desc: Hide window with remove window OK + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHideWindow06, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("ShowHideWindow06"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Hide()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetSystemBarProperty01 + * @tc.desc: SetSystemBarProperty with default param + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetSystemBarProperty01, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetSystemBarProperty01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + WindowType type = WindowType::WINDOW_TYPE_STATUS_BAR; + SystemBarProperty prop; + ASSERT_EQ(WMError::WM_OK, window->SetSystemBarProperty(type, prop)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetSystemBarProperty02 + * @tc.desc: SetSystemBarProperty with adapter return WM_ERROR_SAMGR + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetSystemBarProperty02, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetSystemBarProperty02"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + WindowType type = WindowType::WINDOW_TYPE_STATUS_BAR; + const SystemBarProperty SYS_BAR_PROP(false, 0xE5222222, 0xE5333333); + ASSERT_EQ(WMError::WM_ERROR_SAMGR, window->SetSystemBarProperty(type, SYS_BAR_PROP)); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetSystemBarProperty03 + * @tc.desc: SetSystemBarProperty to invalid window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetSystemBarProperty03, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetSystemBarProperty03"); + sptr window = new WindowImpl(option); + WindowType type = WindowType::WINDOW_TYPE_STATUS_BAR; + SystemBarProperty prop; + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetSystemBarProperty(type, prop)); +} + +/** + * @tc.name: GetSystemBarPropertyByType01 + * @tc.desc: GetSystemBarPropertyByType with exist key + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetSystemBarPropertyByType01, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("GetSystemBarPropertyByType01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + WindowType type = WindowType::WINDOW_TYPE_STATUS_BAR; + const SystemBarProperty SYS_BAR_PROP(false, 0xE5222222, 0xE5333344); + ASSERT_EQ(WMError::WM_OK, window->SetSystemBarProperty(type, SYS_BAR_PROP)); + ASSERT_EQ(SYS_BAR_PROP, window->GetSystemBarPropertyByType(type)); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: GetSystemBarPropertyByType02 + * @tc.desc: GetSystemBarPropertyByType with nonexist key + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetSystemBarPropertyByType02, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("GetSystemBarPropertyByType02"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + const SystemBarProperty SYS_BAR_PROP(false, 0xE5222222, 0xE5333333); + const SystemBarProperty DEFAULT_PROP; + ASSERT_EQ(WMError::WM_OK, window->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP)); + ASSERT_EQ(DEFAULT_PROP, window->GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_BAR)); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: GetSystemBarPropertyByType03 + * @tc.desc: GetSystemBarPropertyByType with not systemBar type + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetSystemBarPropertyByType03, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("GetSystemBarPropertyByType03"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + const SystemBarProperty SYS_BAR_PROP(false, 0xE5222222, 0xE5333366); + const SystemBarProperty DEFAULT_PROP; + ASSERT_EQ(WMError::WM_OK, window->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP)); + ASSERT_EQ(DEFAULT_PROP, window->GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW)); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: Maximize02 + * @tc.desc: Maximize the sub window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Maximize02, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("Maximize02"); + sptr window = new WindowImpl(option); + window->Maximize(); + ASSERT_EQ(WindowMode::WINDOW_MODE_UNDEFINED, window->GetMode()); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + window->Maximize(); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, window->GetMode()); + + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: Recover01 + * @tc.desc: Recover the main window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Recover01, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("Recover01"); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Recover()); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(INVALID_WINDOW_ID); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Recover(); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, window->GetMode()); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: Recover02 + * @tc.desc: Recover the sub window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Recover02, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("Recover02"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(INVALID_WINDOW_ID); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + window->Recover(); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, window->GetMode()); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Hide(); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: Minimize01 + * @tc.desc: Minimize the main window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Minimize01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("Minimize01"); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Minimize()); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Create(INVALID_WINDOW_ID); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + ASSERT_TRUE((window->GetWindowState() == WindowState::STATE_SHOWN)); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Minimize(); + ASSERT_FALSE((window->GetWindowState() == WindowState::STATE_SHOWN)); + window->uiContent_ = std::make_unique(); + ASSERT_EQ(WMError::WM_OK, window->Minimize()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: Minimize02 + * @tc.desc: Minimize the sub window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Minimize02, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("Minimize02"); + sptr 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(INVALID_WINDOW_ID); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + window->Show(); + ASSERT_TRUE((window->GetWindowState() == WindowState::STATE_SHOWN)); + window->Minimize(); + ASSERT_TRUE((window->GetWindowState() == WindowState::STATE_SHOWN)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: IsSupportWideGamut01 + * @tc.desc: IsSupportWideGamut + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, IsSupportWideGamut01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("IsSupportWideGamut01"); + sptr 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(INVALID_WINDOW_ID); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + ASSERT_TRUE(window->IsSupportWideGamut()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetColorSpace01 + * @tc.desc: SetColorSpace + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetColorSpace01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("SetColorSpace01"); + sptr 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(INVALID_WINDOW_ID); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + window->SetColorSpace(ColorSpace::COLOR_SPACE_WIDE_GAMUT); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: GetColorSpace01 + * @tc.desc: GetColorSpace + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetColorSpace01, Function | SmallTest | Level3) +{ + auto option = new WindowOption(); + option->SetWindowName("GetColorSpace01"); + sptr 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(INVALID_WINDOW_ID); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + window->SetColorSpace(ColorSpace::COLOR_SPACE_DEFAULT); + ASSERT_EQ(ColorSpace::COLOR_SPACE_DEFAULT, window->GetColorSpace()); + window->SetColorSpace(ColorSpace::COLOR_SPACE_WIDE_GAMUT); + ASSERT_EQ(ColorSpace::COLOR_SPACE_WIDE_GAMUT, window->GetColorSpace()); + uint32_t invalidColorSpace = 54321u; + window->SetColorSpace(static_cast(invalidColorSpace)); + ASSERT_EQ(ColorSpace::COLOR_SPACE_DEFAULT, window->GetColorSpace()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StartMove01 + * @tc.desc: start move main fullscreen window, test startMoveFlag + * @tc.type: FUNC + * @tc.require: issueI5J8IB + */ +HWTEST_F(WindowImplTest, StartMove01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("StartMove01"); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + window->StartMove(); + ASSERT_FALSE(window->moveDragProperty_->startMoveFlag_); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StartMove02 + * @tc.desc: start move main fullscreen window, test startMoveFlag + * @tc.type: FUNC + * @tc.require: issueI5J8IB + */ +HWTEST_F(WindowImplTest, StartMove02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("StartMove02"); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + + window->StartMove(); + ASSERT_FALSE(window->moveDragProperty_->startMoveFlag_); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StartMove03 + * @tc.desc: start move divider, test startMoveFlag + * @tc.type: FUNC + * @tc.require: issueI5J8IB + */ +HWTEST_F(WindowImplTest, StartMove03, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("StartMove03"); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + window->StartMove(); + ASSERT_FALSE(window->moveDragProperty_->startMoveFlag_); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetBackgroundColor01 + * @tc.desc: test SetBackgroundColor withow uiContent + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetBackgroundColor01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetBackgroundColor01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + ASSERT_FALSE(window->IsTransparent()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBackgroundColor("#000")); + ASSERT_FALSE(window->IsTransparent()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, window->SetBackgroundColor("#00FF00")); + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, window->SetBackgroundColor("#FF00FF00")); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTurnScreenOn01 + * @tc.desc: create window but not show, test SetTurnScreenOn + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetTurnScreenOn01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetTurnScreenOn01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetTurnScreenOn(true)); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_FALSE(window->IsTurnScreenOn()); + ASSERT_EQ(WMError::WM_OK, window->SetTurnScreenOn(true)); + ASSERT_TRUE(window->IsTurnScreenOn()); + ASSERT_EQ(WMError::WM_OK, window->SetTurnScreenOn(false)); + ASSERT_FALSE(window->IsTurnScreenOn()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + + +/** + * @tc.name: SetTurnScreenOn02 + * @tc.desc: create window with show, test SetTurnScreenOn + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetTurnScreenOn02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetTurnScreenOn02"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_FALSE(window->IsTurnScreenOn()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2).WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetTurnScreenOn(true)); + ASSERT_TRUE(window->IsTurnScreenOn()); + ASSERT_EQ(WMError::WM_OK, window->SetTurnScreenOn(false)); + ASSERT_FALSE(window->IsTurnScreenOn()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetKeepScreenOn01 + * @tc.desc: create window but not show, test SetKeepScreenOn + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetKeepScreenOn01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetKeepScreenOn01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetKeepScreenOn(true)); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_FALSE(window->IsKeepScreenOn()); + ASSERT_EQ(WMError::WM_OK, window->SetKeepScreenOn(true)); + ASSERT_TRUE(window->IsKeepScreenOn()); + ASSERT_EQ(WMError::WM_OK, window->SetKeepScreenOn(false)); + ASSERT_FALSE(window->IsKeepScreenOn()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetKeepScreenOn02 + * @tc.desc: create window with show, test SetKeepScreenOn + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetKeepScreenOn02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetKeepScreenOn02"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_FALSE(window->IsKeepScreenOn()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2).WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK));; + ASSERT_EQ(WMError::WM_OK, window->SetKeepScreenOn(true)); + ASSERT_TRUE(window->IsKeepScreenOn()); + ASSERT_EQ(WMError::WM_OK, window->SetKeepScreenOn(false)); + ASSERT_FALSE(window->IsKeepScreenOn()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetBrightness01 + * @tc.desc: test SetBrightness with invalid brightness + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetBrightness01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetBrightness01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetBrightness(0.f)); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WMError::WM_OK, window->SetBrightness(MAXIMUM_BRIGHTNESS)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(MAXIMUM_BRIGHTNESS, window->GetBrightness()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetBrightness(2.0f)); // 2.0f: brightness + ASSERT_EQ(MAXIMUM_BRIGHTNESS, window->GetBrightness()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetBrightness02 + * @tc.desc: test SetBrightness with valid brightness + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetBrightness02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetBrightness02"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(UNDEFINED_BRIGHTNESS, window->GetBrightness()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2).WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetBrightness(MAXIMUM_BRIGHTNESS)); + ASSERT_EQ(MAXIMUM_BRIGHTNESS, window->GetBrightness()); + ASSERT_EQ(WMError::WM_OK, window->SetBrightness(MINIMUM_BRIGHTNESS)); + ASSERT_EQ(MINIMUM_BRIGHTNESS, window->GetBrightness()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetBrightness03 + * @tc.desc: test SetBrightness with invalid type window + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetBrightness03, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetBrightness03"); + option->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(UNDEFINED_BRIGHTNESS, window->GetBrightness()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_TYPE, window->SetBrightness(MAXIMUM_BRIGHTNESS)); + ASSERT_EQ(UNDEFINED_BRIGHTNESS, window->GetBrightness()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetFocusable01 + * @tc.desc: create window but not show, test SetFocusable + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetFocusable01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetFocusable01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->RequestFocus()); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_TRUE(window->GetFocusable()); + EXPECT_CALL(m->Mock(), RequestFocus(_)).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->RequestFocus()); + ASSERT_EQ(WMError::WM_OK, window->SetFocusable(false)); + ASSERT_FALSE(window->GetFocusable()); + ASSERT_EQ(WMError::WM_OK, window->SetFocusable(true)); + ASSERT_TRUE(window->GetFocusable()); + WindowState state = window->GetWindowState(); + window->SetWindowState(WindowState::STATE_UNFROZEN); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetFocusable(false)); + ASSERT_TRUE(window->GetFocusable()); + window->SetWindowState(state); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetFocusable02 + * @tc.desc: create window with show, test SetFocusable + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetFocusable02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetFocusable02"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(window->GetFocusable()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2).WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetFocusable(false)); + ASSERT_FALSE(window->GetFocusable()); + ASSERT_EQ(WMError::WM_OK, window->SetFocusable(true)); + ASSERT_TRUE(window->GetFocusable()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTouchable01 + * @tc.desc: create window but not show, test SetTouchable + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetTouchable01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetTouchable01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_TRUE(window->GetTouchable()); + ASSERT_EQ(WMError::WM_OK, window->SetTouchable(false)); + ASSERT_FALSE(window->GetTouchable()); + ASSERT_EQ(WMError::WM_OK, window->SetTouchable(true)); + ASSERT_TRUE(window->GetTouchable()); + WindowState state = window->GetWindowState(); + window->SetWindowState(WindowState::STATE_UNFROZEN); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetTouchable(false)); + ASSERT_TRUE(window->GetTouchable()); + window->SetWindowState(state); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTouchable02 + * @tc.desc: create window with show, test SetTouchable + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetTouchable02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetTouchable02"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_TRUE(window->GetTouchable()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2).WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetTouchable(false)); + ASSERT_FALSE(window->GetTouchable()); + ASSERT_EQ(WMError::WM_OK, window->SetTouchable(true)); + ASSERT_TRUE(window->GetTouchable()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: DisableAppWindowDecor01 + * @tc.desc: disable app window decor + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, DisableAppWindowDecor01, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("DisableAppWindowDecor01"); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->isAppDecorEnable_ = true; + window->SetWindowType(WindowType::WINDOW_TYPE_FLOAT); + window->DisableAppWindowDecor(); + ASSERT_TRUE(window->isAppDecorEnable_); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + window->DisableAppWindowDecor(); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_FALSE(window->isAppDecorEnable_); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTouchHotAreas01 + * @tc.desc: create window with show, test SetTouchHotAreas + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetTouchHotAreas01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetTouchHotAreas01"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + std::unique_ptr m = std::make_unique(); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + std::vector requestedTouchHotAreas; + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_TRUE(requestedTouchHotAreas.empty()); + + std::vector rects; + rects.emplace_back(Rect{ 0, 0, 720, 400 }); + rects.emplace_back(Rect{ 0, 800, 720, 300 }); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetTouchHotAreas(rects)); + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_EQ(rects.size(), requestedTouchHotAreas.size()); + for (uint32_t i = 0; i < rects.size(); ++i) { + ASSERT_TRUE(rects[i] == requestedTouchHotAreas[i]); + } + + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + rects.clear(); + ASSERT_EQ(WMError::WM_OK, window->SetTouchHotAreas(rects)); + window->GetRequestedTouchHotAreas(requestedTouchHotAreas); + ASSERT_TRUE(requestedTouchHotAreas.empty()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTransform01 + * @tc.desc: set transform + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowImplTest, SetTransform01, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetTransform01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->DisableAppWindowDecor(); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + Transform trans_; + window->UpdateZoomTransform(trans_, true); + ASSERT_TRUE(window->GetZoomTransform() == trans_); + window->SetTransform(trans_); + window->UpdateZoomTransform(trans_, false); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + window->SetTransform(trans_); + ASSERT_TRUE(trans_ == window->GetTransform()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTransform02 + * @tc.desc: set transform and getTransform + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowImplTest, SetTransform02, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetTransform01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->DisableAppWindowDecor(); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + Transform trans_; + trans_.pivotX_ = 1.0f; + trans_.pivotY_ = 0.6f; + window->SetTransform(trans_); + ASSERT_TRUE(trans_ != window->GetTransform()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTransform03 + * @tc.desc: set transform and getTransform + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowImplTest, SetTransform03, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetTransform01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->DisableAppWindowDecor(); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + Transform trans_; + trans_.pivotX_ = 1.0f; + trans_.pivotY_ = 0.6f; + window->SetTransform(trans_); + ASSERT_TRUE(trans_ == window->GetTransform()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetTransform04 + * @tc.desc: set transform and getTransform + * @tc.type: FUNC + * @tc.require: issueI5NDLK + */ +HWTEST_F(WindowImplTest, SetTransform04, Function | SmallTest | Level3) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + option->SetWindowName("SetTransform01"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->DisableAppWindowDecor(); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + Transform trans_; + trans_.pivotX_ = 1.0f; + trans_.pivotY_ = 0.6f; + Transform defaultTrans_; + window->SetTransform(trans_); + ASSERT_TRUE(defaultTrans_ != window->GetTransform()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: SetAPPWindowLabel + * @tc.desc: set window label to ace + * @tc.type: FUNC + * @tc.require: issueI5Q2KW + */ +HWTEST_F(WindowImplTest, SetAPPWindowLabel, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetAPPWindowLabel"); + sptr window = new WindowImpl(option); + std::string label = "openharmony"; + + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, SetAppWindowTitle(_)); + ASSERT_EQ(WMError::WM_OK, window->SetAPPWindowLabel(label)); + window->uiContent_ = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, window->SetAPPWindowLabel(label)); +} + +/** + * @tc.name: SetAPPWindowIcon + * @tc.desc: set window Icon to ace + * @tc.type: FUNC + * @tc.require: issueI5Q2KW + */ +HWTEST_F(WindowImplTest, SetAPPWindowIcon, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("SetAPPWindowIcon"); + sptr window = new WindowImpl(option); + + std::shared_ptr icon1(nullptr); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, window->SetAPPWindowIcon(icon1)); + std::shared_ptr icon2 = std::make_shared(); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, window->SetAPPWindowIcon(icon2)); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, SetAppWindowIcon(_)); + ASSERT_EQ(WMError::WM_OK, window->SetAPPWindowIcon(icon2)); +} + +/** + * @tc.name: NotifyMemoryLevel01 + * @tc.desc: NotifyMemoryLevel without mainWindow + * @tc.type: FUNC + * @tc.require: issueI5JQ04 + */ +HWTEST_F(WindowImplTest, NotifyMemoryLevel01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowName("NotifyMemoryLevel01"); + int32_t level = 0; + sptr window = new WindowImpl(option); + + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, window->NotifyMemoryLevel(level)); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, NotifyMemoryLevel(_)); + ASSERT_EQ(WMError::WM_OK, window->NotifyMemoryLevel(level)); +} + +/** + * @tc.name: StretchableUpdateRectDragStartTest + * @tc.desc: UpdateRect test for stretchable window when drag start. + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, StretchableUpdateRectDragStartTest, Function | SmallTest | Level3) +{ + Rect rect1 { 10, 10, 10, 10 }; + sptr window; + CreateStretchableWindow(window, rect1); + Rect rect2 { 100, 100, 100, 100 }; + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, UpdateViewportConfig(_, _)); + window->UpdateRect(rect2, true, WindowSizeChangeReason::DRAG_START); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect1); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StretchableUpdateRectDragTest + * @tc.desc: UpdateRect test for stretchable window when drag. + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, StretchableUpdateRectDragTest, Function | SmallTest | Level3) +{ + Rect rect1 { 10, 10, 10, 10 }; + sptr window; + CreateStretchableWindow(window, rect1); + Rect rect2 { 100, 100, 100, 100 }; + window->UpdateRect(rect2, true, WindowSizeChangeReason::DRAG); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect1); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StretchableUpdateRectDragEndTest + * @tc.desc: UpdateRect test for stretchable window when drag end. + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, StretchableUpdateRectDragEndTest, Function | SmallTest | Level3) +{ + Rect rect1 { 10, 10, 10, 10 }; + sptr window; + CreateStretchableWindow(window, rect1); + Rect rect2 { 100, 100, 100, 100 }; + window->UpdateRect(rect2, true, WindowSizeChangeReason::DRAG_END); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect1); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StretchableUpdateRectRecoverTest + * @tc.desc: UpdateRect test for stretchable window when recover. + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, StretchableUpdateRectRecoverTest, Function | SmallTest | Level3) +{ + Rect rect1 { 10, 10, 10, 10 }; + sptr window; + CreateStretchableWindow(window, rect1); + Rect rect2 { 100, 100, 100, 100 }; + window->UpdateRect(rect2, true, WindowSizeChangeReason::RECOVER); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect1); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StretchableUpdateRectRecoverTest + * @tc.desc: UpdateRect test for stretchable window when move. + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, StretchableUpdateRectMoveTest, Function | SmallTest | Level3) +{ + Rect rect1 { 10, 10, 10, 10 }; + sptr window; + CreateStretchableWindow(window, rect1); + Rect rect2 { 100, 100, 100, 100 }; + window->UpdateRect(rect2, true, WindowSizeChangeReason::MOVE); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect1); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: StretchableUpdateRectResizeTest + * @tc.desc: UpdateRect test for stretchable window when resize. + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, StretchableUpdateRectResizeTest, Function | SmallTest | Level3) +{ + Rect rect1 { 110, 110, 10, 10 }; + sptr window; + CreateStretchableWindow(window, rect1); + Rect rect2 { 100, 100, 100, 100 }; + ASSERT_EQ(true, rect1.IsInsideOf(rect2)); + ASSERT_EQ(true, rect1 != rect2); + window->UpdateRect(rect2, true, WindowSizeChangeReason::RESIZE); + ASSERT_EQ(window->GetWindowProperty()->GetOriginRect(), rect2); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: PrivacyMode01 + * @tc.desc: Set window privacy mode + * @tc.type: FUNC + * @tc.require: issueI5MYNX + */ +HWTEST_F(WindowImplTest, PrivacyMode01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("PrivacyMode01"); + sptr window = new WindowImpl(option); + ASSERT_NE(nullptr, window); + + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(4).WillRepeatedly(Return(WMError::WM_OK)); + + window->SetPrivacyMode(true); + window->SetSystemPrivacyMode(true); + ASSERT_EQ(true, window->IsPrivacyMode()); + + window->SetPrivacyMode(true); + window->SetSystemPrivacyMode(false); + ASSERT_EQ(true, window->IsPrivacyMode()); + + window->SetPrivacyMode(false); + window->SetSystemPrivacyMode(true); + ASSERT_EQ(false, window->IsPrivacyMode()); + + window->SetPrivacyMode(false); + window->SetSystemPrivacyMode(false); + ASSERT_EQ(false, window->IsPrivacyMode()); +} + +/** + * @tc.name: CalculatePointerDirection + * @tc.desc: calculate mouse style id + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, CalculatePointerDirection, Function | SmallTest | Level3) +{ + Rect rect1 { 1, 1, 100, 100 }; + sptr option = new WindowOption(); + option->SetWindowName("CalculatePointerDirection"); + sptr window = new WindowImpl(option); + + window->moveDragProperty_->startRectExceptCorner_ = rect1; + ASSERT_EQ(12, window->CalculatePointerDirection(0, 0)); + ASSERT_EQ(6, window->CalculatePointerDirection(50, 0)); + ASSERT_EQ(11, window->CalculatePointerDirection(102, 0)); + ASSERT_EQ(5, window->CalculatePointerDirection(102, 50)); +} + + /* + * @tc.name: FindTopWindow + * @tc.desc: FindTopWindow Test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, FindTopWindow, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("FindTopWindow"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(nullptr, window->FindTopWindow(INVALID_WINDOW_ID)); + ASSERT_EQ(sptr(window), window->FindTopWindow(window->GetWindowId())); + EXPECT_CALL(m->Mock(), GetTopWindowId(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(nullptr, sptr(window)->GetTopWindowWithId(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), GetTopWindowId(_, _)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(nullptr, sptr(window)->GetTopWindowWithId(INVALID_WINDOW_ID)); + std::shared_ptr context; + EXPECT_CALL(m->Mock(), GetTopWindowId(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(nullptr, sptr(window)->GetTopWindowWithContext(context)); +} + + /* + * @tc.name: GetSubWindow + * @tc.desc: GetSubWindow Test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetSubWindow, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowName("main"); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + option = new WindowOption(); + option->SetWindowName("sub"); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + sptr subWindow = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, subWindow->Create(window->GetWindowId())); + + auto subWindowVec = sptr(window)->GetSubWindow(window->GetWindowId()); + ASSERT_EQ(1, subWindowVec.size()); + ASSERT_EQ(sptr(subWindow), subWindowVec[0]); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + + /* + * @tc.name: UpdateConfigurationForAll + * @tc.desc: UpdateConfigurationForAll Test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdateConfigurationForAll, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + std::shared_ptr configuration; + sptr(window)->UpdateConfigurationForAll(configuration); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + + /* + * @tc.name: SetAlpha + * @tc.desc: SetAlpha | GetAlpha + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetAlpha, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + float alpha = 0.5f; + window->SetAlpha(alpha); + ASSERT_EQ(alpha, window->GetAlpha()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + + /* + * @tc.name: GetAvoidAreaByType + * @tc.desc: Test GetAvoidAreaByType when ret is not ok + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetAvoidAreaByType, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), GetAvoidAreaByType(_, _, _)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + AvoidArea avoidarea; + ASSERT_EQ(WMError::WM_DO_NOTHING, window->GetAvoidAreaByType(AvoidAreaType::TYPE_CUTOUT, avoidarea)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: SetWindowType + * @tc.desc: SetWindowType Test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowType, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + + window->SetWindowState(WindowState::STATE_UNFROZEN); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW)); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetWindowType(WindowType::SYSTEM_WINDOW_END)); + + window->SetWindowState(WindowState::STATE_FROZEN); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: SetWindowMode + * @tc.desc: SetWindowMode Test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowMode, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + + window->SetWindowState(WindowState::STATE_UNFROZEN); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN)); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, HideWindowTitleButton(_, _, _)); + EXPECT_CALL(*content, UpdateWindowMode(_)); + ASSERT_EQ(WMError::WM_OK, window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN)); + window->uiContent_ = nullptr; + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + window->UpdateModeSupportInfo(0); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE, + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN)); + window->UpdateModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN)); + window->SetWindowState(WindowState::STATE_FROZEN); + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: WindowFlag + * @tc.desc: GetWindowFlags | SetWindowFlags | AddWindowFlag | RemoveWindowFlag + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, WindowFlag, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetWindowFlags(0)); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + ASSERT_EQ(static_cast(1), window->GetWindowFlags()); + ASSERT_EQ(WindowState::STATE_SHOWN, window->GetWindowState()); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->SetWindowFlags(static_cast(0))); + ASSERT_EQ(static_cast(1), window->GetWindowFlags()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: OnNewWant + * @tc.desc: OnNewWant test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, OnNewWant, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + AAFwk::Want want; + EXPECT_CALL(*content, OnNewWant(_)).Times(1).WillOnce(Return()); + window->OnNewWant(want); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: GetContentInfo + * @tc.desc: GetContentInfo test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, GetContentInfo, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + ASSERT_EQ(std::string(""), window->GetContentInfo()); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, GetContentInfo()).Times(1).WillOnce(Return("info")); + ASSERT_EQ(std::string("info"), window->GetContentInfo()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: Snapshot + * @tc.desc: Snapshot test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Snapshot, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + ASSERT_EQ(nullptr, window->Snapshot()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: DumpInfo + * @tc.desc: DumpInfo test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, DumpInfo, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + window->uiContent_ = std::make_unique(); + std::vector params{"-h"}; + std::vector info{""}; + window->DumpInfo(params, info); + params.push_back(""); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, DumpInfo(_, _)).Times(1).WillOnce(Return()); + window->DumpInfo(params, info); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: SetLayoutFullScreen01 + * @tc.desc: SetLayoutFullScreen true test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetLayoutFullScreen01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetLayoutFullScreen(true)); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + window->UpdateModeSupportInfo(0); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetLayoutFullScreen(true)); + window->UpdateModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->SetLayoutFullScreen(true)); + + window->property_->SetWindowFlags(window->property_->GetWindowFlags() | + (static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetLayoutFullScreen(true)); + + window->property_->SetWindowFlags(window->property_->GetWindowFlags() | + (static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->SetLayoutFullScreen(true)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: SetLayoutFullScreen02 + * @tc.desc: SetLayoutFullScreen false test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetLayoutFullScreen02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + window->property_->SetWindowFlags(window->property_->GetWindowFlags() & + (~static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetLayoutFullScreen(false)); + + window->property_->SetWindowFlags(window->property_->GetWindowFlags() & + (~static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->SetLayoutFullScreen(false)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: SetFullScreen + * @tc.desc: SetFullScreen test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetFullScreen, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetFullScreen(true)); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + window->UpdateModeSupportInfo(0); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetFullScreen(true)); + window->UpdateModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_STATUS_BAR].enable_ = true; + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_NAVIGATION_BAR].enable_ = true; + window->property_->SetWindowFlags(window->property_->GetWindowFlags() | + (static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(3).WillRepeatedly(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetFullScreen(true)); + + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_STATUS_BAR].enable_ = false; + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_NAVIGATION_BAR].enable_ = false; + window->property_->SetWindowFlags(window->property_->GetWindowFlags() & + (~static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(3) + .WillRepeatedly(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetFullScreen(false)); + + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_STATUS_BAR].enable_ = true; + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_NAVIGATION_BAR].enable_ = true; + window->property_->SetWindowFlags(window->property_->GetWindowFlags() | + (static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(2) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->SetFullScreen(true)); + + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_STATUS_BAR].enable_ = true; + window->property_->sysBarPropMap_[WindowType::WINDOW_TYPE_NAVIGATION_BAR].enable_ = true; + window->property_->SetWindowFlags(window->property_->GetWindowFlags() | + (static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID))); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).Times(3) + .WillOnce(Return(WMError::WM_DO_NOTHING)) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->SetFullScreen(true)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: UpdateTitleButtonVisibility + * @tc.desc: UpdateTitleButtonVisibility test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdateTitleButtonVisibility, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, HideWindowTitleButton(_, _, _)); + window->UpdateTitleButtonVisibility(); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: SetWindowCornerRadiusAccordingToSystemConfig + * @tc.desc: SetWindowCornerRadiusAccordingToSystemConfig test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetWindowCornerRadiusAccordingToSystemConfig, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + window->SetWindowCornerRadiusAccordingToSystemConfig(); + window->windowSystemConfig_.effectConfig_.fullScreenCornerRadius_ = 1.0f; + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + window->SetWindowCornerRadiusAccordingToSystemConfig(); + window->windowSystemConfig_.effectConfig_.fullScreenCornerRadius_ = 0.0f; + window->windowSystemConfig_.effectConfig_.splitCornerRadius_ = 1.0f; + window->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + window->SetWindowCornerRadiusAccordingToSystemConfig(); + window->windowSystemConfig_.effectConfig_.splitCornerRadius_ = 0.0f; + window->windowSystemConfig_.effectConfig_.floatCornerRadius_ = 1.0f; + window->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + window->SetWindowCornerRadiusAccordingToSystemConfig(); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: UpdateWindowShadowAccordingToSystemConfig + * @tc.desc: UpdateWindowShadowAccordingToSystemConfig test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdateWindowShadowAccordingToSystemConfig, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + window->windowSystemConfig_.effectConfig_.unfocusedShadow_.elevation_ = 1.0f; + window->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + window->UpdateWindowShadowAccordingToSystemConfig(); + + window->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + window->windowSystemConfig_.effectConfig_.unfocusedShadow_.color_ = "????"; + window->UpdateWindowShadowAccordingToSystemConfig(); + + window->windowSystemConfig_.effectConfig_.unfocusedShadow_.color_ = "#000000"; + window->UpdateWindowShadowAccordingToSystemConfig(); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: WindowCreateCheck + * @tc.desc: WindowCreateCheck test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, WindowCreateCheck, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW); + sptr window = new WindowImpl(option); + + ASSERT_EQ(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW, window->GetType()); + ASSERT_EQ(false, window->WindowCreateCheck(INVALID_WINDOW_ID)); + ASSERT_EQ(false, window->WindowCreateCheck(static_cast(-1))); +} + +/* + * @tc.name: BindDialogTarget + * @tc.desc: BindDialogTarget test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, BindDialogTarget, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), BindDialogTarget(_, _)).Times(2) + .WillOnce(Return(WMError::WM_OK)) + .WillOnce(Return(WMError::WM_DO_NOTHING)); + sptr targetToken; + ASSERT_EQ(WMError::WM_OK, window->BindDialogTarget(targetToken)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->BindDialogTarget(targetToken)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: Destroy + * @tc.desc: Destroy test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, Destroy, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->Destroy()); + + window->SetWindowType(WindowType::WINDOW_TYPE_DIALOG); + ASSERT_EQ(WindowType::WINDOW_TYPE_DIALOG, window->GetType()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->Destroy()); +} + +/* + * @tc.name: UpdateSurfaceNodeAfterCustomAnimation + * @tc.desc: UpdateSurfaceNodeAfterCustomAnimation test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdateSurfaceNodeAfterCustomAnimation, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->UpdateSurfaceNodeAfterCustomAnimation(true)); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, window->UpdateSurfaceNodeAfterCustomAnimation(true)); + + window->SetWindowType(WindowType::WINDOW_TYPE_FLOAT); + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->UpdateSurfaceNodeAfterCustomAnimation(true)); + + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(m->Mock(), UpdateRsTree(_, _)).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->UpdateSurfaceNodeAfterCustomAnimation(true)); + + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(m->Mock(), UpdateRsTree(_, _)).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->UpdateSurfaceNodeAfterCustomAnimation(true)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: ShowHide + * @tc.desc: Show and Hide test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ShowHide, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Show()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Hide()); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + auto state = window->GetWindowState(); + window->SetWindowState(WindowState::STATE_FROZEN); + ASSERT_EQ(WindowState::STATE_FROZEN, window->GetWindowState()); + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, window->PreProcessShow(0, false)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, window->Show()); + + window->SetWindowState(state); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + ASSERT_EQ(WindowState::STATE_SHOWN, window->GetWindowState()); + + ASSERT_EQ(WMError::WM_OK, window->Show(static_cast(WindowStateChangeReason::KEYGUARD))); + EXPECT_CALL(m->Mock(), ProcessPointDown(_, _)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + window->property_->SetWindowType(WindowType::WINDOW_TYPE_DESKTOP); + ASSERT_EQ(WindowType::WINDOW_TYPE_DESKTOP, window->GetType()); + EXPECT_CALL(m->Mock(), MinimizeAllAppWindows(_)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + + EXPECT_CALL(m->Mock(), UpdateProperty(_, _)).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->Hide()); + ASSERT_EQ(WindowState::STATE_SHOWN, window->GetWindowState()); + + window->property_->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + + ASSERT_EQ(WMError::WM_OK, window->Hide(static_cast(WindowStateChangeReason::TOGGLING))); + ASSERT_EQ(WindowState::STATE_HIDDEN, window->GetWindowState()); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE, window->Show()); + ASSERT_EQ(WindowState::STATE_HIDDEN, window->GetWindowState()); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + ASSERT_EQ(WMError::WM_DO_NOTHING, window->Show()); + ASSERT_EQ(WindowState::STATE_HIDDEN, window->GetWindowState()); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: InvalidWindow + * @tc.desc: InvalidWindow test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, InvalidWindow, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->MoveTo(0, 0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Resize(0, 0)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetCallingWindow(INVALID_WINDOW_ID)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetBackgroundColor(std::string("???"))); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->Close()); + ASSERT_EQ(nullptr, window->GetWindowProperty()); +} + +/* + * @tc.name: BackgroundColor + * @tc.desc: GetBackgroundColor | SetBackGroundColor test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, BackgroundColor, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + MockAceAbilityHandler* aceAbilityHandler = new MockAceAbilityHandler(); + window->aceAbilityHandler_ = aceAbilityHandler; + EXPECT_CALL(*aceAbilityHandler, SetBackgroundColor(_)); + ASSERT_EQ(WMError::WM_OK, window->SetBackgroundColor(0)); + EXPECT_CALL(*aceAbilityHandler, GetBackgroundColor()).WillOnce(Return(0)); + ASSERT_EQ(0, window->GetBackgroundColor()); + + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, SetBackgroundColor(_)); + ASSERT_EQ(WMError::WM_OK, window->SetBackgroundColor(0)); + EXPECT_CALL(*content, GetBackgroundColor()).WillOnce(Return(0)); + ASSERT_EQ(0, window->GetBackgroundColor()); +} + +/* + * @tc.name: SetTransparent + * @tc.desc: SetTransparent test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetTransparent, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, window->SetTransparent(true)); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, window->SetTransparent(true)); + ASSERT_EQ(WMError::WM_OK, window->SetTransparent(false)); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: TransferLifeCycleEventToString + * @tc.desc: TransferLifeCycleEventToString test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, TransferLifeCycleEventToString, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + ASSERT_EQ(std::string("DESTROY"), window->TransferLifeCycleEventToString(LifeCycleEvent::DESTROY_EVENT)); + ASSERT_EQ(std::string("UNDEFINE"), window->TransferLifeCycleEventToString( + static_cast(uint32_t(-1)))); +} + +/* + * @tc.name: NotifyWindowTransition + * @tc.desc: NotifyWindowTransition test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifyWindowTransition, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + NotifyNativeWinDestroyFunc func = [](std::string) {}; + window->RegisterWindowDestroyedListener(func); + ASSERT_EQ(WMError::WM_ERROR_NO_MEM, window->NotifyWindowTransition(TransitionReason::ABILITY_TRANSITION)); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Close()); +} + +/* + * @tc.name: RegisterAnimationTransitionController + * @tc.desc: RegisterAnimationTransitionController test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, RegisterAnimationTransitionController, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + sptr listener; + ASSERT_EQ(nullptr, listener); + window->RegisterAnimationTransitionController(listener); + listener = new MockAnimationTransitionController(); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, SetNextFrameLayoutCallback(_)); + window->RegisterAnimationTransitionController(listener); + window->property_ = new WindowProperty(); + EXPECT_CALL(*content, SetNextFrameLayoutCallback(_)); + window->RegisterAnimationTransitionController(listener); + window->property_->SetAnimationFlag(static_cast(WindowAnimation::CUSTOM)); + EXPECT_CALL(*content, SetNextFrameLayoutCallback(_)); + window->RegisterAnimationTransitionController(listener); +} + +/* + * @tc.name: RegisterDialogDeathRecipientListener + * @tc.desc: RegisterDialogDeathRecipientListener | NotifyDestroy test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, RegisterDialogDeathRecipientListener, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + ASSERT_EQ(nullptr, listener); + window->RegisterDialogDeathRecipientListener(sptr(listener)); + listener = new MockDialogDeathRecipientListener(); + ASSERT_NE(nullptr, listener); + window->RegisterDialogDeathRecipientListener(sptr(listener)); + EXPECT_CALL(*listener, OnDialogDeathRecipient()); + window->NotifyDestroy(); + window->UnregisterDialogDeathRecipientListener(sptr(listener)); + window->NotifyDestroy(); +} + +/* + * @tc.name: NotifyScreenshot + * @tc.desc: NotifyScreenshot test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifyScreenshot, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + window->screenshotListeners_[window->GetWindowId()].push_back(sptr(listener)); + listener = new MockScreenshotListener; + window->screenshotListeners_[window->GetWindowId()].push_back(sptr(listener)); + EXPECT_CALL(*listener, OnScreenshot()).Times(1); + window->NotifyScreenshot(); +} + +/* + * @tc.name: NotifyTouchDialogTarget + * @tc.desc: NotifyTouchDialogTarget test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifyTouchDialogTarget, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + window->dialogTargetTouchListeners_[window->GetWindowId()].push_back(sptr(listener)); + listener = new MockDialogTargetTouchListener; + window->dialogTargetTouchListeners_[window->GetWindowId()].push_back(sptr(listener)); + EXPECT_CALL(*listener, OnDialogTargetTouch()); + EXPECT_CALL(m->Mock(), ProcessPointDown(_, _)); + window->NotifyTouchDialogTarget(); +} + +/* + * @tc.name: NotifySizeChange + * @tc.desc: NotifySizeChange test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifySizeChange, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + window->windowChangeListeners_[window->GetWindowId()].push_back(sptr(listener)); + listener = new MockWindowChangeListener; + window->windowChangeListeners_[window->GetWindowId()].push_back(sptr(listener)); + EXPECT_CALL(*listener, OnSizeChange(_, _)); + Rect rect; + window->NotifySizeChange(rect, WindowSizeChangeReason::UNDEFINED); + window->windowChangeListeners_[window->GetWindowId()].clear(); +} + +/* + * @tc.name: NotifyModeChange + * @tc.desc: NotifyModeChange test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifyModeChange, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + window->windowChangeListeners_[window->GetWindowId()].push_back(sptr(listener)); + listener = new MockWindowChangeListener; + window->windowChangeListeners_[window->GetWindowId()].push_back(sptr(listener)); + EXPECT_CALL(*listener, OnModeChange(_)); + window->NotifyModeChange(WindowMode::WINDOW_MODE_UNDEFINED); + window->windowChangeListeners_[window->GetWindowId()].clear(); +} + +/* + * @tc.name: NotifyAvoidAreaChange + * @tc.desc: NotifyAvoidAreaChange test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifyAvoidAreaChange, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + window->avoidAreaChangeListeners_[window->GetWindowId()].push_back(sptr(listener)); + listener = new MockAvoidAreaChangedListener; + window->avoidAreaChangeListeners_[window->GetWindowId()].push_back(sptr(listener)); + EXPECT_CALL(*listener, OnAvoidAreaChanged(_, _)); + sptr avoidArea = new AvoidArea; + window->NotifyAvoidAreaChange(avoidArea, AvoidAreaType::TYPE_CUTOUT); +} + +/* + * @tc.name: NotifyDisplayMoveChange + * @tc.desc: NotifyDisplayMoveChange test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, NotifyDisplayMoveChange, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr listener; + window->displayMoveListeners_.push_back(sptr(listener)); + listener = new MockDisplayMoveListener; + window->displayMoveListeners_.push_back(sptr(listener)); + EXPECT_CALL(*listener, OnDisplayMove(_, _)); + window->NotifyDisplayMoveChange(DisplayId{}, DisplayId{}); +} + +/* + * @tc.name: SetAceAbilityHandler + * @tc.desc: SetAceAbilityHandler test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, SetAceAbilityHandler, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + sptr handler; + ASSERT_EQ(nullptr, handler); + window->SetAceAbilityHandler(handler); + handler = new MockAceAbilityHandler(); + ASSERT_NE(nullptr, handler); + window->SetAceAbilityHandler(handler); +} + +/* + * @tc.name: HandleBackKeyPressedEvent + * @tc.desc: HandleBackKeyPressedEvent test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, HandleBackKeyPressedEvent, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + ASSERT_EQ(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, window->GetType()); + std::shared_ptr keyEvent; + window->HandleBackKeyPressedEvent(keyEvent); + + window->property_->SetWindowType(WindowType::WINDOW_TYPE_FLOAT); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, ProcessBackPressed()).WillOnce(Return(false)); + window->HandleBackKeyPressedEvent(keyEvent); + + window->inputEventConsumer_.reset(new MockInputEventConsumer); + EXPECT_CALL(*reinterpret_cast(window->inputEventConsumer_.get()), + OnInputEvent(keyEvent)).WillOnce(Return(true)); + window->HandleBackKeyPressedEvent(keyEvent); +} + +/* + * @tc.name: ConsumeKeyEvent + * @tc.desc: ConsumeKeyEvent test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ConsumeKeyEvent, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + std::shared_ptr keyEvent = std::make_shared(); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, ProcessKeyEvent(_)); + window->ConsumeKeyEvent(keyEvent); + + window->inputEventConsumer_.reset(new MockInputEventConsumer); + EXPECT_CALL(*reinterpret_cast(window->inputEventConsumer_.get()), + OnInputEvent(keyEvent)); + window->ConsumeKeyEvent(keyEvent); + + keyEvent->SetKeyCode(MMI::KeyEvent::KEYCODE_BACK); + keyEvent->SetKeyAction(MMI::KeyEvent::KEY_ACTION_UP); + window->inputEventConsumer_ = nullptr; + EXPECT_CALL(*content, ProcessBackPressed()); + window->ConsumeKeyEvent(keyEvent); +} + +/* + * @tc.name: ConsumePointerEvent + * @tc.desc: ConsumePointerEvent test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, ConsumePointerEvent, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_LAUNCHER_RECENT); + sptr window = new WindowImpl(option); + Rect rect{ 0, 0, 10u, 10u }; + window->property_->SetWindowRect(rect); + std::shared_ptr pointerEvent = std::make_shared(); + MMI::PointerEvent::PointerItem item; + pointerEvent->SetPointerId(0); + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_DOWN); + window->ConsumePointerEvent(pointerEvent); + + item.SetPointerId(0); + item.SetDisplayX(15); // 15 : position x + item.SetDisplayY(15); // 15 : position y + pointerEvent->AddPointerItem(item); + window->ConsumePointerEvent(pointerEvent); + + item.SetDisplayX(5); // 5 : position x + item.SetDisplayY(5); // 5 : position y + pointerEvent->UpdatePointerItem(0, item); + EXPECT_CALL(m->Mock(), ProcessPointDown(_, _)); + window->ConsumePointerEvent(pointerEvent); +} + +/* + * @tc.name: HandleModeChangeHotZones + * @tc.desc: HandleModeChangeHotZones test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, HandleModeChangeHotZones, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr window = new WindowImpl(option); + window->HandleModeChangeHotZones(0, 0); + window->property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + EXPECT_CALL(m->Mock(), GetModeChangeHotZones(_, _)).Times(1).WillOnce(Return(WMError::WM_DO_NOTHING)); + window->HandleModeChangeHotZones(0, 0); + EXPECT_CALL(m->Mock(), GetModeChangeHotZones(_, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->HandleModeChangeHotZones(0, 0); +} + +/* + * @tc.name: UpdatePointerEventForStretchableWindow + * @tc.desc: UpdatePointerEventForStretchableWindow test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdatePointerEventForStretchableWindow, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + window->property_->SetWindowRect(Rect{ 0, 0, 10, 10 }); + window->property_->SetOriginRect(Rect{ 0, 0, 100, 100 }); + std::shared_ptr pointerEvent = std::make_shared(); + MMI::PointerEvent::PointerItem item; + ASSERT_FALSE(pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)); + window->UpdatePointerEventForStretchableWindow(pointerEvent); + pointerEvent->SetPointerId(0); + item.SetPointerId(0); + item.SetDisplayX(5); // 5 : position x + item.SetDisplayY(5); // 5 : position y + pointerEvent->AddPointerItem(item); + window->UpdatePointerEventForStretchableWindow(pointerEvent); + ASSERT_TRUE(pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)); + ASSERT_EQ(50, item.GetDisplayX()); + ASSERT_EQ(50, item.GetDisplayY()); +} + +/** + * @tc.name: MoveDrag + * @tc.desc: StartMove | ReadyToMoveOrDragWindow | EndMoveOrDragWindow test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, MoveDrag, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->Show(); + window->moveDragProperty_->startDragFlag_ = false; + window->moveDragProperty_->pointEventStarted_ = true; + EXPECT_CALL(m->Mock(), NotifyServerReadyToMoveOrDrag(_, _, _)); + window->StartMove(); + window->moveDragProperty_->pointEventStarted_ = false; + window->StartMove(); + + std::shared_ptr pointerEvent = std::make_shared(); + MMI::PointerEvent::PointerItem item; + pointerEvent->SetTargetDisplayId(0); + item.SetDisplayX(10000); + item.SetDisplayY(10000); + + window->moveDragProperty_->pointEventStarted_ = true; + window->ReadyToMoveOrDragWindow(pointerEvent, item); + window->moveDragProperty_->startMoveFlag_ = true; + window->moveDragProperty_->startDragFlag_ = true; + EXPECT_CALL(m->Mock(), ProcessPointUp(_)).Times(2); + EXPECT_CALL(m->Mock(), GetModeChangeHotZones(_, _)); + window->EndMoveOrDragWindow(uint32_t(), uint32_t(), + window->moveDragProperty_->startPointerId_, window->moveDragProperty_->sourceType_); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: TransferPointerEvent + * @tc.desc: TransferPointerEvent test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, TransferPointerEvent, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + sptr window = new WindowImpl(option); + std::shared_ptr pointerEvent = std::make_shared(); + window->windowSystemConfig_.isStretchable_ = true; + window->TransferPointerEvent(pointerEvent); + window->windowSystemConfig_.isStretchable_ = false; + window->TransferPointerEvent(pointerEvent); + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + EXPECT_CALL(*content, ProcessPointerEvent(_)); + window->TransferPointerEvent(pointerEvent); + + window->inputEventConsumer_.reset(new MockInputEventConsumer); + EXPECT_CALL(*reinterpret_cast(window->inputEventConsumer_.get()), + OnInputEvent(pointerEvent)); + window->TransferPointerEvent(pointerEvent); +} + +/* + * @tc.name: RequestVsync + * @tc.desc: RequestVsync test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, RequestVsync, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + EXPECT_CALL(m->Mock(), AddWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Show()); + std::shared_ptr callback; + window->RequestVsync(callback); + + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); + ASSERT_EQ(WindowState::STATE_DESTROYED, window->GetWindowState()); + window->RequestVsync(callback); +} + +/* + * @tc.name: UpdateConfiguration + * @tc.desc: UpdateConfiguration test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdateConfiguration, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + + option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + option->SetWindowName("subwindow"); + sptr subWindow = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, subWindow->Create(window->GetWindowId())); + std::shared_ptr configuration; + window->UpdateConfiguration(configuration); + + window->uiContent_ = std::make_unique(); + Ace::UIContentMocker* content = reinterpret_cast(window->uiContent_.get()); + subWindow->uiContent_ = std::make_unique(); + Ace::UIContentMocker* subContent = reinterpret_cast(subWindow->uiContent_.get()); + EXPECT_CALL(*content, UpdateConfiguration(_)); + EXPECT_CALL(*subContent, UpdateConfiguration(_)); + window->UpdateConfiguration(configuration); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + EXPECT_CALL(*content, Destroy()); + EXPECT_CALL(*subContent, Destroy()); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: UpdateWindowState + * @tc.desc: UpdateWindowState test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, UpdateWindowState, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->UpdateWindowState(WindowState::STATE_FROZEN); + window->UpdateWindowState(WindowState::STATE_UNFROZEN); + window->UpdateWindowState(WindowState::STATE_SHOWN); + EXPECT_CALL(m->Mock(), RemoveWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + window->UpdateWindowState(WindowState::STATE_HIDDEN); + window->UpdateWindowState(WindowState::STATE_INITIAL); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: RestoreSplitWindowMode + * @tc.desc: RestoreSplitWindowMode test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, RestoreSplitWindowMode, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + window->RestoreSplitWindowMode(0u); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->RestoreSplitWindowMode(static_cast(WindowMode::WINDOW_MODE_SPLIT_PRIMARY)); + window->RestoreSplitWindowMode(static_cast(WindowMode::WINDOW_MODE_SPLIT_SECONDARY)); + window->RestoreSplitWindowMode(static_cast(WindowMode::WINDOW_MODE_UNDEFINED)); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/* + * @tc.name: IsFocused + * @tc.desc: IsFocused test + * @tc.type: FUNC + */ +HWTEST_F(WindowImplTest, IsFocused, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Create(INVALID_WINDOW_ID)); + window->UpdateFocusStatus(false); + ASSERT_FALSE(window->IsFocused()); + window->UpdateFocusStatus(true); + ASSERT_TRUE(window->IsFocused()); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_input_channel_test.cpp b/window_manager/wm/test/unittest/window_input_channel_test.cpp new file mode 100644 index 0000000..68729bf --- /dev/null +++ b/window_manager/wm/test/unittest/window_input_channel_test.cpp @@ -0,0 +1,86 @@ +/* + * 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 "window_impl.h" +#include "window_input_channel.h" +#include "mock_window_adapter.h" +#include "singleton_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using WindowMocker = SingletonMocker; +class WindowInputChannelTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + sptr window_; +}; +void WindowInputChannelTest::SetUpTestCase() +{ +} + +void WindowInputChannelTest::TearDownTestCase() +{ +} + +void WindowInputChannelTest::SetUp() +{ + sptr option = new WindowOption(); + option->SetWindowName("window"); + window_ = new WindowImpl(option); + window_->Create(INVALID_WINDOW_ID); +} + +void WindowInputChannelTest::TearDown() +{ + window_->Destroy(); + window_ = nullptr; +} + +namespace { +/** + * @tc.name: HandlePointerEvent + * @tc.desc: consume pointer event when receive callback from input + * @tc.type: FUNC + */ +HWTEST_F(WindowInputChannelTest, HandlePointerEvent, Function | SmallTest | Level2) +{ + auto pointerEvent = MMI::PointerEvent::Create(); + sptr inputChannel = new WindowInputChannel(window_); + window_->ConsumePointerEvent(pointerEvent); + inputChannel->HandlePointerEvent(pointerEvent); +} + +/** + * @tc.name: HandleKeyEvent + * @tc.desc: consume key event when receive callback from input + * @tc.type: FUNC + */ +HWTEST_F(WindowInputChannelTest, HandleKeyEvent, Function | SmallTest | Level2) +{ + auto keyEvent = MMI::KeyEvent::Create(); + sptr inputChannel = new WindowInputChannel(window_); + window_->ConsumeKeyEvent(keyEvent); + inputChannel->HandleKeyEvent(keyEvent); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_manager_agent_proxy_test.cpp b/window_manager/wm/test/unittest/window_manager_agent_proxy_test.cpp new file mode 100644 index 0000000..b634dbc --- /dev/null +++ b/window_manager/wm/test/unittest/window_manager_agent_proxy_test.cpp @@ -0,0 +1,122 @@ +/* + * 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 "window_manager_agent_proxy.h" +#include "window_manager_agent.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowManagerAgentProxyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr mockWindowManagerAgent_; + sptr windowManagerAgentProxy_; +}; + +void WindowManagerAgentProxyTest::SetUpTestCase() +{ +} + +void WindowManagerAgentProxyTest::TearDownTestCase() +{ +} + +void WindowManagerAgentProxyTest::SetUp() +{ + mockWindowManagerAgent_ = new WindowManagerAgent(); + windowManagerAgentProxy_ = new WindowManagerAgentProxy(mockWindowManagerAgent_); +} + +void WindowManagerAgentProxyTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: UpdateFocusChangeInfo01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, UpdateFocusChangeInfo01, Function | SmallTest | Level2) +{ + sptr focusChangeInfo; + windowManagerAgentProxy_->UpdateFocusChangeInfo(focusChangeInfo, false); +} + +/** + * @tc.name: UpdateFocusChangeInfo02 + * @tc.desc: test failed + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, UpdateFocusChangeInfo02, Function | SmallTest | Level2) +{ + sptr focusChangeInfo = nullptr; + windowManagerAgentProxy_->UpdateFocusChangeInfo(focusChangeInfo, false); +} + +/** + * @tc.name: UpdateSystemBarRegionTints01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, UpdateSystemBarRegionTints01, Function | SmallTest | Level2) +{ + SystemBarRegionTints tints; + windowManagerAgentProxy_->UpdateSystemBarRegionTints(0, tints); +} + +/** + * @tc.name: NotifyAccessibilityWindowInfo01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, NotifyAccessibilityWindowInfo01, Function | SmallTest | Level2) +{ + std::vector> info; + WindowUpdateType type = WindowUpdateType::WINDOW_UPDATE_ADDED; + windowManagerAgentProxy_->NotifyAccessibilityWindowInfo(info, type); +} + +/** + * @tc.name: UpdateWindowVisibilityInfo01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, UpdateWindowVisibilityInfo01, Function | SmallTest | Level2) +{ + std::vector> visibilityInfos; + windowManagerAgentProxy_->UpdateWindowVisibilityInfo(visibilityInfos); +} + +/** + * @tc.name: UpdateCameraFloatWindowStatus01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentProxyTest, UpdateCameraFloatWindowStatus01, Function | SmallTest | Level2) +{ + windowManagerAgentProxy_->UpdateCameraFloatWindowStatus(100, false); +} + +} +} +} diff --git a/window_manager/wm/test/unittest/window_manager_agent_stub_test.cpp b/window_manager/wm/test/unittest/window_manager_agent_stub_test.cpp new file mode 100644 index 0000000..08f6938 --- /dev/null +++ b/window_manager/wm/test/unittest/window_manager_agent_stub_test.cpp @@ -0,0 +1,200 @@ +/* + * 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 "window_manager_agent_stub.h" +#include "window_manager_agent.h" +#include "marshalling_helper.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowManagerAgentStubTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr stub_; +}; + +void WindowManagerAgentStubTest::SetUpTestCase() +{ +} + +void WindowManagerAgentStubTest::TearDownTestCase() +{ +} + +void WindowManagerAgentStubTest::SetUp() +{ + stub_ = new WindowManagerAgent(); +} + +void WindowManagerAgentStubTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnRemoteRequest01 + * @tc.desc: test InterfaceToken check failed + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentStubTest, OnRemoteRequest01, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(u"error.GetDescriptor"); + + uint32_t code = static_cast(IWindowManagerAgent::WindowManagerAgentMsg::TRANS_ID_UPDATE_FOCUS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, -1); +} + +/** + * @tc.name: OnRemoteRequest02 + * @tc.desc: test TRANS_ID_UPDATE_FOCUS + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentStubTest, OnRemoteRequest02, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerAgentStub::GetDescriptor()); + + sptr focusChangeInfo = new FocusChangeInfo(); + data.WriteParcelable(focusChangeInfo); + data.WriteRemoteObject(focusChangeInfo->abilityToken_); + data.WriteBool(false); + + uint32_t code = static_cast(IWindowManagerAgent::WindowManagerAgentMsg::TRANS_ID_UPDATE_FOCUS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest03 + * @tc.desc: test TRANS_ID_UPDATE_FOCUS success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentStubTest, OnRemoteRequest03, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerAgentStub::GetDescriptor()); + + uint32_t code = static_cast(IWindowManagerAgent::WindowManagerAgentMsg::TRANS_ID_UPDATE_FOCUS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest04 + * @tc.desc: test TRANS_ID_UPDATE_WINDOW_STATUS success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentStubTest, OnRemoteRequest04, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerAgentStub::GetDescriptor()); + + sptr info = new AccessibilityWindowInfo(); + std::vector> infos; + infos.emplace_back(info); + MarshallingHelper::MarshallingVectorParcelableObj(data, infos); + + data.WriteUint32(static_cast(WindowUpdateType::WINDOW_UPDATE_ADDED)); + + uint32_t code = static_cast(IWindowManagerAgent::WindowManagerAgentMsg::TRANS_ID_UPDATE_WINDOW_STATUS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest06 + * @tc.desc: test TRANS_ID_UPDATE_WINDOW_VISIBILITY success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentStubTest, OnRemoteRequest06, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerAgentStub::GetDescriptor()); + + sptr visibilityInfo = new WindowVisibilityInfo(); + std::vector> visibilityInfos; + visibilityInfos.emplace_back(visibilityInfo); + data.WriteUint32(static_cast(visibilityInfos.size())); + for (auto& info : visibilityInfos) { + data.WriteParcelable(info); + } + + auto code = static_cast(IWindowManagerAgent::WindowManagerAgentMsg::TRANS_ID_UPDATE_WINDOW_VISIBILITY); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest08 + * @tc.desc: test TRANS_ID_UPDATE_SYSTEM_BAR_PROPS success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerAgentStubTest, OnRemoteRequest08, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerAgentStub::GetDescriptor()); + + data.WriteUint64(0); + + SystemBarRegionTints tints; + MarshallingHelper::MarshallingVectorObj(data, tints, + [](Parcel& parcel, const SystemBarRegionTint& tint) { + return parcel.WriteUint32(static_cast(tint.type_)) && parcel.WriteBool(tint.prop_.enable_) && + parcel.WriteUint32(tint.prop_.backgroundColor_) && parcel.WriteUint32(tint.prop_.contentColor_) && + parcel.WriteInt32(tint.region_.posX_) && parcel.WriteInt32(tint.region_.posY_) && + parcel.WriteInt32(tint.region_.width_) && parcel.WriteInt32(tint.region_.height_); + } + ); + + uint32_t code = static_cast(IWindowManagerAgent::WindowManagerAgentMsg::TRANS_ID_UPDATE_SYSTEM_BAR_PROPS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +} +} +} diff --git a/window_manager/wm/test/unittest/window_manager_test.cpp b/window_manager/wm/test/unittest/window_manager_test.cpp new file mode 100644 index 0000000..9c0edaf --- /dev/null +++ b/window_manager/wm/test/unittest/window_manager_test.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2021-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 "window_manager.h" +#include "mock_window_adapter.h" +#include "singleton_mocker.h" + +#include "window_manager.cpp" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class TestCameraFloatWindowChangedListener : public ICameraFloatWindowChangedListener { +public: + void OnCameraFloatWindowChange(uint32_t accessTokenId, bool isShowing) override + { + WLOGFI("TestCameraFloatWindowChangedListener [%{public}u, %{public}u]", accessTokenId, isShowing); + }; +}; + +class TestVisibilityChangedListener : public IVisibilityChangedListener { +public: + void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override + { + WLOGFI("TestVisibilityChangedListener"); + }; +}; + +class TestSystemBarChangedListener : public ISystemBarChangedListener { +public: + void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override + { + WLOGFI("TestSystemBarChangedListener"); + }; +}; + +class TestWindowUpdateListener : public IWindowUpdateListener { +public: + void OnWindowUpdate(const std::vector>& infos, WindowUpdateType type) override + { + WLOGFI("TestWindowUpdateListener"); + }; +}; + +class WindowManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void WindowManagerTest::SetUpTestCase() +{ +} + +void WindowManagerTest::TearDownTestCase() +{ +} + +void WindowManagerTest::SetUp() +{ +} + +void WindowManagerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Create01 + * @tc.desc: Create window with no WindowName and no abilityToken + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, GetVisibilityWindowInfo01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + std::vector> infos; + infos.clear(); + EXPECT_CALL(m->Mock(), GetVisibilityWindowInfo(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, WindowManager::GetInstance().GetVisibilityWindowInfo(infos)); + EXPECT_CALL(m->Mock(), GetVisibilityWindowInfo(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_INVALID_WINDOW)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, WindowManager::GetInstance().GetVisibilityWindowInfo(infos)); +} + +/** + * @tc.name: Create01 + * @tc.desc: Create window with no WindowName and no abilityToken + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, GetAccessibilityWindowInfo01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + std::vector> infos; + infos.clear(); + EXPECT_CALL(m->Mock(), GetAccessibilityWindowInfo(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, WindowManager::GetInstance().GetAccessibilityWindowInfo(infos)); + EXPECT_CALL(m->Mock(), GetAccessibilityWindowInfo(_)).Times(1).WillOnce(Return(WMError::WM_ERROR_INVALID_WINDOW)); + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, WindowManager::GetInstance().GetAccessibilityWindowInfo(infos)); +} + +/** + * @tc.name: RegisterCameraFloatWindowChangedListener01 + * @tc.desc: check RegisterCameraFloatWindowChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, RegisterCameraFloatWindowChangedListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_; + auto oldListeners = windowManager.pImpl_->cameraFloatWindowChangedListeners_; + windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_ = nullptr; + windowManager.pImpl_->cameraFloatWindowChangedListeners_.clear(); + ASSERT_EQ(false, windowManager.RegisterCameraFloatWindowChangedListener(nullptr)); + + sptr listener = new TestCameraFloatWindowChangedListener(); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(false)); + ASSERT_EQ(false, windowManager.RegisterCameraFloatWindowChangedListener(listener)); + + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + ASSERT_EQ(true, windowManager.RegisterCameraFloatWindowChangedListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->cameraFloatWindowChangedListeners_.size()); + + // to check that the same listner can not be registered twice + ASSERT_EQ(true, windowManager.RegisterCameraFloatWindowChangedListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->cameraFloatWindowChangedListeners_.size()); + + windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->cameraFloatWindowChangedListeners_ = oldListeners; +} +/** + * @tc.name: UnregisterCameraFloatWindowChangedListener01 + * @tc.desc: check UnregisterCameraFloatWindowChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, UnregisterCameraFloatWindowChangedListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_; + auto oldListeners = windowManager.pImpl_->cameraFloatWindowChangedListeners_; + windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_ = new WindowManagerAgent(); + windowManager.pImpl_->cameraFloatWindowChangedListeners_.clear(); + + // check nullpter + ASSERT_EQ(false, windowManager.UnregisterCameraFloatWindowChangedListener(nullptr)); + + sptr listener1 = new TestCameraFloatWindowChangedListener(); + sptr listener2 = new TestCameraFloatWindowChangedListener(); + ASSERT_EQ(true, windowManager.UnregisterCameraFloatWindowChangedListener(listener1)); + + windowManager.RegisterCameraFloatWindowChangedListener(listener1); + windowManager.RegisterCameraFloatWindowChangedListener(listener2); + ASSERT_EQ(2, windowManager.pImpl_->cameraFloatWindowChangedListeners_.size()); + + ASSERT_EQ(true, windowManager.UnregisterCameraFloatWindowChangedListener(listener1)); + + ASSERT_EQ(false, windowManager.UnregisterCameraFloatWindowChangedListener(listener2)); + ASSERT_EQ(0, windowManager.pImpl_->cameraFloatWindowChangedListeners_.size()); + ASSERT_EQ(nullptr, windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_); + + windowManager.pImpl_->cameraFloatWindowChangedListeners_.emplace_back(listener1); + ASSERT_EQ(true, windowManager.UnregisterCameraFloatWindowChangedListener(listener1)); + ASSERT_EQ(0, windowManager.pImpl_->cameraFloatWindowChangedListeners_.size()); + + windowManager.pImpl_->cameraFloatWindowChangedListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->cameraFloatWindowChangedListeners_ = oldListeners; +} + +/** + * @tc.name: RegisterVisibilityChangedListener01 + * @tc.desc: check RegisterVisibilityChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, RegisterVisibilityChangedListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->windowVisibilityListenerAgent_; + auto oldListeners = windowManager.pImpl_->windowVisibilityListeners_; + windowManager.pImpl_->windowVisibilityListenerAgent_ = nullptr; + windowManager.pImpl_->windowVisibilityListeners_.clear(); + ASSERT_EQ(false, windowManager.RegisterVisibilityChangedListener(nullptr)); + + sptr listener = new TestVisibilityChangedListener(); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(false)); + ASSERT_EQ(false, windowManager.RegisterVisibilityChangedListener(listener)); + ASSERT_EQ(nullptr, windowManager.pImpl_->windowVisibilityListenerAgent_); + + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + ASSERT_EQ(true, windowManager.RegisterVisibilityChangedListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->windowVisibilityListeners_.size()); + + // to check that the same listner can not be registered twice + ASSERT_EQ(true, windowManager.RegisterVisibilityChangedListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->windowVisibilityListeners_.size()); + + windowManager.pImpl_->windowVisibilityListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->windowVisibilityListeners_ = oldListeners; +} +/** + * @tc.name: UnregisterVisibilityChangedListener01 + * @tc.desc: check UnregisterVisibilityChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, UnregisterVisibilityChangedListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->windowVisibilityListenerAgent_; + auto oldListeners = windowManager.pImpl_->windowVisibilityListeners_; + windowManager.pImpl_->windowVisibilityListenerAgent_ = new WindowManagerAgent(); + windowManager.pImpl_->windowVisibilityListeners_.clear(); + + // check nullpter + ASSERT_EQ(false, windowManager.UnregisterVisibilityChangedListener(nullptr)); + + sptr listener1 = new TestVisibilityChangedListener(); + sptr listener2 = new TestVisibilityChangedListener(); + + windowManager.RegisterVisibilityChangedListener(listener1); + windowManager.RegisterVisibilityChangedListener(listener2); + ASSERT_EQ(2, windowManager.pImpl_->windowVisibilityListeners_.size()); + + ASSERT_EQ(true, windowManager.UnregisterVisibilityChangedListener(listener1)); + ASSERT_EQ(false, windowManager.UnregisterVisibilityChangedListener(listener2)); + ASSERT_EQ(0, windowManager.pImpl_->windowVisibilityListeners_.size()); + ASSERT_EQ(nullptr, windowManager.pImpl_->windowVisibilityListenerAgent_); + + windowManager.pImpl_->windowVisibilityListeners_.emplace_back(listener1); + ASSERT_EQ(true, windowManager.UnregisterVisibilityChangedListener(listener1)); + ASSERT_EQ(0, windowManager.pImpl_->windowVisibilityListeners_.size()); + + windowManager.pImpl_->windowVisibilityListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->windowVisibilityListeners_ = oldListeners; +} + +/** + * @tc.name: RegisterWindowUpdateListener01 + * @tc.desc: check RegisterWindowUpdateListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, RegisterWindowUpdateListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->windowUpdateListenerAgent_; + auto oldListeners = windowManager.pImpl_->windowUpdateListeners_; + windowManager.pImpl_->windowUpdateListenerAgent_ = nullptr; + windowManager.pImpl_->windowUpdateListeners_.clear(); + ASSERT_EQ(false, windowManager.RegisterWindowUpdateListener(nullptr)); + + sptr listener = new TestWindowUpdateListener(); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(false)); + ASSERT_EQ(false, windowManager.RegisterWindowUpdateListener(listener)); + ASSERT_EQ(nullptr, windowManager.pImpl_->windowUpdateListenerAgent_); + + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + ASSERT_EQ(true, windowManager.RegisterWindowUpdateListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->windowUpdateListeners_.size()); + + // to check that the same listner can not be registered twice + ASSERT_EQ(true, windowManager.RegisterWindowUpdateListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->windowUpdateListeners_.size()); + + windowManager.pImpl_->windowUpdateListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->windowUpdateListeners_ = oldListeners; +} +/** + * @tc.name: UnregisterWindowUpdateListener01 + * @tc.desc: check UnregisterWindowUpdateListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, UnregisterWindowUpdateListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->windowUpdateListenerAgent_; + auto oldListeners = windowManager.pImpl_->windowUpdateListeners_; + windowManager.pImpl_->windowUpdateListenerAgent_ = new WindowManagerAgent(); + windowManager.pImpl_->windowUpdateListeners_.clear(); + + // check nullpter + ASSERT_EQ(false, windowManager.UnregisterWindowUpdateListener(nullptr)); + + sptr listener1 = new TestWindowUpdateListener(); + sptr listener2 = new TestWindowUpdateListener(); + ASSERT_EQ(true, windowManager.UnregisterWindowUpdateListener(listener1)); + + windowManager.RegisterWindowUpdateListener(listener1); + windowManager.RegisterWindowUpdateListener(listener2); + ASSERT_EQ(2, windowManager.pImpl_->windowUpdateListeners_.size()); + + ASSERT_EQ(true, windowManager.UnregisterWindowUpdateListener(listener1)); + + ASSERT_EQ(false, windowManager.UnregisterWindowUpdateListener(listener2)); + ASSERT_EQ(0, windowManager.pImpl_->windowUpdateListeners_.size()); + ASSERT_EQ(nullptr, windowManager.pImpl_->windowUpdateListenerAgent_); + + windowManager.pImpl_->windowUpdateListeners_.emplace_back(listener1); + ASSERT_EQ(true, windowManager.UnregisterWindowUpdateListener(listener1)); + ASSERT_EQ(0, windowManager.pImpl_->windowUpdateListeners_.size()); + + windowManager.pImpl_->windowUpdateListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->windowUpdateListeners_ = oldListeners; +} + +/** + * @tc.name: RegisterSystemBarChangedListener01 + * @tc.desc: check RegisterSystemBarChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, RegisterSystemBarChangedListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->systemBarChangedListenerAgent_; + auto oldListeners = windowManager.pImpl_->systemBarChangedListeners_; + windowManager.pImpl_->systemBarChangedListenerAgent_ = nullptr; + windowManager.pImpl_->systemBarChangedListeners_.clear(); + ASSERT_EQ(false, windowManager.RegisterSystemBarChangedListener(nullptr)); + + sptr listener = new TestSystemBarChangedListener(); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(false)); + ASSERT_EQ(false, windowManager.RegisterSystemBarChangedListener(listener)); + ASSERT_EQ(nullptr, windowManager.pImpl_->systemBarChangedListenerAgent_); + + EXPECT_CALL(m->Mock(), RegisterWindowManagerAgent(_, _)).Times(1).WillOnce(Return(true)); + ASSERT_EQ(true, windowManager.RegisterSystemBarChangedListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->systemBarChangedListeners_.size()); + + // to check that the same listner can not be registered twice + ASSERT_EQ(true, windowManager.RegisterSystemBarChangedListener(listener)); + ASSERT_EQ(1, windowManager.pImpl_->systemBarChangedListeners_.size()); + + windowManager.pImpl_->systemBarChangedListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->systemBarChangedListeners_ = oldListeners; +} +/** + * @tc.name: UnregisterSystemBarChangedListener01 + * @tc.desc: check UnregisterSystemBarChangedListener + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, UnregisterSystemBarChangedListener01, Function | SmallTest | Level2) +{ + auto& windowManager = WindowManager::GetInstance(); + auto oldWindowManagerAgent = windowManager.pImpl_->systemBarChangedListenerAgent_; + auto oldListeners = windowManager.pImpl_->systemBarChangedListeners_; + windowManager.pImpl_->systemBarChangedListenerAgent_ = new WindowManagerAgent(); + windowManager.pImpl_->systemBarChangedListeners_.clear(); + // check nullpter + ASSERT_EQ(false, windowManager.UnregisterSystemBarChangedListener(nullptr)); + + sptr listener1 = new TestSystemBarChangedListener(); + sptr listener2 = new TestSystemBarChangedListener(); + ASSERT_EQ(true, windowManager.UnregisterSystemBarChangedListener(listener1)); + + windowManager.RegisterSystemBarChangedListener(listener1); + windowManager.RegisterSystemBarChangedListener(listener2); + ASSERT_EQ(2, windowManager.pImpl_->systemBarChangedListeners_.size()); + + + ASSERT_EQ(true, windowManager.UnregisterSystemBarChangedListener(listener1)); + ASSERT_EQ(false, windowManager.UnregisterSystemBarChangedListener(listener2)); + ASSERT_EQ(0, windowManager.pImpl_->systemBarChangedListeners_.size()); + ASSERT_EQ(nullptr, windowManager.pImpl_->systemBarChangedListenerAgent_); + + windowManager.pImpl_->systemBarChangedListeners_.push_back(listener1); + ASSERT_EQ(true, windowManager.UnregisterSystemBarChangedListener(listener1)); + ASSERT_EQ(0, windowManager.pImpl_->systemBarChangedListeners_.size()); + + windowManager.pImpl_->systemBarChangedListenerAgent_ = oldWindowManagerAgent; + windowManager.pImpl_->systemBarChangedListeners_ = oldListeners; +} +/** + * @tc.name: ToggleShownStateForAllAppWindows + * @tc.desc: ToggleShownStateForAllAppWindows ok + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerTest, ToggleShownStateForAllAppWindows, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), ToggleShownStateForAllAppWindows()).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, WindowManager::GetInstance().ToggleShownStateForAllAppWindows()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_option_test.cpp b/window_manager/wm/test/unittest/window_option_test.cpp new file mode 100644 index 0000000..fb8da6c --- /dev/null +++ b/window_manager/wm/test/unittest/window_option_test.cpp @@ -0,0 +1,366 @@ +/* + * 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 "window_option.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + const SystemBarProperty SYS_BAR_PROP_DEFAULT; + const SystemBarProperty SYS_BAR_PROP_1(true, 0xE5111111, 0xE5222222); + const SystemBarProperty SYS_BAR_PROP_2(false, 0xE5222222, 0xE5333333); + const std::unordered_map& SYS_BAR_PROPS_TEST = { + { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_1 }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_2 }, + }; + const std::unordered_map& SYS_BAR_PROPS_DEFAULT = { + { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_DEFAULT }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_DEFAULT }, + }; +} +class WindowOptionTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; +void WindowOptionTest::SetUpTestCase() +{ +} + +void WindowOptionTest::TearDownTestCase() +{ +} + +void WindowOptionTest::SetUp() +{ +} + +void WindowOptionTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowRect01 + * @tc.desc: SetWindowRect/GetWindowRect + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowRect01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + struct Rect rect = {1, 2, 3u, 4u}; + option->SetWindowRect(rect); + + ASSERT_EQ(1, option->GetWindowRect().posX_); + ASSERT_EQ(2, option->GetWindowRect().posY_); + ASSERT_EQ(3u, option->GetWindowRect().width_); + ASSERT_EQ(4u, option->GetWindowRect().height_); +} + +/** + * @tc.name: WindowType01 + * @tc.desc: SetWindowType/GetWindowType + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowType01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + ASSERT_EQ(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, option->GetWindowType()); +} + +/** + * @tc.name: WindowMode01 + * @tc.desc: SetWindowMode/GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowMode01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, option->GetWindowMode()); +} + +/** + * @tc.name: WindowMode02 + * @tc.desc: SetWindowMode/GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowMode02, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + WindowMode defaultMode = option->GetWindowMode(); + option->SetWindowMode(WindowMode::WINDOW_MODE_UNDEFINED); + ASSERT_EQ(defaultMode, option->GetWindowMode()); +} + +/** + * @tc.name: WindowMode03 + * @tc.desc: SetWindowMode/GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowMode03, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, option->GetWindowMode()); +} + +/** + * @tc.name: WindowMode04 + * @tc.desc: SetWindowMode/GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowMode04, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, option->GetWindowMode()); +} + +/** + * @tc.name: WindowMode05 + * @tc.desc: SetWindowMode/GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowMode05, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, option->GetWindowMode()); +} + +/** + * @tc.name: WindowMode06 + * @tc.desc: SetWindowMode/GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowMode06, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowMode(WindowMode::WINDOW_MODE_PIP); + ASSERT_EQ(WindowMode::WINDOW_MODE_PIP, option->GetWindowMode()); +} +/** + * @tc.name: Focusable01 + * @tc.desc: SetFocusable/GetFocusable + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, Focusable01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetFocusable(true); + ASSERT_EQ(true, option->GetFocusable()); +} + +/** + * @tc.name: Touchable01 + * @tc.desc: SetTouchable/GetTouchable + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, Touchable01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetTouchable(true); + ASSERT_EQ(true, option->GetTouchable()); +} + +/** + * @tc.name: DisplayId01 + * @tc.desc: SetDisplayId/GetDisplayId + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, DisplayId01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetDisplayId(1); + ASSERT_EQ(1, option->GetDisplayId()); +} + +/** + * @tc.name: ParentId01 + * @tc.desc: SetParentId/GetParentId + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, ParentId01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetParentId(1); + ASSERT_EQ(1, option->GetParentId()); +} + +/** + * @tc.name: WindowName01 + * @tc.desc: SetWindowName/GetWindowName + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowName01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowName("Sub Window"); + ASSERT_EQ("Sub Window", option->GetWindowName()); +} + +/** + * @tc.name: WindowFlag01 + * @tc.desc: SetWindowFlags/GetWindowFlags + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowFlag01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->SetWindowFlags(1u); + ASSERT_EQ(1u, option->GetWindowFlags()); +} + +/** + * @tc.name: WindowFlag02 + * @tc.desc: AddWindowFlag/GetWindowFlags + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowFlag02, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + ASSERT_EQ(static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID), option->GetWindowFlags()); +} + +/** + * @tc.name: WindowFlag03 + * @tc.desc: AddWindowFlag/RemoveWindowFlag/GetWindowFlags + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, WindowFlag03, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + option->AddWindowFlag(WindowFlag::WINDOW_FLAG_PARENT_LIMIT); + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + ASSERT_EQ(static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT), option->GetWindowFlags()); +} + +/** + * @tc.name: SetGetSystemBarProperty01 + * @tc.desc: SetSystemBarProperty with test param and get + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, SetGetSystemBarProperty01, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_1); + option->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_2); + ASSERT_EQ(SYS_BAR_PROPS_TEST, option->GetSystemBarProperty()); +} + +/** + * @tc.name: SetGetSystemBarProperty02 + * @tc.desc: SetSystemBarProperty with invalid type and get + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, SetGetSystemBarProperty02, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetSystemBarProperty(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, SYS_BAR_PROP_1); + option->SetSystemBarProperty(WindowType::WINDOW_TYPE_MEDIA, SYS_BAR_PROP_2); + ASSERT_EQ(SYS_BAR_PROPS_DEFAULT, option->GetSystemBarProperty()); +} + +/** + * @tc.name: SetGetSystemBarProperty03 + * @tc.desc: GetSystemBarProperty with no set + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, SetGetSystemBarProperty03, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + ASSERT_EQ(SYS_BAR_PROPS_DEFAULT, option->GetSystemBarProperty()); +} + +/** + * @tc.name: HitOffset + * @tc.desc: HitOffset setter/getter test + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, HitOffset, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetHitOffset(1, 1); + PointInfo point = {1, 1}; + ASSERT_EQ(point.x, option->GetHitOffset().x); + ASSERT_EQ(point.y, option->GetHitOffset().y); +} + +/** + * @tc.name: KeepScreenOn + * @tc.desc: KeepScreenOn setter/getter test + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, KeepScreenOn, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetKeepScreenOn(true); + ASSERT_EQ(true, option->IsKeepScreenOn()); + option->SetKeepScreenOn(false); + ASSERT_EQ(false, option->IsKeepScreenOn()); +} + +/** + * @tc.name: TurnScreenOn + * @tc.desc: TurnScreenOn setter/getter test + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, TurnScreenOn, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetTurnScreenOn(true); + ASSERT_EQ(true, option->IsTurnScreenOn()); + option->SetTurnScreenOn(false); + ASSERT_EQ(false, option->IsTurnScreenOn()); +} + +/** + * @tc.name: Brightness + * @tc.desc: Brightness setter/getter test + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, Brightness, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetBrightness(MINIMUM_BRIGHTNESS); + ASSERT_EQ(MINIMUM_BRIGHTNESS, option->GetBrightness()); + option->SetBrightness(MAXIMUM_BRIGHTNESS); + ASSERT_EQ(MAXIMUM_BRIGHTNESS, option->GetBrightness()); +} + +/** + * @tc.name: CallingWindow + * @tc.desc: CallingWindow setter/getter test + * @tc.type: FUNC + */ +HWTEST_F(WindowOptionTest, CallingWindow, Function | SmallTest | Level3) +{ + sptr option = new WindowOption(); + option->SetCallingWindow(1); + ASSERT_EQ(1, option->GetCallingWindow()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wm/test/unittest/window_proxy_test.cpp b/window_manager/wm/test/unittest/window_proxy_test.cpp new file mode 100644 index 0000000..3fb124d --- /dev/null +++ b/window_manager/wm/test/unittest/window_proxy_test.cpp @@ -0,0 +1,299 @@ +/* + * 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 "window_proxy.h" + +#include "window_agent.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowProxyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr mockWindowAgent_; + sptr windowProxy_; +}; + +void WindowProxyTest::SetUpTestCase() +{ +} + +void WindowProxyTest::TearDownTestCase() +{ +} + +void WindowProxyTest::SetUp() +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + mockWindowAgent_ = new WindowAgent(window); + windowProxy_ = new WindowProxy(mockWindowAgent_); +} + +void WindowProxyTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: UpdateWindowRect01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateWindowRect01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateWindowRect(Rect {0, 0, 0, 0}, false, WindowSizeChangeReason::HIDE); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateWindowMode01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateWindowMode01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateWindowModeSupportInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateWindowModeSupportInfo01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateWindowModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateFocusStatus01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateFocusStatus01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateFocusStatus(false); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateAvoidArea01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateAvoidArea01, Function | SmallTest | Level2) +{ + const sptr& avoidArea = new AvoidArea(); + WMError err = windowProxy_->UpdateAvoidArea(avoidArea, AvoidAreaType::TYPE_SYSTEM); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateWindowState01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateWindowState01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateWindowState(WindowState::STATE_BOTTOM); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateWindowDragInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateWindowDragInfo01, Function | SmallTest | Level2) +{ + PointInfo point; + point.x = 1; + point.y = 2; + WMError err = windowProxy_->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_MOVE); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateDisplayId01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateDisplayId01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateDisplayId(0, 1); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateOccupiedAreaChangeInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateOccupiedAreaChangeInfo01, Function | SmallTest | Level2) +{ + Rect overlapRect = {0, 0, 0, 0}; + sptr info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT, overlapRect); + WMError err = windowProxy_->UpdateOccupiedAreaChangeInfo(info); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateActiveStatus01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateActiveStatus01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->UpdateActiveStatus(false); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: GetWindowProperty01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, GetWindowProperty01, Function | SmallTest | Level2) +{ + ASSERT_TRUE(windowProxy_->GetWindowProperty() == nullptr); +} + +/** + * @tc.name: NotifyTouchOutside01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyTouchOutside01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->NotifyTouchOutside(); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: DumpInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, DumpInfo01, Function | SmallTest | Level2) +{ + std::vector params; + WMError err = windowProxy_->DumpInfo(params); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: NotifyDestroy01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyDestroy01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->NotifyDestroy(); + ASSERT_EQ(err, WMError::WM_OK); +} + + +/** + * @tc.name: NotifyForeground01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyForeground01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->NotifyForeground(); + ASSERT_EQ(err, WMError::WM_OK); +} + + +/** + * @tc.name: NotifyBackground01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyBackground01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->NotifyBackground(); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: NotifyWindowClientPointUp01 + * @tc.desc: param is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyWindowClientPointUp01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->NotifyWindowClientPointUp(nullptr); + ASSERT_EQ(err, WMError::WM_ERROR_NULLPTR); +} + +/** + * @tc.name: NotifyWindowClientPointUp02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyWindowClientPointUp02, Function | SmallTest | Level2) +{ + auto pointerEvent = MMI::PointerEvent::Create(); + WMError err = windowProxy_->NotifyWindowClientPointUp(pointerEvent); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: UpdateZoomTransform01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, UpdateZoomTransform01, Function | SmallTest | Level2) +{ + Transform transform; + WMError err = windowProxy_->UpdateZoomTransform(transform, false); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: RestoreSplitWindowMode01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, RestoreSplitWindowMode01, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->RestoreSplitWindowMode(200); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: NotifyScreenshot + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(WindowProxyTest, NotifyScreenshot, Function | SmallTest | Level2) +{ + WMError err = windowProxy_->NotifyScreenshot(); + ASSERT_EQ(err, WMError::WM_OK); +} + +} +} +} diff --git a/window_manager/wm/test/unittest/window_scene_test.cpp b/window_manager/wm/test/unittest/window_scene_test.cpp new file mode 100644 index 0000000..ebcb66b --- /dev/null +++ b/window_manager/wm/test/unittest/window_scene_test.cpp @@ -0,0 +1,419 @@ +/* + * 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 "window_scene.h" +#include "ability_context_impl.h" +#include "mock_static_call.h" +#include "singleton_mocker.h" +#include "window_impl.h" +#include + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class WindowSceneTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + sptr scene_ = nullptr; + std::shared_ptr abilityContext_; +}; +void WindowSceneTest::SetUpTestCase() +{ +} + +void WindowSceneTest::TearDownTestCase() +{ +} + +void WindowSceneTest::SetUp() +{ + DisplayId displayId = 0; + sptr listener = nullptr; + scene_ = new WindowScene(); + abilityContext_ = std::make_shared(); + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(option))); + ASSERT_EQ(WMError::WM_OK, scene_->Init(displayId, abilityContext_, listener)); +} + +void WindowSceneTest::TearDown() +{ + scene_->GoDestroy(); + scene_ = nullptr; + abilityContext_ = nullptr; +} + +namespace { +/** + * @tc.name: Init01 + * @tc.desc: Init Scene with null abilityContext, null listener + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Init01, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext, listener)); +} + +/** + * @tc.name: Init02 + * @tc.desc: Mock window Create Static Method return nullptr, init Scene with null abilityContext, null listener + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Init02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(nullptr)); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->Init(displayId, abilityContext, listener)); +} + +/** + * @tc.name: Init03 + * @tc.desc: Init Scene with abilityContext, null listener + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Init03, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext_, listener)); +} + +/** + * @tc.name: Create01 + * @tc.desc: CreateWindow without windowName + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Create01, Function | SmallTest | Level2) +{ + sptr optionTest = new WindowOption(); + sptr scene = new WindowScene(); + ASSERT_EQ(nullptr, scene->CreateWindow("", optionTest)); +} + +/** + * @tc.name: Create02 + * @tc.desc: CreateWindow with windowName and without mainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Create02, Function | SmallTest | Level2) +{ + sptr optionTest = new WindowOption(); + sptr scene = new WindowScene(); + ASSERT_EQ(nullptr, scene->CreateWindow("WindowSceneTest02", optionTest)); +} + +/** + * @tc.name: Create03 + * @tc.desc: CreateWindow with windowName and mainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Create03, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + ASSERT_NE(nullptr, scene_->CreateWindow("WindowSceneTest03", optionTest)); +} + +/** + * @tc.name: Create04 + * @tc.desc: Mock window Create Static Method return nullptr, createWindow with windowName and mainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Create04, Function | SmallTest | Level2) +{ + sptr optionTest = new WindowOption(); + std::unique_ptr m = std::make_unique(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(nullptr)); + ASSERT_EQ(nullptr, scene_->CreateWindow("WindowSceneTest04", optionTest)); +} + +/** + * @tc.name: Create05 + * @tc.desc: createWindow with windowName and null option + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, Create05, Function | SmallTest | Level2) +{ + sptr optionTest = nullptr; + ASSERT_EQ(nullptr, scene_->CreateWindow("WindowSceneTest05", optionTest)); +} + +/** + * @tc.name: GetMainWindow01 + * @tc.desc: GetMainWindow without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GetMainWindow01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + ASSERT_EQ(nullptr, scene->GetMainWindow()); +} + +/** + * @tc.name: GetMainWindow02 + * @tc.desc: GetMainWindow01 with nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GetMainWindow02, Function | SmallTest | Level2) +{ + ASSERT_NE(nullptr, scene_->GetMainWindow()); +} + +/** + * @tc.name: GetSubWindow01 + * @tc.desc: GetSubWindow without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GetSubWindow01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + std::vector> subWindows = scene->GetSubWindow(); + ASSERT_TRUE(subWindows.empty()); +} + +/** + * @tc.name: GetSubWindow02 + * @tc.desc: GetSubWindow without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GetSubWindow02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext, listener)); + std::vector> subWindows = scene->GetSubWindow(); + ASSERT_TRUE(subWindows.empty()); +} + +/** + * @tc.name: OnNewWant01 + * @tc.desc: OnNewWant nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, OnNewWant01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + AAFwk::Want want; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->OnNewWant(want)); +} + +/** + * @tc.name: OnNewWant02 + * @tc.desc: OnNewWant without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, OnNewWant02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext, listener)); + AAFwk::Want want; + ASSERT_EQ(WMError::WM_OK, scene->OnNewWant(want)); +} + +/** + * @tc.name: UpdateConfiguration01 + * @tc.desc: UpdateConfiguration nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, UpdateConfiguration01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + std::shared_ptr configuration = nullptr; + scene->UpdateConfiguration(configuration); +} + +/** + * @tc.name: UpdateConfiguration02 + * @tc.desc: UpdateConfiguration without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, UpdateConfiguration02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext, listener)); + std::shared_ptr configuration = std::make_shared(); + scene->UpdateConfiguration(configuration); +} + +/** + * @tc.name: GetContentInfo01 + * @tc.desc: GetContentInfo nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GetContentInfo01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + ASSERT_EQ("", scene->GetContentInfo()); +} + +/** + * @tc.name: GetContentInfo02 + * @tc.desc: GetContentInfo without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GetContentInfo02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext, listener)); + ASSERT_EQ("", scene->GetContentInfo()); +} + +/** + * @tc.name: SetSystemBarProperty01 + * @tc.desc: SetSystemBarProperty nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, SetSystemBarProperty01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + WindowType type = WindowType::WINDOW_TYPE_DIALOG; + SystemBarProperty property; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->SetSystemBarProperty(type, property)); +} + +/** + * @tc.name: SetSystemBarProperty02 + * @tc.desc: SetSystemBarProperty without scene init + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, SetSystemBarProperty02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr optionTest = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(optionTest))); + DisplayId displayId = 0; + sptr listener = nullptr; + sptr scene = new WindowScene(); + std::shared_ptr abilityContext = nullptr; + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext, listener)); + WindowType type = WindowType::WINDOW_TYPE_DIALOG; + SystemBarProperty property; + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, scene->SetSystemBarProperty(type, property)); +} + +/** + * @tc.name: GoForeground01 + * @tc.desc: GoForeground01 without mainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GoForeground01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->GoForeground()); +} + +/** + * @tc.name: GoBackground01 + * @tc.desc: GoBackground01 without mainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, GoBackground01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->GoBackground()); +} + +/** + * @tc.name: RequestFocus01 + * @tc.desc: RequestFocus01 without mainWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowSceneTest, RequestFocus01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->RequestFocus()); +} + +/** + * @tc.name: NotifyMemoryLevel01 + * @tc.desc: NotifyMemoryLevel without mainWindow + * @tc.type: FUNC + * @tc.require: issueI5JQ04 + */ +HWTEST_F(WindowSceneTest, NotifyMemoryLevel01, Function | SmallTest | Level2) +{ + sptr scene = new WindowScene(); + int32_t level = 0; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->NotifyMemoryLevel(level)); +} + +/** + * @tc.name: NotifyMemoryLevel02 + * @tc.desc: NotifyMemoryLevel with level + * @tc.type: FUNC + * @tc.require: issueI5JQ04 + */ +HWTEST_F(WindowSceneTest, NotifyMemoryLevel02, Function | SmallTest | Level2) +{ + DisplayId displayId = 0; + std::unique_ptr m = std::make_unique(); + sptr listener = nullptr; + sptr scene = new WindowScene(); + sptr option = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _)).Times(1).WillOnce(Return(new WindowImpl(option))); + ASSERT_EQ(WMError::WM_OK, scene->Init(displayId, abilityContext_, listener)); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, scene->NotifyMemoryLevel(0)); // ui content is null +} +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wm/test/unittest/window_stub_test.cpp b/window_manager/wm/test/unittest/window_stub_test.cpp new file mode 100644 index 0000000..30ac50c --- /dev/null +++ b/window_manager/wm/test/unittest/window_stub_test.cpp @@ -0,0 +1,242 @@ +/* + * 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 "window_stub.h" +#include "window_agent.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowStubTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr windowStub_; +}; + +void WindowStubTest::SetUpTestCase() +{ +} + +void WindowStubTest::TearDownTestCase() +{ +} + +void WindowStubTest::SetUp() +{ + sptr option = new WindowOption(); + sptr window = new WindowImpl(option); + windowStub_ = new WindowAgent(window); +} + +void WindowStubTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnRemoteRequest01 + * @tc.desc: test InterfaceToken check failed + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest01, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(u"error.GetDescriptor"); + + data.WriteInt32(0); + data.WriteInt32(0); + data.WriteUint32(100); + data.WriteUint32(100); + + data.WriteBool(false); + + data.WriteUint32(static_cast(WindowSizeChangeReason::DRAG_START)); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_UPDATE_WINDOW_RECT); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, -1); +} + +/** + * @tc.name: OnRemoteRequest02 + * @tc.desc: test TRANS_ID_UPDATE_WINDOW_RECT + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest02, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + + data.WriteInt32(0); + data.WriteInt32(0); + data.WriteUint32(100); + data.WriteUint32(100); + + data.WriteBool(false); + + data.WriteUint32(static_cast(WindowSizeChangeReason::DRAG_START)); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_UPDATE_WINDOW_RECT); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest03 + * @tc.desc: test TRANS_ID_UPDATE_AVOID_AREA success + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest03, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + + sptr avoidArea = new AvoidArea(); + data.WriteStrongParcelable(avoidArea); + + data.WriteUint32(static_cast(AvoidAreaType::TYPE_SYSTEM)); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_UPDATE_AVOID_AREA); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest04 + * @tc.desc: test TRANS_ID_UPDATE_AVOID_AREA success + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest04, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + + sptr avoidArea = new AvoidArea(); + data.WriteStrongParcelable(avoidArea); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_UPDATE_AVOID_AREA); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, -1); +} + +/** + * @tc.name: OnRemoteRequest05 + * @tc.desc: test TRANS_ID_DUMP_INFO success + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest05, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + + std::vector params; + params.push_back("-a"); + data.WriteStringVector(params); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_DUMP_INFO); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest06 + * @tc.desc: test TRANS_ID_DUMP_INFO failed + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest06, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + data.WriteRawData(nullptr, 0); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_DUMP_INFO); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + + +/** + * @tc.name: OnRemoteRequest07 + * @tc.desc: test TRANS_ID_NOTIFY_CLIENT_POINT_UP success + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest07, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + pointerEvent->WriteToParcel(data); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_NOTIFY_CLIENT_POINT_UP); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest08 + * @tc.desc: test TRANS_ID_NOTIFY_CLIENT_POINT_UP success + * @tc.type: FUNC + */ +HWTEST_F(WindowStubTest, OnRemoteRequest08, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowStub::GetDescriptor()); + + uint32_t code = static_cast(IWindow::WindowMessage::TRANS_ID_NOTIFY_CLIENT_POINT_UP); + + int res = windowStub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, -1); +} + +} +} +} diff --git a/window_manager/wm/test/unittest/window_test.cpp b/window_manager/wm/test/unittest/window_test.cpp new file mode 100644 index 0000000..d75d75d --- /dev/null +++ b/window_manager/wm/test/unittest/window_test.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-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 "ability_context_impl.h" +#include "window.h" +#include "mock_window_adapter.h" +#include "singleton_mocker.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using Mocker = SingletonMocker; +class WindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static inline std::shared_ptr abilityContext_; +}; +void WindowTest::SetUpTestCase() +{ + abilityContext_ = std::make_shared(); +} + +void WindowTest::TearDownTestCase() +{ +} + +void WindowTest::SetUp() +{ +} + +void WindowTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Create01 + * @tc.desc: Create window with no WindowName and no abilityToken + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, Create01, Function | SmallTest | Level2) +{ + sptr option = new WindowOption(); + ASSERT_EQ(nullptr, Window::Create("", option)); +} + +/** + * @tc.name: Create02 + * @tc.desc: Create window with WindowName and no abilityToken + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, Create02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + auto window = Window::Create("WindowTest02", option); + ASSERT_NE(nullptr, window); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: Create03 + * @tc.desc: Mock CreateWindow return WM_ERROR_SAMGR, create window with WindowName and no abilityToken + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, Create03, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_ERROR_SAMGR)); + ASSERT_EQ(nullptr, Window::Create("WindowTest03", option)); +} + +/** + * @tc.name: Create06 + * @tc.desc: Create window with WindowName and no option + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, Create06, Function | SmallTest | Level2) +{ + sptr option = nullptr; + ASSERT_EQ(nullptr, Window::Create("", option)); +} + +/** + * @tc.name: Find01 + * @tc.desc: Find with no name + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, Find01, Function | SmallTest | Level2) +{ + ASSERT_EQ(nullptr, Window::Find("")); +} + +/** + * @tc.name: Find02 + * @tc.desc: Find with name + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, Find02, Function | SmallTest | Level2) +{ + std::unique_ptr m = std::make_unique(); + sptr option = new WindowOption(); + EXPECT_CALL(m->Mock(), CreateWindow(_, _, _, _, _)).Times(1).WillOnce(Return(WMError::WM_OK)); + auto window = Window::Create("WindowTest03", option); + ASSERT_NE(nullptr, window); + ASSERT_NE(nullptr, Window::Find("WindowTest03")); + EXPECT_CALL(m->Mock(), DestroyWindow(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/BUILD.gn b/window_manager/wmserver/BUILD.gn new file mode 100644 index 0000000..4ae1f29 --- /dev/null +++ b/window_manager/wmserver/BUILD.gn @@ -0,0 +1,122 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") +config("libwms_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "include/window_snapshot", + "//utils/system/safwk/native/include", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/interfaces/innerkits/dm", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/utils/include", + "//foundation/window/window_manager/dm/include", + "//foundation/window/window_manager/dmserver/include", + ] +} + +ohos_shared_library("libwms") { + if (use_musl) { + if (use_jemalloc && use_jemalloc_dfx_intf) { + defines = [ "CONFIG_USE_JEMALLOC_DFX_INTF" ] + } + } + sources = [ + "../wm/src/zidl/window_manager_agent_proxy.cpp", + "../wm/src/zidl/window_proxy.cpp", + "src/accessibility_connection.cpp", + "src/avoid_area_controller.cpp", + "src/display_group_controller.cpp", + "src/display_group_info.cpp", + "src/display_zoom_controller.cpp", + "src/drag_controller.cpp", + "src/freeze_controller.cpp", + "src/inner_window.cpp", + "src/input_window_monitor.cpp", + "src/memory_guard.cpp", + "src/minimize_app.cpp", + "src/remote_animation.cpp", + "src/starting_window.cpp", + "src/window_common_event.cpp", + "src/window_controller.cpp", + "src/window_dumper.cpp", + "src/window_inner_manager.cpp", + "src/window_layout_policy.cpp", + "src/window_layout_policy_cascade.cpp", + "src/window_layout_policy_tile.cpp", + "src/window_manager_agent_controller.cpp", + "src/window_manager_config.cpp", + "src/window_manager_service.cpp", + "src/window_node.cpp", + "src/window_node_container.cpp", + "src/window_node_state_machine.cpp", + "src/window_pair.cpp", + "src/window_root.cpp", + "src/window_snapshot/snapshot_controller.cpp", + "src/window_snapshot/snapshot_proxy.cpp", + "src/window_snapshot/snapshot_stub.cpp", + "src/window_zorder_policy.cpp", + "src/zidl/ressched_report.cpp", + "src/zidl/window_manager_stub.cpp", + ] + + configs = [ + ":libwms_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + ] + + deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/etc:wms_etc", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//third_party/libxml2:libxml2", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", + "display_manager:displaymgr", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hicollie_native:libhicollie", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + "power_manager:powermgr_client", + "safwk:system_ability_fwk", + ] + + if (is_standard_system) { + external_deps += [ "init:libbegetutil" ] + } else { + external_deps += [ "init_lite:libbegetutil" ] + } + + part_name = "window_manager" + subsystem_name = "window" +} + +group("test") { + testonly = true + deps = [ "test:test" ] +} diff --git a/window_manager/wmserver/include/README.md b/window_manager/wmserver/include/README.md new file mode 100644 index 0000000..5392499 --- /dev/null +++ b/window_manager/wmserver/include/README.md @@ -0,0 +1 @@ +Store code of window sever inner header files \ No newline at end of file diff --git a/window_manager/wmserver/include/accessibility_connection.h b/window_manager/wmserver/include/accessibility_connection.h new file mode 100644 index 0000000..b36db5d --- /dev/null +++ b/window_manager/wmserver/include/accessibility_connection.h @@ -0,0 +1,49 @@ +/* + * 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_ROSEN_ACCESSIBILITY_CONNECTION_H +#define OHOS_ROSEN_ACCESSIBILITY_CONNECTION_H + +#include +#include +#include + +#include "window_node.h" +#include "window_root.h" +#include "window_node_container.h" +#include "wm_common.h" + +namespace OHOS::Rosen { +class AccessibilityConnection : public RefBase { +public: + explicit AccessibilityConnection(sptr& root) : windowRoot_(root) {} + ~AccessibilityConnection() = default; + void NotifyAccessibilityWindowInfo(const sptr& node, WindowUpdateType type); + void NotifyAccessibilityWindowInfo(DisplayId displayId, const std::vector>& nodes, + WindowUpdateType type); + void NotifyAccessibilityWindowInfo(DisplayId displayId, WindowUpdateType type); + void GetAccessibilityWindowInfo(std::vector>& infos) const; + +private: + sptr windowRoot_; + std::map, uint32_t> focusedWindowMap_; + void NotifyAccessibilityWindowInfo(const std::vector>& nodes, uint32_t focusedWindow, + WindowUpdateType type) const; + void FillAccessibilityWindowInfo(const std::vector>& nodes, uint32_t focusedWindow, + std::vector>& windowInfo) const; + void UpdateFocusChangeEvent(const sptr& container); +}; +} +#endif // OHOS_ROSEN_ACCESSIBILITY_CONTROLLER_H diff --git a/window_manager/wmserver/include/animation_config.h b/window_manager/wmserver/include/animation_config.h new file mode 100644 index 0000000..7ffdca9 --- /dev/null +++ b/window_manager/wmserver/include/animation_config.h @@ -0,0 +1,44 @@ +/* + * 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_ROSEN_ANIMATION_CONFIG_H +#define OHOS_ROSEN_ANIMATION_CONFIG_H + +#include "animation/rs_animation_timing_curve.h" +#include "animation/rs_animation_timing_protocol.h" +#include "common/rs_vector3.h" +#include "common/rs_vector4.h" + +namespace OHOS { +namespace Rosen { +struct AnimationConfig { + struct WindowAnimationConfig { + struct AnimationTiming { + RSAnimationTimingProtocol timingProtocol_ = 200; + RSAnimationTimingCurve timingCurve_ = RSAnimationTimingCurve::EASE_OUT; + } animationTiming_; + float opacity_ = 0; + Vector3f scale_ { 0.7f, 0.7f, 1.0f }; + Vector3f translate_ { 0, 0, 0 }; + Vector4f rotation_ { 0, 0, 1, 0 }; + } windowAnimationConfig_; + struct KeyboardAnimationConfig { + RSAnimationTimingCurve curve_ = RSAnimationTimingCurve::CreateCubicCurve(0.2f, 0.0f, 0.2f, 1.0f); + RSAnimationTimingProtocol durationIn_ = 500; + RSAnimationTimingProtocol durationOut_ = 300; + } keyboardAnimationConfig_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_ANIMATION_CONFIG_H \ No newline at end of file diff --git a/window_manager/wmserver/include/avoid_area_controller.h b/window_manager/wmserver/include/avoid_area_controller.h new file mode 100644 index 0000000..82af226 --- /dev/null +++ b/window_manager/wmserver/include/avoid_area_controller.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021-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_ROSEN_AVOID_AREA_CONTROLLER_H +#define OHOS_ROSEN_AVOID_AREA_CONTROLLER_H + +#include +#include +#include +#include + +#include + +#include "class_var_definition.h" +#include "window_node.h" +#include "wm_common.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +enum class AvoidControlType : uint32_t { + AVOID_NODE_ADD, + AVOID_NODE_UPDATE, + AVOID_NODE_REMOVE, + AVOID_NODE_UNKNOWN, +}; + +class AvoidAreaController : public RefBase { +public: + AvoidAreaController(uint32_t& focusedWindow) : focusedWindow_(focusedWindow) {}; + ~AvoidAreaController() = default; + + void UpdateAvoidAreaListener(sptr& windowNode, bool isRegisterListener); + void ProcessWindowChange(const sptr& windowNode, AvoidControlType avoidType, + const std::function)>& checkFunc); + AvoidArea GetAvoidAreaByType(const sptr& node, AvoidAreaType avoidAreaType) const; + +private: + void AddOrRemoveOverlayWindowIfNeed(const sptr& overlayNode, bool isAdding); + void AddOrRemoveKeyboard(const sptr& keyboardNode, bool isAdding); + void UpdateOverlayWindowIfNeed(const sptr& node, + const std::function)>& checkFunc); + AvoidPosType CalculateOverlayRect(const sptr& node, + const sptr& overlayNode, Rect& overlayRect) const; + AvoidPosType GetAvoidPosType(const Rect& windowRect, const Rect& overlayRect) const; + void SetAvoidAreaRect(AvoidArea& avoidArea, const Rect& rect, AvoidPosType type) const; + bool UpdateAvoidAreaIfNeed(const AvoidArea& avoidArea, const sptr& node, AvoidAreaType avoidAreaType); + AvoidArea GetAvoidAreaSystemType(const sptr& node) const; + AvoidArea GetAvoidAreaKeyboardType(const sptr& node) const; + + uint32_t& focusedWindow_; + std::unordered_map> overlayWindowMap_; + std::set> avoidAreaListenerNodes_; + std::map> lastUpdatedAvoidArea_; + uint32_t lastSoftInputKeyboardAreaUpdatedWindowId_ { 0 }; + DEFINE_VAR_DEFAULT_FUNC_SET(bool, FlagForProcessWindowChange, isForbidProcessingWindowChange, false) +}; +} +} +#endif // OHOS_ROSEN_AVOID_AREA_CONTROLLER_H diff --git a/window_manager/wmserver/include/display_group_controller.h b/window_manager/wmserver/include/display_group_controller.h new file mode 100644 index 0000000..85d9bb8 --- /dev/null +++ b/window_manager/wmserver/include/display_group_controller.h @@ -0,0 +1,86 @@ +/* + * 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_ROSEN_DISPLAY_GROUP_CONTROLLER_H +#define OHOS_ROSEN_DISPLAY_GROUP_CONTROLLER_H + +#include + +#include "avoid_area_controller.h" +#include "display_group_info.h" +#include "display_info.h" +#include "display_manager_service_inner.h" +#include "window_layout_policy.h" +#include "window_manager.h" +#include "window_node.h" +#include "window_pair.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +using SysBarNodeMap = std::unordered_map>; +using SysBarTintMap = std::unordered_map; +class WindowNodeContainer; + +class DisplayGroupController : public RefBase { +public: + DisplayGroupController(const sptr& windowNodeContainer, + const sptr& displayGroupInfo) + : windowNodeContainer_(windowNodeContainer), displayGroupInfo_(displayGroupInfo) {} + ~DisplayGroupController() = default; + + void InitNewDisplay(DisplayId displayId); + void UpdateDisplayGroupWindowTree(); + void PreProcessWindowNode(const sptr& node, WindowUpdateType type); + void PostProcessWindowNode(const sptr& node); + void ProcessDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, + const std::map& displayRectMap); + void ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr displayInfo, + const std::map& displayRectMap, + std::vector& windowIds); + void ProcessDisplayChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map& displayRectMap, + DisplayStateChangeType type); + sptr GetWindowPairByDisplayId(DisplayId displayId); + void SetDividerRect(DisplayId displayId, const Rect& rect); + + DisplayGroupWindowTree displayGroupWindowTree_; + std::map sysBarNodeMaps_; + std::map sysBarTintMaps_; + +private: + std::vector>* GetWindowNodesByDisplayIdAndRootType(DisplayId displayId, WindowRootNodeType type); + void AddWindowNodeOnWindowTree(sptr& node, WindowRootNodeType rootType); + void ProcessNotCrossNodesOnDestroyedDisplay(DisplayId displayId, std::vector& windowIds); + void ProcessDisplaySizeChangeOrRotation(DisplayId defaultDisplayId, DisplayId displayId, + const std::map& displayRectMap, DisplayStateChangeType type); + void ProcessCrossNodes(DisplayId defaultDisplayId, DisplayStateChangeType type); + void MoveCrossNodeToTargetDisplay(const sptr& node, DisplayId targetDisplayId); + void MoveNotCrossNodeToDefaultDisplay(const sptr& node, DisplayId displayId); + void UpdateWindowDisplayIdIfNeeded(const sptr& node); + void UpdateWindowShowingDisplays(const sptr& node); + void UpdateWindowDisplayId(const sptr& node, DisplayId newDisplayId); + void ClearMapOfDestroyedDisplay(DisplayId displayId); + void ChangeToRectInDisplayGroup(const sptr& node, DisplayId displayId); + void UpdateNodeSizeChangeReasonWithRotation(DisplayId displayId); + + sptr windowNodeContainer_; + sptr displayGroupInfo_; + std::map> windowPairMap_; + DisplayId defaultDisplayId_ { 0 }; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_DISPLAY_GROUP_CONTROLLER_H diff --git a/window_manager/wmserver/include/display_group_info.h b/window_manager/wmserver/include/display_group_info.h new file mode 100644 index 0000000..08c4cb6 --- /dev/null +++ b/window_manager/wmserver/include/display_group_info.h @@ -0,0 +1,58 @@ +/* + * 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_ROSEN_DISPLAY_GROUP_INFO_H +#define OHOS_ROSEN_DISPLAY_GROUP_INFO_H + +#include +#include + +#include "display_info.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class DisplayGroupInfo : public RefBase { +public: + DisplayGroupInfo(ScreenId displayGroupId, const sptr& displayInfo); + ~DisplayGroupInfo() = default; + void AddDisplayInfo(const sptr& displayInfo); + void RemoveDisplayInfo(DisplayId displayId); + void UpdateLeftAndRightDisplayId(); + + void SetDisplayRotation(DisplayId displayId, Rotation rotation); + void SetDisplayVirtualPixelRatio(DisplayId displayId, float vpr); + void SetDisplayRect(DisplayId displayId, Rect displayRect); + + Rotation GetDisplayRotation(DisplayId displayId) const; + float GetDisplayVirtualPixelRatio(DisplayId displayId) const; + std::map GetAllDisplayRects() const; + Rect GetDisplayRect(DisplayId displayId) const; + sptr GetDisplayInfo(DisplayId displayId) const; + void UpdateDisplayInfo(sptr displayInfo) const; + std::vector> GetAllDisplayInfo() const; + DisplayId GetLeftDisplayId() const; + DisplayId GetRightDisplayId() const; + +private: + ScreenId displayGroupId_; + DisplayId leftDisplayId_ { 0 }; + DisplayId rightDisplayId_ { 0 }; + mutable std::map> displayInfosMap_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_DISPLAY_GROUP_INFO_H + diff --git a/window_manager/wmserver/include/display_zoom_controller.h b/window_manager/wmserver/include/display_zoom_controller.h new file mode 100644 index 0000000..1f29718 --- /dev/null +++ b/window_manager/wmserver/include/display_zoom_controller.h @@ -0,0 +1,62 @@ +/* + * 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_ROSEN_DISPLAY_ZOOM_CONTROLLER_H +#define OHOS_ROSEN_DISPLAY_ZOOM_CONTROLLER_H + +#include + +#include "window_node.h" +#include "window_root.h" +#include "window_node_container.h" +#include "wm_common.h" + +namespace OHOS::Rosen { +class DisplayZoomController : public RefBase { +public: + explicit DisplayZoomController(sptr& root) : windowRoot_(root) {} + ~DisplayZoomController() = default; + void SetAnchorAndScale(int32_t x, int32_t y, float scale); + void SetAnchorOffset(int32_t deltaX, int32_t deltaY); + void OffWindowZoom(); + void UpdateAllWindowsZoomInfo(DisplayId displayId); + void UpdateWindowZoomInfo(uint32_t windowId); + void ClearZoomTransform(std::vector> nodes); +private: + struct DisplayZoomInfo { + int32_t pivotX; + int32_t pivotY; + float scale; + int32_t translateX; + int32_t translateY; + }; + sptr windowRoot_; + void ClearZoomTransformInner(sptr node); + bool UpdateZoomTranslateInfo(sptr windowNodeContainer, DisplayId displayId, + int32_t& deltaX, int32_t& deltaY); + Transform CalcuAnimateZoomTrans(sptr node); + Transform CalcuZoomTransByZoomInfo(sptr node); + Transform CalcuZoomTrans(sptr node, const DisplayZoomInfo& zoomInfo); + void UpdateClientAndSurfaceZoomInfo(sptr node, const Transform& zoomTrans); + void HandleUpdateWindowZoomInfo(sptr node); + void TransformSurfaceNode(std::shared_ptr surfaceNode, const Transform& trans); + DisplayZoomInfo zoomInfo_ = {0, 0, 1.0, 0, 0}; // compared with original window rect + std::unordered_set displayZoomWindowTypeSkipped_ { + WindowType::WINDOW_TYPE_NAVIGATION_BAR, + WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, + }; +}; +} +#endif // OHOS_ROSEN_DISPLAY_ZOOM_CONTROLLER_H diff --git a/window_manager/wmserver/include/drag_controller.h b/window_manager/wmserver/include/drag_controller.h new file mode 100644 index 0000000..f42e365 --- /dev/null +++ b/window_manager/wmserver/include/drag_controller.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021-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_ROSEN_DRAG_CONTROLLER_H +#define OHOS_ROSEN_DRAG_CONTROLLER_H + +#include + +#include "event_handler.h" +#include "event_runner.h" +#include "input_manager.h" +#include "pointer_event.h" +#include "window_root.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +using EventRunner = OHOS::AppExecFwk::EventRunner; +using EventHandler = OHOS::AppExecFwk::EventHandler; +/* + * DragController is the class which is used to handle drag cross window + */ +class DragController : public RefBase { +public: + explicit DragController(sptr& root) : windowRoot_(root) {} + ~DragController() = default; + void StartDrag(uint32_t windowId); + void UpdateDragInfo(uint32_t windowId); + void FinishDrag(uint32_t windowId); +private: + sptr GetHitWindow(DisplayId id, const PointInfo point); + bool GetHitPoint(uint32_t windowId, PointInfo& point); + sptr windowRoot_; + uint64_t hitWindowId_ = 0; +}; + +class DragInputEventListener : public MMI::IInputEventConsumer { +public: + DragInputEventListener() = default; + void OnInputEvent(std::shared_ptr pointerEvent) const override; + void OnInputEvent(std::shared_ptr keyEvent) const override; + void OnInputEvent(std::shared_ptr axisEvent) const override; +}; + +/* + * MoveDragController is the class which is used to handle move or drag floating window + */ +class MoveDragController : public RefBase { +public: + MoveDragController() : windowProperty_(new WindowProperty()), moveDragProperty_(new MoveDragProperty()) + { + vsyncCallback_->onCallback = std::bind(&MoveDragController::OnReceiveVsync, this, std::placeholders::_1); + } + ~MoveDragController() = default; + + bool Init(); + void Stop(); + void HandleReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty); + void HandleEndUpMovingOrDragging(uint32_t windowId); + void HandleWindowRemovedOrDestroyed(uint32_t windowId); + void ConsumePointerEvent(const std::shared_ptr& pointerEvent); + uint32_t GetActiveWindowId() const; + void HandleDisplayChange(const std::map& displayRectMap); + void SetInputEventConsumer(); + +private: + void SetDragProperty(const sptr& moveDragProperty); + void SetWindowProperty(const sptr& windowProperty); + void SetActiveWindowId(uint32_t); + const sptr& GetMoveDragProperty() const; + const sptr& GetWindowProperty() const; + Rect GetHotZoneRect(); + void ConvertPointerPosToDisplayGroupPos(DisplayId displayId, int32_t& posX, int32_t& posY); + + void HandlePointerEvent(const std::shared_ptr& pointerEvent); + void HandleDragEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); + void HandleMoveEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); + void OnReceiveVsync(int64_t timeStamp); + void ResetMoveOrDragState(); + + sptr windowProperty_; + sptr moveDragProperty_; + uint32_t activeWindowId_ = INVALID_WINDOW_ID; + std::shared_ptr moveEvent_ = nullptr; + std::shared_ptr inputListener_ = nullptr; + std::shared_ptr vsyncCallback_ = std::make_shared(VsyncCallback()); + std::map displayRectMap_; + + // event handler for input event + std::shared_ptr inputEventHandler_; + const std::string INNER_WM_INPUT_THREAD_NAME = "InnerInputManager"; +}; +} +} +#endif // OHOS_ROSEN_DRAG_CONTROLLER_H + diff --git a/window_manager/wmserver/include/freeze_controller.h b/window_manager/wmserver/include/freeze_controller.h new file mode 100644 index 0000000..5c2dcac --- /dev/null +++ b/window_manager/wmserver/include/freeze_controller.h @@ -0,0 +1,42 @@ +/* + * 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_ROSEN_FREEZE_CONTROLLER_H +#define OHOS_ROSEN_FREEZE_CONTROLLER_H + +#include +#include + +#include "display.h" +#include "window.h" + +namespace OHOS { +namespace Rosen { +class FreezeController : public RefBase { +public: + FreezeController() = default; + ~FreezeController() = default; + + bool FreezeDisplay(DisplayId displayId); + bool UnfreezeDisplay(DisplayId displayId); + +private: + sptr CreateCoverWindow(DisplayId displayId); + std::map> coverWindowMap_; +}; +} +} +#endif // OHOS_ROSEN_FREEZE_CONTROLLER_H + diff --git a/window_manager/wmserver/include/inner_window.h b/window_manager/wmserver/include/inner_window.h new file mode 100644 index 0000000..f9d1600 --- /dev/null +++ b/window_manager/wmserver/include/inner_window.h @@ -0,0 +1,73 @@ +/* + * 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_ROSEN_INNER_WINDOW_H +#define OHOS_ROSEN_INNER_WINDOW_H + +#include "window.h" +#include "wm_common_inner.h" +#include "wm_single_instance.h" + +namespace OHOS { +namespace Rosen { +class IInnerWindow : virtual public RefBase { +public: + virtual void Create(std::string name, DisplayId displyId, Rect rect, WindowMode mode) = 0; + virtual void Update(uint32_t width, uint32_t height) = 0; + virtual void Destroy() = 0; +}; + +class PlaceholderWindowListener : public IWindowLifeCycle, public ITouchOutsideListener { +public: + // touch outside listener + virtual void OnTouchOutside() const; + // lifecycle listener + virtual void AfterUnfocused(); + // lifecycle do nothing + virtual void AfterForeground() {}; + virtual void AfterBackground() {}; + virtual void AfterFocused() {}; + virtual void AfterInactive() {}; +}; + +class PlaceholderInputEventConsumer : public IInputEventConsumer { +public: + ~PlaceholderInputEventConsumer() override = default; + virtual bool OnInputEvent(const std::shared_ptr& keyEvent) const override; + virtual bool OnInputEvent(const std::shared_ptr& pointerEvent) const override; + virtual bool OnInputEvent(const std::shared_ptr& axisEvent) const override; +}; + +class PlaceHolderWindow : public IInnerWindow { +WM_DECLARE_SINGLE_INSTANCE(PlaceHolderWindow); +public: + virtual void Create(std::string name, DisplayId displyId, Rect rect, WindowMode mode); + virtual void Update(uint32_t width, uint32_t height) {}; + virtual void Destroy(); + +private: + void RegisterWindowListener(); + void UnRegisterWindowListener(); + void SetInputEventConsumer(); + +private: + sptr window_; + sptr windowListener_; + std::shared_ptr inputEventConsumer_; +}; + +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_INNER_WINDOW_H diff --git a/window_manager/wmserver/include/input_window_monitor.h b/window_manager/wmserver/include/input_window_monitor.h new file mode 100644 index 0000000..79103b3 --- /dev/null +++ b/window_manager/wmserver/include/input_window_monitor.h @@ -0,0 +1,52 @@ +/* + * 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_INPUT_WINDOW_MONITOR_H +#define OHOS_INPUT_WINDOW_MONITOR_H + +#include +#include + +#include "display_info.h" +#include "window_root.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class InputWindowMonitor : public RefBase { +public: + explicit InputWindowMonitor(sptr& root) : windowRoot_(root) {} + ~InputWindowMonitor() = default; + void UpdateInputWindow(uint32_t windowId); + void UpdateInputWindowByDisplayId(DisplayId displayId); + MMI::DisplayGroupInfo GetDisplayInfo(uint32_t windowId); + void HandleDisplayInfo(DisplayId displayId); + +private: + sptr windowRoot_; + MMI::DisplayGroupInfo displayGroupInfo_ = {}; + void TraverseWindowNodes(const std::vector>& windowNodes, + std::vector& windowsInfo); + void UpdateDisplayGroupInfo(const sptr& windowNodeContainer, + MMI::DisplayGroupInfo& displayGroupInfo); + void UpdateDisplayInfo(const std::vector>& displayInfos, + std::vector& displayInfoVector); + MMI::Direction GetDisplayDirectionForMmi(Rotation rotation); + void TransformWindowRects(const sptr& windowNode, Rect& areaRect, + std::vector& touchHotAreas, std::vector& pointerHotAreas); +}; +} +} +#endif // OHOS_INPUT_WINDOW_MONITOR_H diff --git a/window_manager/wmserver/include/memory_guard.h b/window_manager/wmserver/include/memory_guard.h new file mode 100644 index 0000000..5e99deb --- /dev/null +++ b/window_manager/wmserver/include/memory_guard.h @@ -0,0 +1,27 @@ +/* +* Copyright (C) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_ROSEN_MEMORY_GUARD_H +#define OHOS_ROSEN_MEMORY_GUARD_H +namespace OHOS { +namespace Rosen { +class MemoryGuard { +public: + MemoryGuard(); + ~MemoryGuard(); +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_MEMORY_GUARD_H \ No newline at end of file diff --git a/window_manager/wmserver/include/minimize_app.h b/window_manager/wmserver/include/minimize_app.h new file mode 100644 index 0000000..33061f1 --- /dev/null +++ b/window_manager/wmserver/include/minimize_app.h @@ -0,0 +1,69 @@ +/* + * 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_ROSEN_MINIMIZE_APP_H +#define OHOS_ROSEN_MINIMIZE_APP_H + +#include +#include + +#include +#include "wm_common.h" +#include "window_node.h" + +namespace OHOS { +namespace Rosen { +enum MinimizeReason : uint32_t { + MINIMIZE_BUTTON = 1, + MINIMIZE_ALL = 1 << 1, + LAYOUT_TILE = 1 << 2, + LAYOUT_CASCADE = 1 << 3, + MAX_APP_COUNT = 1 << 4, + SPLIT_REPLACE = 1 << 5, + SPLIT_QUIT = 1 << 6, + GESTURE_ANIMATION = 1 << 7, + OTHER_WINDOW = 1 << 8, +}; + +class MinimizeApp : public RefBase { +public: + MinimizeApp() = delete; + ~MinimizeApp() = default; + + static void AddNeedMinimizeApp(const sptr& node, MinimizeReason reason); + static void ExecuteMinimizeAll(); + static void ExecuteMinimizeTargetReasons(uint32_t reasons); + static void SetMinimizedByOtherConfig(bool isMinimizedByOther); + static void ClearNodesWithReason(MinimizeReason reason); + static bool IsNodeNeedMinimize(const sptr& node); + static std::vector> GetNeedMinimizeAppNodesWithReason(MinimizeReason reason); + static sptr GetRecoverdNodeFromMinimizeList(); + static bool IsNodeNeedMinimizeWithReason(const sptr& node, MinimizeReason reason); + static bool EnableMinimize(MinimizeReason reason); +private: + static inline bool IsFromUser(MinimizeReason reason) + { + return (reason == MinimizeReason::MINIMIZE_ALL || reason == MinimizeReason::MINIMIZE_BUTTON || + reason == MinimizeReason::MAX_APP_COUNT || reason == MinimizeReason::LAYOUT_TILE || + reason == MinimizeReason::SPLIT_REPLACE || reason == MinimizeReason::SPLIT_QUIT); + } + + static std::map>> needMinimizeAppNodes_; + static bool isMinimizedByOtherWindow_; + static std::recursive_mutex mutex_; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_MINIMIZE_APP_H diff --git a/window_manager/wmserver/include/remote_animation.h b/window_manager/wmserver/include/remote_animation.h new file mode 100644 index 0000000..3fc7aa7 --- /dev/null +++ b/window_manager/wmserver/include/remote_animation.h @@ -0,0 +1,108 @@ +/* + * 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_ROSEN_REMOTE_ANIMATION_H +#define OHOS_ROSEN_REMOTE_ANIMATION_H + +#include +#include +#include +#include + +#include "wm_common.h" +#include "window_controller.h" +#include "window_node.h" +#include "window_root.h" +#include "window_transition_info.h" + +namespace OHOS { +namespace Rosen { +enum class TransitionEvent : uint32_t { + APP_TRANSITION, + HOME, + MINIMIZE, + CLOSE, + UNKNOWN, + BACK_TRANSITION, +}; + +class RemoteAnimation : public RefBase { +public: + RemoteAnimation() = delete; + ~RemoteAnimation() = default; + + static bool CheckTransition(sptr srcInfo, const sptr& srcNode, + sptr dstInfo, const sptr& dstNode); + static TransitionEvent GetTransitionEvent(sptr srcInfo, + sptr dstInfo, const sptr& srcNode, const sptr& dstNode); + static WMError SetWindowAnimationController(const sptr& controller); + static WMError NotifyAnimationTransition(sptr srcInfo, sptr dstInfo, + const sptr& srcNode, const sptr& dstNode); + static WMError NotifyAnimationMinimize(sptr srcInfo, const sptr& srcNode); + static WMError NotifyAnimationClose(sptr srcInfo, const sptr& srcNode, + TransitionEvent event); + static WMError NotifyAnimationBackTransition(sptr srcInfo, + sptr dstInfo, const sptr& srcNode, + const sptr& dstNode); + static void NotifyAnimationUpdateWallpaper(sptr node); + static void OnRemoteDie(const sptr& remoteObject); + static bool CheckAnimationController(); + static bool CheckRemoteAnimationEnabled(DisplayId displayId); + static WMError NotifyAnimationByHome(); + static WMError NotifyAnimationScreenUnlock(std::function callback); + static void SetMainTaskHandler(std::shared_ptr handler); + static void NotifyAnimationTargetsUpdate(std::vector& fullScreenWinIds, + std::vector& floatWinIds); + static void SetAnimationFirst(bool animationFirst); + static void SetWindowControllerAndRoot(const sptr& windowController, + const sptr& windowRoot); + static bool IsRemoteAnimationEnabledAndFirst(DisplayId displayId = 0); + static void CallbackTimeOutProcess(); + static sptr CreateAnimationFinishedCallback( + const std::function& callback); + static inline bool IsAnimationFirst() + { + return animationFirst_; + } + static bool isRemoteAnimationEnable_; +private: + static sptr CreateWindowAnimationTarget(sptr info, + const sptr& windowNode); + static WMError NotifyAnimationStartApp(sptr srcInfo, + const sptr& srcNode, const sptr& dstNode, + sptr& dstTarget, sptr& finishedCallback); + static sptr CreateShowAnimationFinishedCallback( + const sptr& srcNode, const sptr& dstNode, bool needMinimizeSrcNode); + static sptr CreateHideAnimationFinishedCallback( + const sptr& srcNode, TransitionEvent event); + static void ProcessNodeStateTask(sptr& node); + static void GetExpectRect(const sptr& dstNode, const sptr& dstTarget); + static void PostProcessShowCallback(const sptr& node); + static void ExecuteFinalStateTask(sptr& node); + static void GetAnimationTargetsForHome(std::vector>& animationTargets, + std::vector> needMinimizeAppNodes); + static sptr GetTransitionFinishedCallback( + const sptr& srcNode, const sptr& dstNode); + + static sptr windowAnimationController_; + static wptr windowRoot_; + static std::weak_ptr wmsTaskHandler_; + static wptr windowController_; + static bool animationFirst_; + static std::atomic allocationId_; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_REMOTE_ANIMATION_H diff --git a/window_manager/wmserver/include/starting_window.h b/window_manager/wmserver/include/starting_window.h new file mode 100644 index 0000000..a34fc2c --- /dev/null +++ b/window_manager/wmserver/include/starting_window.h @@ -0,0 +1,52 @@ +/* + * 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_ROSEN_STARTING_WINDOW_H +#define OHOS_ROSEN_STARTING_WINDOW_H + +#include +#include "pixel_map.h" +#include "animation_config.h" +#include "surface_draw.h" +#include "wm_common.h" +#include "window_node.h" +#include "window_transition_info.h" + +namespace OHOS { +namespace Rosen { +class StartingWindow : public RefBase { +public: + StartingWindow() = delete; + ~StartingWindow() = default; + + static sptr CreateWindowNode(const sptr& info, uint32_t winId); + static void HandleClientWindowCreate(sptr& node, sptr& window, + uint32_t& windowId, const std::shared_ptr& surfaceNode, sptr& property, + int32_t pid, int32_t uid); + static WMError DrawStartingWindow(sptr& node, std::shared_ptr pixelMap, + uint32_t bkgColor, bool isColdStart); + static void AddNodeOnRSTree(sptr& node, const AnimationConfig& animationConfig, bool isMultiDisplay); + static void ReleaseStartWinSurfaceNode(sptr& node); + static void SetDefaultWindowMode(WindowMode defaultMode); + +private: + static WMError CreateLeashAndStartingSurfaceNode(sptr& node); + static SurfaceDraw surfaceDraw_; + static std::recursive_mutex mutex_; + static WindowMode defaultMode_; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_STARTING_WINDOW_H diff --git a/window_manager/wmserver/include/window_common_event.h b/window_manager/wmserver/include/window_common_event.h new file mode 100644 index 0000000..abc8218 --- /dev/null +++ b/window_manager/wmserver/include/window_common_event.h @@ -0,0 +1,60 @@ +/* + * 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 WINDOW_COMMON_EVENT_H +#define WINDOW_COMMON_EVENT_H + +#include +#include +#include +#include + +#include "window_root.h" + +namespace OHOS { +namespace Rosen { +class WindowCommonEvent : public RefBase, public std::enable_shared_from_this { +public: + WindowCommonEvent(); + ~WindowCommonEvent(); + void SubscriberEvent(); + void UnSubscriberEvent(); + void OnReceiveEvent(const EventFwk::CommonEventData& data); +private: + class EventSubscriber : public EventFwk::CommonEventSubscriber { + public: + EventSubscriber(const EventFwk::CommonEventSubscribeInfo &subscriberInfo, + const std::shared_ptr& eventHandler) + : EventFwk::CommonEventSubscriber(subscriberInfo), eventHandler_(eventHandler) {}; + ~EventSubscriber() = default; + void OnReceiveEvent(const EventFwk::CommonEventData& data) override + { + eventHandler_->OnReceiveEvent(data); + } + private: + std::shared_ptr eventHandler_; + }; + void SubscriberEventInner(int retry); + void HandleAccountSwitched(const EventFwk::CommonEventData& data) const; + + typedef void (WindowCommonEvent::*HandleCommonEventFunc)(const EventFwk::CommonEventData& data) const; + + std::map handleCommonEventFuncs_; + std::shared_ptr subscriber_; + std::shared_ptr eventHandler_; +}; +} // Rosen +} // OHOS +#endif // WINDOW_COMMON_EVENT_H \ No newline at end of file diff --git a/window_manager/wmserver/include/window_controller.h b/window_manager/wmserver/include/window_controller.h new file mode 100644 index 0000000..a1339fe --- /dev/null +++ b/window_manager/wmserver/include/window_controller.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_CONTROLLER_H +#define OHOS_ROSEN_WINDOW_CONTROLLER_H + +#include +#include + +#include "accessibility_connection.h" +#include "display_zoom_controller.h" +#include "input_window_monitor.h" +#include "zidl/window_manager_agent_interface.h" +#include "window_root.h" +#include "window_transition_info.h" +#include "wm_common.h" +#include "wm_occlusion_region.h" +#include "struct_multimodal.h" + +namespace OHOS { +namespace Rosen { +class WindowController : public RefBase { +public: + WindowController(sptr& root, sptr inputWindowMonitor) : windowRoot_(root), + inputWindowMonitor_(inputWindowMonitor), accessibilityConnection_(new AccessibilityConnection(windowRoot_)), + displayZoomController_(new DisplayZoomController(root)) {} + ~WindowController() = default; + + WMError CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, + uint32_t& windowId, sptr token, int32_t pid, int32_t uid); + WMError AddWindowNode(sptr& property); + WMError RemoveWindowNode(uint32_t windowId, bool fromAnimation = false); + WMError NotifyWindowTransition(sptr& fromInfo, sptr& toInfo); + WMError GetFocusWindowInfo(sptr& abilityToken); + WMError DestroyWindow(uint32_t windowId, bool onlySelf); + WMError RequestFocus(uint32_t windowId); + WMError SetAlpha(uint32_t windowId, float alpha); + AvoidArea GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) const; + WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId); + void NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type); + WMError NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& moveDragProperty); + WMError ProcessPointDown(uint32_t windowId, bool isPointDown); + WMError ProcessPointUp(uint32_t windowId); + void MinimizeAllAppWindows(DisplayId displayId); + WMError ToggleShownStateForAllAppWindows(); + WMError SetWindowLayoutMode(WindowLayoutMode mode); + WMError UpdateProperty(sptr& property, PropertyChangeAction action); + void NotifySystemBarTints(); + WMError SetWindowAnimationController(const sptr& controller); + WMError GetModeChangeHotZones(DisplayId displayId, + ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config); + void StartingWindow(sptr info, std::shared_ptr pixelMap, + uint32_t bkgColor, bool isColdStart); + void CancelStartingWindow(sptr abilityToken); + void MinimizeWindowsByLauncher(std::vector& windowIds, bool isAnimated, + sptr& finishCallback); + void OnScreenshot(DisplayId displayId); + WMError GetAccessibilityWindowInfo(std::vector>& infos) const; + WMError GetVisibilityWindowInfo(std::vector>& infos) const; + void SetAnchorAndScale(int32_t x, int32_t y, float scale); + void SetAnchorOffset(int32_t deltaX, int32_t deltaY); + void OffWindowZoom(); + WMError BindDialogTarget(uint32_t& windowId, sptr targetToken); + WMError InterceptInputEventToServer(uint32_t windowId); + WMError RecoverInputEventToClient(uint32_t windowId); + WMError NotifyWindowClientPointUp(uint32_t windowId, const std::shared_ptr& pointerEvent); + WMError ChangeMouseStyle(uint32_t windowId, sptr& moveDragProperty); + void RecoverDefaultMouseStyle(uint32_t windowId); + +private: + uint32_t GenWindowId(); + void FlushWindowInfo(uint32_t windowId); + void FlushWindowInfoWithDisplayId(DisplayId displayId); + void UpdateWindowAnimation(const sptr& node); + void ProcessDisplayChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type); + void StopBootAnimationIfNeed(const sptr& node); + void RecordBootAnimationEvent() const; + WMError SetWindowType(uint32_t windowId, WindowType type); + WMError SetWindowFlags(uint32_t windowId, uint32_t flags); + WMError SetSystemBarProperty(uint32_t windowId, WindowType type, const SystemBarProperty& property); + WMError ResizeRect(uint32_t windowId, const Rect& rect, WindowSizeChangeReason reason); + WMError ResizeRectAndFlush(uint32_t windowId, const Rect& rect, WindowSizeChangeReason reason); + WMError SetWindowMode(uint32_t windowId, WindowMode dstMode); + void ResizeSoftInputCallingWindowIfNeed(const sptr& node); + void RestoreCallingWindowSizeIfNeed(); + void HandleTurnScreenOn(const sptr& node); + void ProcessSystemBarChange(const sptr& displayInfo); + WMError UpdateTouchHotAreas(const sptr& node, const std::vector& rects); + WMError UpdateTransform(uint32_t windowId); + void NotifyTouchOutside(const sptr& node); + uint32_t GetEmbedNodeId(const std::vector>& windowNodes, const sptr& node); + void NotifyWindowPropertyChanged(const sptr& node); + WMError GetFocusWindowNode(DisplayId displayId, sptr& windowNode); + void SetDefaultDisplayInfo(DisplayId defaultDisplayId, sptr displayInfo); + void ProcessDisplayCompression(DisplayId defaultDisplayId, const sptr& displayInfo); + void NotifyAfterAddWindow(sptr& node); + void AsyncFlushInputInfo(uint32_t windowId); + void RelayoutKeyboard(const sptr& node); + + sptr windowRoot_; + sptr inputWindowMonitor_; + sptr accessibilityConnection_; + sptr displayZoomController_; + std::atomic windowId_ { INVALID_WINDOW_ID }; + // Remove 'sysBarWinId_' after SystemUI resize 'systembar', systemBar only exist on default display currently + std::unordered_map sysBarWinId_ { + { WindowType::WINDOW_TYPE_STATUS_BAR, INVALID_WINDOW_ID }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, INVALID_WINDOW_ID }, + }; + bool isScreenLocked_ { false }; + Rect callingWindowRestoringRect_ { 0, 0, 0, 0 }; + uint32_t callingWindowId_ = 0u; + Rect defaultDisplayRect_ = { 0, 0, 0, 0 }; + bool isBootAnimationStopped_ = false; + std::shared_ptr maskingSurfaceNode_ = nullptr; + const std::map STYLEID_MAP = { + {DragType::DRAG_UNDEFINED, MMI::MOUSE_ICON::DEFAULT}, + {DragType::DRAG_BOTTOM_OR_TOP, MMI::MOUSE_ICON::NORTH_SOUTH}, + {DragType::DRAG_LEFT_OR_RIGHT, MMI::MOUSE_ICON::WEST_EAST}, + {DragType::DRAG_LEFT_TOP_CORNER, MMI::MOUSE_ICON::NORTH_WEST_SOUTH_EAST}, + {DragType::DRAG_RIGHT_TOP_CORNER, MMI::MOUSE_ICON::NORTH_EAST_SOUTH_WEST} + }; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_WINDOW_CONTROLLER_H diff --git a/window_manager/wmserver/include/window_dumper.h b/window_manager/wmserver/include/window_dumper.h new file mode 100644 index 0000000..63201bb --- /dev/null +++ b/window_manager/wmserver/include/window_dumper.h @@ -0,0 +1,52 @@ +/* + * 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_ROSEN_WINDOW_DUMPER_H +#define OHOS_ROSEN_WINDOW_DUMPER_H + +#include "dm_common.h" +#include "future.h" +#include "window_root.h" + +namespace OHOS { +namespace Rosen { +enum DumpType : uint32_t { + DUMP_ALL = 0, + DUMP_WINDOW, + DUMP_NONE = 100, +}; +class WindowDumper : public RefBase { +public: + explicit WindowDumper(const sptr& root) : windowRoot_(root) {} + WMError Dump(int fd, const std::vector& args); +public: + RunnableFuture> dumpInfoFuture_; + +private: + WMError DumpWindowInfo(const std::vector& args, std::string& dumpInfo); + WMError DumpAllWindowInfo(std::string& dumpInfo); + WMError DumpScreenGroupWindowInfo(ScreenId screenGroupId, const sptr& windowNodeContainer, + std::string& dumpInfo); + bool IsValidDigitString(const std::string& windowIdStr); + WMError DumpSpecifiedWindowInfo(uint32_t windowId, const std::vector& params, + std::string& dumpInfo); + void ShowHelpInfo(std::string& dumpInfo); + void ShowAceDumpHelp(std::string& dumpInfo); + void ShowIllegalArgsInfo(std::string& dumpInfo, WMError errCode); + const sptr windowRoot_; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_DUMPER_H \ No newline at end of file diff --git a/window_manager/wmserver/include/window_inner_manager.h b/window_manager/wmserver/include/window_inner_manager.h new file mode 100644 index 0000000..101157d --- /dev/null +++ b/window_manager/wmserver/include/window_inner_manager.h @@ -0,0 +1,83 @@ +/* + * 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_ROSEN_WINDOW_INNER_MANAGER_H +#define OHOS_ROSEN_WINDOW_INNER_MANAGER_H + +#include +#include "event_handler.h" +#include "event_runner.h" + +#include "drag_controller.h" +#include "inner_window.h" +#include "wm_common.h" +#include "window_node.h" +#include "wm_single_instance.h" + +enum class InnerWMRunningState { + STATE_NOT_START, + STATE_RUNNING, +}; +namespace OHOS { +namespace Rosen { +using InnerTask = std::function; +using EventRunner = OHOS::AppExecFwk::EventRunner; +using EventHandler = OHOS::AppExecFwk::EventHandler; +using EventPriority = OHOS::AppExecFwk::EventQueue::Priority; +class WindowInnerManager : public RefBase { +WM_DECLARE_SINGLE_INSTANCE_BASE(WindowInnerManager); +public: + void Start(bool enableRecentholder); + void Stop(); + void CreateInnerWindow(std::string name, DisplayId displayId, Rect rect, WindowType type, WindowMode mode); + void DestroyInnerWindow(DisplayId displayId, WindowType type); + void UpdateInnerWindow(DisplayId displayId, WindowType type, uint32_t width, uint32_t height); + void PostTask(InnerTask &&callback, std::string name = "WindowInnerManagerTask", + EventPriority priority = EventPriority::LOW); + + // asynchronously calls the functions of AbilityManager + void MinimizeAbility(const wptr &node, bool isFromUser); + void TerminateAbility(const wptr &node); + void CloseAbility(const wptr &node); + void CompleteFirstFrameDrawing(const wptr &node); + + void ConsumePointerEvent(const std::shared_ptr& pointerEvent); + void NotifyDisplayChange(const std::map& displayRectMap); + bool NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty); + void NotifyWindowEndUpMovingOrDragging(uint32_t windowId); + void NotifyWindowRemovedOrDestroyed(uint32_t windowId); + pid_t GetPid(); + void SetInputEventConsumer(); + +protected: + WindowInnerManager(); + ~WindowInnerManager(); + +private: + bool Init(); + + pid_t pid_ = INVALID_PID; + bool isRecentHolderEnable_ = false; + sptr moveDragController_; + // event handle for inner window + std::shared_ptr eventHandler_; + std::shared_ptr eventLoop_; + InnerWMRunningState state_; + const std::string INNER_WM_THREAD_NAME = "InnerWindowManager"; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_INNER_MANAGER_H \ No newline at end of file diff --git a/window_manager/wmserver/include/window_layout_policy.h b/window_manager/wmserver/include/window_layout_policy.h new file mode 100644 index 0000000..be21e4b --- /dev/null +++ b/window_manager/wmserver/include/window_layout_policy.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_LAYOUT_POLICY_H +#define OHOS_ROSEN_WINDOW_LAYOUT_POLICY_H + +#include +#include +#include + +#include "display_group_info.h" +#include "display_info.h" +#include "window_node.h" +#include "wm_common.h" + + +namespace OHOS { +namespace Rosen { +using DisplayGroupWindowTree = std::map>>>>; +enum class DockWindowShowState : uint32_t { + NOT_SHOWN = 0, + SHOWN_IN_BOTTOM = 1, + SHOWN_IN_LEFT = 2, + SHOWN_IN_RIGHT = 3, + SHOWN_IN_TOP = 4, +}; +class WindowLayoutPolicy : public RefBase { +public: + WindowLayoutPolicy() = delete; + WindowLayoutPolicy(const sptr& displayGroupInfo, DisplayGroupWindowTree& displayGroupWindowTree); + ~WindowLayoutPolicy() = default; + virtual void Launch(); + virtual void Clean(); + virtual void Reset(); + virtual void Reorder(); + virtual void AddWindowNode(const sptr& node) = 0; + virtual void LayoutWindowTree(DisplayId displayId); + virtual void RemoveWindowNode(const sptr& node); + virtual void UpdateWindowNode(const sptr& node, bool isAddWindow = false); + virtual void UpdateLayoutRect(const sptr& node) = 0; + virtual void SetSplitDividerWindowRects(std::map dividerWindowRects) {}; + virtual Rect GetDividerRect(DisplayId displayId) const; + virtual std::vector GetExitSplitPoints(DisplayId displayId) const; + float GetVirtualPixelRatio(DisplayId displayId) const; + void UpdateClientRectAndResetReason(const sptr& node, const Rect& winRect); + void UpdateClientRect(const Rect& rect, const sptr& node, WindowSizeChangeReason reason); + Rect GetDisplayGroupRect() const; + bool IsMultiDisplay(); + void ProcessDisplayCreate(DisplayId displayId, const std::map& displayRectMap); + void ProcessDisplayDestroy(DisplayId displayId, const std::map& displayRectMap); + void ProcessDisplaySizeChangeOrRotation(DisplayId displayId, const std::map& displayRectMap); + void SetSplitRatioConfig(const SplitRatioConfig& splitRatioConfig); + virtual bool IsTileRectSatisfiedWithSizeLimits(const sptr& node); + // methods for setting bottom posY limit for cascade rect on pc + static void SetCascadeRectBottomPosYLimit(uint32_t floatingBottomPosY); + +protected: + void UpdateFloatingLayoutRect(Rect& limitRect, Rect& winRect); + void UpdateLimitRect(const sptr& node, Rect& limitRect); + virtual void LayoutWindowNode(const sptr& node); + AvoidPosType GetAvoidPosType(const Rect& rect, DisplayId displayId) const; + void CalcAndSetNodeHotZone(const Rect& winRect, const sptr& node) const; + void ComputeDecoratedRequestRect(const sptr& node) const; + bool IsVerticalDisplay(DisplayId displayId) const; + bool IsFullScreenRecentWindowExist(const std::vector>& nodeVec) const; + void LayoutWindowNodesByRootType(const std::vector>& nodeVec); + virtual void UpdateSurfaceBounds(const sptr& node, const Rect& winRect, const Rect& preRect); + void UpdateRectInDisplayGroupForAllNodes(DisplayId displayId, + const Rect& oriDisplayRect, const Rect& newDisplayRect); + void UpdateRectInDisplayGroup(const sptr& node, + const Rect& oriDisplayRect, const Rect& newDisplayRect); + void LimitWindowToBottomRightCorner(const sptr& node); + void UpdateDisplayGroupRect(); + void UpdateDisplayGroupLimitRect(); + void UpdateMultiDisplayFlag(); + void PostProcessWhenDisplayChange(); + void UpdateDisplayRectAndDisplayGroupInfo(const std::map& displayRectMap); + DockWindowShowState GetDockWindowShowState(DisplayId displayId, Rect& dockWinRect) const; + void LimitFloatingWindowSize(const sptr& node, const Rect& displayRect, Rect& winRect) const; + void LimitMainFloatingWindowPosition(const sptr& node, Rect& winRect) const; + + void UpdateFloatingWindowSizeForStretchableWindow(const sptr& node, + const Rect& displayRect, Rect& winRect) const; + void UpdateFloatingWindowSizeBySizeLimits(const sptr& node, + const Rect& displayRect, Rect& winRect) const; + void LimitWindowPositionWhenInitRectOrMove(const sptr& node, Rect& winRect) const; + void LimitWindowPositionWhenDrag(const sptr& node, Rect& winRect) const; + void FixWindowSizeByRatioIfDragBeyondLimitRegion(const sptr& node, Rect& winRect); + void UpdateWindowSizeLimits(const sptr& node); + WindowSizeLimits GetSystemSizeLimits(const sptr& node, + const Rect& displayRect, float virtualPixelRatio); + Rect CalcEntireWindowHotZone(const sptr& node, const Rect& winRect, uint32_t hotZone, + float vpr, TransformHelper::Vector2 hotZoneScale) const; + void NotifyAnimationSizeChangeIfNeeded(); + const std::set avoidTypes_ { + WindowType::WINDOW_TYPE_STATUS_BAR, + WindowType::WINDOW_TYPE_NAVIGATION_BAR, + }; + struct LayoutRects { + Rect primaryRect_; + Rect secondaryRect_; + Rect primaryLimitRect_; + Rect secondaryLimitRect_; + Rect dividerRect_; + Rect firstCascadeRect_; + std::vector exitSplitPoints_; // 2 element, first element < second element + std::vector splitRatioPoints_; + }; + sptr displayGroupInfo_; + mutable std::map limitRectMap_; + DisplayGroupWindowTree& displayGroupWindowTree_; + Rect displayGroupRect_; + Rect displayGroupLimitRect_; + bool isMultiDisplay_ = false; + SplitRatioConfig splitRatioConfig_; + // bottom posY limit for cascade rect on pc + static uint32_t floatingBottomPosY_; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_LAYOUT_POLICY_H diff --git a/window_manager/wmserver/include/window_layout_policy_cascade.h b/window_manager/wmserver/include/window_layout_policy_cascade.h new file mode 100644 index 0000000..16a926e --- /dev/null +++ b/window_manager/wmserver/include/window_layout_policy_cascade.h @@ -0,0 +1,84 @@ +/* + * 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_ROSEN_WINDOW_LAYOUT_POLICY_CASCADE_H +#define OHOS_ROSEN_WINDOW_LAYOUT_POLICY_CASCADE_H + +#include +#include +#include + +#include "window_layout_policy.h" +#include "window_node.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowLayoutPolicyCascade : public WindowLayoutPolicy { +public: + WindowLayoutPolicyCascade() = delete; + WindowLayoutPolicyCascade(const sptr& displayGroupInfo, + DisplayGroupWindowTree& displayGroupWindowTree); + ~WindowLayoutPolicyCascade() = default; + void Launch() override; + void Clean() override; + void Reset() override; + void Reorder() override; + void AddWindowNode(const sptr& node) override; + void UpdateWindowNode(const sptr& node, bool isAddWindow = false) override; + void UpdateLayoutRect(const sptr& node) override; + void SetSplitDividerWindowRects(std::map dividerWindowRects) override; + void RemoveWindowNode(const sptr& node) override; + Rect GetDividerRect(DisplayId displayId) const override; + std::vector GetExitSplitPoints(DisplayId displayId) const override; + +private: + void InitAllRects(); + void InitSplitRects(DisplayId displayId); + int32_t GetSplitRatioPoint(float ratio, DisplayId displayId); + void SetSplitRect(const Rect& rect, DisplayId displayId); + void UpdateSplitLimitRect(const Rect& limitRect, Rect& limitSplitRect); + void UpdateSplitRatioPoints(DisplayId displayId); + void UpdateDockSlicePosition(DisplayId displayId, int32_t& origin) const; + void LayoutWindowNode(const sptr& node) override; + void LayoutWindowTree(DisplayId displayId) override; + void InitLimitRects(DisplayId displayId); + void LimitDividerMoveBounds(Rect& rect, DisplayId displayId) const; + void InitCascadeRect(DisplayId displayId); + void SetCascadeRect(const sptr& node); + void ApplyWindowRectConstraints(const sptr& node, Rect& winRect) const; + void UpdateWindowNodeRectOffset(const sptr& node) const; + bool SpecialReasonProcess(const sptr& node, bool isAddWindow) const; + + Rect GetRectByWindowMode(const WindowMode& mode) const; + Rect GetLimitRect(const WindowMode mode, DisplayId displayId) const; + Rect GetDisplayRect(const WindowMode mode, DisplayId displayId) const; + Rect GetCurCascadeRect(const sptr& node) const; + Rect StepCascadeRect(Rect rect, DisplayId displayId) const; + + struct CascadeRects { + Rect primaryRect_; + Rect secondaryRect_; + Rect primaryLimitRect_; + Rect secondaryLimitRect_; + Rect dividerRect_; + Rect firstCascadeRect_; + }; + mutable std::map cascadeRectsMap_; + std::map restoringDividerWindowRects_; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_LAYOUT_POLICY_CASCADE_H diff --git a/window_manager/wmserver/include/window_layout_policy_tile.h b/window_manager/wmserver/include/window_layout_policy_tile.h new file mode 100644 index 0000000..7e8da06 --- /dev/null +++ b/window_manager/wmserver/include/window_layout_policy_tile.h @@ -0,0 +1,58 @@ +/* + * 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_ROSEN_WINDOW_LAYOUT_POLICY_TILE_H +#define OHOS_ROSEN_WINDOW_LAYOUT_POLICY_TILE_H + +#include +#include +#include +#include + +#include "window_layout_policy.h" +#include "window_node.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowLayoutPolicyTile : public WindowLayoutPolicy { +public: + WindowLayoutPolicyTile() = delete; + WindowLayoutPolicyTile(const sptr& displayGroupInfo, + DisplayGroupWindowTree& displayGroupWindowTree); + ~WindowLayoutPolicyTile() = default; + void Launch() override; + void AddWindowNode(const sptr& node) override; + void UpdateWindowNode(const sptr& node, bool isAddWindow = false) override; + void RemoveWindowNode(const sptr& node) override; + void UpdateLayoutRect(const sptr& node) override; + bool IsTileRectSatisfiedWithSizeLimits(const sptr& node) override; + +private: + std::map maxTileWinNumMap_; + std::map>> presetRectsMap_; + std::map>> foregroundNodesMap_; + void InitAllRects(); + uint32_t GetMaxTileWinNum(DisplayId displayId) const; + void InitTileWindowRects(DisplayId displayId); + void AssignNodePropertyForTileWindows(DisplayId displayId); + void LayoutForegroundNodeQueue(DisplayId displayId); + void InitForegroundNodeQueue(); + void ForegroundNodeQueuePushBack(const sptr& node, DisplayId displayId); + void ForegroundNodeQueueRemove(const sptr& node); +}; +} +} +#endif // OHOS_ROSEN_WINDOW_LAYOUT_POLICY_TILE_H diff --git a/window_manager/wmserver/include/window_manager_agent_controller.h b/window_manager/wmserver/include/window_manager_agent_controller.h new file mode 100644 index 0000000..e503596 --- /dev/null +++ b/window_manager/wmserver/include/window_manager_agent_controller.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021-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_ROSEN_WINDOW_MANAGER_AGENT_CONTROLLER_H +#define OHOS_ROSEN_WINDOW_MANAGER_AGENT_CONTROLLER_H + +#include +#include "client_agent_container.h" +#include "wm_single_instance.h" +#include "zidl/window_manager_agent_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerAgentController { +WM_DECLARE_SINGLE_INSTANCE_BASE(WindowManagerAgentController) +public: + bool RegisterWindowManagerAgent(const sptr& windowManagerAgent, + WindowManagerAgentType type); + bool UnregisterWindowManagerAgent(const sptr& windowManagerAgent, + WindowManagerAgentType type); + + void UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused); + void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints); + void NotifyAccessibilityWindowInfo(const std::vector>& infos, WindowUpdateType type); + void UpdateWindowVisibilityInfo(const std::vector>& windowVisibilityInfos); + void UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing); + +private: + WindowManagerAgentController() {} + virtual ~WindowManagerAgentController() = default; + + ClientAgentContainer wmAgentContainer_; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_MANAGER_AGENT_CONTROLLER_H diff --git a/window_manager/wmserver/include/window_manager_config.h b/window_manager/wmserver/include/window_manager_config.h new file mode 100644 index 0000000..f3ead6f --- /dev/null +++ b/window_manager/wmserver/include/window_manager_config.h @@ -0,0 +1,53 @@ +/* + * 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_ROSEN_WINDOW_MANAGER_CONFIG_H +#define OHOS_ROSEN_WINDOW_MANAGER_CONFIG_H + +#include +#include "xml_config_base.h" +#include "libxml/parser.h" +#include "libxml/tree.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerConfig : public RefBase, public XmlConfigBase { +public: + WindowManagerConfig() = delete; + ~WindowManagerConfig() = default; + + static bool LoadConfigXml(); + static const ConfigItem& GetConfig() + { + return config_; + } + static void DumpConfig(const std::map& config); + +private: + static ConfigItem config_; + static const std::map configItemTypeMap_; + + static bool IsValidNode(const xmlNode& currNode); + static void ReadProperty(const xmlNodePtr& currNode, std::map& property); + static void ReadIntNumbersConfigInfo(const xmlNodePtr& currNode, std::vector& intsValue); + static void ReadFloatNumbersConfigInfo(const xmlNodePtr& currNode, std::vector& floatsValue, bool allowNeg); + static void ReadStringConfigInfo(const xmlNodePtr& currNode, std::string& stringValue); + static void ReadConfig(const xmlNodePtr& rootPtr, std::map& mapValue); + static std::string GetConfigPath(const std::string& configFileName); + static std::vector ReadNumberStrings(const xmlNodePtr& node); +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_MANAGER_CONFIG_H diff --git a/window_manager/wmserver/include/window_manager_service.h b/window_manager/wmserver/include/window_manager_service.h new file mode 100644 index 0000000..efe492a --- /dev/null +++ b/window_manager/wmserver/include/window_manager_service.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2021-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_WINDOW_MANAGER_SERVICE_H +#define OHOS_WINDOW_MANAGER_SERVICE_H + +#include +#include +#include "event_handler.h" + +#include +#include +#include +#include +#include +#include "atomic_map.h" +#include "display_change_listener.h" +#include "drag_controller.h" +#include "freeze_controller.h" +#include "rsscreen_change_listener.h" +#include "singleton_delegator.h" +#include "wm_common_inner.h" +#include "wm_single_instance.h" +#include "window_common_event.h" +#include "window_controller.h" +#include "zidl/window_manager_stub.h" +#include "window_dumper.h" +#include "window_manager_config.h" +#include "window_root.h" +#include "snapshot_controller.h" +#include "perform_reporter.h" +#include "struct_multimodal.h" + +namespace OHOS { +namespace Rosen { +class DisplayChangeListener : public IDisplayChangeListener { +public: + virtual void OnDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) override; + virtual void OnScreenshot(DisplayId displayId) override; +}; + +class WindowInfoQueriedListener : public IWindowInfoQueriedListener { +public: + virtual void HasPrivateWindow(DisplayId id, bool& hasPrivateWindow) override; +}; + +class WindowManagerServiceHandler : public AAFwk::WindowManagerServiceHandlerStub { +public: + virtual void NotifyWindowTransition( + sptr from, sptr to) override; + int32_t GetFocusWindow(sptr& abilityToken) override; + virtual void StartingWindow( + sptr info, std::shared_ptr pixelMap, uint32_t bgColor) override; + virtual void StartingWindow( + sptr info, std::shared_ptr pixelMap) override; + virtual void CancelStartingWindow(sptr abilityToken) override; +}; + +class RSUIDirector; +class WindowManagerService : public SystemAbility, public WindowManagerStub { +friend class DisplayChangeListener; +friend class WindowManagerServiceHandler; +DECLARE_SYSTEM_ABILITY(WindowManagerService); +WM_DECLARE_SINGLE_INSTANCE_BASE(WindowManagerService); + +public: + using Task = std::function; + void OnStart() override; + void OnStop() override; + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + int Dump(int fd, const std::vector& args) override; + + WMError CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, + uint32_t& windowId, sptr token) override; + WMError AddWindow(sptr& property) override; + WMError RemoveWindow(uint32_t windowId) override; + WMError NotifyWindowTransition(sptr& from, sptr& to, + bool isFromClient = false) override; + WMError DestroyWindow(uint32_t windowId, bool onlySelf = false) override; + WMError RequestFocus(uint32_t windowId) override; + AvoidArea GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) override; + void NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) override; + void ProcessPointDown(uint32_t windowId, bool isPointDown) override; + void ProcessPointUp(uint32_t windowId) override; + WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) override; + void MinimizeAllAppWindows(DisplayId displayId) override; + WMError ToggleShownStateForAllAppWindows() override; + WMError SetWindowLayoutMode(WindowLayoutMode mode) override; + WMError UpdateProperty(sptr& windowProperty, PropertyChangeAction action, + bool isAsyncTask = false) override; + WMError GetAccessibilityWindowInfo(std::vector>& infos) override; + WMError GetVisibilityWindowInfo(std::vector>& infos) override; + std::shared_ptr GetSnapshot(int32_t windowId) override; + void NotifyDumpInfoResult(const std::vector& info) override; + bool RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) override; + bool UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) override; + + WMError SetWindowAnimationController(const sptr& controller) override; + WMError GetSystemConfig(SystemConfig& systemConfig) override; + WMError GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) override; + WMError UpdateAvoidAreaListener(uint32_t windowId, bool haveAvoidAreaListener) override; + void StartingWindow(sptr info, std::shared_ptr pixelMap, + bool isColdStart, uint32_t bkgColor = 0xffffffff); + void CancelStartingWindow(sptr abilityToken); + void MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback) override; + WMError UpdateRsTree(uint32_t windowId, bool isAdd) override; + void OnScreenshot(DisplayId displayId); + void OnAccountSwitched(int accountId); + WMError BindDialogTarget(uint32_t& windowId, sptr targetToken) override; + void HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow); + void NotifyWindowClientPointUp(uint32_t windowId, const std::shared_ptr& pointerEvent); + + void SetAnchorAndScale(int32_t x, int32_t y, float scale) override; + void SetAnchorOffset(int32_t deltaX, int32_t deltaY) override; + void OffWindowZoom() override; + void PostAsyncTask(Task task); +protected: + WindowManagerService(); + virtual ~WindowManagerService() = default; + +private: + bool Init(); + void InitWithAbilityManagerServiceAdded(); + void InitWithRanderServiceAdded(); + void WindowVisibilityChangeCallback(std::shared_ptr occlusionData); + void OnWindowEvent(Event event, const sptr& remoteObject); + void NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type); + WMError GetFocusWindowInfo(sptr& abilityToken); + bool CheckSystemWindowPermission(const sptr& property) const; + bool CheckAnimationPermission(const sptr& property) const; + void ConfigureWindowManagerService(); + void PostVoidSyncTask(Task task); + template> + Return PostSyncTask(SyncTask&& task) + { + Return ret; + std::function syncTask([&ret, &task]() {ret = task();}); + if (handler_) { + handler_->PostSyncTask(syncTask, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } + return ret; + } + void ConfigHotZones(const std::vector& hotZones); + void ConfigWindowAnimation(const WindowManagerConfig::ConfigItem& animeConfig); + void ConfigKeyboardAnimation(const WindowManagerConfig::ConfigItem& animeConfig); + RSAnimationTimingCurve CreateCurve(const WindowManagerConfig::ConfigItem& curveConfig); + void RecordShowTimeEvent(int64_t costTime); + void ConfigWindowEffect(const WindowManagerConfig::ConfigItem& effectConfig); + bool ConfigAppWindowCornerRadius(const WindowManagerConfig::ConfigItem& item, float& out); + bool ConfigAppWindowShadow(const WindowManagerConfig::ConfigItem& shadowConfig, WindowShadowParameters& outShadow); + void OnRSScreenConnected(); + void OnRSScreenDisconnected(); + void OnRenderModeChanged(bool isUniRender); + + static inline SingletonDelegator delegator; + std::string name_ = "WindowManagerService"; + AtomicMap accessTokenIdMaps_; + sptr windowRoot_; + sptr windowController_; + sptr inputWindowMonitor_; + sptr snapshotController_; + sptr wmsHandler_; + sptr dragController_; + sptr freezeDisplayController_; + sptr windowDumper_; + SystemConfig systemConfig_; + ModeChangeHotZonesConfig hotZonesConfig_ { false, 0, 0, 0 }; + std::shared_ptr windowCommonEvent_; + std::shared_ptr runner_ = nullptr; + std::shared_ptr handler_ = nullptr; + RSInterfaces& rsInterface_; + bool startingOpen_ = true; + std::shared_ptr rsUiDirector_; + std::shared_ptr windowShowPerformReport_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_WINDOW_MANAGER_SERVICE_H diff --git a/window_manager/wmserver/include/window_node.h b/window_manager/wmserver/include/window_node.h new file mode 100644 index 0000000..4cf5695 --- /dev/null +++ b/window_manager/wmserver/include/window_node.h @@ -0,0 +1,168 @@ +/* + * 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_WINDOW_NODE_H +#define OHOS_ROSEN_WINDOW_NODE_H + +#include +#include +#include +#include +#include "zidl/window_interface.h" +#include "window_manager_hilog.h" +#include "window_node_state_machine.h" + +namespace OHOS { +namespace Rosen { +class WindowNode : public RefBase { +public: + WindowNode(const sptr& property, const sptr& window, + std::shared_ptr surfaceNode) + : surfaceNode_(surfaceNode), property_(property), windowToken_(window) + { + if (property != nullptr) { + abilityInfo_ = property->GetAbilityInfo(); + } + } + WindowNode(const sptr& property, const sptr& window, + std::shared_ptr surfaceNode, int32_t pid, int32_t uid) + : surfaceNode_(surfaceNode), property_(property), windowToken_(window), callingPid_(pid), callingUid_(uid) + { + inputCallingPid_ = pid; + if (property != nullptr) { + abilityInfo_ = property->GetAbilityInfo(); + } + } + WindowNode() : property_(new WindowProperty()) + { + } + explicit WindowNode(const sptr& property) : property_(property) + { + } + ~WindowNode(); + + void SetDisplayId(DisplayId displayId); + void SetEntireWindowTouchHotArea(const Rect& rect); + void SetEntireWindowPointerHotArea(const Rect& rect); + void SetWindowRect(const Rect& rect); + void SetDecoStatus(bool decoStatus); + void SetRequestRect(const Rect& rect); + void SetWindowProperty(const sptr& property); + void SetSystemBarProperty(WindowType type, const SystemBarProperty& property); + void SetWindowMode(WindowMode mode); + void SetBrightness(float brightness); + void SetFocusable(bool focusable); + void SetTouchable(bool touchable); + void SetTurnScreenOn(bool turnScreenOn); + void SetKeepScreenOn(bool keepScreenOn); + void SetCallingWindow(uint32_t windowId); + void SetInputEventCallingPid(int32_t pid); + void SetCallingPid(int32_t pid); + void SetCallingUid(int32_t uid); + void SetWindowToken(sptr window); + uint32_t GetCallingWindow() const; + void SetWindowSizeChangeReason(WindowSizeChangeReason reason); + void SetRequestedOrientation(Orientation orientation); + void SetShowingDisplays(const std::vector& displayIdVec); + void SetModeSupportInfo(uint32_t modeSupportInfo); + void SetDragType(DragType dragType); + void SetOriginRect(const Rect& rect); + void SetTouchHotAreas(const std::vector& rects); + void SetPointerHotAreas(const std::vector& rects); + void SetWindowSizeLimits(const WindowSizeLimits& sizeLimits); + void SetWindowUpdatedSizeLimits(const WindowSizeLimits& sizeLimits); + void ComputeTransform(); + void SetTransform(const Transform& trans); + void SetSnapshot(std::shared_ptr pixelMap); + std::shared_ptr GetSnapshot(); + Transform GetZoomTransform() const; + void UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn); + + const sptr& GetWindowToken() const; + uint32_t GetWindowId() const; + uint32_t GetParentId() const; + const std::string& GetWindowName() const; + DisplayId GetDisplayId() const; + Rect GetEntireWindowTouchHotArea() const; + Rect GetEntireWindowPointerHotArea() const; + Rect GetWindowRect() const; + bool GetDecoStatus() const; + Rect GetRequestRect() const; + WindowType GetWindowType() const; + WindowMode GetWindowMode() const; + float GetBrightness() const; + bool IsTurnScreenOn() const; + bool IsKeepScreenOn() const; + uint32_t GetWindowFlags() const; + const sptr& GetWindowProperty() const; + int32_t GetInputEventCallingPid() const; + int32_t GetCallingPid() const; + int32_t GetCallingUid() const; + const std::unordered_map& GetSystemBarProperty() const; + bool IsSplitMode() const; + WindowSizeChangeReason GetWindowSizeChangeReason() const; + Orientation GetRequestedOrientation() const; + std::vector GetShowingDisplays() const; + uint32_t GetModeSupportInfo() const; + DragType GetDragType() const; + bool GetStretchable() const; + const Rect& GetOriginRect() const; + void ResetWindowSizeChangeReason(); + void GetTouchHotAreas(std::vector& rects) const; + void GetPointerHotAreas(std::vector& rects) const; + uint32_t GetAccessTokenId() const; + WindowSizeLimits GetWindowSizeLimits() const; + WindowSizeLimits GetWindowUpdatedSizeLimits() const; + + bool EnableDefaultAnimation(bool animationPlayed); + sptr parent_; + std::vector> children_; + std::shared_ptr surfaceNode_; + std::shared_ptr leashWinSurfaceNode_ = nullptr; + std::shared_ptr startingWinSurfaceNode_ = nullptr; + sptr dialogTargetToken_ = nullptr; + sptr abilityToken_ = nullptr; + std::shared_ptr keepScreenLock_; + int32_t priority_ { 0 }; + uint32_t zOrder_ { 0 }; + bool requestedVisibility_ { false }; + bool currentVisibility_ { false }; + bool isVisible_ { false }; + bool isAppCrash_ { false }; + bool isPlayAnimationShow_ { false }; // delete when enable state machine + bool isPlayAnimationHide_ { false }; // delete when enable state machine + bool startingWindowShown_ { false }; + bool firstFrameAvaliable_ { false }; + bool isShowingOnMultiDisplays_ { false }; + std::vector showingDisplays_; + AbilityInfo abilityInfo_; + WindowNodeStateMachine stateMachine_; + +private: + sptr property_ = nullptr; + sptr windowToken_ = nullptr; + Rect entireWindowTouchHotArea_ { 0, 0, 0, 0 }; + Rect entireWindowPointerHotArea_ { 0, 0, 0, 0 }; + std::vector touchHotAreas_; // coordinates relative to display. + std::vector pointerHotAreas_; // coordinates relative to display. + std::shared_ptr snapshot_; + int32_t callingPid_ = { 0 }; + int32_t inputCallingPid_ = { 0 }; + int32_t callingUid_ = { 0 }; + WindowSizeChangeReason windowSizeChangeReason_ {WindowSizeChangeReason::UNDEFINED}; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_WINDOW_NODE_H diff --git a/window_manager/wmserver/include/window_node_container.h b/window_manager/wmserver/include/window_node_container.h new file mode 100644 index 0000000..b46a240 --- /dev/null +++ b/window_manager/wmserver/include/window_node_container.h @@ -0,0 +1,200 @@ +/* + * 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_WINDOW_NODE_CONTAINER_H +#define OHOS_ROSEN_WINDOW_NODE_CONTAINER_H + +#include "animation_config.h" +#include "avoid_area_controller.h" +#include "display_info.h" +#include "minimize_app.h" +#include "display_group_controller.h" +#include "display_group_info.h" +#include "window_layout_policy.h" +#include "window_manager.h" +#include "window_node.h" +#include "window_zorder_policy.h" +#include "wm_common.h" +#include "wm_common_inner.h" +#include "window_pair.h" + +namespace OHOS { +namespace Rosen { +using WindowNodeOperationFunc = std::function)>; // return true indicates to stop traverse +class WindowNodeContainer : public RefBase { +public: + WindowNodeContainer(const sptr& displayInfo, ScreenId displayGroupId); + ~WindowNodeContainer(); + WMError ShowStartingWindow(sptr& node); + WMError AddWindowNode(sptr& node, sptr& parentNode, bool afterAnimation = false); + WMError RemoveWindowNode(sptr& node, bool fromAnimation = false); + WMError HandleRemoveWindow(sptr& node); + WMError UpdateWindowNode(sptr& node, WindowUpdateReason reason); + WMError DestroyWindowNode(sptr& node, std::vector& windowIds); + const std::vector& Destroy(); + void AssignZOrder(); + WMError SetFocusWindow(uint32_t windowId); + uint32_t GetFocusWindow() const; + WMError SetActiveWindow(uint32_t windowId, bool byRemoved); + uint32_t GetActiveWindow() const; + void SetDisplayBrightness(float brightness); + float GetDisplayBrightness() const; + void SetBrightnessWindow(uint32_t windowId); + uint32_t GetBrightnessWindow() const; + uint32_t ToOverrideBrightness(float brightness); + void UpdateBrightness(uint32_t id, bool byRemoved); + void HandleKeepScreenOn(const sptr& node, bool requireLock); + AvoidArea GetAvoidAreaByType(const sptr& node, AvoidAreaType avoidAreaType) const; + WMError MinimizeStructuredAppWindowsExceptSelf(const sptr& node); + void TraverseContainer(std::vector>& windowNodes) const; + Rect GetDisplayRect(DisplayId displayId) const; + std::unordered_map GetExpectImmersiveProperty() const; + uint32_t GetWindowCountByType(WindowType windowType); + bool IsForbidDockSliceMove(DisplayId displayId) const; + bool IsDockSliceInExitSplitModeArea(DisplayId displayId) const; + void ExitSplitMode(DisplayId displayId); + + bool IsVerticalDisplay(DisplayId displayId) const; + WMError RaiseZOrderForAppWindow(sptr& node, sptr& parentNode); + sptr GetNextFocusableWindow(uint32_t windowId) const; + sptr GetNextRotatableWindow(uint32_t windowId) const; + sptr GetNextActiveWindow(uint32_t windowId) const; + void MinimizeAllAppWindows(DisplayId displayId); + void MinimizeOldestAppWindow(); + WMError ToggleShownStateForAllAppWindows(std::function restoreFunc, bool restore); + void BackUpAllAppWindows(); + void RestoreAllAppWindows(std::function restoreFunc); + bool IsAppWindowsEmpty() const; + void SetSurfaceNodeVisible(sptr& node, int32_t topPriority, bool visible); + void SetBelowScreenlockVisible(sptr& node, bool visible); + void ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason); + void NotifySystemBarTints(std::vector displayIdVec); + WMError MinimizeAppNodeExceptOptions(MinimizeReason reason, const std::vector &exceptionalIds = {}, + const std::vector &exceptionalModes = {}); + WMError SetWindowMode(sptr& node, WindowMode dstMode); + WMError SwitchLayoutPolicy(WindowLayoutMode mode, DisplayId displayId, bool reorder = false); + void RaiseSplitRelatedWindowToTop(sptr& node); + float GetVirtualPixelRatio(DisplayId displayId) const; + Rect GetDisplayGroupRect() const; + void TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom = true) const; + void UpdateSizeChangeReason(sptr& node, WindowSizeChangeReason reason); + void DropShowWhenLockedWindowIfNeeded(const sptr& node); + + void SetMinimizedByOther(bool isMinimizedByOther); + void GetModeChangeHotZones(DisplayId displayId, + ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config); + sptr GetDisplayInfo(DisplayId displayId); + void UpdateDisplayInfo(sptr displayInfo); + std::vector> GetAllDisplayInfo(); + float GetDisplayVirtualPixelRatio(DisplayId displayId) const; + + // parentDisplayId is the same as displayId in single-display mode + bool AddNodeOnRSTree(sptr& node, DisplayId displayId, DisplayId parentDisplayId, + WindowUpdateType type, bool animationPlayed = false); + // parentDisplayId is the same as displayId in single-display mode + bool RemoveNodeFromRSTree(sptr& node, DisplayId displayId, DisplayId parentDisplayId, + WindowUpdateType type, bool animationPlayed = false); + bool AddAppSurfaceNodeOnRSTree(sptr& node); + + sptr GetLayoutPolicy() const; + sptr GetAvoidController() const; + sptr GetMultiDisplayController() const; + sptr GetRootNode(WindowRootNodeType type) const; + void NotifyDockWindowStateChanged(sptr& node, bool isEnable); + void UpdateCameraFloatWindowStatus(const sptr& node, bool isShowing); + void UpdateAvoidAreaListener(sptr& windowNode, bool haveAvoidAreaListener); + void BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const; + void ProcessWindowAvoidAreaChangeWhenDisplayChange() const; + WindowLayoutMode GetCurrentLayoutMode() const; + void RemoveSingleUserWindowNodes(int accountId); + WMError IsTileRectSatisfiedWithSizeLimits(sptr& node); + bool HasPrivateWindow(); + sptr GetDeskTopWindow(); + static AnimationConfig& GetAnimationConfigRef(); + bool TakeWindowPairSnapshot(DisplayId displayId); + void ClearWindowPairSnapshot(DisplayId displayId); + bool IsScreenLocked(); + void LayoutWhenAddWindowNode(sptr& node, bool afterAnimation = false); +private: + void TraverseWindowNode(sptr& root, std::vector>& windowNodes) const; + sptr FindRoot(WindowType type) const; + sptr FindWindowNodeById(uint32_t id) const; + void UpdateFocusStatus(uint32_t id, bool focused); + void UpdateActiveStatus(uint32_t id, bool isActive); + void NotifyIfAvoidAreaChanged(const sptr& node, const AvoidControlType avoidType) const; + void NotifyIfSystemBarTintChanged(DisplayId displayId) const; + void NotifyIfSystemBarRegionChanged(DisplayId displayId) const; + void NotifyIfKeyboardRegionChanged(const sptr& node, const AvoidControlType avoidType) const; + void TraverseAndUpdateWindowState(WindowState state, int32_t topPriority); + void UpdateWindowTree(sptr& node); + void UpdateWindowState(sptr node, int32_t topPriority, WindowState state); + void HandleKeepScreenOn(const sptr& node, WindowState state); + bool IsTopWindow(uint32_t windowId, sptr& rootNode) const; + sptr FindDividerNode() const; + void RaiseWindowToTop(uint32_t windowId, std::vector>& windowNodes); + void ResetLayoutPolicy(); + bool IsAboveSystemBarNode(sptr node) const; + bool IsSplitImmersiveNode(sptr node) const; + bool TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const; + bool TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const; + void RaiseOrderedWindowToTop(std::vector>& orderedNodes, + std::vector>& windowNodes); + void DumpScreenWindowTree(); + void RaiseInputMethodWindowPriorityIfNeeded(const sptr& node) const; + void ReZOrderShowWhenLockedWindowIfNeeded(const sptr& node); + void RaiseShowWhenLockedWindowIfNeeded(const sptr& node); + void ReZOrderShowWhenLockedWindows(bool up); + + WMError AddWindowNodeOnWindowTree(sptr& node, const sptr& parentNode); + void RemoveWindowNodeFromWindowTree(sptr& node); + void UpdateRSTreeWhenShowingDisplaysChange(sptr& node, + const std::vector& lastShowingDisplays); + bool CheckWindowNodeWhetherInWindowTree(const sptr& node) const; + void UpdateModeSupportInfoWhenKeyguardChange(const sptr& node, bool up); + void RemoveFromRsTreeWhenRemoveWindowNode(sptr& node, bool fromAnimation); + void ProcessInputMethodWindowAddAnimation(sptr& node, std::function updateRSTreeFunc); + uint32_t GetAppWindowNum(); + + float displayBrightness_ = UNDEFINED_BRIGHTNESS; + uint32_t brightnessWindow_ = INVALID_WINDOW_ID; + uint32_t zOrder_ { 0 }; + uint32_t focusedWindow_ { INVALID_WINDOW_ID }; + int32_t focusedPid_ = -1; + uint32_t activeWindow_ = INVALID_WINDOW_ID; + int32_t activePid_ = -1; + bool isScreenLocked_ = false; + + std::vector backupWindowIds_; + std::map backupWindowMode_; + std::map backupDividerWindowRect_; + std::map> backupDisplaySplitWindowMode_; + sptr zorderPolicy_ = new WindowZorderPolicy(); + std::unordered_map> layoutPolicies_; + WindowLayoutMode layoutMode_ = WindowLayoutMode::CASCADE; + std::vector currentCoveredArea_; + std::vector removedIds_; + static AnimationConfig animationConfig_; + + sptr belowAppWindowNode_ = new WindowNode(); + sptr appWindowNode_ = new WindowNode(); + sptr aboveAppWindowNode_ = new WindowNode(); + sptr layoutPolicy_; + sptr avoidController_; + sptr displayGroupController_; + sptr displayGroupInfo_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_NODE_CONTAINER_H diff --git a/window_manager/wmserver/include/window_node_state_machine.h b/window_manager/wmserver/include/window_node_state_machine.h new file mode 100644 index 0000000..19f1952 --- /dev/null +++ b/window_manager/wmserver/include/window_node_state_machine.h @@ -0,0 +1,103 @@ +/* + * 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_ROSEN_WINDOW_NODE_STATE_MACHINE_H +#define OHOS_ROSEN_WINDOW_NODE_STATE_MACHINE_H + +#include +#include +#include +#include +#include +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + using StateTask = std::function; +} +enum class WindowNodeState : uint32_t { + INITIAL, + STARTING_CREATED, + SHOW_ANIMATION_PLAYING, + SHOW_ANIMATION_DONE, + HIDE_ANIMATION_PLAYING, + HIDE_ANIMATION_DONE, + SHOWN, + HIDDEN, + DESTROYED +}; + +class WindowNodeStateMachine { +public: + WindowNodeStateMachine(); + + ~WindowNodeStateMachine(); + + void TransitionTo(WindowNodeState state); + + void UpdateAnimationTaskCount(bool isAdd); + + int32_t GetAnimationCount(); + + bool IsWindowNodeShownOrShowing(); + + bool IsRemoteAnimationPlaying(); + + bool IsWindowNodeHiddenOrHiding(); + + WindowNodeState GetCurrentState(); + + bool IsShowAnimationPlaying(); + + bool IsHideAnimationPlaying(); + + void SetDestroyTaskParam(bool onlySelf); + + bool GetDestroyTaskParam(); + + void SetDestroyTask(StateTask task); + + bool GetDestroyTask(StateTask& task); + + void ResetAnimationTaskCount(int32_t taskCount); + + // test + void SetWindowId(uint32_t id) + { + windowId_ = id; + } + + void SetWindowType(WindowType type) + { + type_ = type; + } + +private: + std::deque> stateTaskQ_; + WindowNodeState currState_ = WindowNodeState::INITIAL; + int32_t taskCount_ = 0; + std::recursive_mutex mutex_; + bool destroyOnlySelf_ = true; + // just for test + uint32_t windowId_ = 0; + WindowType type_ { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW }; + uint32_t count1 = 0; + uint32_t count2 = 0; + StateTask destroyTask_; +}; +} // namespace Rosen +} // namespace OHOS +#endif \ No newline at end of file diff --git a/window_manager/wmserver/include/window_pair.h b/window_manager/wmserver/include/window_pair.h new file mode 100644 index 0000000..1d4606c --- /dev/null +++ b/window_manager/wmserver/include/window_pair.h @@ -0,0 +1,257 @@ +/* + * 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_ROSEN_WINDOW_PAIR_H +#define OHOS_ROSEN_WINDOW_PAIR_H + +#include +#include "class_var_definition.h" +#include "window_node.h" +#include "window_layout_policy.h" +#include "wm_common_inner.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +/** + * @brief Enumerates the status of window pair. + */ +enum class WindowPairStatus : uint32_t { + STATUS_EMPTY, + STATUS_SINGLE_PRIMARY, + STATUS_SINGLE_SECONDARY, + STATUS_PAIRING, + STATUS_PAIRED_DONE +}; + +/** + * @brief Enumerates the message of split event. + */ +enum class SplitEventMsgType : uint32_t { + MSG_SHOW_PRIMARY, + MSG_SHOW_SECONDARY, + MSG_SHOW_DIVIDER, + MSG_DESTROY_DIVIDER, +}; + +class WindowPair : public RefBase { +public: + /** + * @brief Constructor used to create an empty WindowPair instance. + * + * @param displayId the display of window pair + */ + explicit WindowPair(const DisplayId& displayId) : displayId_(displayId) {}; + + /** + * @brief Deconstructor used to deconstruct. + * + */ + ~WindowPair(); + + /** + * @brief Clear window pair. + * + */ + void Clear(); + + /** + * @brief Set split ratio. + * + * @param ratio split ratio + */ + void SetSplitRatio(float ratio); + + /** + * @brief Get split ratio. + * + * @return split ratio + */ + float GetSplitRatio() const; + + /** + * @brief Get whether the window pair is paired.. + * + * @return the pair state of window pair + */ + bool IsPaired() const; + + /** + * @brief Handle changes in the state of the window pair + * + * @param node trigger window node + */ + void UpdateIfSplitRelated(sptr& node); + + /** + * @brief Handle remove window from pair. + * + * @param node target node + */ + void HandleRemoveWindow(sptr& node); + + /** + * @brief Find window node from window pair. + * + * @param node target window node + * @return window node + */ + sptr Find(sptr& node); + + /** + * @brief Get divider window node. + * + * @return divider window node + */ + sptr GetDividerWindow() const; + + /** + * @brief Get pair status. + * + * @return the pair status of window pair + */ + WindowPairStatus GetPairStatus() const; + + /** + * @brief Get all window node form pair in Z order. + * + * @return the list window form pair + */ + std::vector> GetOrderedPair(sptr& node); + + /** + * @brief Get all window node form pair. + * + * @return the list window form pair + */ + std::vector> GetPairedWindows(); + + /** + * @brief Get whether dock slice is forbidden to move. + * + * @return whether dock slice is forbidden to move + */ + bool IsForbidDockSliceMove() const; + + /** + * @brief Exit split screen mode when dock slice in exit split screen mode area. + */ + void ExitSplitMode(); + + /** + * @brief whether dock slice in exit split screen mode area + */ + bool IsDockSliceInExitSplitModeArea(const std::vector& exitSplitPoints); + + /** + * @brief Set the initial rect of divider window. + * + * @param rect divider window rect + */ + void SetDividerRect(const Rect& rect); + + /** + * @brief Update divider window rect when display orientation changed. + * + * @param rect default divider rect + */ + void RotateDividerWindow(const Rect& rect); + + /** + * @brief Take window pair node snapshot. + */ + bool TakePairSnapshot(); + + /** + * @brief Clear window pair node snapshot. + */ + void ClearPairSnapshot(); + +private: + /** + * @brief Gets whether the window is related to split window. + * + * @param node target node + * @return Whether target node is related to the split window + */ + bool IsSplitRelated(sptr& node) const; + + /** + * @brief Replace paired window. + * + * @param node current node + */ + void Insert(sptr& node); + + /** + * @brief Update paired window node + * + */ + void HandlePairedNodesChange(); + + /** + * @brief Update pair status + * + */ + void UpdateWindowPairStatus(); + + /** + * @brief Switch the position of two paired window. + * + */ + void SwitchPosition(); + + /** + * @brief Dump the info of pair. + * + */ + void DumpPairInfo(); + + /** + * @brief Send split screen event. + * + * @param msgType split event message type + * @param missionId mission id + */ + void SendSplitScreenCommonEvent(SplitEventMsgType msgType, int32_t missionId); + + /** + * @brief Send split screen event to notify create recent view. + * + * @param node split node + */ + void NotifyShowRecent(sptr node); + + /** + * @brief Send split screen event to notify create or destroy divider window. + * + * @param node split node + * @param isDestroy destroy or create divider window flag + */ + void NotifyCreateOrDestroyDivider(sptr node, bool isDestroy); + +private: + float ratio_ = DEFAULT_SPLIT_RATIO; + DisplayId displayId_; + sptr primary_; + sptr secondary_; + sptr divider_; + WindowPairStatus status_ = {WindowPairStatus::STATUS_EMPTY}; + Rect dividerRect_ {0, 0, 0, 0}; + DEFINE_VAR_DEFAULT_FUNC_SET(bool, AllSplitAppWindowsRestoring, isAllSplitAppWindowsRestoring, false) +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_PAIR_H \ No newline at end of file diff --git a/window_manager/wmserver/include/window_root.h b/window_manager/wmserver/include/window_root.h new file mode 100644 index 0000000..4045209 --- /dev/null +++ b/window_manager/wmserver/include/window_root.h @@ -0,0 +1,176 @@ +/* + * 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_WINDOW_ROOT_H +#define OHOS_ROSEN_WINDOW_ROOT_H + +#include +#include +#include + +#include "agent_death_recipient.h" +#include "display_manager_service_inner.h" +#include "parameters.h" +#include "window_node_container.h" +#include "zidl/window_manager_agent_interface.h" + +namespace OHOS { +namespace Rosen { +enum class Event : uint32_t { + REMOTE_DIED, +}; + +class WindowRoot : public RefBase { +using Callback = std::function& remoteObject)>; + +public: + explicit WindowRoot(Callback callback) : callback_(callback) {} + ~WindowRoot() = default; + + sptr GetOrCreateWindowNodeContainer(DisplayId displayId); + sptr GetWindowNodeContainer(DisplayId displayId); + sptr CreateWindowNodeContainer(sptr displayInfo); + sptr GetWindowNode(uint32_t windowId) const; + void GetBackgroundNodesByScreenId(ScreenId screenGroupId, std::vector>& windowNodes) const; + + WMError SaveWindow(const sptr& node); + void AddDeathRecipient(sptr node); + sptr FindWindowNodeWithToken(const sptr& token) const; + WMError AddWindowNode(uint32_t parentId, sptr& node, bool fromStartingWin = false); + WMError RemoveWindowNode(uint32_t windowId, bool fromAnimation = false); + WMError DestroyWindow(uint32_t windowId, bool onlySelf); + WMError UpdateWindowNode(uint32_t windowId, WindowUpdateReason reason); + bool IsVerticalDisplay(sptr& node) const; + bool IsForbidDockSliceMove(DisplayId displayId) const; + bool IsDockSliceInExitSplitModeArea(DisplayId displayId) const; + void ExitSplitMode(DisplayId displayId); + void NotifyWindowVisibilityChange(std::shared_ptr occlusionData); + void AddSurfaceNodeIdWindowNodePair(uint64_t surfaceNodeId, sptr node); + + WMError RequestFocus(uint32_t windowId); + WMError RequestActiveWindow(uint32_t windowId); + WMError MinimizeStructuredAppWindowsExceptSelf(sptr& node); + AvoidArea GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType); + WMError SetWindowMode(sptr& node, WindowMode dstMode); + WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId); + void MinimizeAllAppWindows(DisplayId displayId); + WMError ToggleShownStateForAllAppWindows(); + WMError SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mode); + + void ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason); + void ProcessDisplayChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type); + void ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap); + void ProcessDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap); + + void NotifySystemBarTints(); + WMError RaiseZOrderForAppWindow(sptr& node); + void FocusFaultDetection() const; + float GetVirtualPixelRatio(DisplayId displayId) const; + Rect GetDisplayGroupRect(DisplayId displayId) const; + WMError UpdateSizeChangeReason(uint32_t windowId, WindowSizeChangeReason reason); + void SetBrightness(uint32_t windowId, float brightness); + void HandleKeepScreenOn(uint32_t windowId, bool requireLock); + void UpdateFocusableProperty(uint32_t windowId); + void SetMaxAppWindowNumber(uint32_t windowNum); + void SetMaxUniRenderAppWindowNumber(uint32_t uniAppWindowNum); + uint32_t GetMaxUniRenderAppWindowNumber() const; + WMError GetModeChangeHotZones(DisplayId displayId, + ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config); + std::vector GetAllDisplayIds() const; + uint32_t GetTotalWindowNum() const; + uint32_t GetWindowIdByObject(const sptr& remoteObject); + sptr GetWindowForDumpAceHelpInfo() const; + void DestroyLeakStartingWindow(); + void SetSplitRatios(const std::vector& splitRatioNumbers); + std::vector> GetSplitScreenWindowNodes(DisplayId displayId); + void SetExitSplitRatios(const std::vector& exitSplitRatios); + void MinimizeTargetWindows(std::vector& windowIds); + WMError UpdateRsTree(uint32_t windowId, bool isAdd); + void RemoveSingleUserWindowNodes(int accountId); + sptr FindDialogCallerNode(WindowType type, sptr token); + bool CheckMultiDialogWindows(WindowType type, sptr token); + bool HasPrivateWindow(DisplayId displayId); + Rect GetDisplayRectWithoutSystemBarAreas(DisplayId displayId); + void SwitchRenderModeIfNeeded(); + void OnRenderModeChanged(bool isUniRender); + sptr GetWindowNodeByAbilityToken(const sptr& abilityToken); + bool TakeWindowPairSnapshot(DisplayId displayId); + void ClearWindowPairSnapshot(DisplayId displayId); + bool IsUniRender() + { + return renderMode_ == RenderMode::UNIFIED; + } + void LayoutWhenAddWindowNode(sptr& node, bool afterAnimation = false); + void GetAllAnimationPlayingNodes(std::vector>& windowNodes); + void GetVisibilityWindowInfo(std::vector>& infos) const; +private: + enum class RenderMode : uint8_t { + SEPARATED, + UNIFIED, + SEPARATING, + UNIFYING, + }; + + void OnRemoteDied(const sptr& remoteObject); + WMError DestroyWindowInner(sptr& node); + WMError DestroyWindowSelf(sptr& node, const sptr& container); + WMError DestroyWindowWithChild(sptr& node, const sptr& container); + void UpdateFocusWindowWithWindowRemoved(const sptr& node, + const sptr& container) const; + void UpdateActiveWindowWithWindowRemoved(const sptr& node, + const sptr& container) const; + void UpdateBrightnessWithWindowRemoved(uint32_t windowId, const sptr& container) const; + std::string GenAllWindowsLogInfo() const; + bool CheckDisplayInfo(const sptr& display); + ScreenId GetScreenGroupId(DisplayId displayId, bool& isRecordedDisplay); + void ProcessExpandDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, + std::map& displayRectMap); + std::map> GetAllDisplayInfos(const std::vector& displayIdVec); + std::map GetAllDisplayRectsByDMS(sptr displayInfo); + std::map GetAllDisplayRectsByDisplayInfo( + const std::map>& displayInfoMap); + void MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId, DisplayId displayId); + WMError PostProcessAddWindowNode(sptr& node, sptr& parentNode, + sptr& container); + std::vector> GetWindowVisibilityChangeInfo( + std::shared_ptr occlusionData); + bool NeedToStopAddingNode(sptr& node, const sptr& container); + void ChangeRSRenderModeIfNeeded(bool isToUnified); + bool IsAppWindowExceed() const; + + std::map> windowNodeMap_; + std::map, uint32_t> windowIdMap_; + std::map> surfaceIdWindowNodeMap_; + std::shared_ptr lastOcclusionData_ = std::make_shared(); + std::map> windowNodeContainerMap_; + std::map> displayIdMap_; + + bool needCheckFocusWindow = false; + + std::map>> windowManagerAgents_; + + sptr windowDeath_ = new AgentDeathRecipient(std::bind(&WindowRoot::OnRemoteDied, + this, std::placeholders::_1)); + Callback callback_; + uint32_t maxAppWindowNumber_ = 100; + uint32_t maxUniRenderAppWindowNumber_ { maxAppWindowNumber_ }; + SplitRatioConfig splitRatioConfig_ = {0.1, 0.9, {}}; + RenderMode renderMode_ { RenderMode::UNIFIED }; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_ROOT_H diff --git a/window_manager/wmserver/include/window_snapshot/snapshot_controller.h b/window_manager/wmserver/include/window_snapshot/snapshot_controller.h new file mode 100644 index 0000000..440eb74 --- /dev/null +++ b/window_manager/wmserver/include/window_snapshot/snapshot_controller.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-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_ROSEN_SNAPSHOT_CONTROLLER_H +#define OHOS_ROSEN_SNAPSHOT_CONTROLLER_H + +#include +#include + +#include "event_handler.h" +#include "future.h" +#include "snapshot_stub.h" +#include "wm_common_inner.h" +#include "window_root.h" +#include "window_manager_hilog.h" +#include "perform_reporter.h" + +namespace OHOS { +namespace Rosen { +class SnapshotController : public SnapshotStub { +public: + SnapshotController(sptr& root, std::shared_ptr& handler) + : windowRoot_(root), handler_(handler), + performReport_(new PerformReporter("GET_SNAPSHOT_TIME", {25, 35, 50, 200})) {}; + ~SnapshotController() = default; + int32_t GetSnapshot(const sptr &token, AAFwk::Snapshot& snapshot) override; + +private: + sptr windowRoot_; + std::shared_ptr handler_; + std::shared_ptr performReport_; +}; +} // Rosen +} // OHOS +#endif // OHOS_ROSEN_SNAPSHOT_CONTROLLER_H diff --git a/window_manager/wmserver/include/window_snapshot/snapshot_proxy.h b/window_manager/wmserver/include/window_snapshot/snapshot_proxy.h new file mode 100644 index 0000000..cf433d5 --- /dev/null +++ b/window_manager/wmserver/include/window_snapshot/snapshot_proxy.h @@ -0,0 +1,37 @@ +/* + * 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_SNAPSHOT_PROXY_H +#define OHOS_SNAPSHOT_PROXY_H + +#include +#include +#include +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class SnapshotProxy : public IRemoteProxy { +public: + explicit SnapshotProxy(const sptr& impl) : IRemoteProxy(impl) {}; + ~SnapshotProxy() = default; + int32_t GetSnapshot(const sptr &token, AAFwk::Snapshot& snapshot) override; + +private: + static inline BrokerDelegator delegator_; +}; +} +} +#endif // OHOS_SNAPSHOT_PROXY_H diff --git a/window_manager/wmserver/include/window_snapshot/snapshot_stub.h b/window_manager/wmserver/include/window_snapshot/snapshot_stub.h new file mode 100644 index 0000000..76dc374 --- /dev/null +++ b/window_manager/wmserver/include/window_snapshot/snapshot_stub.h @@ -0,0 +1,35 @@ +/* + * 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_SNAPSHOT_STUB_H +#define OHOS_SNAPSHOT_STUB_H + +#include +#include +#include + +namespace OHOS { +using namespace AAFwk; +namespace Rosen { +class SnapshotStub : public IRemoteStub { +public: + SnapshotStub() = default; + ~SnapshotStub() = default; + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) override; +}; +} +} +#endif // OHOS_SNAPSHOT_STUB_H diff --git a/window_manager/wmserver/include/window_zorder_policy.h b/window_manager/wmserver/include/window_zorder_policy.h new file mode 100644 index 0000000..a16e1c4 --- /dev/null +++ b/window_manager/wmserver/include/window_zorder_policy.h @@ -0,0 +1,76 @@ +/* + * 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_WINDOW_ZORDER_POLICY_H +#define OHOS_ROSEN_WINDOW_ZORDER_POLICY_H + +#include +#include + +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +class WindowZorderPolicy : public RefBase { +public: + WindowZorderPolicy() = default; + ~WindowZorderPolicy() = default; + + int32_t GetWindowPriority(WindowType type) const; + +private: + const std::map windowPriorityMap_ { + // sub-windows types + { WindowType::WINDOW_TYPE_MEDIA, -1 }, + { WindowType::WINDOW_TYPE_APP_SUB_WINDOW, 1 }, + { WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW, 1 }, + { WindowType::WINDOW_TYPE_APP_COMPONENT, 1 }, + + // main window + { WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, 0 }, + + // system-specific window + { WindowType::WINDOW_TYPE_WALLPAPER, 0 }, + { WindowType::WINDOW_TYPE_DESKTOP, 1 }, + { WindowType::WINDOW_TYPE_DIALOG, 1 }, + { WindowType::WINDOW_TYPE_APP_LAUNCHING, 101 }, + { WindowType::WINDOW_TYPE_DOCK_SLICE, 0 }, + { WindowType::WINDOW_TYPE_PLACEHOLDER, 0 }, + { WindowType::WINDOW_TYPE_LAUNCHER_RECENT, 102 }, + { WindowType::WINDOW_TYPE_LAUNCHER_DOCK, 103 }, + { WindowType::WINDOW_TYPE_INCOMING_CALL, 104 }, + { WindowType::WINDOW_TYPE_SEARCHING_BAR, 105 }, + { WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW, 106 }, + { WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT, 107 }, + { WindowType::WINDOW_TYPE_FLOAT, 108 }, + { WindowType::WINDOW_TYPE_FLOAT_CAMERA, 108 }, + { WindowType::WINDOW_TYPE_TOAST, 109 }, + { WindowType::WINDOW_TYPE_STATUS_BAR, 110 }, + { WindowType::WINDOW_TYPE_PANEL, 111 }, + { WindowType::WINDOW_TYPE_VOLUME_OVERLAY, 112 }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, 113 }, + { WindowType::WINDOW_TYPE_KEYGUARD, 114 }, + // reserve 115 for app window above keyguard, 116 for input method window above keyguard + { WindowType::WINDOW_TYPE_SCREENSHOT, 117 }, + { WindowType::WINDOW_TYPE_VOICE_INTERACTION, 117 }, + { WindowType::WINDOW_TYPE_DRAGGING_EFFECT, 118 }, + { WindowType::WINDOW_TYPE_POINTER, 119 }, + { WindowType::WINDOW_TYPE_BOOT_ANIMATION, 120 }, + { WindowType::WINDOW_TYPE_FREEZE_DISPLAY, 121 }, + }; +}; +} +} +#endif // OHOS_ROSEN_WINDOW_STATE_H diff --git a/window_manager/wmserver/include/zidl/ressched_report.h b/window_manager/wmserver/include/zidl/ressched_report.h new file mode 100644 index 0000000..583420c --- /dev/null +++ b/window_manager/wmserver/include/zidl/ressched_report.h @@ -0,0 +1,44 @@ +/* + * 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_WINDOW_MANAGER_RESSCHED_REPORT_H +#define OHOS_WINDOW_MANAGER_RESSCHED_REPORT_H + +#include +#include +#include + +namespace OHOS::Rosen { +constexpr uint32_t RES_TYPE_SHOW_REMOTE_ANIMATION = 33; +constexpr int32_t REMOTE_ANIMATION_BEGIN = 0; +constexpr int32_t REMOTE_ANIMATION_END = 1; + +using ReportDataFunc = void (*)(uint32_t resType, int64_t value, + const std::unordered_map& payload); + +ReportDataFunc __attribute__((visibility("default"))) LoadReportDataFunc(); + +class __attribute__((visibility("default"))) ResSchedReport final { +public: + static ResSchedReport& GetInstance(); + void ResSchedDataReport(uint32_t resType, int32_t value = 0, + const std::unordered_map& payload = {}); +private: + ResSchedReport() {} + ~ResSchedReport() {} + ReportDataFunc reportDataFunc_ = nullptr; +}; +} // namespace OHOS::Rosen +#endif // OHOS_WINDOW_MANAGER_RESSCHED_REPORT_H \ No newline at end of file diff --git a/window_manager/wmserver/include/zidl/window_manager_interface.h b/window_manager/wmserver/include/zidl/window_manager_interface.h new file mode 100644 index 0000000..a1e49af --- /dev/null +++ b/window_manager/wmserver/include/zidl/window_manager_interface.h @@ -0,0 +1,116 @@ +/* + * 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_WINDOW_MANAGER_INTERFACE_H +#define OHOS_WINDOW_MANAGER_INTERFACE_H + +#include +#include +#include + +#include "pixel_map.h" +#include "window_property.h" +#include "window_transition_info.h" +#include "zidl/window_interface.h" +#include "zidl/window_manager_agent_interface.h" + +namespace OHOS { +namespace Rosen { +class RSIWindowAnimationController; + +class IWindowManager : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.IWindowManager"); + + enum class WindowManagerMessage : uint32_t { + TRANS_ID_CREATE_WINDOW, + TRANS_ID_ADD_WINDOW, + TRANS_ID_REMOVE_WINDOW, + TRANS_ID_DESTROY_WINDOW, + TRANS_ID_REQUEST_FOCUS, + TRANS_ID_REGISTER_FOCUS_CHANGED_LISTENER, + TRANS_ID_UNREGISTER_FOCUS_CHANGED_LISTENER, + TRANS_ID_REGISTER_WINDOW_MANAGER_AGENT, + TRANS_ID_UNREGISTER_WINDOW_MANAGER_AGENT, + TRANS_ID_GET_AVOID_AREA, + TRANS_ID_GET_TOP_WINDOW_ID, + TRANS_ID_PROCESS_POINT_DOWN, + TRANS_ID_PROCESS_POINT_UP, + TRANS_ID_MINIMIZE_ALL_APP_WINDOWS, + TRANS_ID_TOGGLE_SHOWN_STATE_FOR_ALL_APP_WINDOWS, + TRANS_ID_SET_BACKGROUND_BLUR, + TRANS_ID_SET_ALPHA, + TRANS_ID_UPDATE_LAYOUT_MODE, + TRANS_ID_UPDATE_PROPERTY, + TRANS_ID_GET_ACCESSIBILITY_WINDOW_INFO_ID, + TRANS_ID_GET_VISIBILITY_WINDOW_INFO_ID, + TRANS_ID_ANIMATION_SET_CONTROLLER, + TRANS_ID_GET_SYSTEM_CONFIG, + TRANS_ID_NOTIFY_WINDOW_TRANSITION, + TRANS_ID_GET_FULLSCREEN_AND_SPLIT_HOT_ZONE, + TRANS_ID_GET_ANIMATION_CALLBACK, + TRANS_ID_UPDATE_AVOIDAREA_LISTENER, + TRANS_ID_UPDATE_RS_TREE, + TRANS_ID_BIND_DIALOG_TARGET, + TRANS_ID_NOTIFY_READY_MOVE_OR_DRAG, + TRANS_ID_SET_ANCHOR_AND_SCALE, + TRANS_ID_SET_ANCHOR_OFFSET, + TRANS_ID_OFF_WINDOW_ZOOM, + TRANS_ID_GET_SNAPSHOT, + TRANS_ID_NOTIFY_DUMP_INFO_RESULT, + }; + virtual WMError CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, + uint32_t& windowId, sptr token) = 0; + virtual WMError AddWindow(sptr& property) = 0; + virtual WMError RemoveWindow(uint32_t windowId) = 0; + virtual WMError DestroyWindow(uint32_t windowId, bool onlySelf = false) = 0; + virtual WMError RequestFocus(uint32_t windowId) = 0; + virtual AvoidArea GetAvoidAreaByType(uint32_t windowId, AvoidAreaType type) = 0; + virtual WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) = 0; + virtual void NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) = 0; + virtual void ProcessPointDown(uint32_t windowId, bool isPointDown) = 0; + virtual void ProcessPointUp(uint32_t windowId) = 0; + virtual void MinimizeAllAppWindows(DisplayId displayId) = 0; + virtual WMError ToggleShownStateForAllAppWindows() = 0; + virtual WMError SetWindowLayoutMode(WindowLayoutMode mode) = 0; + virtual WMError UpdateProperty(sptr& windowProperty, PropertyChangeAction action, + bool isAsyncTask = false) = 0; + virtual bool RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) = 0; + virtual bool UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) = 0; + virtual WMError GetAccessibilityWindowInfo(std::vector>& infos) = 0; + virtual WMError GetVisibilityWindowInfo(std::vector>& infos) = 0; + virtual WMError SetWindowAnimationController(const sptr& controller) = 0; + virtual WMError GetSystemConfig(SystemConfig& systemConfig) = 0; + virtual WMError NotifyWindowTransition(sptr& from, sptr& to, + bool isFromClient = false) = 0; + virtual WMError GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) = 0; + virtual void MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback) = 0; + virtual WMError UpdateAvoidAreaListener(uint32_t windowId, bool haveListener) = 0; + virtual WMError UpdateRsTree(uint32_t windowId, bool isAdd) = 0; + virtual WMError BindDialogTarget(uint32_t& windowId, sptr targetToken) = 0; + virtual void SetAnchorAndScale(int32_t x, int32_t y, float scale) = 0; + virtual void SetAnchorOffset(int32_t deltaX, int32_t deltaY) = 0; + virtual void OffWindowZoom() = 0; + virtual std::shared_ptr GetSnapshot(int32_t windowId) = 0; + virtual void NotifyDumpInfoResult(const std::vector& info) {}; +}; +} +} +#endif // OHOS_WINDOW_MANAGER_INTERFACE_H diff --git a/window_manager/wmserver/include/zidl/window_manager_proxy.h b/window_manager/wmserver/include/zidl/window_manager_proxy.h new file mode 100644 index 0000000..fc2695a --- /dev/null +++ b/window_manager/wmserver/include/zidl/window_manager_proxy.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-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_WINDOW_MANAGER_PROXY_H +#define OHOS_WINDOW_MANAGER_PROXY_H + +#include +#include "window_manager_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerProxy : public IRemoteProxy { +public: + explicit WindowManagerProxy(const sptr& impl) : IRemoteProxy(impl) {}; + + ~WindowManagerProxy() {}; + + WMError CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, + uint32_t& windowId, sptr token) override; + WMError AddWindow(sptr& property) override; + WMError RemoveWindow(uint32_t windowId) override; + WMError NotifyWindowTransition(sptr& from, sptr& to, + bool isFromClient = false) override; + WMError DestroyWindow(uint32_t windowId, bool onlySelf = false) override; + WMError RequestFocus(uint32_t windowId) override; + AvoidArea GetAvoidAreaByType(uint32_t windowId, AvoidAreaType type) override; + WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) override; + void NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) override; + void ProcessPointDown(uint32_t windowId, bool isPointDown) override; + void ProcessPointUp(uint32_t windowId) override; + void MinimizeAllAppWindows(DisplayId displayId) override; + WMError ToggleShownStateForAllAppWindows() override; + WMError SetWindowLayoutMode(WindowLayoutMode mode) override; + WMError UpdateProperty(sptr& windowProperty, PropertyChangeAction action, + bool isAsyncTask = false) override; + bool RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) override; + bool UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) override; + WMError SetWindowAnimationController(const sptr& controller) override; + + WMError GetAccessibilityWindowInfo(std::vector>& infos) override; + WMError GetVisibilityWindowInfo(std::vector>& infos) override; + WMError GetSystemConfig(SystemConfig& systemConfig) override; + WMError GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) override; + void MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback) override; + WMError UpdateAvoidAreaListener(uint32_t windowId, bool haveListener) override; + WMError UpdateRsTree(uint32_t windowId, bool isAdd) override; + WMError BindDialogTarget(uint32_t& windowId, sptr targetToken) override; + void SetAnchorAndScale(int32_t x, int32_t y, float scale) override; + void SetAnchorOffset(int32_t deltaX, int32_t deltaY) override; + void OffWindowZoom() override; + std::shared_ptr GetSnapshot(int32_t windowId) override; + void NotifyDumpInfoResult(const std::vector& info) override; +private: + static inline BrokerDelegator delegator_; +}; +} +} +#endif // OHOS_WINDOW_MANAGER_PROXY_H diff --git a/window_manager/wmserver/include/zidl/window_manager_stub.h b/window_manager/wmserver/include/zidl/window_manager_stub.h new file mode 100644 index 0000000..1cfcc03 --- /dev/null +++ b/window_manager/wmserver/include/zidl/window_manager_stub.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021-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_WINDOW_MANAGER_STUB_H +#define OHOS_WINDOW_MANAGER_STUB_H + +#include +#include "window_manager_interface.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerStub : public IRemoteStub { +public: + WindowManagerStub() = default; + ~WindowManagerStub() = default; + virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) override; +}; +} +} +#endif // OHOS_WINDOW_MANAGER_STUB_H diff --git a/window_manager/wmserver/src/README.md b/window_manager/wmserver/src/README.md new file mode 100644 index 0000000..6aa13c7 --- /dev/null +++ b/window_manager/wmserver/src/README.md @@ -0,0 +1 @@ +Store code of window server source files diff --git a/window_manager/wmserver/src/accessibility_connection.cpp b/window_manager/wmserver/src/accessibility_connection.cpp new file mode 100644 index 0000000..3d72219 --- /dev/null +++ b/window_manager/wmserver/src/accessibility_connection.cpp @@ -0,0 +1,162 @@ +/* + * 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 "accessibility_connection.h" + +#include "display_manager_service_inner.h" +#include "window_manager.h" +#include "window_manager_agent_controller.h" +#include "window_manager_hilog.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "AccessibilityConnection"}; +} + +void AccessibilityConnection::NotifyAccessibilityWindowInfo(const sptr& node, WindowUpdateType type) +{ + if (node == nullptr) { + WLOGFE("window node is null"); + return; + } + auto container = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("container is null"); + return; + } + std::vector> nodes; + nodes.emplace_back(node); + UpdateFocusChangeEvent(container); + NotifyAccessibilityWindowInfo(nodes, container->GetFocusWindow(), type); +} + +void AccessibilityConnection::NotifyAccessibilityWindowInfo(DisplayId displayId, + const std::vector>& nodes, WindowUpdateType type) +{ + if (nodes.empty()) { + WLOGFE("nodes is empty"); + return; + } + auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("container is null"); + return; + } + UpdateFocusChangeEvent(container); + NotifyAccessibilityWindowInfo(nodes, container->GetFocusWindow(), type); +} + +void AccessibilityConnection::NotifyAccessibilityWindowInfo(DisplayId displayId, WindowUpdateType type) +{ + auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("container is null"); + return; + } + std::vector> nodes; + container->TraverseContainer(nodes); + UpdateFocusChangeEvent(container); + NotifyAccessibilityWindowInfo(nodes, container->GetFocusWindow(), type); +} + +void AccessibilityConnection::NotifyAccessibilityWindowInfo(const std::vector>& nodes, + uint32_t focusedWindow, WindowUpdateType type) const +{ + std::vector> infos; + FillAccessibilityWindowInfo(nodes, focusedWindow, infos); + if (infos.empty()) { + WLOGFE("infos is empty"); + return; + } + WindowManagerAgentController::GetInstance().NotifyAccessibilityWindowInfo(infos, type); +} + +void AccessibilityConnection::FillAccessibilityWindowInfo(const std::vector>& nodes, + uint32_t focusedWindow, std::vector>& infos) const +{ + for (auto& node : nodes) { + sptr info = new (std::nothrow) AccessibilityWindowInfo(); + if (info == nullptr) { + WLOGFE("new accessibilityWindowInfo is null"); + return; + } + if (node == nullptr) { + WLOGFW("node is null"); + break; + } + info->wid_ = static_cast(node->GetWindowId()); + info->windowRect_ = node->GetWindowRect(); + info->focused_ = node->GetWindowId() == focusedWindow; + info->displayId_ = node->GetDisplayId(); + info->layer_ = node->zOrder_; + info->mode_ = node->GetWindowMode(); + info->type_ = node->GetWindowType(); + auto property = node->GetWindowProperty(); + if (property != nullptr) { + info->isDecorEnable_ = property->GetDecorEnable(); + } + infos.emplace_back(info); + } +} + +void AccessibilityConnection::GetAccessibilityWindowInfo(std::vector>& infos) const +{ + std::map> windowNodeContainers; + std::vector displayIds = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds(); + for (DisplayId displayId : displayIds) { + ScreenId screenGroupId = DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(displayId); + auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (windowNodeContainers.count(screenGroupId) == 0 && container != nullptr) { + windowNodeContainers.insert(std::make_pair(screenGroupId, container)); + std::vector> nodes; + container->TraverseContainer(nodes); + FillAccessibilityWindowInfo(nodes, container->GetFocusWindow(), infos); + } + } +} + +void AccessibilityConnection::UpdateFocusChangeEvent(const sptr& container) +{ + if (container == nullptr) { + WLOGFE("container is null"); + return; + } + bool focusChange = false; + uint32_t focusWindowId = container->GetFocusWindow(); + auto iter = focusedWindowMap_.find(container); + if (iter == focusedWindowMap_.end()) { + focusedWindowMap_.insert(std::make_pair(container, focusWindowId)); + if (focusWindowId != INVALID_WINDOW_ID) { + focusChange = true; + } + } else { + if (focusWindowId != iter->second) { + focusChange = true; + iter->second = focusWindowId; + } + } + if (focusChange) { + auto focusWindowNode = windowRoot_->GetWindowNode(focusWindowId); + if (focusWindowNode == nullptr) { + WLOGFE("could not find window"); + return; + } + std::vector> focusNodes; + focusNodes.emplace_back(focusWindowNode); + WLOGFI("notify accessibility window info: focus change, focusWindowId: %{public}u", focusWindowId); + NotifyAccessibilityWindowInfo(focusNodes, focusWindowId, WindowUpdateType::WINDOW_UPDATE_FOCUSED); + } +} +} diff --git a/window_manager/wmserver/src/avoid_area_controller.cpp b/window_manager/wmserver/src/avoid_area_controller.cpp new file mode 100644 index 0000000..711d48d --- /dev/null +++ b/window_manager/wmserver/src/avoid_area_controller.cpp @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2021-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 "avoid_area_controller.h" + +#include + +#include "display_manager_service_inner.h" +#include "window_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "AvoidAreaController"}; +} + +void AvoidAreaController::UpdateAvoidAreaListener(sptr& windowNode, bool isRegisterListener) +{ + WLOGFE("haveAvoidAreaListener %{public}d", isRegisterListener); + if (windowNode == nullptr) { + WLOGFE("windowNode is nullptr."); + return; + } + if (isRegisterListener) { + avoidAreaListenerNodes_.insert(windowNode); + } else { + lastUpdatedAvoidArea_.erase(windowNode->GetWindowId()); + avoidAreaListenerNodes_.erase(windowNode); + } +} + +void AvoidAreaController::ProcessWindowChange(const sptr& windowNode, AvoidControlType avoidType, + const std::function)>& checkFunc) +{ + if (isForbidProcessingWindowChange_) { + WLOGFI("do not process window change."); + return; + } + if (windowNode == nullptr || windowNode->GetWindowToken() == nullptr) { + WLOGFE("invalid WindowNode."); + return; + } + switch (avoidType) { + case AvoidControlType::AVOID_NODE_ADD: + case AvoidControlType::AVOID_NODE_REMOVE: + AddOrRemoveOverlayWindowIfNeed(windowNode, avoidType == AvoidControlType::AVOID_NODE_ADD); + break; + case AvoidControlType::AVOID_NODE_UPDATE: + UpdateOverlayWindowIfNeed(windowNode, checkFunc); + break; + default: + break; + } +} + +void AvoidAreaController::AddOrRemoveOverlayWindowIfNeed(const sptr& overlayNode, bool isAdding) +{ + if (!WindowHelper::IsOverlayWindow(overlayNode->GetWindowType())) { + WLOGFE("IsOverlayWindow Failed."); + return; + } + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + + uint32_t overlayId = overlayNode->GetWindowId(); + bool isRecorded = (overlayWindowMap_.find(overlayId) != overlayWindowMap_.end()); + if (isAdding == isRecorded) { + WLOGFE("error occured in overlay. overlayId %{public}u isAdding %{public}d record flag %{public}d", + overlayId, isAdding, isRecorded); + return; + } + if (isAdding) { + overlayWindowMap_.insert(std::make_pair(overlayId, overlayNode)); + } else { + overlayWindowMap_.erase(overlayId); + } + + if (overlayNode->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + AddOrRemoveKeyboard(overlayNode, isAdding); + return; + } + + for (auto& node : avoidAreaListenerNodes_) { + AvoidArea systemAvoidArea = GetAvoidAreaByType(node, AvoidAreaType::TYPE_SYSTEM); + UpdateAvoidAreaIfNeed(systemAvoidArea, node, AvoidAreaType::TYPE_SYSTEM); + } +} + +void AvoidAreaController::AddOrRemoveKeyboard(const sptr& keyboardNode, bool isAdding) +{ + const uint32_t callingWindowId = keyboardNode->GetCallingWindow(); + sptr callingWindow = nullptr; + sptr focusWindow = nullptr; + sptr lastKeyboardAreaUpdatedWindow = nullptr; + for (auto window : avoidAreaListenerNodes_) { + if (window == nullptr || window->GetWindowToken() == nullptr) { + continue; + } + if (window->GetWindowId() == callingWindowId) { + callingWindow = window; + } + if (window->GetWindowId() == focusedWindow_) { + focusWindow = window; + } + if (window->GetWindowId() == lastSoftInputKeyboardAreaUpdatedWindowId_) { + lastKeyboardAreaUpdatedWindow = window; + } + } + if (callingWindow == nullptr) { + callingWindow = focusWindow; + } + if (lastKeyboardAreaUpdatedWindow != nullptr && lastKeyboardAreaUpdatedWindow != callingWindow) { + const WindowMode windowMode = lastKeyboardAreaUpdatedWindow->GetWindowMode(); + if (windowMode == WindowMode::WINDOW_MODE_FULLSCREEN || windowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + windowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + auto avoidArea = GetAvoidAreaByType(lastKeyboardAreaUpdatedWindow, AvoidAreaType::TYPE_KEYBOARD); + UpdateAvoidAreaIfNeed(avoidArea, lastKeyboardAreaUpdatedWindow, AvoidAreaType::TYPE_KEYBOARD); + } + } + if (callingWindow == nullptr) { + WLOGFE("callingWindow: %{public}u is nullptr, focusWindow: %{public}u is nullptr.", + callingWindowId, focusedWindow_); + return; + } + const WindowMode callingWindowMode = callingWindow->GetWindowMode(); + if (callingWindowMode == WindowMode::WINDOW_MODE_FULLSCREEN || + callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + auto avoidArea = GetAvoidAreaByType(callingWindow, AvoidAreaType::TYPE_KEYBOARD); + bool res = UpdateAvoidAreaIfNeed(avoidArea, callingWindow, AvoidAreaType::TYPE_KEYBOARD); + if (res) { + lastSoftInputKeyboardAreaUpdatedWindowId_ = callingWindow->GetWindowId(); + } + return; + } + WLOGFE("does not have correct callingWindowMode for input method window"); +} + +void AvoidAreaController::UpdateOverlayWindowIfNeed(const sptr& node, + const std::function)>& checkFunc) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + if (WindowHelper::IsOverlayWindow(node->GetWindowType())) { + AvoidAreaType type = WindowHelper::IsSystemBarWindow(node->GetWindowType()) ? + AvoidAreaType::TYPE_SYSTEM : AvoidAreaType::TYPE_KEYBOARD; + for (auto& appNode : avoidAreaListenerNodes_) { + if (checkFunc != nullptr && checkFunc(appNode)) { + bool res = UpdateAvoidAreaIfNeed(GetAvoidAreaByType(appNode, type), appNode, type); + if (type == AvoidAreaType::TYPE_KEYBOARD && res) { + lastSoftInputKeyboardAreaUpdatedWindowId_ = appNode->GetWindowId(); + } + } + } + } else { + if (avoidAreaListenerNodes_.find(node) == avoidAreaListenerNodes_.end()) { + WLOGE("window: %{public}u is not in avoidAreaListenerNodes, don't update avoid area.", node->GetWindowId()); + return; + } + uint32_t start = static_cast(AvoidAreaType::TYPE_SYSTEM); + uint32_t end = static_cast(AvoidAreaType::TYPE_KEYBOARD); + for (uint32_t type = start; type <= end; type++) { + AvoidArea systemAvoidArea = GetAvoidAreaByType(node, static_cast(type)); + bool res = UpdateAvoidAreaIfNeed(systemAvoidArea, node, static_cast(type)); + if (res && type == static_cast(AvoidAreaType::TYPE_KEYBOARD)) { + lastSoftInputKeyboardAreaUpdatedWindowId_ = node->GetWindowId(); + } + } + } +} + +bool AvoidAreaController::UpdateAvoidAreaIfNeed(const AvoidArea& avoidArea, const sptr& node, + AvoidAreaType avoidAreaType) +{ + auto iter = lastUpdatedAvoidArea_.find(node->GetWindowId()); + bool needUpdate = true; + if (iter != lastUpdatedAvoidArea_.end()) { + auto avoidAreaIter = iter->second.find(avoidAreaType); + if (avoidAreaIter != iter->second.end()) { + needUpdate = avoidAreaIter->second != avoidArea; + } else { + if (avoidArea.isEmptyAvoidArea()) { + needUpdate = false; + } + } + } else { + if (avoidArea.isEmptyAvoidArea()) { + needUpdate = false; + } + } + if (needUpdate) { + lastUpdatedAvoidArea_[node->GetWindowId()][avoidAreaType] = avoidArea; + node->GetWindowToken()->UpdateAvoidArea(new AvoidArea(avoidArea), avoidAreaType); + } + return needUpdate; +} + +AvoidPosType AvoidAreaController::CalculateOverlayRect(const sptr& node, + const sptr& overlayNode, Rect& overlayRect) const +{ + if (node->GetWindowId() == overlayNode->GetWindowId()) { + WLOGE("overlay not support self. windowId %{public}u", node->GetWindowId()); + return AvoidPosType::AVOID_POS_UNKNOWN; + } + const Rect rect = node->GetWindowRect(); + overlayRect = WindowHelper::GetOverlap(overlayNode->GetWindowRect(), rect, rect.posX_, rect.posY_); + return GetAvoidPosType(rect, overlayRect); +} + +AvoidPosType AvoidAreaController::GetAvoidPosType(const Rect& windowRect, const Rect& overlayRect) const +{ + if (windowRect.width_ == 0 || windowRect.height_ == 0) { + return AvoidPosType::AVOID_POS_UNKNOWN; + } + uint32_t centerX = overlayRect.posX_ + (overlayRect.width_ >> 1); + uint32_t centerY = overlayRect.posY_ + (overlayRect.height_ >> 1); + float res1 = float(centerY) - float(windowRect.height_) / float(windowRect.width_) * float(centerX); + float res2 = float(centerY) + float(windowRect.height_) / float(windowRect.width_) * float(centerX) + - float(windowRect.height_); + if (res1 < 0) { + if (res2 < 0) { + return AvoidPosType::AVOID_POS_TOP; + } + return AvoidPosType::AVOID_POS_RIGHT; + } + if (res2 < 0) { + return AvoidPosType::AVOID_POS_LEFT; + } + return AvoidPosType::AVOID_POS_BOTTOM; +} + +void AvoidAreaController::SetAvoidAreaRect(AvoidArea& avoidArea, const Rect& rect, AvoidPosType type) const +{ + switch (type) { + case AvoidPosType::AVOID_POS_TOP : { + avoidArea.topRect_ = rect; + break; + } + case AvoidPosType::AVOID_POS_LEFT : { + avoidArea.leftRect_ = rect; + break; + } + case AvoidPosType::AVOID_POS_RIGHT : { + avoidArea.rightRect_ = rect; + break; + } + case AvoidPosType::AVOID_POS_BOTTOM : { + avoidArea.bottomRect_ = rect; + break; + } + default : { + WLOGFI("default type: %{public}u", type); + } + } +} + +AvoidArea AvoidAreaController::GetAvoidAreaByType(const sptr& node, AvoidAreaType avoidAreaType) const +{ + WLOGFI("avoidAreaType: %{public}u", avoidAreaType); + if (node == nullptr) { + WLOGFE("invalid WindowNode."); + return {}; + } + WindowMode windowMode = node->GetWindowMode(); + if (avoidAreaType != AvoidAreaType::TYPE_KEYBOARD && + windowMode != WindowMode::WINDOW_MODE_FULLSCREEN && + windowMode != WindowMode::WINDOW_MODE_SPLIT_PRIMARY && + windowMode != WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + WLOGFI("avoidAreaType: %{public}u, windowMode: %{public}u, return default avoid area.", + avoidAreaType, windowMode); + return {}; + } + switch (avoidAreaType) { + case AvoidAreaType::TYPE_SYSTEM : { + return GetAvoidAreaSystemType(node); + } + case AvoidAreaType::TYPE_KEYBOARD : { + return GetAvoidAreaKeyboardType(node); + } + case AvoidAreaType::TYPE_CUTOUT : { + sptr cutoutInfo = DisplayManagerServiceInner::GetInstance().GetCutoutInfo(node->GetDisplayId()); + if (cutoutInfo == nullptr) { + WLOGFE("there is no cutoutInfo"); + return {}; + } + std::vector cutoutAreas = cutoutInfo->GetBoundingRects(); + if (cutoutAreas.empty()) { + WLOGFE("there is no cutout"); + return {}; + } + // 0 means the index in the vector. + Rect cutoutAreaRect { cutoutAreas[0].posX_, cutoutAreas[0].posY_, + cutoutAreas[0].width_, cutoutAreas[0].height_ }; + auto rect = node->GetWindowRect(); + Rect overlayRect = WindowHelper::GetOverlap(cutoutAreaRect, rect, rect.posX_, rect.posY_); + auto type = GetAvoidPosType(rect, overlayRect); + AvoidArea avoidArea; + SetAvoidAreaRect(avoidArea, overlayRect, type); + return avoidArea; + } + default : { + WLOGFI("cannot find avoidAreaType: %{public}u", avoidAreaType); + return {}; + } + } +} + +AvoidArea AvoidAreaController::GetAvoidAreaSystemType(const sptr& node) const +{ + AvoidArea systemAvoidArea; + Rect statusBarAvoidArea; + AvoidPosType statusBarAvoidPosType = AvoidPosType::AVOID_POS_UNKNOWN; + Rect navigationBarAvoidArea; + AvoidPosType navigationBarAvoidPosType = AvoidPosType::AVOID_POS_UNKNOWN; + for (auto& iter : overlayWindowMap_) { + if (iter.second != nullptr) { + if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR) { + statusBarAvoidPosType = CalculateOverlayRect(node, iter.second, statusBarAvoidArea); + } + if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR) { + navigationBarAvoidPosType = CalculateOverlayRect(node, iter.second, navigationBarAvoidArea); + } + } + } + SetAvoidAreaRect(systemAvoidArea, statusBarAvoidArea, statusBarAvoidPosType); + SetAvoidAreaRect(systemAvoidArea, navigationBarAvoidArea, navigationBarAvoidPosType); + return systemAvoidArea; +} + +AvoidArea AvoidAreaController::GetAvoidAreaKeyboardType(const sptr& node) const +{ + for (auto& iter : overlayWindowMap_) { + if (iter.second != nullptr && + iter.second->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + const uint32_t callingWindowId = iter.second->GetCallingWindow(); + if (callingWindowId != node->GetWindowId() && focusedWindow_ != node->GetWindowId()) { + WLOGFI("windowId: %{public}u is not focusedWindow: %{public}u or callingWindow: %{public}u", + node->GetWindowId(), focusedWindow_, callingWindowId); + continue; + } + Rect avoidAreaRect { 0, 0, 0, 0 }; + AvoidPosType avoidPosType = CalculateOverlayRect(node, iter.second, avoidAreaRect); + AvoidArea avoidArea; + SetAvoidAreaRect(avoidArea, avoidAreaRect, avoidPosType); + return avoidArea; + } + } + return {}; +} +} +} diff --git a/window_manager/wmserver/src/display_group_controller.cpp b/window_manager/wmserver/src/display_group_controller.cpp new file mode 100644 index 0000000..19b5ee2 --- /dev/null +++ b/window_manager/wmserver/src/display_group_controller.cpp @@ -0,0 +1,523 @@ +/* + * 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 "display_group_controller.h" + +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "window_node_container.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayGroupController"}; +} + +void DisplayGroupController::InitNewDisplay(DisplayId displayId) +{ + // system bar map for display + SysBarNodeMap sysBarNodeMap { + { WindowType::WINDOW_TYPE_STATUS_BAR, nullptr }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, nullptr }, + }; + sysBarNodeMaps_.insert(std::make_pair(displayId, sysBarNodeMap)); + + SysBarTintMap sysBarTintMap { + { WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarRegionTint() }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarRegionTint() }, + }; + sysBarTintMaps_.insert(std::make_pair(displayId, sysBarTintMap)); + + // window node maps for display + std::map>>> displayWindowTree; + displayWindowTree.insert(std::make_pair(WindowRootNodeType::APP_WINDOW_NODE, + std::make_unique>>())); + displayWindowTree.insert(std::make_pair(WindowRootNodeType::ABOVE_WINDOW_NODE, + std::make_unique>>())); + displayWindowTree.insert(std::make_pair(WindowRootNodeType::BELOW_WINDOW_NODE, + std::make_unique>>())); + displayGroupWindowTree_.insert(std::make_pair(displayId, std::move(displayWindowTree))); + + // window pair for display + auto windowPair = new WindowPair(displayId); + windowPairMap_.insert(std::make_pair(displayId, windowPair)); +} + +std::vector>* DisplayGroupController::GetWindowNodesByDisplayIdAndRootType(DisplayId displayId, + WindowRootNodeType type) +{ + if (displayGroupWindowTree_.find(displayId) != displayGroupWindowTree_.end()) { + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + if (displayWindowTree.find(type) != displayWindowTree.end()) { + return displayWindowTree[type].get(); + } + } + return nullptr; +} + +void DisplayGroupController::AddWindowNodeOnWindowTree(sptr& node, WindowRootNodeType rootType) +{ + std::vector>* rootNodeVectorPtr = GetWindowNodesByDisplayIdAndRootType(node->GetDisplayId(), + rootType); + if (rootNodeVectorPtr != nullptr) { + rootNodeVectorPtr->push_back(node); + WLOGFD("add node in node vector of root, displayId: %{public}" PRIu64" windowId: %{public}d, " + "rootType: %{public}d", node->GetDisplayId(), node->GetWindowId(), rootType); + } else { + WLOGFE("add node failed, rootNode vector is empty, windowId: %{public}d, rootType: %{public}d", + node->GetWindowId(), rootType); + } +} + +void DisplayGroupController::UpdateDisplayGroupWindowTree() +{ + // clear ori window tree of displayGroup + for (auto& elem : displayGroupWindowTree_) { + for (auto& nodeVec : elem.second) { + auto emptyVector = std::vector>(); + nodeVec.second->swap(emptyVector); + } + } + std::vector rootNodeType = { + WindowRootNodeType::ABOVE_WINDOW_NODE, + WindowRootNodeType::APP_WINDOW_NODE, + WindowRootNodeType::BELOW_WINDOW_NODE + }; + for (auto& rootType : rootNodeType) { + auto rootNode = windowNodeContainer_->GetRootNode(rootType); + if (rootNode == nullptr) { + WLOGFE("rootNode is nullptr, %{public}d", rootType); + continue; + } + for (auto& node : rootNode->children_) { + AddWindowNodeOnWindowTree(node, rootType); + } + } +} + +void DisplayGroupController::ProcessCrossNodes(DisplayId defaultDisplayId, DisplayStateChangeType type) +{ + defaultDisplayId_ = defaultDisplayId; + for (auto& iter : displayGroupWindowTree_) { + auto nodeVec = *(iter.second[WindowRootNodeType::APP_WINDOW_NODE]); + for (auto node : nodeVec) { + if (node->isShowingOnMultiDisplays_) { + WLOGFD("process cross node, windowId: %{public}u, displayId: %{public}" PRIu64"", + node->GetWindowId(), node->GetDisplayId()); + auto showingDisplays = node->GetShowingDisplays(); + + DisplayId newDisplayId; + if (type == DisplayStateChangeType::SIZE_CHANGE || type == DisplayStateChangeType::UPDATE_ROTATION || + type == DisplayStateChangeType::DISPLAY_COMPRESS) { + newDisplayId = node->GetDisplayId(); + } else { + newDisplayId = defaultDisplayId; + } + + for (auto& displayId : showingDisplays) { + if (displayId == newDisplayId) { + continue; + } + windowNodeContainer_->RemoveNodeFromRSTree(node, displayId, newDisplayId, + WindowUpdateType::WINDOW_UPDATE_ACTIVE); + } + // update shown displays and displayId + MoveCrossNodeToTargetDisplay(node, newDisplayId); + } + } + } +} + +void DisplayGroupController::UpdateWindowShowingDisplays(const sptr& node) +{ + auto leftDisplayId = displayGroupInfo_->GetLeftDisplayId(); + auto rightDisplayId = displayGroupInfo_->GetRightDisplayId(); + auto displayRectMap = displayGroupInfo_->GetAllDisplayRects(); + auto showingDisplays = std::vector(); + const auto& winRect = node->GetWindowRect(); + for (auto& elem : displayRectMap) { + auto& curDisplayRect = elem.second; + + // if window is showing in display region + if (((winRect.posX_ + static_cast(winRect.width_)) > curDisplayRect.posX_) && + (winRect.posX_ < (curDisplayRect.posX_ + static_cast(curDisplayRect.width_)))) { + showingDisplays.push_back(elem.first); + } + } + + // if window is not showing on any display, maybe in the left of minPosX display, or the right of maxPosX display + if (showingDisplays.empty()) { + if (((winRect.posX_ + static_cast(winRect.width_)) <= + displayRectMap[leftDisplayId].posX_)) { + showingDisplays.push_back(leftDisplayId); + } + if (winRect.posX_ >= + (displayRectMap[rightDisplayId].posX_ + static_cast(displayRectMap[rightDisplayId].width_))) { + showingDisplays.push_back(rightDisplayId); + } + } + + // mean that this is cross-display window + if (showingDisplays.size() > 1) { + node->isShowingOnMultiDisplays_ = true; + } else { + node->isShowingOnMultiDisplays_ = false; + } + node->SetShowingDisplays(showingDisplays); +} + +void DisplayGroupController::UpdateWindowDisplayIdIfNeeded(const sptr& node) +{ + // current multi-display is only support left-right combination, maxNum is two + DisplayId newDisplayId = node->GetDisplayId(); + const auto& curShowingDisplays = node->GetShowingDisplays(); + if (curShowingDisplays.empty()) { + WLOGFE("id:%{public}u not show on any display!", node->GetWindowId()); + return; + } + const auto& winRect = node->GetWindowRect(); + if (curShowingDisplays.size() == 1) { + newDisplayId = *(curShowingDisplays.begin()); + } else { + // if more than half width of the window is showing on the display, means the window belongs to this display + int32_t halfWidth = static_cast(winRect.width_ * 0.5); + const auto& displayRectMap = displayGroupInfo_->GetAllDisplayRects(); + for (auto& elem : displayRectMap) { + auto& displayRect = elem.second; + if ((winRect.posX_ < displayRect.posX_) && + (winRect.posX_ + static_cast(winRect.width_) > + displayRect.posX_ + static_cast(displayRect.width_))) { // window covers whole display region + newDisplayId = elem.first; + break; + } + if (winRect.posX_ >= displayRect.posX_) { // current display is default display + if ((displayRect.posX_ + static_cast(displayRect.width_) - winRect.posX_) >= halfWidth) { + newDisplayId = elem.first; + break; + } + } else { // current display is expand display + if ((winRect.posX_ + static_cast(winRect.width_) - displayRect.posX_) >= halfWidth) { + newDisplayId = elem.first; + break; + } + } + } + } + + // update displayId if needed + if (node->GetDisplayId() != newDisplayId) { + UpdateWindowDisplayId(node, newDisplayId); + UpdateDisplayGroupWindowTree(); + } +} + +void DisplayGroupController::ChangeToRectInDisplayGroup(const sptr& node, DisplayId displayId) +{ + Rect requestRect = node->GetRequestRect(); + const Rect& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + requestRect.posX_ += displayRect.posX_; + requestRect.posY_ += displayRect.posY_; + node->SetRequestRect(requestRect); + + std::vector curShowingDisplays = { node->GetDisplayId() }; + node->SetShowingDisplays(curShowingDisplays); +} + +void DisplayGroupController::PreProcessWindowNode(const sptr& node, WindowUpdateType type) +{ + if (!windowNodeContainer_->GetLayoutPolicy()->IsMultiDisplay()) { + if (type == WindowUpdateType::WINDOW_UPDATE_ADDED) { + std::vector curShowingDisplays = { node->GetDisplayId() }; + node->SetShowingDisplays(curShowingDisplays); + for (auto& childNode : node->children_) { + PreProcessWindowNode(childNode, type); + } + } + WLOGFD("Current mode is not multi-display"); + return; + } + + switch (type) { + case WindowUpdateType::WINDOW_UPDATE_ADDED: { + if (!node->isShowingOnMultiDisplays_) { + // change rect to rect in display group + ChangeToRectInDisplayGroup(node, node->GetDisplayId()); + } + WLOGFD("preprocess node when add window"); + break; + } + case WindowUpdateType::WINDOW_UPDATE_ACTIVE: { + // MoveTo can be called by user, calculate rect in display group if the reason is move + if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) { + ChangeToRectInDisplayGroup(node, defaultDisplayId_); + } + WLOGFD("preprocess node when update window"); + break; + } + default: + break; + } + + for (auto& childNode : node->children_) { + PreProcessWindowNode(childNode, type); + } +} + +void DisplayGroupController::PostProcessWindowNode(const sptr& node) +{ + if (!windowNodeContainer_->GetLayoutPolicy()->IsMultiDisplay()) { + WLOGFD("Current mode is not multi-display"); + return; + } + + UpdateWindowShowingDisplays(node); + UpdateWindowDisplayIdIfNeeded(node); +} + +void DisplayGroupController::UpdateWindowDisplayId(const sptr& node, DisplayId newDisplayId) +{ + WLOGFD("update node displayId, srcDisplayId: %{public}" PRIu64", newDisplayId: %{public}" PRIu64"", + node->GetDisplayId(), newDisplayId); + if (node->GetWindowToken()) { + node->GetWindowToken()->UpdateDisplayId(node->GetDisplayId(), newDisplayId); + } + node->SetDisplayId(newDisplayId); +} + +void DisplayGroupController::MoveCrossNodeToTargetDisplay(const sptr& node, DisplayId targetDisplayId) +{ + node->isShowingOnMultiDisplays_ = false; + // update showing display + std::vector newShowingDisplays = { targetDisplayId }; + node->SetShowingDisplays(newShowingDisplays); + // update new displayId + if (node->GetDisplayId() != targetDisplayId) { + UpdateWindowDisplayId(node, targetDisplayId); + } + + for (auto& childNode : node->children_) { + MoveCrossNodeToTargetDisplay(childNode, targetDisplayId); + } +} + +void DisplayGroupController::MoveNotCrossNodeToDefaultDisplay(const sptr& node, DisplayId displayId) +{ + WLOGFD("windowId: %{public}d, displayId: %{public}" PRIu64"", node->GetWindowId(), displayId); + // update new rect in display group + const Rect& srcDisplayRect = displayGroupInfo_->GetDisplayRect(displayId); + const Rect& dstDisplayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayId_); + Rect newRect = node->GetRequestRect(); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_POINTER) { + newRect.posX_ = static_cast(dstDisplayRect.width_ / 2); // default pointerX : displayRect.width / 2 + newRect.posY_ = static_cast(dstDisplayRect.height_ / 2); // default pointerY : displayRect.height / 2 + } else { + newRect.posX_ = newRect.posX_ - srcDisplayRect.posX_ + dstDisplayRect.posX_; + newRect.posY_ = newRect.posY_ - srcDisplayRect.posY_ + dstDisplayRect.posY_; + } + + node->SetRequestRect(newRect); + // update showing display + std::vector newShowingDisplays = { defaultDisplayId_ }; + node->SetShowingDisplays(newShowingDisplays); + // update new displayId + UpdateWindowDisplayId(node, defaultDisplayId_); + + for (auto& childNode : node->children_) { + MoveNotCrossNodeToDefaultDisplay(childNode, displayId); + } +} + +void DisplayGroupController::ProcessNotCrossNodesOnDestroyedDisplay(DisplayId displayId, + std::vector& windowIds) +{ + if (displayId == defaultDisplayId_) { + WLOGFE("Move window nodes failed, displayId is the same as defaultDisplayId"); + return; + } + if (displayGroupWindowTree_.find(displayId) == displayGroupWindowTree_.end()) { + WLOGFE("displayId: %{public}" PRIu64" not in display group window tree", displayId); + return; + } + WLOGFI("move window nodes for display destroy, displayId: %{public}" PRIu64"", displayId); + + std::vector rootNodeType = { + WindowRootNodeType::ABOVE_WINDOW_NODE, + WindowRootNodeType::APP_WINDOW_NODE, + WindowRootNodeType::BELOW_WINDOW_NODE + }; + for (const auto& type : rootNodeType) { + if (displayGroupWindowTree_[displayId].find(type) == displayGroupWindowTree_[displayId].end()) { + continue; + } + auto nodesVec = *(displayGroupWindowTree_[displayId][type]); + for (auto node : nodesVec) { + WLOGFD("node on destroied display, windowId: %{public}d, isShowingOnMulti: %{public}d", + node->GetWindowId(), node->isShowingOnMultiDisplays_); + if (node->GetDisplayId() != displayId || node->isShowingOnMultiDisplays_) { + continue; + } + // destroy status and navigation bar + if (node->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR || + node->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR) { + windowNodeContainer_->DestroyWindowNode(node, windowIds); + WLOGFW("destroy status or navigation bar on destroyed display, windowId: %{public}d", + node->GetWindowId()); + continue; + } + // move not cross-display nodes to default display + MoveNotCrossNodeToDefaultDisplay(node, displayId); + + // update RS tree + windowNodeContainer_->RemoveNodeFromRSTree(node, displayId, defaultDisplayId_, + WindowUpdateType::WINDOW_UPDATE_ACTIVE); + windowNodeContainer_->AddNodeOnRSTree(node, defaultDisplayId_, defaultDisplayId_, + WindowUpdateType::WINDOW_UPDATE_ACTIVE); + } + } +} + +void DisplayGroupController::ProcessDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, + const std::map& displayRectMap) +{ + WindowInnerManager::GetInstance().NotifyDisplayChange(displayRectMap); + defaultDisplayId_ = defaultDisplayId; + WLOGFI("defaultDisplay, displayId: %{public}" PRIu64"", defaultDisplayId); + + DisplayId displayId = displayInfo->GetDisplayId(); + + InitNewDisplay(displayId); + + // add displayInfo in displayGroupInfo + displayGroupInfo_->AddDisplayInfo(displayInfo); + + // modify RSTree and window tree of displayGroup for cross-display nodes + ProcessCrossNodes(defaultDisplayId, DisplayStateChangeType::CREATE); + UpdateDisplayGroupWindowTree(); + const auto& layoutPolicy = windowNodeContainer_->GetLayoutPolicy(); + layoutPolicy->ProcessDisplayCreate(displayId, displayRectMap); + Rect initialDividerRect = layoutPolicy->GetDividerRect(displayId); + SetDividerRect(displayId, initialDividerRect); +} + +void DisplayGroupController::ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr displayInfo, + const std::map& displayRectMap, + std::vector& windowIds) +{ + WindowInnerManager::GetInstance().NotifyDisplayChange(displayRectMap); + DisplayId displayId = displayInfo->GetDisplayId(); + + // delete nodes and map element of deleted display + ProcessNotCrossNodesOnDestroyedDisplay(displayId, windowIds); + // modify RSTree and window tree of displayGroup for cross-display nodes + ProcessCrossNodes(defaultDisplayId, DisplayStateChangeType::DESTROY); + UpdateDisplayGroupWindowTree(); + ClearMapOfDestroyedDisplay(displayId); + windowNodeContainer_->GetLayoutPolicy()->ProcessDisplayDestroy(displayId, displayRectMap); +} + +void DisplayGroupController::UpdateNodeSizeChangeReasonWithRotation(DisplayId displayId) +{ + std::vector rootNodeType = { + WindowRootNodeType::ABOVE_WINDOW_NODE, + WindowRootNodeType::APP_WINDOW_NODE, + WindowRootNodeType::BELOW_WINDOW_NODE + }; + for (auto& rootType : rootNodeType) { + std::vector>* rootNodeVectorPtr = GetWindowNodesByDisplayIdAndRootType(displayId, rootType); + if (rootNodeVectorPtr == nullptr) { + WLOGFE("rootNodeVectorPtr is nullptr, %{public}d, displayId: %{public}" PRIu64, rootType, displayId); + return; + } + for (auto& node : (*rootNodeVectorPtr)) { + // DOCK_SLICE not need do rotation animation + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + continue; + } + node->SetWindowSizeChangeReason(WindowSizeChangeReason::ROTATION); + } + } +} + +void DisplayGroupController::ProcessDisplayChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map& displayRectMap, + DisplayStateChangeType type) +{ + WindowInnerManager::GetInstance().NotifyDisplayChange(displayRectMap); + DisplayId displayId = displayInfo->GetDisplayId(); + WLOGFI("display change, displayId: %{public}" PRIu64", type: %{public}d", displayId, type); + switch (type) { + case DisplayStateChangeType::UPDATE_ROTATION: { + displayGroupInfo_->SetDisplayRotation(displayId, displayInfo->GetRotation()); + [[fallthrough]]; + } + case DisplayStateChangeType::DISPLAY_COMPRESS: + case DisplayStateChangeType::SIZE_CHANGE: { + ProcessDisplaySizeChangeOrRotation(defaultDisplayId, displayId, displayRectMap, type); + break; + } + case DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE: { + displayGroupInfo_->SetDisplayVirtualPixelRatio(displayId, displayInfo->GetVirtualPixelRatio()); + windowNodeContainer_->GetLayoutPolicy()->LayoutWindowTree(displayId); + break; + } + default: { + break; + } + } +} + +void DisplayGroupController::ProcessDisplaySizeChangeOrRotation(DisplayId defaultDisplayId, DisplayId displayId, + const std::map& displayRectMap, DisplayStateChangeType type) +{ + // modify RSTree and window tree of displayGroup for cross-display nodes + ProcessCrossNodes(defaultDisplayId, type); + UpdateDisplayGroupWindowTree(); + const auto& layoutPolicy = windowNodeContainer_->GetLayoutPolicy(); + if (layoutPolicy == nullptr) { + return; + } + // update reason after process cross Nodes to get correct display attribution + UpdateNodeSizeChangeReasonWithRotation(displayId); + layoutPolicy->ProcessDisplaySizeChangeOrRotation(displayId, displayRectMap); + Rect curDividerRect = layoutPolicy->GetDividerRect(displayId); + if (windowPairMap_[displayId] != nullptr) { + windowPairMap_[displayId]->RotateDividerWindow(curDividerRect); + } +} + +void DisplayGroupController::ClearMapOfDestroyedDisplay(DisplayId displayId) +{ + sysBarTintMaps_.erase(displayId); + sysBarNodeMaps_.erase(displayId); + displayGroupWindowTree_.erase(displayId); + displayGroupInfo_->RemoveDisplayInfo(displayId); + windowPairMap_.erase(displayId); +} + +sptr DisplayGroupController::GetWindowPairByDisplayId(DisplayId displayId) +{ + if (windowPairMap_.find(displayId) != windowPairMap_.end()) { + return windowPairMap_[displayId]; + } + return nullptr; +} + +void DisplayGroupController::SetDividerRect(DisplayId displayId, const Rect& rect) +{ + if (windowPairMap_.find(displayId) != windowPairMap_.end()) { + windowPairMap_[displayId]->SetDividerRect(rect); + } +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/display_group_info.cpp b/window_manager/wmserver/src/display_group_info.cpp new file mode 100644 index 0000000..c6a602d --- /dev/null +++ b/window_manager/wmserver/src/display_group_info.cpp @@ -0,0 +1,181 @@ +/* + * 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 "display_group_info.h" + +#include +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayGroupInfo"}; +} + +DisplayGroupInfo::DisplayGroupInfo(ScreenId displayGroupId, const sptr& displayInfo) +{ + displayGroupId_ = displayGroupId; + AddDisplayInfo(displayInfo); +} + +void DisplayGroupInfo::AddDisplayInfo(const sptr& displayInfo) +{ + DisplayId displayId = displayInfo->GetDisplayId(); + if (displayInfosMap_.find(displayId) != displayInfosMap_.end()) { + WLOGFE("current display is exits, displayId: %{public}" PRIu64"", displayId); + return; + } + displayInfosMap_.insert(std::make_pair(displayId, displayInfo)); +} + +void DisplayGroupInfo::RemoveDisplayInfo(DisplayId displayId) +{ + if (displayInfosMap_.find(displayId) == displayInfosMap_.end()) { + WLOGFE("current display is not exits, displayId: %{public}" PRIu64"", displayId); + return; + } + displayInfosMap_.erase(displayId); +} + +void DisplayGroupInfo::UpdateLeftAndRightDisplayId() +{ + auto displayRectMap = GetAllDisplayRects(); + leftDisplayId_ = displayRectMap.begin()->first; + rightDisplayId_ = displayRectMap.begin()->first; + for (auto& elem : displayRectMap) { + auto& curDisplayRect = elem.second; + if (curDisplayRect.posX_ < displayRectMap[leftDisplayId_].posX_) { + leftDisplayId_ = elem.first; + } + if ((curDisplayRect.posX_ + static_cast(curDisplayRect.width_)) > + (displayRectMap[rightDisplayId_].posX_ + static_cast(displayRectMap[rightDisplayId_].width_))) { + rightDisplayId_ = elem.first; + } + } + WLOGFI("max posX displayId: %{public}" PRIu64", min posX displayId: %{public}" PRIu64"", + rightDisplayId_, leftDisplayId_); +} + +void DisplayGroupInfo::SetDisplayRotation(DisplayId displayId, Rotation rotation) +{ + if (displayInfosMap_.find(displayId) == displayInfosMap_.end()) { + WLOGFE("current display is not exits, displayId: %{public}" PRIu64"", displayId); + return; + } + displayInfosMap_[displayId]->SetRotation(rotation); +} + +void DisplayGroupInfo::SetDisplayVirtualPixelRatio(DisplayId displayId, float vpr) +{ + if (displayInfosMap_.find(displayId) == displayInfosMap_.end()) { + WLOGFE("current display is not exits, displayId: %{public}" PRIu64"", displayId); + return; + } + displayInfosMap_[displayId]->SetVirtualPixelRatio(vpr); +} + +void DisplayGroupInfo::SetDisplayRect(DisplayId displayId, Rect displayRect) +{ + if (displayInfosMap_.find(displayId) == displayInfosMap_.end()) { + WLOGFE("current display is not exits, displayId: %{public}" PRIu64"", displayId); + return; + } + auto& displayInfo = displayInfosMap_[displayId]; + displayInfo->SetOffsetX(displayRect.posX_); + displayInfo->SetOffsetY(displayRect.posY_); + displayInfo->SetWidth(displayRect.width_); + displayInfo->SetHeight(displayRect.height_); +} + +Rotation DisplayGroupInfo::GetDisplayRotation(DisplayId displayId) const +{ + Rotation rotation = Rotation::ROTATION_0; + if (displayInfosMap_.find(displayId) != displayInfosMap_.end()) { + auto& displayInfo = displayInfosMap_[displayId]; + rotation = displayInfo->GetRotation(); + } + return rotation; +} + +float DisplayGroupInfo::GetDisplayVirtualPixelRatio(DisplayId displayId) const +{ + float vpr = 1.0; + if (displayInfosMap_.find(displayId) != displayInfosMap_.end()) { + auto& displayInfo = displayInfosMap_[displayId]; + vpr = displayInfo->GetVirtualPixelRatio(); + } + return vpr; +} + +std::map DisplayGroupInfo::GetAllDisplayRects() const +{ + std::map displayRectMap; + for (auto elem : displayInfosMap_) { + auto& displayInfo = elem.second; + Rect displayRect = { displayInfo->GetOffsetX(), displayInfo->GetOffsetY(), + displayInfo->GetWidth(), displayInfo->GetHeight() }; + displayRectMap.insert(std::make_pair(elem.first, displayRect)); + } + return displayRectMap; +} + +Rect DisplayGroupInfo::GetDisplayRect(DisplayId displayId) const +{ + Rect rect; + if (displayInfosMap_.find(displayId) != displayInfosMap_.end()) { + auto& displayInfo = displayInfosMap_[displayId]; + rect = { displayInfo->GetOffsetX(), displayInfo->GetOffsetY(), + displayInfo->GetWidth(), displayInfo->GetHeight() }; + } + return rect; +} + +sptr DisplayGroupInfo::GetDisplayInfo(DisplayId displayId) const +{ + if (displayInfosMap_.find(displayId) != displayInfosMap_.end()) { + return displayInfosMap_[displayId]; + } + return nullptr; +} + +void DisplayGroupInfo::UpdateDisplayInfo(sptr displayInfo) const +{ + DisplayId displayId = displayInfo->GetDisplayId(); + if (displayInfosMap_.find(displayId) != displayInfosMap_.end()) { + displayInfosMap_[displayId] = displayInfo; + WLOGFD("Update displayInfo"); + } +} + +std::vector> DisplayGroupInfo::GetAllDisplayInfo() const +{ + std::vector> displayInfos; + for (auto& iter : displayInfosMap_) { + displayInfos.push_back(iter.second); + } + return displayInfos; +} + +DisplayId DisplayGroupInfo::GetLeftDisplayId() const +{ + return leftDisplayId_; +} + +DisplayId DisplayGroupInfo::GetRightDisplayId() const +{ + return rightDisplayId_; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/display_zoom_controller.cpp b/window_manager/wmserver/src/display_zoom_controller.cpp new file mode 100644 index 0000000..1b33799 --- /dev/null +++ b/window_manager/wmserver/src/display_zoom_controller.cpp @@ -0,0 +1,352 @@ +/* + * 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 "display_zoom_controller.h" +#include "window_helper.h" + +namespace OHOS::Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayZoomController"}; +} + +void DisplayZoomController::SetAnchorAndScale(int32_t x, int32_t y, float scale) +{ + WLOGFD("DisplayZoom: On, anchor x:%{public}d, y:%{public}d, scale:%{public}f", x, y, scale); + if (scale <= 0) { + return; + } else if (zoomInfo_.scale * scale < DISPLAY_ZOOM_MIN_SCALE) { + scale = DISPLAY_ZOOM_MIN_SCALE / zoomInfo_.scale; + } else if (zoomInfo_.scale * scale > DISPLAY_ZOOM_MAX_SCALE) { + scale = DISPLAY_ZOOM_MAX_SCALE / zoomInfo_.scale; + } + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + sptr windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (windowNodeContainer == nullptr) { + return; + } + std::vector> windowNodes; + windowNodeContainer->TraverseContainer(windowNodes); + bool isAlreadyCalcu = false; + for (auto& node : windowNodes) { + if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != + displayZoomWindowTypeSkipped_.end()) { + continue; + } + Transform zoomTrans; + if (!isAlreadyCalcu) { + zoomTrans = CalcuZoomTrans(node, {x, y, scale, 0, 0}); + zoomInfo_.scale *= scale; + Rect rect = node->GetWindowRect(); + zoomInfo_.pivotX = rect.posX_ + zoomTrans.pivotX_ * rect.width_; + zoomInfo_.pivotY = rect.posY_ + zoomTrans.pivotY_ * rect.height_; + zoomInfo_.translateX = zoomTrans.translateX_; + zoomInfo_.translateY = zoomTrans.translateY_; + isAlreadyCalcu = true; + } else { + zoomTrans = CalcuZoomTransByZoomInfo(node); + } + UpdateClientAndSurfaceZoomInfo(node, zoomTrans); + } +} + +void DisplayZoomController::SetAnchorOffset(int32_t deltaX, int32_t deltaY) +{ + WLOGFD("DisplayZoom: SetAnchorOffset"); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + sptr windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (windowNodeContainer == nullptr) { + return; + } + if (!UpdateZoomTranslateInfo(windowNodeContainer, displayId, deltaX, deltaY)) { + return; + } + WindowNodeOperationFunc translateFunc = [this, deltaX, deltaY](sptr node) { + if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != + displayZoomWindowTypeSkipped_.end()) { + return false; + } + Transform zoomTrans = node->GetZoomTransform(); + zoomTrans.translateX_ += static_cast(deltaX); + zoomTrans.translateY_ += static_cast(deltaY); + UpdateClientAndSurfaceZoomInfo(node, zoomTrans); + return false; + }; + windowNodeContainer->TraverseWindowTree(translateFunc, false); +} + +void DisplayZoomController::OffWindowZoom() +{ + WLOGFD("DisplayZoom: Off"); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + sptr windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (windowNodeContainer == nullptr) { + return; + } + zoomInfo_ = {0, 0, 1.0, 0, 0}; + std::vector> windowNodes; + windowNodeContainer->TraverseContainer(windowNodes); + for (auto& node : windowNodes) { + if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != + displayZoomWindowTypeSkipped_.end()) { + continue; + } + ClearZoomTransformInner(node); + } +} + +void DisplayZoomController::UpdateAllWindowsZoomInfo(DisplayId displayId) +{ + if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) { + return; + } + DisplayId defaultDisplayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + if (defaultDisplayId != displayId) { + return; + } + sptr windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (windowNodeContainer == nullptr) { + return; + } + int32_t deltaX, deltaY; + deltaX = deltaY = 0; + if (UpdateZoomTranslateInfo(windowNodeContainer, displayId, deltaX, deltaY)) { + WLOGFD("Change ZoomInfo translation, deltaX:%{public}d, deltaY:%{public}d", deltaX, deltaY); + } + std::vector> windowNodes; + windowNodeContainer->TraverseContainer(windowNodes); + for (auto& node: windowNodes) { + HandleUpdateWindowZoomInfo(node); + } +} + +void DisplayZoomController::UpdateWindowZoomInfo(uint32_t windowId) +{ + if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) { + return; + } + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + return; + } + if (!node->currentVisibility_) { + return; + } + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + if (node->GetDisplayId() != displayId) { + return; + } + std::vector> windowNodes; + windowNodes.push_back(node); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + windowNodes = windowRoot_->GetSplitScreenWindowNodes(node->GetDisplayId()); + } + for (auto& windowNode: windowNodes) { + HandleUpdateWindowZoomInfo(windowNode); + } +} + +void DisplayZoomController::ClearZoomTransform(std::vector> nodes) +{ + if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) { + return; + } + for (auto& node: nodes) { + ClearZoomTransformInner(node); + } +} + +void DisplayZoomController::ClearZoomTransformInner(sptr node) +{ + Transform recoverTrans; + node->UpdateZoomTransform(recoverTrans, false); + auto surfaceNode = node->leashWinSurfaceNode_ ? node->leashWinSurfaceNode_ : node->surfaceNode_; + if (!node->GetWindowProperty()->IsAnimateWindow()) { + TransformSurfaceNode(surfaceNode, recoverTrans); + } +} + +bool DisplayZoomController::UpdateZoomTranslateInfo(sptr windowNodeContainer, + DisplayId displayId, int32_t& deltaX, int32_t& deltaY) +{ + sptr deskTop = windowNodeContainer->GetDeskTopWindow(); + if (deskTop == nullptr) { + WLOGFE("DisplayZoom: can't find deskTop windowNode"); + return false; + } + Transform zoomTrans = deskTop->GetZoomTransform(); + Rect originalRect = deskTop->GetWindowRect(); + Rect zoomRect = originalRect; + if (zoomTrans != Transform::Identity()) { + deskTop->ComputeTransform(); + zoomRect = WindowHelper::TransformRect(deskTop->GetWindowProperty()->GetTransformMat(), originalRect); + } + sptr displayInfo = windowNodeContainer->GetDisplayInfo(displayId); + if (displayInfo == nullptr) { + WLOGFE("DisplayZoom: can't get displayInfo"); + return false; + } + int32_t deltaXMax = displayInfo->GetOffsetX() - zoomRect.posX_; + int32_t deltaXMin = displayInfo->GetOffsetX() + displayInfo->GetWidth() - zoomRect.posX_ + - static_cast(zoomRect.width_); + int32_t deltaYMax = displayInfo->GetOffsetY() - zoomRect.posY_; + int32_t deltaYMin = displayInfo->GetOffsetY() + displayInfo->GetHeight() - zoomRect.posY_ + - static_cast(zoomRect.height_); + deltaX = MathHelper::Clamp(deltaX, deltaXMin, deltaXMax); + deltaY = MathHelper::Clamp(deltaY, deltaYMin, deltaYMax); + if (deltaX == 0 && deltaY == 0) { + return false; + } + zoomInfo_.translateX += deltaX; + zoomInfo_.translateY += deltaY; + return true; +} + +Transform DisplayZoomController::CalcuAnimateZoomTrans(sptr node) +{ + Rect rect = node->GetWindowRect(); + if (rect.width_ == 0 || rect.height_ == 0) { + return Transform::Identity(); + } + Transform lastZoomTrans = CalcuZoomTransByZoomInfo(node); + TransformHelper::Vector3 lastPivotPos = { rect.posX_ + lastZoomTrans.pivotX_ * rect.width_, + rect.posY_ + lastZoomTrans.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 lastWorldMat = TransformHelper::CreateTranslation(-lastPivotPos) * + WindowHelper::ComputeWorldTransformMat4(lastZoomTrans) * + TransformHelper::CreateTranslation(lastPivotPos); + + Transform animateTrans = node->GetWindowProperty()->GetTransform(); + if (animateTrans.translateZ_ != 0.f) { + node->GetWindowProperty()->ClearTransformZAxisOffset(animateTrans); + } + TransformHelper::Vector3 animatePivotPos = { rect.posX_ + animateTrans.pivotX_ * rect.width_, + rect.posY_ + animateTrans.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 animateWorldMat = TransformHelper::CreateTranslation(-animatePivotPos) * + WindowHelper::ComputeWorldTransformMat4(animateTrans) * + TransformHelper::CreateTranslation(animatePivotPos); + + TransformHelper::Matrix4 finalWorldMat = animateWorldMat * lastWorldMat; + Transform finalZoomTrans; + finalZoomTrans.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; + finalZoomTrans.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; + TransformHelper::Vector3 scale = finalWorldMat.GetScale(); + TransformHelper::Vector3 translation = finalWorldMat.GetTranslation(); + finalZoomTrans.scaleX_ = scale.x_; + finalZoomTrans.scaleY_ = scale.y_; + finalZoomTrans.translateX_ = translation.x_; + finalZoomTrans.translateY_ = translation.y_; + finalZoomTrans.translateZ_ = translation.z_; + finalZoomTrans.rotationX_ = animateTrans.rotationX_; + finalZoomTrans.rotationY_ = animateTrans.rotationY_; + finalZoomTrans.rotationZ_ = animateTrans.rotationZ_; + + return finalZoomTrans; +} + +Transform DisplayZoomController::CalcuZoomTransByZoomInfo(sptr node) +{ + Transform zoomTrans; + Rect rect = node->GetWindowRect(); + if (rect.width_ == 0 || rect.height_ == 0) { + return zoomTrans; + } + zoomTrans.pivotX_ = (zoomInfo_.pivotX - rect.posX_) * 1.0 / rect.width_; + zoomTrans.pivotY_ = (zoomInfo_.pivotY - rect.posY_) * 1.0 / rect.height_; + zoomTrans.scaleX_ = zoomTrans.scaleY_ = zoomInfo_.scale; + zoomTrans.translateX_ = zoomInfo_.translateX; + zoomTrans.translateY_ = zoomInfo_.translateY; + return zoomTrans; +} + +Transform DisplayZoomController::CalcuZoomTrans(sptr node, const DisplayZoomInfo& zoomInfo) +{ + Rect rect = node->GetWindowRect(); + if (rect.width_ == 0 || rect.height_ == 0) { + return Transform::Identity(); + } + Transform lastZoomTrans = node->GetZoomTransform(); + TransformHelper::Vector3 lastPivotPos = { rect.posX_ + lastZoomTrans.pivotX_ * rect.width_, + rect.posY_ + lastZoomTrans.pivotY_ * rect.height_, 0 }; + TransformHelper::Matrix4 lastWorldMat = TransformHelper::CreateTranslation(-lastPivotPos) * + WindowHelper::ComputeWorldTransformMat4(lastZoomTrans) * + TransformHelper::CreateTranslation(lastPivotPos); + + Transform zoomTrans; + zoomTrans.scaleX_ = zoomTrans.scaleY_ = zoomInfo.scale; + zoomTrans.translateX_ = zoomInfo.translateX; + zoomTrans.translateY_ = zoomInfo.translateY; + TransformHelper::Vector3 pivotPos = { zoomInfo.pivotX, zoomInfo.pivotY, 0 }; + TransformHelper::Matrix4 worldMat = TransformHelper::CreateTranslation(-pivotPos) * + WindowHelper::ComputeWorldTransformMat4(zoomTrans) * + TransformHelper::CreateTranslation(pivotPos); + + TransformHelper::Matrix4 finalWorldMat = lastWorldMat * worldMat; + Transform finalZoomTrans; + finalZoomTrans.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; + finalZoomTrans.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; + TransformHelper::Vector3 scale = finalWorldMat.GetScale(); + TransformHelper::Vector3 translation = finalWorldMat.GetTranslation(); + finalZoomTrans.scaleX_ = scale.x_; + finalZoomTrans.scaleY_ = scale.y_; + finalZoomTrans.translateX_ = translation.x_; + finalZoomTrans.translateY_ = translation.y_; + + return finalZoomTrans; +} + +void DisplayZoomController::UpdateClientAndSurfaceZoomInfo(sptr node, const Transform& zoomTrans) +{ + node->UpdateZoomTransform(zoomTrans, true); + auto surfaceNode = node->leashWinSurfaceNode_ ? node->leashWinSurfaceNode_ : node->surfaceNode_; + if (!node->GetWindowProperty()->IsAnimateWindow()) { + TransformSurfaceNode(surfaceNode, zoomTrans); + } + WLOGFD("%{public}s zoomTrans, pivotX:%{public}f, pivotY:%{public}f, scaleX:%{public}f, scaleY:%{public}f" + ", transX:%{public}f, transY:%{public}f, transZ:%{public}f, rotateX:%{public}f, rotateY:%{public}f " + "rotateZ:%{public}f", node->GetWindowName().c_str(), zoomTrans.pivotX_, zoomTrans.pivotY_, zoomTrans.scaleX_, + zoomTrans.scaleY_, zoomTrans.translateX_, zoomTrans.translateY_, zoomTrans.translateZ_, zoomTrans.rotationX_, + zoomTrans.rotationY_, zoomTrans.rotationZ_); +} + +void DisplayZoomController::HandleUpdateWindowZoomInfo(sptr node) +{ + if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != + displayZoomWindowTypeSkipped_.end()) { + return; + } + Transform zoomTrans; + if (node->GetWindowProperty()->IsAnimateWindow()) { + zoomTrans = CalcuAnimateZoomTrans(node); + } else { + zoomTrans = CalcuZoomTransByZoomInfo(node); + } + UpdateClientAndSurfaceZoomInfo(node, zoomTrans); +} + +void DisplayZoomController::TransformSurfaceNode(std::shared_ptr surfaceNode, const Transform& trans) +{ + if (surfaceNode == nullptr) { + return; + } + surfaceNode->SetPivotX(trans.pivotX_); + surfaceNode->SetPivotY(trans.pivotY_); + surfaceNode->SetScaleX(trans.scaleX_); + surfaceNode->SetScaleY(trans.scaleY_); + surfaceNode->SetTranslateX(trans.translateX_); + surfaceNode->SetTranslateY(trans.translateY_); + surfaceNode->SetTranslateZ(trans.translateZ_); + surfaceNode->SetRotationX(trans.rotationX_); + surfaceNode->SetRotationY(trans.rotationY_); + surfaceNode->SetRotation(trans.rotationZ_); +} +} \ No newline at end of file diff --git a/window_manager/wmserver/src/drag_controller.cpp b/window_manager/wmserver/src/drag_controller.cpp new file mode 100644 index 0000000..b8b419b --- /dev/null +++ b/window_manager/wmserver/src/drag_controller.cpp @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2021-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 "drag_controller.h" + +#include + +#include "display.h" +#include "vsync_station.h" +#include "wm_common.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "window_manager_service.h" +#include "window_node.h" +#include "window_node_container.h" +#include "window_property.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DragController"}; +} + +void DragController::UpdateDragInfo(uint32_t windowId) +{ + PointInfo point; + if (!GetHitPoint(windowId, point)) { + return; + } + 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; + } + auto token = hitWindowNode->GetWindowToken(); + if (token) { + if (hitWindowNode->GetWindowId() == hitWindowId_) { + token->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_MOVE); + return; + } + token->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_IN); + } + sptr oldHitWindow = windowRoot_->GetWindowNode(hitWindowId_); + if (oldHitWindow != nullptr && oldHitWindow->GetWindowToken()) { + oldHitWindow->GetWindowToken()->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_OUT); + } + hitWindowId_ = hitWindowNode->GetWindowId(); +} + +void DragController::StartDrag(uint32_t windowId) +{ + PointInfo point; + if (!GetHitPoint(windowId, point)) { + WLOGFE("Get hit point failed"); + return; + } + 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; + } + if (hitWindow->GetWindowToken()) { + hitWindow->GetWindowToken()->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_IN); + } + hitWindowId_ = windowId; + WLOGFI("start Drag"); +} + +void DragController::FinishDrag(uint32_t windowId) +{ + sptr node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("get node failed"); + return; + } + if (node->GetWindowType() != WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { + return; + } + + sptr hitWindow = windowRoot_->GetWindowNode(hitWindowId_); + if (hitWindow != nullptr) { + auto property = node->GetWindowProperty(); + PointInfo point = {property->GetWindowRect().posX_ + property->GetHitOffset().x, + property->GetWindowRect().posY_ + property->GetHitOffset().y}; + if (hitWindow->GetWindowToken()) { + hitWindow->GetWindowToken()->UpdateWindowDragInfo(point, DragEvent::DRAG_EVENT_END); + } + } + WLOGFI("end drag"); +} + +sptr DragController::GetHitWindow(DisplayId id, PointInfo point) +{ + // Need get display by point + if (id == DISPLAY_ID_INVALID) { + WLOGFE("Get invalid display"); + return nullptr; + } + sptr container = windowRoot_->GetOrCreateWindowNodeContainer(id); + if (container == nullptr) { + WLOGFE("get container failed %{public}" PRIu64"", id); + return nullptr; + } + + std::vector> windowNodes; + container->TraverseContainer(windowNodes); + for (auto windowNode : windowNodes) { + if (windowNode->GetWindowType() >= WindowType::WINDOW_TYPE_PANEL) { + continue; + } + if (WindowHelper::IsPointInTargetRect(point.x, point.y, windowNode->GetWindowRect())) { + return windowNode; + } + } + return nullptr; +} + +bool DragController::GetHitPoint(uint32_t windowId, PointInfo& point) +{ + sptr windowNode = windowRoot_->GetWindowNode(windowId); + if (windowNode == nullptr || windowNode->GetWindowType() != WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { + WLOGFE("Get hit point failed"); + return false; + } + sptr property = windowNode->GetWindowProperty(); + point.x = property->GetWindowRect().posX_ + property->GetHitOffset().x; + point.y = property->GetWindowRect().posY_ + property->GetHitOffset().y; + return true; +} + +void DragInputEventListener::OnInputEvent(std::shared_ptr keyEvent) const +{ + if (keyEvent == nullptr) { + WLOGFE("KeyEvent is nullptr"); + return; + } + uint32_t windowId = static_cast(keyEvent->GetAgentWindowId()); + WLOGFD("[WMS] Receive keyEvent, windowId: %{public}u", windowId); + keyEvent->MarkProcessed(); +} + +void DragInputEventListener::OnInputEvent(std::shared_ptr axisEvent) const +{ + if (axisEvent == nullptr) { + WLOGFE("AxisEvent is nullptr"); + return; + }; + WLOGFD("[WMS] Receive axisEvent, windowId: %{public}u", axisEvent->GetAgentWindowId()); + axisEvent->MarkProcessed(); +} + +void DragInputEventListener::OnInputEvent(std::shared_ptr pointerEvent) const +{ + if (pointerEvent == nullptr) { + WLOGFE("PointerEvent is nullptr"); + return; + } + uint32_t windowId = static_cast(pointerEvent->GetAgentWindowId()); + WLOGFD("[WMS] Receive pointerEvent, windowId: %{public}u", windowId); + + WindowInnerManager::GetInstance().ConsumePointerEvent(pointerEvent); +} + +void MoveDragController::SetInputEventConsumer() +{ + if (!inputListener_ || !inputEventHandler_) { + WLOGFE("InputListener or inputEventHandler is nullptr"); + return; + } + MMI::InputManager::GetInstance()->SetWindowInputEventConsumer(inputListener_, inputEventHandler_); +} + +bool MoveDragController::Init() +{ + // create handler for input event + inputEventHandler_ = std::make_shared( + AppExecFwk::EventRunner::Create(INNER_WM_INPUT_THREAD_NAME)); + if (inputEventHandler_ == nullptr) { + return false; + } + inputListener_ = std::make_shared(DragInputEventListener()); + SetInputEventConsumer(); + VsyncStation::GetInstance().SetIsMainHandlerAvailable(false); + VsyncStation::GetInstance().SetVsyncEventHandler(inputEventHandler_); + return true; +} + +void MoveDragController::Stop() +{ + if (inputEventHandler_ != nullptr) { + inputEventHandler_.reset(); + } +} + +void MoveDragController::HandleReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) +{ + SetActiveWindowId(windowId); + SetWindowProperty(windowProperty); + SetDragProperty(moveDragProperty); +} + +void MoveDragController::HandleEndUpMovingOrDragging(uint32_t windowId) +{ + if (activeWindowId_ != windowId) { + WLOGFE("end up moving or dragging failed, windowId: %{public}u", windowId); + return; + } + ResetMoveOrDragState(); +} + +void MoveDragController::HandleWindowRemovedOrDestroyed(uint32_t windowId) +{ + if (GetMoveDragProperty() == nullptr) { + return; + } + if (!(GetMoveDragProperty()->startMoveFlag_ || GetMoveDragProperty()->startDragFlag_)) { + return; + } + VsyncStation::GetInstance().RemoveCallback(); + ResetMoveOrDragState(); +} + +void MoveDragController::ConvertPointerPosToDisplayGroupPos(DisplayId displayId, int32_t& posX, int32_t& posY) +{ + if (displayRectMap_.size() <= 1) { + return; + } + + auto iter = displayRectMap_.find(displayId); + if (iter == displayRectMap_.end()) { + return; + } + auto displayRect = iter->second; + posX += displayRect.posX_; + posY += displayRect.posY_; +} + +void MoveDragController::HandleDisplayChange(const std::map& displayRectMap) +{ + displayRectMap_.clear(); + for (auto& elem : displayRectMap) { + displayRectMap_.insert(elem); + } +} + +void MoveDragController::ConsumePointerEvent(const std::shared_ptr& pointerEvent) +{ + if (pointerEvent == nullptr) { + WLOGFE("pointerEvent is nullptr or is handling pointer event"); + return; + } + if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) { + moveEvent_ = pointerEvent; + VsyncStation::GetInstance().RequestVsync(vsyncCallback_); + } else { + WLOGFD("[WMS] Dispatch non-move event, action: %{public}d", pointerEvent->GetPointerAction()); + HandlePointerEvent(pointerEvent); + pointerEvent->MarkProcessed(); + } +} + +void MoveDragController::OnReceiveVsync(int64_t timeStamp) +{ + if (moveEvent_ == nullptr) { + WLOGFE("moveEvent is nullptr"); + return; + } + WLOGFD("[OnReceiveVsync] receive move event, action: %{public}d", moveEvent_->GetPointerAction()); + HandlePointerEvent(moveEvent_); + moveEvent_->MarkProcessed(); +} + +Rect MoveDragController::GetHotZoneRect() +{ + auto startPointPosX = moveDragProperty_->startPointPosX_; + auto startPointPosY = moveDragProperty_->startPointPosY_; + ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY); + + Rect hotZoneRect; + const auto& startRectExceptCorner = moveDragProperty_->startRectExceptCorner_; + const auto& startRectExceptFrame = moveDragProperty_->startRectExceptFrame_; + if ((startPointPosX > startRectExceptCorner.posX_ && + (startPointPosX < startRectExceptCorner.posX_ + + static_cast(startRectExceptCorner.width_))) && + (startPointPosY > startRectExceptCorner.posY_ && + (startPointPosY < startRectExceptCorner.posY_ + + static_cast(startRectExceptCorner.height_)))) { + hotZoneRect = startRectExceptFrame; // drag type: left/right/top/bottom + } else { + hotZoneRect = startRectExceptCorner; // drag type: left_top/right_top/left_bottom/right_bottom + } + return hotZoneRect; +} + +void MoveDragController::HandleDragEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType) +{ + if (moveDragProperty_ == nullptr) { + return; + } + if (!moveDragProperty_->startDragFlag_ || + (pointId != moveDragProperty_->startPointerId_) || + (sourceType != moveDragProperty_->sourceType_)) { + return; + } + auto startPointPosX = moveDragProperty_->startPointPosX_; + auto startPointPosY = moveDragProperty_->startPointPosY_; + ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY); + const auto& startPointRect = moveDragProperty_->startPointRect_; + Rect newRect = startPointRect; + Rect hotZoneRect = GetHotZoneRect(); + int32_t diffX = posX - startPointPosX; + int32_t diffY = posY - startPointPosY; + + if (startPointPosX <= hotZoneRect.posX_) { + if (diffX > static_cast(startPointRect.width_)) { + diffX = static_cast(startPointRect.width_); + } + newRect.posX_ += diffX; + newRect.width_ = static_cast(static_cast(newRect.width_) - diffX); + } else if (startPointPosX >= hotZoneRect.posX_ + static_cast(hotZoneRect.width_)) { + if (diffX < 0 && (-diffX > static_cast(startPointRect.width_))) { + diffX = -(static_cast(startPointRect.width_)); + } + newRect.width_ = static_cast(static_cast(newRect.width_) + diffX); + } + if (startPointPosY <= hotZoneRect.posY_) { + if (diffY > static_cast(startPointRect.height_)) { + diffY = static_cast(startPointRect.height_); + } + newRect.posY_ += diffY; + newRect.height_ = static_cast(static_cast(newRect.height_) - diffY); + } else if (startPointPosY >= hotZoneRect.posY_ + static_cast(hotZoneRect.height_)) { + if (diffY < 0 && (-diffY > static_cast(startPointRect.height_))) { + diffY = -(static_cast(startPointRect.height_)); + } + newRect.height_ = static_cast(static_cast(newRect.height_) + diffY); + } + WLOGFD("[WMS] HandleDragEvent, id: %{public}u, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]", + windowProperty_->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); + windowProperty_->SetRequestRect(newRect); + windowProperty_->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG); + windowProperty_->SetDragType(moveDragProperty_->dragType_); + WindowManagerService::GetInstance().UpdateProperty(windowProperty_, PropertyChangeAction::ACTION_UPDATE_RECT, true); +} + +void MoveDragController::HandleMoveEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType) +{ + if (moveDragProperty_ == nullptr) { + return; + } + if (!moveDragProperty_->startMoveFlag_ || + (pointId != moveDragProperty_->startPointerId_) || + (sourceType != moveDragProperty_->sourceType_)) { + return; + } + auto startPointPosX = moveDragProperty_->startPointPosX_; + auto startPointPosY = moveDragProperty_->startPointPosY_; + ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY); + int32_t targetX = moveDragProperty_->startPointRect_.posX_ + (posX - startPointPosX); + int32_t targetY = moveDragProperty_->startPointRect_.posY_ + (posY - startPointPosY); + + const Rect& oriRect = windowProperty_->GetRequestRect(); + Rect newRect = { targetX, targetY, oriRect.width_, oriRect.height_ }; + WLOGFD("[WMS] HandleMoveEvent, id: %{public}u, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]", + windowProperty_->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); + windowProperty_->SetRequestRect(newRect); + windowProperty_->SetWindowSizeChangeReason(WindowSizeChangeReason::MOVE); + WindowManagerService::GetInstance().UpdateProperty(windowProperty_, PropertyChangeAction::ACTION_UPDATE_RECT, true); +} + +void MoveDragController::HandlePointerEvent(const std::shared_ptr& pointerEvent) +{ + if (windowProperty_) { + windowProperty_->UpdatePointerEvent(pointerEvent); + } + MMI::PointerEvent::PointerItem pointerItem; + int32_t pointId = pointerEvent->GetPointerId(); + int32_t sourceType = pointerEvent->GetSourceType(); + if (!pointerEvent->GetPointerItem(pointId, pointerItem) || + (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE && + pointerEvent->GetButtonId() != MMI::PointerEvent::MOUSE_BUTTON_LEFT)) { + WLOGFW("invalid pointerEvent"); + return; + } + + int32_t pointPosX = pointerItem.GetDisplayX(); + int32_t pointPosY = pointerItem.GetDisplayY(); + int32_t action = pointerEvent->GetPointerAction(); + int32_t targetDisplayId = pointerEvent->GetTargetDisplayId(); + ConvertPointerPosToDisplayGroupPos(targetDisplayId, pointPosX, pointPosY); + switch (action) { + case MMI::PointerEvent::POINTER_ACTION_DOWN: + case MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN: { + if (pointId == moveDragProperty_->startPointerId_ && sourceType == moveDragProperty_->sourceType_) { + moveDragProperty_->startMoveFlag_ = false; + moveDragProperty_->startDragFlag_ = false; + } + WLOGFD("[Server Point Down]: windowId: %{public}u, pointId: %{public}d, sourceType: %{public}d, " + "hasPointStarted: %{public}d, startMove: %{public}d, startDrag: %{public}d, targetDisplayId: " + "%{public}d, pointPos: [%{public}d, %{public}d]", activeWindowId_, pointId, sourceType, + moveDragProperty_->pointEventStarted_, moveDragProperty_->startMoveFlag_, + moveDragProperty_->startDragFlag_, targetDisplayId, pointPosX, pointPosY); + break; + } + // ready to move or drag + case MMI::PointerEvent::POINTER_ACTION_MOVE: { + HandleMoveEvent(pointPosX, pointPosY, pointId, sourceType); + HandleDragEvent(pointPosX, pointPosY, pointId, sourceType); + break; + } + // End move or drag + case MMI::PointerEvent::POINTER_ACTION_UP: + case MMI::PointerEvent::POINTER_ACTION_BUTTON_UP: + case MMI::PointerEvent::POINTER_ACTION_CANCEL: { + WindowManagerService::GetInstance().NotifyWindowClientPointUp(activeWindowId_, pointerEvent); + WLOGFD("[Server Point Up/Cancel]: windowId: %{public}u, action: %{public}d, sourceType: %{public}d", + activeWindowId_, action, sourceType); + break; + } + default: + break; + } +} + +void MoveDragController::SetDragProperty(const sptr& moveDragProperty) +{ + moveDragProperty_->CopyFrom(moveDragProperty); +} + +void MoveDragController::SetWindowProperty(const sptr& windowProperty) +{ + windowProperty_->CopyFrom(windowProperty); +} + +const sptr& MoveDragController::GetMoveDragProperty() const +{ + return moveDragProperty_; +} + +const sptr& MoveDragController::GetWindowProperty() const +{ + return windowProperty_; +} + +void MoveDragController::ResetMoveOrDragState() +{ + activeWindowId_ = INVALID_WINDOW_ID; + auto moveDragProperty = new MoveDragProperty(); + SetDragProperty(moveDragProperty); +} + +void MoveDragController::SetActiveWindowId(uint32_t activeWindowId) +{ + activeWindowId_ = activeWindowId; +} + +uint32_t MoveDragController::GetActiveWindowId() const +{ + return activeWindowId_; +} +} +} diff --git a/window_manager/wmserver/src/freeze_controller.cpp b/window_manager/wmserver/src/freeze_controller.cpp new file mode 100644 index 0000000..b312cd5 --- /dev/null +++ b/window_manager/wmserver/src/freeze_controller.cpp @@ -0,0 +1,90 @@ +/* + * 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 "freeze_controller.h" + +#include + +#include "display_manager_service_inner.h" +#include "pixel_map.h" +#include "surface_draw.h" +#include "window_manager_hilog.h" +#include "window_option.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "FreezeController"}; +} + +bool FreezeController::FreezeDisplay(DisplayId displayId) +{ + sptr window = CreateCoverWindow(displayId); + if (window == nullptr) { + return false; + } + + WMError res = window->Show(); + if (res != WMError::WM_OK) { + WLOGFE("Show window failed"); + return false; + } + std::shared_ptr pixelMap = DisplayManagerServiceInner::GetInstance().GetDisplaySnapshot(displayId); + if (pixelMap == nullptr) { + WLOGE("freeze display fail, pixel map is null. display %{public}" PRIu64"", displayId); + return false; + } + return SurfaceDraw::DrawImage(window->GetSurfaceNode(), window->GetRect().width_, + window->GetRect().height_, pixelMap); +} + +bool FreezeController::UnfreezeDisplay(DisplayId displayId) +{ + auto iter = coverWindowMap_.find(displayId); + if (iter == coverWindowMap_.end()) { + WLOGW("unfreeze fail, no cover window. display %{public}" PRIu64"", displayId); + return false; + } + sptr window = iter->second; + if (window == nullptr) { + WLOGW("unfreeze fail, window is null. display %{public}" PRIu64"", displayId); + return false; + } + return WMError::WM_OK == window->Destroy(); +} + +sptr FreezeController::CreateCoverWindow(DisplayId displayId) +{ + sptr option = new (std::nothrow) WindowOption(); + if (option == nullptr) { + WLOGFE("window option is null"); + return nullptr; + } + option->SetWindowType(WindowType::WINDOW_TYPE_FREEZE_DISPLAY); + option->SetFocusable(false); + option->SetMainHandlerAvailable(false); + option->RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + option->SetDisplayId(displayId); + sptr window = Window::Create("freeze" + std::to_string(displayId), option); + if (window == nullptr) { + WLOGFE("cover window is null"); + return nullptr; + } + coverWindowMap_[displayId] = window; + return window; +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/inner_window.cpp b/window_manager/wmserver/src/inner_window.cpp new file mode 100644 index 0000000..ea81a85 --- /dev/null +++ b/window_manager/wmserver/src/inner_window.cpp @@ -0,0 +1,142 @@ +/* + * 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 "inner_window.h" + +#include "window_manager_hilog.h" +#include "surface_draw.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InnerWindow"}; + const std::string IMAGE_PLACE_HOLDER_PNG_PATH = "/etc/window/resources/bg_place_holder.png"; +} +WM_IMPLEMENT_SINGLE_INSTANCE(PlaceHolderWindow) + +void PlaceholderWindowListener::OnTouchOutside() const +{ + WLOGFD("place holder touch outside"); + PlaceHolderWindow::GetInstance().Destroy(); +} + +void PlaceholderWindowListener::AfterUnfocused() +{ + WLOGFD("place holder after unfocused"); + PlaceHolderWindow::GetInstance().Destroy(); +} + +bool PlaceholderInputEventConsumer::OnInputEvent(const std::shared_ptr& keyEvent) const +{ + WLOGFD("place holder get key event"); + PlaceHolderWindow::GetInstance().Destroy(); + return true; +} + +bool PlaceholderInputEventConsumer::OnInputEvent(const std::shared_ptr& pointerEvent) const +{ + WLOGFD("place holder get point event"); + PlaceHolderWindow::GetInstance().Destroy(); + return true; +} + +bool PlaceholderInputEventConsumer::OnInputEvent(const std::shared_ptr& axisEvent) const +{ + // do nothing + return false; +} + +void PlaceHolderWindow::Create(std::string name, DisplayId displyId, Rect rect, WindowMode mode) +{ + WLOGFD("create inner display id: %{public}" PRIu64"", displyId); + if (window_ != nullptr) { + WLOGFW("window has created."); + return; + } + sptr option = new (std::nothrow) WindowOption(); + if (option == nullptr) { + WLOGFE("window option is nullptr."); + return; + } + option->SetFocusable(false); + option->SetWindowMode(mode); + option->SetWindowRect(rect); + option->SetWindowType(WindowType::WINDOW_TYPE_PLACEHOLDER); + window_ = Window::Create(name, option); + if (window_ == nullptr) { + WLOGFE("window is nullptr."); + return; + } + window_->AddWindowFlag(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE); + RegisterWindowListener(); + SetInputEventConsumer(); + if (!OHOS::Rosen::SurfaceDraw::DrawImage(window_->GetSurfaceNode(), rect.width_, rect.height_, + IMAGE_PLACE_HOLDER_PNG_PATH)) { + WLOGE("draw surface failed"); + return; + } + window_->Show(); + WLOGFD("create palce holder Window end"); +} + +void PlaceHolderWindow::RegisterWindowListener() +{ + if (window_ == nullptr) { + WLOGFE("Window is nullptr, register window listener failed."); + return; + } + if (windowListener_ == nullptr) { + windowListener_ = new (std::nothrow) PlaceholderWindowListener(); + } + window_->RegisterTouchOutsideListener(windowListener_); + window_->RegisterLifeCycleListener(windowListener_); +} + +void PlaceHolderWindow::UnRegisterWindowListener() +{ + if (window_ == nullptr || windowListener_ == nullptr) { + WLOGFE("Window or listener is nullptr, unregister window listener failed."); + return; + } + window_->UnregisterTouchOutsideListener(windowListener_); + window_->UnregisterLifeCycleListener(windowListener_); +} + +void PlaceHolderWindow::SetInputEventConsumer() +{ + if (window_ == nullptr) { + WLOGFE("Window is nullptr, set window input event consumer failed."); + return; + } + if (inputEventConsumer_ == nullptr) { + inputEventConsumer_ = std::make_shared(); + } + window_->SetInputEventConsumer(inputEventConsumer_); +} + +void PlaceHolderWindow::Destroy() +{ + WLOGFI("destroy place holder window begin."); + if (window_ != nullptr) { + WLOGFI("destroy place holder window not nullptr."); + UnRegisterWindowListener(); + window_->SetInputEventConsumer(nullptr); + window_->Destroy(); + } + window_ = nullptr; + WLOGFI("destroy place holder window end."); +} +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/input_window_monitor.cpp b/window_manager/wmserver/src/input_window_monitor.cpp new file mode 100644 index 0000000..1aeac9a --- /dev/null +++ b/window_manager/wmserver/src/input_window_monitor.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2021-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 "input_window_monitor.h" + +#include +#include + +#include "display_manager_service_inner.h" +#include "dm_common.h" +#include "window_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputWindowMonitor"}; +} +static inline void convertRectsToMmiRects(const std::vector& rects, std::vector& mmiRects) +{ + for (const auto& rect : rects) { + mmiRects.emplace_back( + MMI::Rect{ rect.posX_, rect.posY_, static_cast(rect.width_), static_cast(rect.height_) }); + } +} + +void InputWindowMonitor::UpdateInputWindow(uint32_t windowId) +{ + if (windowRoot_ == nullptr) { + WLOGFE("windowRoot is null."); + return; + } + sptr windowNode = windowRoot_->GetWindowNode(windowId); + if (windowNode == nullptr) { + WLOGFE("window node could not be found."); + return; + } + if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowProperty()->GetWindowType()) != + INPUT_WINDOW_TYPE_SKIPPED.end()) { + return; + } + DisplayId displayId = windowNode->GetDisplayId(); + UpdateInputWindowByDisplayId(displayId); +} + +MMI::DisplayGroupInfo InputWindowMonitor::GetDisplayInfo(uint32_t windowId) +{ + if (windowRoot_ == nullptr) { + WLOGFE("windowRoot is null."); + return displayGroupInfo_; + } + sptr windowNode = windowRoot_->GetWindowNode(windowId); + if (windowNode == nullptr) { + WLOGFE("window node could not be found."); + return displayGroupInfo_; + } + if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowProperty()->GetWindowType()) != + INPUT_WINDOW_TYPE_SKIPPED.end()) { + return displayGroupInfo_; + } + DisplayId displayId = windowNode->GetDisplayId(); + HandleDisplayInfo(displayId); + return displayGroupInfo_; +} + +void InputWindowMonitor::HandleDisplayInfo(DisplayId displayId) +{ + if (displayId == DISPLAY_ID_INVALID) { + return; + } + auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("can not get window node container."); + return; + } + + auto displayInfos = container->GetAllDisplayInfo(); + if (displayInfos.empty()) { + return; + } + + UpdateDisplayGroupInfo(container, displayGroupInfo_); + UpdateDisplayInfo(displayInfos, displayGroupInfo_.displaysInfo); + std::vector> windowNodes; + container->TraverseContainer(windowNodes); + TraverseWindowNodes(windowNodes, displayGroupInfo_.windowsInfo); +} + +void InputWindowMonitor::UpdateInputWindowByDisplayId(DisplayId displayId) +{ + HandleDisplayInfo(displayId); + WLOGFI("update display info to IMS, displayId: %{public}" PRIu64"", displayId); + MMI::InputManager::GetInstance()->UpdateDisplayInfo(displayGroupInfo_); +} + +void InputWindowMonitor::UpdateDisplayGroupInfo(const sptr& windowNodeContainer, + MMI::DisplayGroupInfo& displayGroupInfo) +{ + const Rect&& rect = windowNodeContainer->GetDisplayGroupRect(); + displayGroupInfo.width = static_cast(rect.width_); + displayGroupInfo.height = static_cast(rect.height_); + displayGroupInfo.focusWindowId = static_cast(windowNodeContainer->GetFocusWindow()); + displayGroupInfo.windowsInfo.clear(); + displayGroupInfo.displaysInfo.clear(); +} + +void InputWindowMonitor::UpdateDisplayInfo(const std::vector>& displayInfos, + std::vector& displayInfoVector) +{ + for (auto& displayInfo : displayInfos) { + if (displayInfo == nullptr) { + continue; + } + uint32_t displayWidth = static_cast(displayInfo->GetWidth()); + uint32_t displayHeight = static_cast(displayInfo->GetHeight()); + int32_t offsetX = displayInfo->GetOffsetX(); + int32_t offsetY = displayInfo->GetOffsetY(); + if (displayInfo->GetWaterfallDisplayCompressionStatus()) { + displayWidth = static_cast( + static_cast(displayWidth) + offsetX * 2); // 2: Get full width; + displayHeight = static_cast( + static_cast(displayHeight) + offsetY * 2); // 2: Get full height; + offsetX = 0; + offsetY = 0; + } + if (displayInfo->GetRotation() == Rotation::ROTATION_90 || + displayInfo->GetRotation() == Rotation::ROTATION_270) { + std::swap(displayWidth, displayHeight); + } + MMI::DisplayInfo display = { + .id = static_cast(displayInfo->GetDisplayId()), + .x = offsetX, + .y = offsetY, + .width = static_cast(displayWidth), + .height = static_cast(displayHeight), + .name = (std::stringstream("display ")<GetDisplayId()).str(), + .uniq = "default" + std::to_string(displayInfo->GetDisplayId()), + .direction = GetDisplayDirectionForMmi(displayInfo->GetRotation()), + }; + auto displayIter = std::find_if(displayInfoVector.begin(), displayInfoVector.end(), + [&display](MMI::DisplayInfo& displayInfoTmp) { + return displayInfoTmp.id == display.id; + }); + if (displayIter != displayInfoVector.end()) { + *displayIter = display; + } else { + displayInfoVector.emplace_back(display); + } + WLOGFD("UpdateDisplayInfo, displayId: %{public}d, displayRect: " + "[%{public}d, %{public}d, %{public}u, %{public}u]", + display.id, display.x, display.y, display.width, display.height); + } +} + +void InputWindowMonitor::TransformWindowRects(const sptr& windowNode, Rect& areaRect, + std::vector& touchHotAreas, std::vector& pointerHotAreas) +{ + if (windowNode->GetWindowProperty()->isNeedComputerTransform()) { + windowNode->ComputeTransform(); + for (Rect& rect : touchHotAreas) { + rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect); + } + for (Rect& rect : pointerHotAreas) { + rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect); + } + WLOGFI("Area rect before tranform: [%{public}d, %{public}d, %{public}u, %{public}u]", + areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_); + areaRect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), areaRect); + WLOGFI("Area rect after tranform: [%{public}d, %{public}d, %{public}u, %{public}u]", + areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_); + } +} + +void InputWindowMonitor::TraverseWindowNodes(const std::vector> &windowNodes, + std::vector& windowsInfo) +{ + std::map> dialogWindowMap; + for (const auto& windowNode: windowNodes) { + sptr callerNode = + windowRoot_->FindDialogCallerNode(windowNode->GetWindowType(), windowNode->dialogTargetToken_); + if (callerNode != nullptr) { + dialogWindowMap.insert(std::make_pair(callerNode->GetWindowId(), windowNode)); + } + } + for (const auto& windowNode: windowNodes) { + if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowType()) != INPUT_WINDOW_TYPE_SKIPPED.end()) { + WLOGFI("skip node[id:%{public}u, type:%{public}d]", windowNode->GetWindowId(), windowNode->GetWindowType()); + continue; + } + + std::vector touchHotAreas; + std::vector pointerHotAreas; + windowNode->GetTouchHotAreas(touchHotAreas); + windowNode->GetPointerHotAreas(pointerHotAreas); + Rect areaRect = windowNode->GetWindowRect(); + + TransformWindowRects(windowNode, areaRect, touchHotAreas, pointerHotAreas); + + MMI::WindowInfo windowInfo = { + .id = static_cast(windowNode->GetWindowId()), + .pid = windowNode->GetInputEventCallingPid(), + .uid = windowNode->GetCallingUid(), + .area = MMI::Rect { areaRect.posX_, areaRect.posY_, + static_cast(areaRect.width_), static_cast(areaRect.height_) }, + .agentWindowId = static_cast(windowNode->GetWindowId()), + }; + + auto iter = (windowNode->GetParentId() == INVALID_WINDOW_ID) ? + dialogWindowMap.find(windowNode->GetWindowId()) : dialogWindowMap.find(windowNode->GetParentId()); + if (iter != dialogWindowMap.end()) { + windowInfo.pid = iter->second->GetCallingPid(); + windowInfo.uid = iter->second->GetCallingUid(); + windowInfo.agentWindowId = static_cast(iter->second->GetWindowId()); + } + convertRectsToMmiRects(touchHotAreas, windowInfo.defaultHotAreas); + convertRectsToMmiRects(pointerHotAreas, windowInfo.pointerHotAreas); + if (!windowNode->GetWindowProperty()->GetTouchable()) { + WLOGFI("window is not touchable: %{public}u", windowNode->GetWindowId()); + windowInfo.flags |= MMI::WindowInfo::FLAG_BIT_UNTOUCHABLE; + } + windowsInfo.emplace_back(windowInfo); + } +} + +MMI::Direction InputWindowMonitor::GetDisplayDirectionForMmi(Rotation rotation) +{ + MMI::Direction direction = MMI::Direction0; + switch (rotation) { + case Rotation::ROTATION_0: + direction = MMI::Direction0; + break; + case Rotation::ROTATION_90: + direction = MMI::Direction90; + break; + case Rotation::ROTATION_180: + direction = MMI::Direction180; + break; + case Rotation::ROTATION_270: + direction = MMI::Direction270; + break; + default: + break; + } + return direction; +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/src/memory_guard.cpp b/window_manager/wmserver/src/memory_guard.cpp new file mode 100644 index 0000000..0e0e7ee --- /dev/null +++ b/window_manager/wmserver/src/memory_guard.cpp @@ -0,0 +1,42 @@ +/* +* Copyright (C) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "memory_guard.h" + +#include "window_manager_hilog.h" +#include "malloc.h" +namespace OHOS { +namespace Rosen { +#ifdef CONFIG_USE_JEMALLOC_DFX_INTF +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "MemoryGuard"}; +} +#endif +MemoryGuard::MemoryGuard() +{ +#ifdef CONFIG_USE_JEMALLOC_DFX_INTF + int ret1 = mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); // 0 indicates success + int ret2 = mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); + WLOGFD("disable tcache and delay free, result[%{public}d, %{public}d]", ret1, ret2); +#endif +} +MemoryGuard::~MemoryGuard() +{ +#ifdef CONFIG_USE_JEMALLOC_DFX_INTF + int err = mallopt(M_FLUSH_THREAD_CACHE, 0); + WLOGFD("flush cache, result: %{public}d", err); +#endif +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/minimize_app.cpp b/window_manager/wmserver/src/minimize_app.cpp new file mode 100644 index 0000000..9c9f28b --- /dev/null +++ b/window_manager/wmserver/src/minimize_app.cpp @@ -0,0 +1,179 @@ +/* + * 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 "minimize_app.h" + +#include +#include "window_manager_hilog.h" +#include "window_inner_manager.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "MinimizeApp"}; +} + +std::map>> MinimizeApp::needMinimizeAppNodes_; +bool MinimizeApp::isMinimizedByOtherWindow_ = true; +std::recursive_mutex MinimizeApp::mutex_; +void MinimizeApp::AddNeedMinimizeApp(const sptr& node, MinimizeReason reason) +{ + std::lock_guard lock(mutex_); + if (!EnableMinimize(reason)) { + return; + } + if (!node) { + WLOGFE("AddNeedMinimizeApp failed since node is nullptr"); + return; + } + wptr weakNode(node); + for (auto& appNodes: needMinimizeAppNodes_) { + auto windowId = node->GetWindowId(); + auto iter = std::find_if(appNodes.second.begin(), appNodes.second.end(), + [windowId](wptr srcNode) { + auto weakSrcNode = srcNode.promote(); + if (weakSrcNode == nullptr) { + return false; + } + return weakSrcNode->GetWindowId() == windowId; + }); + if (iter != appNodes.second.end()) { + WLOGFI("[Minimize] Window %{public}u is already in minimize list", node->GetWindowId()); + return; + } + } + WLOGFI("[Minimize] Add Window %{public}u to minimize list, reason %{public}u", node->GetWindowId(), reason); + needMinimizeAppNodes_[reason].emplace_back(weakNode); +} + +std::vector> MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason reason) +{ + std::lock_guard lock(mutex_); + std::vector> needMinimizeAppNodes; + if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) { + for (auto& node : needMinimizeAppNodes_[reason]) { + needMinimizeAppNodes.emplace_back(node); + } + } + return needMinimizeAppNodes; +} + +void MinimizeApp::ExecuteMinimizeAll() +{ + std::lock_guard lock(mutex_); + for (auto& appNodes: needMinimizeAppNodes_) { + bool isFromUser = IsFromUser(appNodes.first); + WLOGFI("[Minimize] ExecuteMinimizeAll with size: %{public}zu, reason: %{public}u", + appNodes.second.size(), appNodes.first); + for (auto& node : appNodes.second) { + WindowInnerManager::GetInstance().MinimizeAbility(node, isFromUser); + } + appNodes.second.clear(); + } + needMinimizeAppNodes_.clear(); +} + +void MinimizeApp::ClearNodesWithReason(MinimizeReason reason) +{ + WLOGFI("[Minimize] ClearNodesWithReason reason %{public}u", reason); + std::lock_guard lock(mutex_); + if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) { + needMinimizeAppNodes_.at(reason).clear(); + } +} + +sptr MinimizeApp::GetRecoverdNodeFromMinimizeList() +{ + WLOGFI("[Minimize] RevertMinimizedNodeForTile"); + std::lock_guard lock(mutex_); + if (needMinimizeAppNodes_.find(MinimizeReason::LAYOUT_TILE) != needMinimizeAppNodes_.end()) { + auto& tileNodesForMinimize = needMinimizeAppNodes_.at(MinimizeReason::LAYOUT_TILE); + if (!tileNodesForMinimize.empty()) { + auto recoverNode = tileNodesForMinimize.back().promote(); + tileNodesForMinimize.pop_back(); + return recoverNode; + } + } + return nullptr; +} + +bool MinimizeApp::IsNodeNeedMinimize(const sptr& node) +{ + if (node == nullptr) { + WLOGFE("[Minimize] node is nullptr"); + return false; + } + for (auto iter : needMinimizeAppNodes_) { + auto nodes = iter.second; + if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) { + return true; + } + } + return false; +} + +bool MinimizeApp::IsNodeNeedMinimizeWithReason(const sptr& node, MinimizeReason reason) +{ + if (node == nullptr) { + WLOGFE("[Minimize] node is nullptr"); + return false; + } + if (needMinimizeAppNodes_.find(reason) == needMinimizeAppNodes_.end()) { + WLOGFD("[Minimize] no need to minimize with id:%{public}u reason:%{public}u", + node->GetWindowId(), reason); + return false; + } + auto nodes = needMinimizeAppNodes_.at(reason); + if (std::find(nodes.begin(), nodes.end(), node) != nodes.end()) { + WLOGFI("[Minimize] id:%{public}u need to minimize with reason:%{public}u", + node->GetWindowId(), reason); + return true; + } + return false; +} + +bool MinimizeApp::EnableMinimize(MinimizeReason reason) +{ + bool isFromUser = IsFromUser(reason); + if (!isMinimizedByOtherWindow_ && !isFromUser) { + return false; + } + return true; +} + +void MinimizeApp::ExecuteMinimizeTargetReasons(uint32_t reasons) +{ + std::lock_guard lock(mutex_); + while (reasons) { + MinimizeReason reason = static_cast(reasons & (~reasons + 1)); + if (needMinimizeAppNodes_.find(reason) != needMinimizeAppNodes_.end()) { + WLOGFI("[Minimize] ExecuteMinimizeTargetReason with size: %{public}zu, reason: %{public}u", + needMinimizeAppNodes_.at(reason).size(), reason); + bool isFromUser = IsFromUser(reason); + for (auto& node : needMinimizeAppNodes_.at(reason)) { + WindowInnerManager::GetInstance().MinimizeAbility(node, isFromUser); + } + needMinimizeAppNodes_.at(reason).clear(); + } + reasons -= reason; + } +} + +void MinimizeApp::SetMinimizedByOtherConfig(bool isMinimizedByOther) +{ + isMinimizedByOtherWindow_ = isMinimizedByOther; +} +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/remote_animation.cpp b/window_manager/wmserver/src/remote_animation.cpp new file mode 100644 index 0000000..3ecb7ee --- /dev/null +++ b/window_manager/wmserver/src/remote_animation.cpp @@ -0,0 +1,910 @@ +/* + * 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 "remote_animation.h" + +#include +#include +#include +#include +#include +#include "minimize_app.h" +#include "parameters.h" +#include "surface_draw.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "zidl/ressched_report.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "RemoteAnimation"}; + const std::string ANIMATION_TIME_OUT_TASK = "remote_animation_time_out_task"; + constexpr int64_t ANIMATION_TIME_OUT_MILLISECONDS = 3000; // 3000 is max time +} +bool RemoteAnimation::isRemoteAnimationEnable_ = true; +std::atomic RemoteAnimation::allocationId_ = 0; +sptr RemoteAnimation::windowAnimationController_ = nullptr; +std::weak_ptr RemoteAnimation::wmsTaskHandler_; +wptr RemoteAnimation::windowRoot_; +bool RemoteAnimation::animationFirst_ = false; +wptr RemoteAnimation::windowController_ = nullptr; + +std::map eventMap_ = { + {TransitionReason::CLOSE, TransitionEvent::CLOSE}, + {TransitionReason::MINIMIZE, TransitionEvent::MINIMIZE}, + {TransitionReason::BACK_TRANSITION, TransitionEvent::BACK_TRANSITION} +}; + +void RemoteAnimation::SetAnimationFirst(bool animationFirst) +{ + animationFirst_ = animationFirst; + WLOGFI("RSWindowAnimation:animationFirst: %{public}u!", static_cast(animationFirst_)); +} + +bool RemoteAnimation::IsRemoteAnimationEnabledAndFirst(DisplayId displayId) +{ + return animationFirst_ && CheckRemoteAnimationEnabled(displayId); +} + +WMError RemoteAnimation::SetWindowAnimationController(const sptr& controller) +{ + WLOGFI("RSWindowAnimation: set window animation controller!"); + if (!isRemoteAnimationEnable_) { + WLOGE("RSWindowAnimation: failed to set window animation controller, remote animation is not enabled"); + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + if (controller == nullptr) { + WLOGFE("RSWindowAnimation: failed to set window animation controller, controller is null!"); + return WMError::WM_ERROR_NULLPTR; + } + + if (windowAnimationController_ != nullptr) { + WLOGFI("RSWindowAnimation: maybe user switch!"); + } + + windowAnimationController_ = controller; + return WMError::WM_OK; +} + +void RemoteAnimation::SetMainTaskHandler(std::shared_ptr handler) +{ + wmsTaskHandler_ = handler; +} + +void RemoteAnimation::SetWindowControllerAndRoot(const sptr& windowController, + const sptr& windowRoot) +{ + windowController_ = windowController; + windowRoot_ = windowRoot; +} + +bool RemoteAnimation::CheckAnimationController() +{ + if (windowAnimationController_ == nullptr) { + WLOGFD("RSWindowAnimation: windowAnimationController_ null!"); + return false; + } + return true; +} + +bool RemoteAnimation::CheckRemoteAnimationEnabled(DisplayId displayId) +{ + // When the screen is locked, remote animation cannot take effect because the launcher is frozen. + auto winRoot = windowRoot_.promote(); + if (winRoot == nullptr) { + return false; + } + auto container = winRoot->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr || container->IsScreenLocked()) { + return false; + } + return CheckAnimationController(); +} + +bool RemoteAnimation::CheckTransition(sptr srcInfo, const sptr& srcNode, + sptr dstInfo, const sptr& dstNode) +{ + if (srcNode == nullptr && dstNode == nullptr) { + WLOGFE("RSWindowAnimation: srcNode and dstNode are nullptr"); + return false; + } + + if (srcNode != nullptr && !srcNode->leashWinSurfaceNode_ && !srcNode->surfaceNode_) { + WLOGFE("RSWindowAnimation: srcNode has no surface, winId: %{public}u", srcNode->GetWindowId()); + return false; + } + + if (dstNode != nullptr && !dstNode->leashWinSurfaceNode_ && !dstNode->surfaceNode_) { + WLOGFE("RSWindowAnimation: dstNode has no surface, winId: %{public}u", dstNode->GetWindowId()); + return false; + } + + // check support window mode when one app starts another app + if ((dstNode != nullptr && dstInfo != nullptr) && + !WindowHelper::CheckSupportWindowMode(dstNode->GetWindowMode(), dstNode->GetModeSupportInfo(), dstInfo)) { + WLOGFE("RSWindowAnimation: the mode of dstNode isn't supported, winId: %{public}u, mode: %{public}u, " + "modeSupportInfo: %{public}u", dstNode->GetWindowId(), dstNode->GetWindowMode(), + dstNode->GetModeSupportInfo()); + return false; + } + + auto node = (dstNode != nullptr ? dstNode : srcNode); + return CheckRemoteAnimationEnabled(node->GetDisplayId()); +} + +void RemoteAnimation::OnRemoteDie(const sptr& remoteObject) +{ + WLOGFI("RSWindowAnimation: OnRemoteDie!"); + if (windowAnimationController_ != nullptr && windowAnimationController_->AsObject() == remoteObject) { + windowAnimationController_ = nullptr; + } + if (animationFirst_) { + CallbackTimeOutProcess(); + } +} + +static void GetAndDrawSnapShot(const sptr& srcNode) +{ + if (srcNode == nullptr || srcNode->leashWinSurfaceNode_ == nullptr) { + WLOGFD("srcNode or srcNode->leashWinSurfaceNode_ is empty"); + return; + } + if (srcNode->firstFrameAvaliable_) { + std::shared_ptr pixelMap; + // snapshot time out 2000ms + bool snapSucc = SurfaceDraw::GetSurfaceSnapshot(srcNode->surfaceNode_, pixelMap, 2000, 1.0, 1.0); + if (!snapSucc) { + // need to draw starting window when get pixelmap failed + WLOGFE("get surfaceSnapshot failed for window:%{public}u", srcNode->GetWindowId()); + return; + } + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = "startingWindow" + std::to_string(srcNode->GetWindowId()); + srcNode->startingWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, + RSSurfaceNodeType::STARTING_WINDOW_NODE); + auto rect = srcNode->GetWindowRect(); + srcNode->startingWinSurfaceNode_->SetBounds(0, 0, rect.width_, rect.height_); + SurfaceDraw::DrawImageRect(srcNode->startingWinSurfaceNode_, srcNode->GetWindowRect(), + pixelMap, 0x00ffffff, true); + srcNode->leashWinSurfaceNode_->RemoveChild(srcNode->surfaceNode_); + srcNode->leashWinSurfaceNode_->AddChild(srcNode->startingWinSurfaceNode_, -1); + RSTransaction::FlushImplicitTransaction(); + WLOGFI("Draw surface snapshot in starting window for window:%{public}u", srcNode->GetWindowId()); + } else if (srcNode->surfaceNode_) { + srcNode->surfaceNode_->SetIsNotifyUIBufferAvailable(true); + WLOGFI("Draw startingWindow in starting window for window:%{public}u", srcNode->GetWindowId()); + } +} + +TransitionEvent RemoteAnimation::GetTransitionEvent(sptr srcInfo, + sptr dstInfo, const sptr& srcNode, const sptr& dstNode) +{ + auto transitionReason = srcInfo->GetTransitionReason(); // src reason same as dst reason + if (srcNode != nullptr && eventMap_.find(transitionReason) != eventMap_.end()) { + WLOGFI("current window:%{public}u state: %{public}u", srcNode->GetWindowId(), + static_cast(srcNode->stateMachine_.GetCurrentState())); + if (srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("srcNode is hiding or hidden id: %{public}u!", srcNode->GetWindowId()); + return TransitionEvent::UNKNOWN; + } + return eventMap_[transitionReason]; + } + WLOGFI("Ability Transition"); + if (dstNode == nullptr) { + if (dstInfo->GetAbilityToken() == nullptr) { + WLOGFE("target window abilityToken is null"); + } + return TransitionEvent::UNKNOWN; + } else { + WLOGFI("current window:%{public}u state: %{public}u", dstNode->GetWindowId(), + static_cast(dstNode->stateMachine_.GetCurrentState())); + if (WindowHelper::IsMainWindow(dstInfo->GetWindowType())) { + if (dstNode->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFE("dstNode is showing or shown id: %{public}d state:%{public}u!", + dstNode->GetWindowId(), static_cast(dstNode->stateMachine_.GetCurrentState())); + return TransitionEvent::UNKNOWN; + } + return TransitionEvent::APP_TRANSITION; + } else if (dstInfo->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + return TransitionEvent::HOME; + } + } + return TransitionEvent::UNKNOWN; +} + +sptr RemoteAnimation::GetTransitionFinishedCallback( + const sptr& srcNode, const sptr& dstNode) +{ + wptr weak = dstNode; + wptr weakSrc = srcNode; + auto callback = [weakSrc, weak]() { + WLOGFI("RSWindowAnimation: on finish transition with minimize pre fullscreen!"); + auto weakNode = weak.promote(); + if (weakNode == nullptr) { + WLOGFE("dst windowNode is nullptr!"); + return; + } + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + if (!weakNode->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFI("node:%{public}u is not play show animation with state:%{public}u!", weakNode->GetWindowId(), + static_cast(weakNode->stateMachine_.GetCurrentState())); + return; + } + MinimizeApp::ExecuteMinimizeAll(); // minimize execute in show animation + RSAnimationTimingProtocol timingProtocol(200); // animation time + RSNode::Animate(timingProtocol, RSAnimationTimingCurve::EASE_OUT, [weakNode]() { + auto winRect = weakNode->GetWindowRect(); + WLOGFD("name:%{public}s id:%{public}u winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + weakNode->GetWindowName().c_str(), weakNode->GetWindowId(), + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + if (!weakNode->leashWinSurfaceNode_) { + return; + } + weakNode->leashWinSurfaceNode_->SetBounds( + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + RSTransaction::FlushImplicitTransaction(); + weakNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_DONE); + }); + }; + return CreateAnimationFinishedCallback(callback); +} + +WMError RemoteAnimation::NotifyAnimationStartApp(sptr srcInfo, + const sptr& srcNode, const sptr& dstNode, + sptr& dstTarget, sptr& finishedCallback) +{ + if (animationFirst_) { + // From Recent also need to minimize window + MinimizeApp::ExecuteMinimizeAll(); + } + // start app from launcher + if (srcNode != nullptr && srcNode->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + WLOGFI("RSWindowAnimation: start app id:%{public}u from launcher!", dstNode->GetWindowId()); + windowAnimationController_->OnStartApp(StartingAppType::FROM_LAUNCHER, dstTarget, finishedCallback); + return WMError::WM_OK; + } + // start app from recent + if (srcInfo != nullptr && srcInfo->GetIsRecent()) { + WLOGFI("RSWindowAnimation: start app id:%{public}u from recent!", dstNode->GetWindowId()); + windowAnimationController_->OnStartApp(StartingAppType::FROM_RECENT, dstTarget, finishedCallback); + return WMError::WM_OK; + } + // start app from other + WLOGFI("RSWindowAnimation: start app id:%{public}u from other!", dstNode->GetWindowId()); + windowAnimationController_->OnStartApp(StartingAppType::FROM_OTHER, dstTarget, finishedCallback); + return WMError::WM_OK; +} + +void RemoteAnimation::GetExpectRect(const sptr& dstNode, const sptr& dstTarget) +{ + // when exit immersive, startingWindow (0,0,w,h), but app need avoid + bool needAvoid = (dstNode->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + auto winRoot = windowRoot_.promote(); + if (needAvoid && winRoot) { + auto avoidRect = winRoot->GetDisplayRectWithoutSystemBarAreas(dstNode->GetDisplayId()); + if (WindowHelper::IsEmptyRect(avoidRect)) { + return; + } + WLOGFI("name:%{public}s id:%{public}u avoidRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + dstNode->GetWindowName().c_str(), dstNode->GetWindowId(), + avoidRect.posX_, avoidRect.posY_, avoidRect.width_, avoidRect.height_); + if (WindowHelper::IsMainFullScreenWindow(dstNode->GetWindowType(), dstNode->GetWindowMode())) { + auto& stagingProperties = dstTarget->surfaceNode_->GetStagingProperties(); + auto boundsRect = RectF(avoidRect.posX_, avoidRect.posY_, avoidRect.width_, avoidRect.height_); + dstTarget->windowBounds_ = RRect(boundsRect, stagingProperties.GetCornerRadius()); + if (dstNode->leashWinSurfaceNode_) { + dstNode->leashWinSurfaceNode_->SetBounds(avoidRect.posX_, avoidRect.posY_, + avoidRect.width_, avoidRect.height_); + } + } + } +} + +WMError RemoteAnimation::NotifyAnimationTransition(sptr srcInfo, + sptr dstInfo, const sptr& srcNode, + const sptr& dstNode) +{ + if (!dstNode) { + return WMError::WM_ERROR_NULLPTR; + } + WLOGFI("RSWindowAnimation: notify animation transition with dst currId:%{public}u!", dstNode->GetWindowId()); + bool needMinimizeSrcNode = MinimizeApp::IsNodeNeedMinimizeWithReason(srcNode, MinimizeReason::OTHER_WINDOW); + auto finishedCallback = CreateShowAnimationFinishedCallback(srcNode, dstNode, needMinimizeSrcNode); + if (finishedCallback == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + auto dstTarget = CreateWindowAnimationTarget(dstInfo, dstNode); + if (dstTarget == nullptr) { + WLOGFE("RSWindowAnimation: Failed to create dst target!"); + finishedCallback->OnAnimationFinished(); + return WMError::WM_ERROR_NO_MEM; + } + + std::unordered_map payload; + if (srcNode) { + payload["srcPid"] = std::to_string(srcNode->GetCallingPid()); + } + ResSchedReport::GetInstance().ResSchedDataReport( + Rosen::RES_TYPE_SHOW_REMOTE_ANIMATION, Rosen::REMOTE_ANIMATION_BEGIN, payload); + // when exit immersive, startingWindow (0,0,w,h), but app need avoid + GetExpectRect(dstNode, dstTarget); + dstNode->isPlayAnimationShow_ = true; + // Transition to next state and update task count will success when enable animationFirst_ + dstNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + dstNode->stateMachine_.UpdateAnimationTaskCount(true); + // from app to app + if (needMinimizeSrcNode && srcNode != nullptr) { + auto srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode); + // to avoid normal animation + srcNode->isPlayAnimationHide_ = true; + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); + } + if (animationFirst_) { + // Notify minimize before animation when animationFirst is enable. + // Or notify minimize in animation finished callback. + MinimizeApp::ExecuteMinimizeAll(); + } + WLOGFI("RSWindowAnimation: app transition from id:%{public}u to id:%{public}u!", + srcNode->GetWindowId(), dstNode->GetWindowId()); + windowAnimationController_->OnAppTransition(srcTarget, dstTarget, finishedCallback); + return WMError::WM_OK; + } + return NotifyAnimationStartApp(srcInfo, srcNode, dstNode, dstTarget, finishedCallback); +} + +WMError RemoteAnimation::NotifyAnimationMinimize(sptr srcInfo, const sptr& srcNode) +{ + sptr srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode); + if (srcTarget == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + WLOGFI("RSWindowAnimation: notify animation minimize Id:%{public}u!", srcNode->GetWindowId()); + srcNode->isPlayAnimationHide_ = true; + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); + } + sptr finishedCallback = CreateHideAnimationFinishedCallback( + srcNode, TransitionEvent::MINIMIZE); + if (finishedCallback == nullptr) { + WLOGFE("New RSIWindowAnimationFinishedCallback failed"); + return WMError::WM_ERROR_NO_MEM; + } + + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + windowAnimationController_->OnMinimizeWindow(srcTarget, finishedCallback); + return WMError::WM_OK; +} + +WMError RemoteAnimation::NotifyAnimationClose(sptr srcInfo, const sptr& srcNode, + TransitionEvent event) +{ + sptr srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode); + if (srcTarget == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + WLOGFI("RSWindowAnimation: notify animation close id:%{public}u!", srcNode->GetWindowId()); + srcNode->isPlayAnimationHide_ = true; + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); + } + sptr finishedCallback = CreateHideAnimationFinishedCallback(srcNode, event); + if (finishedCallback == nullptr) { + WLOGFE("New RSIWindowAnimationFinishedCallback failed"); + return WMError::WM_ERROR_NO_MEM; + } + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + windowAnimationController_->OnCloseWindow(srcTarget, finishedCallback); + return WMError::WM_OK; +} + +WMError RemoteAnimation::NotifyAnimationBackTransition(sptr srcInfo, + sptr dstInfo, const sptr& srcNode, + const sptr& dstNode) +{ + if (!animationFirst_) { + WLOGFE("not animation first!"); + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + if (!dstNode || !srcNode) { + WLOGFE("dstNode or srcNode is nullptr, no need transition animation"); + return WMError::WM_ERROR_NULLPTR; + } + WLOGFI("RSWindowAnimation: app back transition from id:%{public}u to id:%{public}u!", + srcNode->GetWindowId(), dstNode->GetWindowId()); + sptr srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode); + sptr dstTarget = CreateWindowAnimationTarget(dstInfo, dstNode); + if (srcTarget == nullptr || dstTarget == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + srcNode->isPlayAnimationHide_ = true; + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); + GetAndDrawSnapShot(srcNode); + } + dstNode->isPlayAnimationShow_ = true; + dstNode->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + dstNode->stateMachine_.UpdateAnimationTaskCount(true); + wptr srcNodeWptr = srcNode; + wptr dstNodeWptr = dstNode; + auto func = [srcNodeWptr, dstNodeWptr]() { + WLOGFI("RSWindowAnimation: animationFirst use state machine process AnimationBackTransition!"); + auto srcNodeSptr = srcNodeWptr.promote(); + auto dstNodeSptr = dstNodeWptr.promote(); + ProcessNodeStateTask(srcNodeSptr); + ProcessNodeStateTask(dstNodeSptr); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + sptr finishedCallback = CreateAnimationFinishedCallback(func); + if (finishedCallback == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + windowAnimationController_->OnAppTransition(srcTarget, dstTarget, finishedCallback); + return WMError::WM_OK; +} + +void RemoteAnimation::GetAnimationTargetsForHome(std::vector>& animationTargets, + std::vector> needMinimizeAppNodes) +{ + for (auto& weakNode : needMinimizeAppNodes) { + auto srcNode = weakNode.promote(); + sptr srcInfo = new(std::nothrow) WindowTransitionInfo(); + sptr srcTarget = CreateWindowAnimationTarget(srcInfo, srcNode); + if (srcTarget == nullptr) { + continue; + } + WLOGFI("notify animation by home, need minimize id%{public}u", srcNode->GetWindowId()); + if (!WindowHelper::IsMainWindow(srcNode->GetWindowType()) || + srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("srcNode is already hiding or hidden id: %{public}d!", srcNode->GetWindowId()); + continue; + } + srcNode->isPlayAnimationHide_ = true; + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + srcNode->stateMachine_.UpdateAnimationTaskCount(true); + auto winController = windowController_.promote(); + if (winController) { + winController->RemoveWindowNode(srcNode->GetWindowId(), true); + } + animationTargets.emplace_back(srcTarget); + } +} + +static void GetAnimationHomeFinishCallback(std::function& func, + std::vector> needMinimizeAppNodes) +{ + func = [needMinimizeAppNodes]() { + WLOGFI("NotifyAnimationByHome in animation callback not animationFirst"); + for (auto& weakNode : needMinimizeAppNodes) { + auto srcNode = weakNode.promote(); + if (srcNode == nullptr || !srcNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("windowNode is nullptr or is not play hide animation!"); + continue; + } + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE); + } + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::MINIMIZE_ALL); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; +} + +WMError RemoteAnimation::NotifyAnimationByHome() +{ + if (!CheckAnimationController()) { + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + auto needMinimizeAppNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL); + WLOGFI("RSWindowAnimation: notify animation by home, need minimize size: %{public}u", + static_cast(needMinimizeAppNodes.size())); + std::vector> animationTargets; + GetAnimationTargetsForHome(animationTargets, needMinimizeAppNodes); + std::function func; + if (animationFirst_) { + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::MINIMIZE_ALL); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + func = [needMinimizeAppNodes]() { + WLOGFI("NotifyAnimationByHome in animation callback in animationFirst with size:%{public}u", + static_cast(needMinimizeAppNodes.size())); + for (auto& weakNode : needMinimizeAppNodes) { + auto srcNode = weakNode.promote(); + ProcessNodeStateTask(srcNode); + } + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } else { + GetAnimationHomeFinishCallback(func, needMinimizeAppNodes); + } + sptr finishedCallback = CreateAnimationFinishedCallback(func); + if (finishedCallback == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + // need use OnMinimizeWindows with controller + windowAnimationController_->OnMinimizeAllWindow(animationTargets, finishedCallback); + return WMError::WM_OK; +} + +void RemoteAnimation::NotifyAnimationTargetsUpdate(std::vector& fullScreenWinIds, + std::vector& floatWinIds) +{ + auto handler = wmsTaskHandler_.lock(); + if (handler == nullptr) { + WLOGFE("wmsTaskHandler_ is nullptr"); + return; + } + // need post task when visit windowRoot node map + auto task = [fullScreenWinIds, floatWinIds]() { + if (!CheckAnimationController()) { + return; + } + auto winRoot = windowRoot_.promote(); + if (winRoot == nullptr) { + WLOGFE("window root is nullptr"); + return; + } + std::vector> floatAnimationTargets; + std::vector> fullScreenAnimationTargets; + for (auto& id : fullScreenWinIds) { + auto fullScreenNode = winRoot->GetWindowNode(id); + sptr fullScreenTarget = CreateWindowAnimationTarget(nullptr, fullScreenNode); + if (fullScreenTarget != nullptr) { + fullScreenAnimationTargets.emplace_back(fullScreenTarget); + } + } + for (auto& id : floatWinIds) { + auto floatNode = winRoot->GetWindowNode(id); + sptr floatTarget = CreateWindowAnimationTarget(nullptr, floatNode); + if (floatTarget != nullptr) { + floatAnimationTargets.emplace_back(floatTarget); + } + } + // delete when need all fullscreen targets + sptr fullScreenAnimationTarget = nullptr; + if (!fullScreenAnimationTargets.empty()) { + fullScreenAnimationTarget = fullScreenAnimationTargets[0]; + } + windowAnimationController_->OnWindowAnimationTargetsUpdate(fullScreenAnimationTarget, + floatAnimationTargets); + }; + bool ret = handler->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + if (!ret) { + WLOGFE("EventHandler PostTask Failed"); + task(); + } +} + +WMError RemoteAnimation::NotifyAnimationScreenUnlock(std::function callback) +{ + if (!CheckAnimationController()) { + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + WLOGFI("NotifyAnimationScreenUnlock"); + sptr finishedCallback = CreateAnimationFinishedCallback(callback); + if (finishedCallback == nullptr) { + return WMError::WM_ERROR_NO_MEM; + } + + windowAnimationController_->OnScreenUnlock(finishedCallback); + return WMError::WM_OK; +} + +sptr RemoteAnimation::CreateWindowAnimationTarget(sptr info, + const sptr& windowNode) +{ + if (windowNode == nullptr) { + WLOGFW("Failed to create window animation target, window node is null!"); + return nullptr; + } + + sptr windowAnimationTarget = new(std::nothrow) RSWindowAnimationTarget(); + if (windowAnimationTarget == nullptr) { + WLOGFE("New RSWindowAnimationTarget failed"); + return nullptr; + } + + if (WindowHelper::IsMainWindow(windowNode->GetWindowType())) { // only starting window has abilityInfo + windowAnimationTarget->bundleName_ = windowNode->abilityInfo_.bundleName_; + windowAnimationTarget->abilityName_ = windowNode->abilityInfo_.abilityName_; + } else if (info) { // use for back, minimize, close + windowAnimationTarget->bundleName_ = info->GetBundleName(); + windowAnimationTarget->abilityName_ = info->GetAbilityName(); + } + + windowAnimationTarget->missionId_ = windowNode->abilityInfo_.missionId_; + windowAnimationTarget->windowId_ = windowNode->GetWindowId(); + windowAnimationTarget->displayId_ = windowNode->GetDisplayId(); + if (WindowHelper::IsAppWindow(windowNode->GetWindowType())) { + windowAnimationTarget->surfaceNode_ = windowNode->leashWinSurfaceNode_; + } else { + windowAnimationTarget->surfaceNode_ = windowNode->surfaceNode_; + } + if (windowAnimationTarget->surfaceNode_ == nullptr) { + WLOGFE("Window surface node is null!"); + return nullptr; + } + + auto& stagingProperties = windowAnimationTarget->surfaceNode_->GetStagingProperties(); + auto rect = windowNode->GetWindowRect(); + // 0, 1, 2, 3: convert bounds to RectF + auto boundsRect = RectF(rect.posX_, rect.posY_, rect.width_, rect.height_); + windowAnimationTarget->windowBounds_ = RRect(boundsRect, stagingProperties.GetCornerRadius()); + return windowAnimationTarget; +} + +void RemoteAnimation::PostProcessShowCallback(const sptr& node) +{ + if (node == nullptr) { + WLOGFD("windowNode is nullptr!"); + return; + } + auto winRect = node->GetWindowRect(); + if (!node->leashWinSurfaceNode_) { + WLOGFD("leashWinSurfaceNode_ is nullptr with id: %{public}u!", node->GetWindowId()); + return; + } + WLOGFD("name:%{public}s id:%{public}u winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + node->GetWindowName().c_str(), node->GetWindowId(), + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + node->leashWinSurfaceNode_->SetBounds( + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + RSTransaction::FlushImplicitTransaction(); +} + +void RemoteAnimation::ExecuteFinalStateTask(sptr& node) +{ + StateTask destroyTask = nullptr; + auto winRoot = windowRoot_.promote(); + if (winRoot == nullptr || node == nullptr) { + WLOGFE("windowRoot or node is nullptr"); + return; + } + if (node->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFI("execute task removing from rs tree id:%{public}u!", node->GetWindowId()); + winRoot->UpdateRsTree(node->GetWindowId(), false); + } else if (node->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFI("execute task layout after show animation id:%{public}u!", node->GetWindowId()); + winRoot->LayoutWhenAddWindowNode(node, true); + } else { + WLOGFD("current State:%{public}u invalid", static_cast(node->stateMachine_.GetCurrentState())); + } + + if (node->stateMachine_.GetDestroyTask(destroyTask)) { + destroyTask(); + } +} + +void RemoteAnimation::CallbackTimeOutProcess() +{ + auto winRoot = windowRoot_.promote(); + if (winRoot == nullptr) { + WLOGFE("windowRoot is nullptr"); + return; + } + std::vector> animationPlayingNodes; + winRoot->GetAllAnimationPlayingNodes(animationPlayingNodes); + WLOGFI("CallbackTimeOutProcess playingNodes:%{public}u", static_cast(animationPlayingNodes.size())); + for (auto& weakNode : animationPlayingNodes) { + auto node = weakNode.promote(); + if (node == nullptr) { + continue; + } + WLOGFI("callback timeout process windowId:%{public}u", node->GetWindowId()); + node->stateMachine_.ResetAnimationTaskCount(1); + ProcessNodeStateTask(node); + } +} + +void RemoteAnimation::ProcessNodeStateTask(sptr& node) +{ + // when callback come, node maybe destroyed + if (node == nullptr) { + WLOGFI("node is nullptr!"); + return; + } + int32_t taskCount = node->stateMachine_.GetAnimationCount(); + if (taskCount <= 0) { // no animation task but finishCallback come + WLOGFE("ProcessNodeStateTask failed with windowId: %{public}u, name:%{public}s taskCount:%{public}d", + node->GetWindowId(), node->GetWindowName().c_str(), taskCount); + return; + } + node->stateMachine_.UpdateAnimationTaskCount(false); + taskCount = node->stateMachine_.GetAnimationCount(); + WLOGFI("ProcessNodeStateTask windowId: %{public}u, name:%{public}s state: %{public}u, taskCount:%{public}d", + node->GetWindowId(), node->GetWindowName().c_str(), + static_cast(node->stateMachine_.GetCurrentState()), taskCount); + if (taskCount > 0 || taskCount < 0) { + WLOGFI("not last state task of window: %{public}d, %{public}d callback left not be executed!", + node->GetWindowId(), taskCount); + return; + } + ExecuteFinalStateTask(node); + if (node->stateMachine_.IsWindowNodeShownOrShowing()) { + // delete when immersive solution change + PostProcessShowCallback(node); + node->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_DONE); + } else if (node->stateMachine_.IsWindowNodeHiddenOrHiding()) { + node->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE); + } +} + +sptr RemoteAnimation::CreateShowAnimationFinishedCallback( + const sptr& srcNode, const sptr& dstNode, bool needMinimizeSrcNode) +{ + wptr srcNodeWptr = srcNode; + wptr dstNodeWptr = dstNode; + // need add timeout check + std::function func; + if (!animationFirst_) { + WLOGFI("RSWindowAnimation: not animationFirst use default callback!"); + return GetTransitionFinishedCallback(srcNode, dstNode); + } else { + func = [srcNodeWptr, dstNodeWptr, needMinimizeSrcNode]() { + WLOGFI("RSWindowAnimation: animationFirst use state machine process ShowAnimationFinishedCallback!"); + auto srcNodeSptr = srcNodeWptr.promote(); + auto dstNodeSptr = dstNodeWptr.promote(); + if (dstNodeSptr == nullptr) { + WLOGFE("dstNode is nullptr!"); + return; + } + ProcessNodeStateTask(dstNodeSptr); + // launcher not do this + if (needMinimizeSrcNode) { + ProcessNodeStateTask(srcNodeSptr); + } + if (dstNodeSptr->stateMachine_.GetCurrentState() == WindowNodeState::SHOW_ANIMATION_DONE && + dstNodeSptr->leashWinSurfaceNode_) { + dstNodeSptr->leashWinSurfaceNode_->SetAnimationFinished(); + } + WLOGFI("current window:%{public}u state: %{public}u", dstNodeSptr->GetWindowId(), + static_cast(dstNodeSptr->stateMachine_.GetCurrentState())); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + std::unordered_map payload; + if (srcNodeWptr != nullptr) { + payload["srcPid"] = std::to_string(srcNodeWptr->GetCallingPid()); + } + ResSchedReport::GetInstance().ResSchedDataReport( + Rosen::RES_TYPE_SHOW_REMOTE_ANIMATION, Rosen::REMOTE_ANIMATION_END, payload); + }; + } + return CreateAnimationFinishedCallback(func); +} + +static void ProcessAbility(const sptr& srcNode, TransitionEvent event) +{ + if (srcNode == nullptr) { + return; + } + switch (event) { + case TransitionEvent::CLOSE: { + WLOGFI("close windowId: %{public}u, name:%{public}s", + srcNode->GetWindowId(), srcNode->GetWindowName().c_str()); + WindowInnerManager::GetInstance().CloseAbility(srcNode); + break; + } + case TransitionEvent::MINIMIZE: { + WLOGFI("minimize windowId: %{public}u, name:%{public}s", + srcNode->GetWindowId(), srcNode->GetWindowName().c_str()); + WindowInnerManager::GetInstance().MinimizeAbility(srcNode, true); + break; + } + default: + break; + } +} + +void RemoteAnimation::NotifyAnimationUpdateWallpaper(sptr node) +{ + if (!CheckAnimationController()) { + return; + } + WLOGFI("NotifyAnimationUpdateWallpaper"); + sptr srcTarget = CreateWindowAnimationTarget(nullptr, node); + // when wallpaper destroy, update with nullptr + windowAnimationController_->OnWallpaperUpdate(srcTarget); +} + +sptr RemoteAnimation::CreateHideAnimationFinishedCallback( + const sptr& srcNode, TransitionEvent event) +{ + wptr srcNodeWptr = srcNode; + // need add timeout check + std::function func; + if (!animationFirst_) { + func = [srcNodeWptr, event]() { + WLOGFI("RSWindowAnimation: not animationFirst use default callback!"); + auto weakNode = srcNodeWptr.promote(); + if (weakNode == nullptr || weakNode->abilityToken_ == nullptr) { + WLOGFE("window node or ability token is nullptr"); + return; + } + if (!weakNode->stateMachine_.IsWindowNodeHiddenOrHiding()) { + WLOGFE("window is not playing hide animation"); + return; + } + ProcessAbility(weakNode, event); + weakNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_DONE); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } else { + if (event != TransitionEvent::MINIMIZE) { + GetAndDrawSnapShot(srcNode); + } + ProcessAbility(srcNode, event); // execute first when animationFirst + func = [srcNodeWptr]() { + WLOGFI("RSWindowAnimation: animationFirst use state machine process HideAnimationFinishedCallback!"); + auto srcNodeSptr = srcNodeWptr.promote(); + ProcessNodeStateTask(srcNodeSptr); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + }; + } + return CreateAnimationFinishedCallback(func); +} + +sptr RemoteAnimation::CreateAnimationFinishedCallback( + const std::function& callback) +{ + if (callback == nullptr) { + WLOGFE("callback is null!"); + return nullptr; + } + auto currentId = allocationId_.fetch_add(1); + std::string timeOutTaskName = ANIMATION_TIME_OUT_TASK + std::to_string(currentId); + auto func = [callback, timeOutTaskName]() { + auto handler = wmsTaskHandler_.lock(); + if (handler != nullptr) { + handler->RemoveTask(timeOutTaskName); + WLOGFD("remove task %{public}s since animationCallback Come", timeOutTaskName.c_str()); + handler->PostTask(callback, AppExecFwk::EventQueue::Priority::IMMEDIATE); + } else { + WLOGFW("callback execute not on main wms thread since handler is null!"); + callback(); + } + }; + auto handlerSptr = wmsTaskHandler_.lock(); + if (handlerSptr != nullptr) { + handlerSptr->PostTask(func, timeOutTaskName, ANIMATION_TIME_OUT_MILLISECONDS); + WLOGFD("PostTask task %{public}s", timeOutTaskName.c_str()); + } + sptr finishCallback = new(std::nothrow) RSWindowAnimationFinishedCallback( + func); + if (finishCallback == nullptr) { + WLOGFE("New RSIWindowAnimationFinishedCallback failed"); + func(); + return nullptr; + } + return finishCallback; +} +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/starting_window.cpp b/window_manager/wmserver/src/starting_window.cpp new file mode 100644 index 0000000..258b087 --- /dev/null +++ b/window_manager/wmserver/src/starting_window.cpp @@ -0,0 +1,247 @@ +/* + * 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 "starting_window.h" +#include +#include +#include +#include +#include +#include "remote_animation.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "window_manager_service.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "StartingWindow"}; +} + +std::recursive_mutex StartingWindow::mutex_; +WindowMode StartingWindow::defaultMode_ = WindowMode::WINDOW_MODE_FULLSCREEN; + +sptr StartingWindow::CreateWindowNode(const sptr& info, uint32_t winId) +{ + sptr property = new(std::nothrow) WindowProperty(); + if (property == nullptr || info == nullptr) { + return nullptr; + } + + property->SetRequestRect(info->GetWindowRect()); + if (WindowHelper::IsValidWindowMode(info->GetWindowMode())) { + property->SetWindowMode(info->GetWindowMode()); + } else { + property->SetWindowMode(defaultMode_); + } + + property->SetDisplayId(info->GetDisplayId()); + property->SetWindowType(info->GetWindowType()); + property->AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID); + if (info->GetShowFlagWhenLocked()) { + property->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); + } + property->SetWindowId(winId); + sptr node = new(std::nothrow) WindowNode(property); + if (node == nullptr) { + return nullptr; + } + // test + node->stateMachine_.SetWindowId(winId); + node->abilityToken_ = info->GetAbilityToken(); + node->SetWindowSizeLimits(info->GetWindowSizeLimits()); + node->abilityInfo_.missionId_ = info->GetMissionId(); + node->abilityInfo_.bundleName_ = info->GetBundleName(); + node->abilityInfo_.abilityName_ = info->GetAbilityName(); + uint32_t modeSupportInfo = WindowHelper::ConvertSupportModesToSupportInfo(info->GetWindowSupportModes()); + node->SetModeSupportInfo(modeSupportInfo); + + if (CreateLeashAndStartingSurfaceNode(node) != WMError::WM_OK) { + return nullptr; + } + node->stateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED); + return node; +} + +WMError StartingWindow::CreateLeashAndStartingSurfaceNode(sptr& node) +{ + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = "leashWindow" + std::to_string(node->GetWindowId()); + node->leashWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::LEASH_WINDOW_NODE); + if (node->leashWinSurfaceNode_ == nullptr) { + WLOGFE("create leashWinSurfaceNode failed"); + return WMError::WM_ERROR_NULLPTR; + } + + rsSurfaceNodeConfig.SurfaceNodeName = "startingWindow" + std::to_string(node->GetWindowId()); + node->startingWinSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig, RSSurfaceNodeType::STARTING_WINDOW_NODE); + if (node->startingWinSurfaceNode_ == nullptr) { + WLOGFE("create startingWinSurfaceNode failed"); + node->leashWinSurfaceNode_ = nullptr; + return WMError::WM_ERROR_NULLPTR; + } + WLOGFI("Create leashWinSurfaceNode and startingWinSurfaceNode success with id:%{public}u!", node->GetWindowId()); + return WMError::WM_OK; +} + +WMError StartingWindow::DrawStartingWindow(sptr& node, + std::shared_ptr pixelMap, uint32_t bkgColor, bool isColdStart) +{ + if (node == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + // using snapshot to support hot start since node destroy when hide + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DrawStartingWindow(%u)", node->GetWindowId()); + Rect rect = node->GetWindowRect(); + if (RemoteAnimation::CheckRemoteAnimationEnabled(node->GetDisplayId()) && node->leashWinSurfaceNode_) { + // hides this node until RSProxyNode send valid context alpha/matrix + node->leashWinSurfaceNode_->ResetContextAlpha(); + } + if (!isColdStart) { + return WMError::WM_OK; + } + if (node->startingWinSurfaceNode_ == nullptr) { + WLOGFE("no starting Window SurfaceNode!"); + return WMError::WM_ERROR_NULLPTR; + } + if (pixelMap == nullptr) { + SurfaceDraw::DrawColor(node->startingWinSurfaceNode_, rect.width_, rect.height_, bkgColor); + return WMError::WM_OK; + } + + WLOGFD("draw background in sperate"); + SurfaceDraw::DrawImageRect(node->startingWinSurfaceNode_, rect, pixelMap, bkgColor); + return WMError::WM_OK; +} + +void StartingWindow::HandleClientWindowCreate(sptr& node, sptr& window, + uint32_t& windowId, const std::shared_ptr& surfaceNode, sptr& property, + int32_t pid, int32_t uid) +{ + if (node == nullptr) { + WLOGFE("node is nullptr"); + return; + } + node->surfaceNode_ = surfaceNode; + node->SetWindowToken(window); + node->SetCallingPid(pid); + node->SetCallingUid(uid); + windowId = node->GetWindowId(); + // test + node->stateMachine_.SetWindowId(windowId); + node->stateMachine_.SetWindowType(property->GetWindowType()); + WLOGFI("after set Id:%{public}u, requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]", + node->GetWindowId(), node->GetRequestRect().posX_, node->GetRequestRect().posY_, + node->GetRequestRect().width_, node->GetRequestRect().height_); + // Register FirstFrame Callback to rs, replace startwin + wptr weak = node; + auto firstFrameCompleteCallback = [weak]() { + WindowManagerService::GetInstance().PostAsyncTask([weak]() { + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::STARTING_WINDOW), + "wms:async:ShowStartingWindow"); + auto weakNode = weak.promote(); + if (weakNode == nullptr || weakNode->leashWinSurfaceNode_ == nullptr) { + WLOGFE("windowNode or leashWinSurfaceNode_ is nullptr"); + return; + } + WLOGFI("StartingWindow::Replace surfaceNode, id: %{public}u", weakNode->GetWindowId()); + weakNode->leashWinSurfaceNode_->RemoveChild(weakNode->startingWinSurfaceNode_); + WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode); + RSTransaction::FlushImplicitTransaction(); + weakNode->firstFrameAvaliable_ = true; + weakNode->startingWinSurfaceNode_ = nullptr; + }); + }; + node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback); + RSTransaction::FlushImplicitTransaction(); +} + +void StartingWindow::ReleaseStartWinSurfaceNode(sptr& node) +{ + std::lock_guard lock(mutex_); + if (!node->leashWinSurfaceNode_) { + WLOGFI("cannot release leashwindow since leash is null, id:%{public}u", node->GetWindowId()); + return; + } + node->leashWinSurfaceNode_->RemoveChild(node->startingWinSurfaceNode_); + node->leashWinSurfaceNode_->RemoveChild(node->surfaceNode_); + node->leashWinSurfaceNode_ = nullptr; + node->startingWinSurfaceNode_ = nullptr; + WLOGFI("Release startwindow surfaceNode end id: %{public}u, [leashWinSurface]: use_count: %{public}ld, \ + [startWinSurface]: use_count: %{public}ld ", node->GetWindowId(), + node->leashWinSurfaceNode_.use_count(), node->startingWinSurfaceNode_.use_count()); + RSTransaction::FlushImplicitTransaction(); +} + +void StartingWindow::AddNodeOnRSTree(sptr& node, const AnimationConfig& animationConfig, + bool isMultiDisplay) +{ + auto updateRSTreeFunc = [&]() { + auto& dms = DisplayManagerServiceInner::GetInstance(); + DisplayId displayId = node->GetDisplayId(); + if (!node->surfaceNode_) { // cold start + if (!WindowHelper::IsMainWindow(node->GetWindowType())) { + WLOGFE("window id:%{public}d type: %{public}u is not Main Window!", + node->GetWindowId(), static_cast(node->GetWindowType())); + } + dms.UpdateRSTree(displayId, displayId, node->leashWinSurfaceNode_, true, isMultiDisplay); + node->leashWinSurfaceNode_->AddChild(node->startingWinSurfaceNode_, -1); + } else { // hot start + const auto& displayIdVec = node->GetShowingDisplays(); + for (auto& shownDisplayId : displayIdVec) { + if (node->leashWinSurfaceNode_) { // to app + dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->leashWinSurfaceNode_, true, isMultiDisplay); + } else { // to launcher + dms.UpdateRSTree(shownDisplayId, shownDisplayId, node->surfaceNode_, true, isMultiDisplay); + } + for (auto& child : node->children_) { + if (child->currentVisibility_) { + dms.UpdateRSTree(shownDisplayId, shownDisplayId, child->surfaceNode_, true, isMultiDisplay); + } + } + } + } + }; + wptr weakNode = node; + auto finishCallBack = [weakNode]() { + auto weak = weakNode.promote(); + if (weak == nullptr) { + return; + } + auto winRect = weak->GetWindowRect(); + WLOGFI("before setBounds windowRect: %{public}d, %{public}d, %{public}d, %{public}d", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + if (weak->leashWinSurfaceNode_) { + weak->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + weak->leashWinSurfaceNode_->SetAnimationFinished(); + } + RSTransaction::FlushImplicitTransaction(); + }; + if (!RemoteAnimation::CheckAnimationController()) { + RSNode::Animate(animationConfig.windowAnimationConfig_.animationTiming_.timingProtocol_, + animationConfig.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc, finishCallBack); + } else { + // add or remove window without animation + updateRSTreeFunc(); + } +} + +void StartingWindow::SetDefaultWindowMode(WindowMode defaultMode) +{ + defaultMode_ = defaultMode; +} +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/window_common_event.cpp b/window_manager/wmserver/src/window_common_event.cpp new file mode 100644 index 0000000..a48962d --- /dev/null +++ b/window_manager/wmserver/src/window_common_event.cpp @@ -0,0 +1,99 @@ +/* + * 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 "window_common_event.h" + +#include +#include +#include "common_event_subscribe_info.h" +#include "event_runner.h" +#include "skills.h" +#include "window_manager_hilog.h" +#include "window_manager_service.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowCommonEvent"}; + constexpr int RETRY_MAX_COUNT = 3; + const std::string THREAD_ID = "WindowCommonEventHandler"; +} + +WindowCommonEvent::WindowCommonEvent() +{ + handleCommonEventFuncs_.insert(make_pair(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED, + &WindowCommonEvent::HandleAccountSwitched)); + auto runner = AppExecFwk::EventRunner::Create(THREAD_ID); + eventHandler_ = std::make_shared(runner); +} + +WindowCommonEvent::~WindowCommonEvent() +{ +} + +void WindowCommonEvent::SubscriberEvent() +{ + EventFwk::MatchingSkills skills; + skills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED); + EventFwk::CommonEventSubscribeInfo info(skills); + subscriber_ = std::make_shared(info, shared_from_this()); + int retry = RETRY_MAX_COUNT; + SubscriberEventInner(retry); +} + +void WindowCommonEvent::SubscriberEventInner(int retry) +{ + if (retry <= 0) { + return; + } + retry--; + WLOGFI("called action = %{public}d", retry); + if (EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber_)) { + return; + } + std::function func = std::bind(&WindowCommonEvent::SubscriberEventInner, this, retry); + // post task delay 500ms + eventHandler_->PostTask(func, 500, AppExecFwk::EventQueue::Priority::HIGH); +} + +void WindowCommonEvent::UnSubscriberEvent() +{ + auto task = [this] { + EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber_); + }; + eventHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void WindowCommonEvent::OnReceiveEvent(const EventFwk::CommonEventData& data) +{ + WLOGFI("receive common event, action = %{public}s", data.GetWant().GetAction().c_str()); + auto task = [this, data] { + std::string action = data.GetWant().GetAction(); + WLOGFI("called action = %{public}s", action.c_str()); + if (handleCommonEventFuncs_.count(action)) { + (this->*handleCommonEventFuncs_[action])(data); + } + }; + eventHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); +} + +void WindowCommonEvent::HandleAccountSwitched(const EventFwk::CommonEventData& data) const +{ + int accountId = data.GetCode(); + WLOGFI("handle account switch, account id = %{public}d", accountId); + WindowManagerService::GetInstance().OnAccountSwitched(accountId); +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/window_controller.cpp b/window_manager/wmserver/src/window_controller.cpp new file mode 100644 index 0000000..67c1779 --- /dev/null +++ b/window_manager/wmserver/src/window_controller.cpp @@ -0,0 +1,1471 @@ +/* + * Copyright (c) 2021-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 "window_controller.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "display_manager_service_inner.h" +#include "minimize_app.h" +#include "remote_animation.h" +#include "starting_window.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "window_helper.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowController"}; + constexpr uint32_t TOUCH_HOT_AREA_MAX_NUM = 10; + constexpr float MASKING_SURFACE_NODE_Z_ORDER = 9999; +} + +uint32_t WindowController::GenWindowId() +{ + return ++windowId_; +} + +void WindowController::StartingWindow(sptr info, std::shared_ptr pixelMap, + uint32_t bkgColor, bool isColdStart) +{ + if (!info || info->GetAbilityToken() == nullptr) { + WLOGFE("info or AbilityToken is nullptr!"); + return; + } + StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::STARTING_WINDOW), + "wms:async:ShowStartingWindow"); + auto node = windowRoot_->FindWindowNodeWithToken(info->GetAbilityToken()); + if (node == nullptr) { + if (!isColdStart) { + WLOGFE("no windowNode exists but is hot start!"); + return; + } + node = StartingWindow::CreateWindowNode(info, GenWindowId()); + if (node == nullptr) { + return; + } + if (windowRoot_->SaveWindow(node) != WMError::WM_OK) { + return; + } + if (!RemoteAnimation::CheckAnimationController()) { + UpdateWindowAnimation(node); + } + } else { + if (node->stateMachine_.IsWindowNodeShownOrShowing()) { + WLOGFD("current window is visible, windowId:%{public}u state:%{public}u!", + node->GetWindowId(), static_cast(node->stateMachine_.GetCurrentState())); + return; + } + if (WindowHelper::IsValidWindowMode(info->GetWindowMode()) && + (node->GetWindowMode() != info->GetWindowMode())) { + WLOGFW("set starting window mode. starting mode is: %{public}u, window mode is:%{public}u.", + node->GetWindowMode(), info->GetWindowMode()); + node->SetWindowMode(info->GetWindowMode()); + } + } + + if (!WindowHelper::CheckSupportWindowMode(node->GetWindowMode(), node->GetModeSupportInfo(), info)) { + WLOGFE("need to cancel starting window"); + return; + } + + if (windowRoot_->AddWindowNode(0, node, true) != WMError::WM_OK) { + return; + } + StartingWindow::DrawStartingWindow(node, pixelMap, bkgColor, isColdStart); + FlushWindowInfo(node->GetWindowId()); + node->startingWindowShown_ = true; + WLOGFD("StartingWindow show success with id:%{public}u!", node->GetWindowId()); +} + +void WindowController::CancelStartingWindow(sptr abilityToken) +{ + auto node = windowRoot_->FindWindowNodeWithToken(abilityToken); + if (node == nullptr) { + WLOGFD("cannot find windowNode!"); + return; + } + if (!node->startingWindowShown_) { + WLOGFE("CancelStartingWindow failed because client window has shown id:%{public}u", node->GetWindowId()); + return; + } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:CancelStartingWindow(%u)", node->GetWindowId()); + FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::STARTING_WINDOW), + "wms:async:ShowStartingWindow"); + WLOGFD("CancelStartingWindow with id:%{public}u!", node->GetWindowId()); + node->isAppCrash_ = true; + WMError res = DestroyWindow(node->GetWindowId(), false); + if (res != WMError::WM_OK) { + WLOGFE("DestroyWindow failed!"); + } +} + +WMError WindowController::NotifyWindowTransition(sptr& srcInfo, + sptr& dstInfo) +{ + WLOGFD("NotifyWindowTransition begin!"); + sptr dstNode = nullptr; + sptr srcNode = nullptr; + if (srcInfo) { + srcNode = windowRoot_->FindWindowNodeWithToken(srcInfo->GetAbilityToken()); + } + if (dstInfo) { + dstNode = windowRoot_->FindWindowNodeWithToken(dstInfo->GetAbilityToken()); + } + if (!RemoteAnimation::CheckTransition(srcInfo, srcNode, dstInfo, dstNode)) { + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast(TraceTaskId::REMOTE_ANIMATION), + "wms:async:ShowRemoteAnimation"); + auto transitionEvent = RemoteAnimation::GetTransitionEvent(srcInfo, dstInfo, srcNode, dstNode); + switch (transitionEvent) { + case TransitionEvent::APP_TRANSITION: { + return RemoteAnimation::NotifyAnimationTransition(srcInfo, dstInfo, srcNode, dstNode); + } + case TransitionEvent::MINIMIZE: + return RemoteAnimation::NotifyAnimationMinimize(srcInfo, srcNode); + case TransitionEvent::CLOSE: + return RemoteAnimation::NotifyAnimationClose(srcInfo, srcNode, TransitionEvent::CLOSE); + case TransitionEvent::BACK_TRANSITION: + return RemoteAnimation::NotifyAnimationBackTransition(srcInfo, dstInfo, srcNode, dstNode); + default: + return WMError::WM_ERROR_NO_REMOTE_ANIMATION; + } + return WMError::WM_OK; +} + +WMError WindowController::GetFocusWindowNode(DisplayId displayId, sptr& windowNode) +{ + auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (windowNodeContainer == nullptr) { + WLOGFE("windowNodeContainer is null, displayId: %{public}" PRIu64"", displayId); + return WMError::WM_ERROR_NULLPTR; + } + uint32_t focusWindowId = windowNodeContainer->GetFocusWindow(); + WLOGFD("focusWindowId: %{public}u", focusWindowId); + auto thisWindowNode = windowRoot_->GetWindowNode(focusWindowId); + if (thisWindowNode == nullptr || !thisWindowNode->currentVisibility_) { + WLOGFE("focusWindowNode is null or invisible, focusWindowId: %{public}u", focusWindowId); + return WMError::WM_ERROR_INVALID_WINDOW; + } + windowNode = thisWindowNode; + return WMError::WM_OK; +} + +WMError WindowController::GetFocusWindowInfo(sptr& abilityToken) +{ + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + sptr windowNode; + WMError res = GetFocusWindowNode(displayId, windowNode); + if (res == WMError::WM_OK) { + abilityToken = windowNode->abilityToken_; + } + return res; +} + +WMError WindowController::CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, uint32_t& windowId, sptr token, + int32_t pid, int32_t uid) +{ + uint32_t parentId = property->GetParentId(); + if ((parentId != INVALID_WINDOW_ID) && + !WindowHelper::IsSubWindow(property->GetWindowType()) && + !WindowHelper::IsSystemSubWindow(property->GetWindowType())) { + WLOGFE("create window failed, type is error"); + return WMError::WM_ERROR_INVALID_TYPE; + } + + if (windowRoot_->CheckMultiDialogWindows(property->GetWindowType(), token)) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + + sptr node = windowRoot_->FindWindowNodeWithToken(token); + if (node != nullptr && WindowHelper::IsMainWindow(property->GetWindowType()) && node->startingWindowShown_) { + StartingWindow::HandleClientWindowCreate(node, window, windowId, surfaceNode, property, pid, uid); + windowRoot_->AddDeathRecipient(node); + windowRoot_->AddSurfaceNodeIdWindowNodePair(surfaceNode->GetId(), node); + return WMError::WM_OK; + } + + windowId = GenWindowId(); + sptr windowProperty = new WindowProperty(property); + windowProperty->SetWindowId(windowId); + node = new WindowNode(windowProperty, window, surfaceNode, pid, uid); + node->abilityToken_ = token; + node->dialogTargetToken_ = token; + UpdateWindowAnimation(node); + WLOGFD("createWindow name:%{public}u, windowName:%{public}s", + windowId, node->GetWindowName().c_str()); + // test + node->stateMachine_.SetWindowId(windowId); + node->stateMachine_.SetWindowType(property->GetWindowType()); + return windowRoot_->SaveWindow(node); +} + +void WindowController::NotifyAfterAddWindow(sptr& node) +{ + std::vector> nodes; + nodes.emplace_back(node); + for (auto& child : node->children_) { + if (child->currentVisibility_) { + nodes.emplace_back(child); + } + } + for (auto& iter : nodes) { + if ((iter->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) && + (node->abilityToken_ != iter->abilityToken_)) { + iter->GetWindowToken()->NotifyForeground(); + } + } + accessibilityConnection_->NotifyAccessibilityWindowInfo(node->GetDisplayId(), nodes, + WindowUpdateType::WINDOW_UPDATE_ADDED); +} + +WMError WindowController::AddWindowNode(sptr& property) +{ + auto node = windowRoot_->GetWindowNode(property->GetWindowId()); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + + if (node->currentVisibility_ && !node->startingWindowShown_) { + WLOGFE("current window is visible, windowId: %{public}u", node->GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + + // using starting window rect if client rect is empty + if (WindowHelper::IsEmptyRect(property->GetRequestRect()) && node->startingWindowShown_) { // for tile and cascade + property->SetRequestRect(node->GetRequestRect()); + property->SetWindowRect(node->GetWindowRect()); + property->SetDecoStatus(true); + } + node->GetWindowProperty()->CopyFrom(property); + // Need 'check permission' + // Need 'adjust property' + UpdateWindowAnimation(node); + WMError res = windowRoot_->AddWindowNode(property->GetParentId(), node); + if (res != WMError::WM_OK) { + MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); + return res; + } + windowRoot_->FocusFaultDetection(); + RelayoutKeyboard(node); + FlushWindowInfo(property->GetWindowId()); + NotifyAfterAddWindow(node); + HandleTurnScreenOn(node); + + if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) { + sysBarWinId_[node->GetWindowType()] = node->GetWindowId(); + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + ResizeSoftInputCallingWindowIfNeed(node); + } + StopBootAnimationIfNeed(node); + // when hide with remote animation first and show with default animation, need transform state + // minimize should execute in finish callback when remote animation enabled + if (!node->stateMachine_.IsShowAnimationPlaying()) { + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + MinimizeApp::ExecuteMinimizeAll(); + WLOGFD("id:%{public}u execute minimize all", node->GetWindowId()); + } + node->stateMachine_.TransitionTo(WindowNodeState::SHOWN); // for normal show which not use remote animation + } else if (WindowHelper::IsMainWindow(node->GetWindowType())) { + MinimizeApp::ExecuteMinimizeTargetReasons(~MinimizeReason::OTHER_WINDOW); + } + return WMError::WM_OK; +} + +void WindowController::RelayoutKeyboard(const sptr& node) +{ + if (node == nullptr) { + WLOGFE("could not find window"); + return; + } + if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + return; + } + + auto container = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("window node container is null"); + return; + } + + uint32_t navigationBarHeight = 0; + bool hasFullScreenKeyGuardWindow = false; + WindowNodeOperationFunc func = [&navigationBarHeight, &hasFullScreenKeyGuardWindow](sptr windowNode) { + if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD && + windowNode->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) { + hasFullScreenKeyGuardWindow = true; + } + if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR && windowNode->isVisible_) { + navigationBarHeight = windowNode->GetWindowRect().height_; + if (hasFullScreenKeyGuardWindow) { + WLOGFW("RelayoutKeyboard: The navigation bar is overlaid by the keyguard window and is invisible"); + navigationBarHeight = 0; + } + return true; + } + return false; + }; + container->TraverseWindowTree(func, true); // FromTopToBottom + + sptr defaultDisplayInfo = DisplayManagerServiceInner::GetInstance().GetDefaultDisplay(); + if (defaultDisplayInfo == nullptr) { + WLOGFE("defaultDisplayInfo is null"); + return; + } + + auto previousRect = node->GetWindowRect(); + WLOGFD("relayout keyboard window with navigationBarHeight: %{public}u", navigationBarHeight); + Rect requestedRect = { previousRect.posX_, + static_cast(defaultDisplayInfo->GetHeight() - previousRect.height_ - navigationBarHeight), + previousRect.width_, previousRect.height_ }; + ResizeRect(node->GetWindowId(), requestedRect, WindowSizeChangeReason::MOVE); +} + +void WindowController::ResizeSoftInputCallingWindowIfNeed(const sptr& node) +{ + auto callingWindowId = node->GetCallingWindow(); + auto callingWindow = windowRoot_->GetWindowNode(callingWindowId); + if (callingWindow == nullptr) { + auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (windowNodeContainer == nullptr) { + WLOGFE("windowNodeContainer is null, displayId:%{public}" PRIu64"", node->GetDisplayId()); + return; + } + callingWindowId = windowNodeContainer->GetFocusWindow(); + callingWindow = windowRoot_->GetWindowNode(callingWindowId); + } + if (callingWindow == nullptr || !callingWindow->currentVisibility_ || + callingWindow->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) { + WLOGFE("callingWindow is null or invisible or not float window, callingWindowId:%{public}u", callingWindowId); + return; + } + Rect softInputWindowRect = node->GetWindowRect(); + Rect callingWindowRect = callingWindow->GetWindowRect(); + Rect rect = WindowHelper::GetOverlap(softInputWindowRect, callingWindowRect, 0, 0); + if (WindowHelper::IsEmptyRect(rect)) { + WLOGFE("there is no overlap"); + return; + } + Rect requestedRect = callingWindowRect; + requestedRect.posY_ = softInputWindowRect.posY_ - static_cast(requestedRect.height_); + Rect statusBarWindowRect = { 0, 0, 0, 0 }; + auto statusbarWindow = windowRoot_->GetWindowNode(sysBarWinId_[WindowType::WINDOW_TYPE_STATUS_BAR]); + if (statusbarWindow != nullptr && statusbarWindow->parent_ != nullptr) { + statusBarWindowRect = statusbarWindow->GetWindowRect(); + } + int32_t posY = std::max(requestedRect.posY_, static_cast(statusBarWindowRect.height_)); + if (posY != requestedRect.posY_) { + requestedRect.height_ = static_cast(softInputWindowRect.posY_ - posY); + requestedRect.posY_ = posY; + } + callingWindowRestoringRect_ = callingWindowRect; + callingWindowId_ = callingWindow->GetWindowId(); + ResizeRectAndFlush(callingWindowId_, requestedRect, WindowSizeChangeReason::DRAG); +} + +void WindowController::RestoreCallingWindowSizeIfNeed() +{ + auto callingWindow = windowRoot_->GetWindowNode(callingWindowId_); + if (!WindowHelper::IsEmptyRect(callingWindowRestoringRect_) && callingWindow != nullptr && + callingWindow->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) { + ResizeRectAndFlush(callingWindowId_, callingWindowRestoringRect_, WindowSizeChangeReason::DRAG); + } + callingWindowRestoringRect_ = { 0, 0, 0, 0 }; + callingWindowId_ = 0u; +} + +void WindowController::HandleTurnScreenOn(const sptr& node) +{ + if (node == nullptr) { + WLOGFE("window is invalid"); + return; + } + WLOGFD("handle turn screen on: [%{public}s, %{public}d]", node->GetWindowName().c_str(), node->IsTurnScreenOn()); + // reset ipc identity + std::string identity = IPCSkeleton::ResetCallingIdentity(); + if (node->IsTurnScreenOn() && !PowerMgr::PowerMgrClient::GetInstance().IsScreenOn()) { + WLOGFD("turn screen on"); + PowerMgr::PowerMgrClient::GetInstance().WakeupDevice(); + } + // set ipc identity to raw + IPCSkeleton::SetCallingIdentity(identity); +} + +WMError WindowController::RemoveWindowNode(uint32_t windowId, bool fromAnimation) +{ + auto windowNode = windowRoot_->GetWindowNode(windowId); + if (windowNode == nullptr) { + WLOGFE("windowNode is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + auto removeFunc = [this, windowId, windowNode, fromAnimation]() { + WMError res = windowRoot_->RemoveWindowNode(windowId, fromAnimation); + if (res != WMError::WM_OK) { + WLOGFE("RemoveWindowNode failed"); + return res; + } + windowRoot_->FocusFaultDetection(); + FlushWindowInfo(windowId); + std::vector> nodes; + nodes.emplace_back(windowNode); + for (auto& child : windowNode->children_) { + nodes.emplace_back(child); + } + for (auto& iter : nodes) { + if ((iter->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) && + (windowNode->abilityToken_ != iter->abilityToken_)) { + iter->GetWindowToken()->NotifyBackground(); + } + } + displayZoomController_->ClearZoomTransform(nodes); + accessibilityConnection_->NotifyAccessibilityWindowInfo(windowNode->GetDisplayId(), nodes, + WindowUpdateType::WINDOW_UPDATE_REMOVED); + return res; + }; + WMError res = WMError::WM_ERROR_NO_REMOTE_ANIMATION; + if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { + if (RemoteAnimation::NotifyAnimationScreenUnlock(removeFunc) == WMError::WM_OK) { + WLOGFD("NotifyAnimationScreenUnlock with remote animation"); + res = WMError::WM_OK; + } + } + if (res != WMError::WM_OK) { + res = removeFunc(); + } + if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + RestoreCallingWindowSizeIfNeed(); + } + if (!windowNode->stateMachine_.IsHideAnimationPlaying()) { + windowNode->stateMachine_.TransitionTo(WindowNodeState::HIDDEN); + } + return res; +} + +WMError WindowController::DestroyWindow(uint32_t windowId, bool onlySelf) +{ + DisplayId displayId = DISPLAY_ID_INVALID; + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("destroy window id:%{public}u failed, because window node is not exist.", windowId); + return WMError::WM_ERROR_NULLPTR; + } + displayId = node->GetDisplayId(); + WMError res = windowRoot_->DestroyWindow(windowId, onlySelf); + if (res != WMError::WM_OK) { + return res; + } + windowRoot_->FocusFaultDetection(); + FlushWindowInfoWithDisplayId(displayId); + std::vector> nodes; + nodes.emplace_back(node); + for (auto& child : node->children_) { + nodes.emplace_back(child); + } + accessibilityConnection_->NotifyAccessibilityWindowInfo(node->GetDisplayId(), nodes, + WindowUpdateType::WINDOW_UPDATE_REMOVED); + node->stateMachine_.TransitionTo(WindowNodeState::DESTROYED); + return res; +} + +WMError WindowController::ResizeRect(uint32_t windowId, const Rect& rect, WindowSizeChangeReason reason) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) { + WLOGFE("fullscreen window could not resize"); + return WMError::WM_ERROR_INVALID_OPERATION; + } + auto property = node->GetWindowProperty(); + node->SetWindowSizeChangeReason(reason); + Rect lastRect = property->GetWindowRect(); + Rect newRect; + if (reason == WindowSizeChangeReason::MOVE) { + newRect = { rect.posX_, rect.posY_, lastRect.width_, lastRect.height_ }; + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + if (windowRoot_->IsForbidDockSliceMove(node->GetDisplayId())) { + WLOGFD("dock slice is forbidden to move"); + newRect = lastRect; + } else if (windowRoot_->IsVerticalDisplay(node)) { + newRect.posX_ = lastRect.posX_; + } else { + newRect.posY_ = lastRect.posY_; + } + } + } else if (reason == WindowSizeChangeReason::RESIZE) { + newRect = { lastRect.posX_, lastRect.posY_, rect.width_, rect.height_ }; + } else if (reason == WindowSizeChangeReason::DRAG || reason == WindowSizeChangeReason::ROTATION) { + newRect = rect; + } + property->SetRequestRect(newRect); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_RECT); + if (res != WMError::WM_OK) { + return res; + } + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + return WMError::WM_OK; +} + +WMError WindowController::ResizeRectAndFlush(uint32_t windowId, const Rect& rect, WindowSizeChangeReason reason) +{ + WMError res = ResizeRect(windowId, rect, reason); + if (res != WMError::WM_OK) { + return res; + } else { + FlushWindowInfo(windowId); + return WMError::WM_OK; + } +} + +WMError WindowController::RequestFocus(uint32_t windowId) +{ + if (windowRoot_ == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + WMError res = windowRoot_->RequestFocus(windowId); + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId), + WindowUpdateType::WINDOW_UPDATE_FOCUSED); + return res; +} + +WMError WindowController::SetWindowMode(uint32_t windowId, WindowMode dstMode) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + WMError ret = windowRoot_->SetWindowMode(node, dstMode); + if (ret != WMError::WM_OK) { + return ret; + } + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + if (!node->stateMachine_.IsShowAnimationPlaying()) { + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + MinimizeApp::ExecuteMinimizeAll(); + WLOGFD("id:%{public}u execute minimize all", node->GetWindowId()); + } + } + return WMError::WM_OK; +} + +void WindowController::NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) +{ + WLOGFD("NotifyDisplayStateChange start: %{public}u", type); + switch (type) { + case DisplayStateChangeType::BEFORE_SUSPEND: { + isScreenLocked_ = true; + windowRoot_->ProcessWindowStateChange(WindowState::STATE_FROZEN, WindowStateChangeReason::KEYGUARD); + break; + } + case DisplayStateChangeType::BEFORE_UNLOCK: { + windowRoot_->ProcessWindowStateChange(WindowState::STATE_UNFROZEN, WindowStateChangeReason::KEYGUARD); + isScreenLocked_ = false; + break; + } + case DisplayStateChangeType::CREATE: { + SetDefaultDisplayInfo(defaultDisplayId, displayInfo); + windowRoot_->ProcessDisplayCreate(defaultDisplayId, displayInfo, displayInfoMap); + FlushWindowInfoWithDisplayId(displayInfo->GetDisplayId()); + break; + } + case DisplayStateChangeType::DESTROY: { + windowRoot_->ProcessDisplayDestroy(defaultDisplayId, displayInfo, displayInfoMap); + FlushWindowInfoWithDisplayId(defaultDisplayId); + break; + } + case DisplayStateChangeType::DISPLAY_COMPRESS: + case DisplayStateChangeType::SIZE_CHANGE: + case DisplayStateChangeType::UPDATE_ROTATION: + case DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE: { + ProcessDisplayChange(defaultDisplayId, displayInfo, displayInfoMap, type); + /* + * Window tile num may change when display rotate or change size, need to execute minimize + */ + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::LAYOUT_TILE); + break; + } + default: { + WLOGFE("unknown DisplayStateChangeType:%{public}u", type); + return; + } + } + WLOGFD("NotifyDisplayStateChange end, type: %{public}u", type); +} + +void WindowController::SetDefaultDisplayInfo(DisplayId defaultDisplayId, sptr displayInfo) +{ + if (displayInfo == nullptr) { + WLOGFE("display is null"); + return; + } + if (displayInfo->GetDisplayId() != defaultDisplayId) { + return; + } + WLOGFD("get default display info"); + auto displayWidth = static_cast(displayInfo->GetWidth()); + auto displayHeight = static_cast(displayInfo->GetHeight()); + defaultDisplayRect_ = { 0, 0, displayWidth, displayHeight }; +} + +void WindowController::ProcessSystemBarChange(const sptr& displayInfo) +{ + DisplayId displayId = displayInfo->GetDisplayId(); + auto width = static_cast(displayInfo->GetWidth()); + auto height = static_cast(displayInfo->GetHeight()); + const auto& statusBarNode = windowRoot_->GetWindowNode(sysBarWinId_[WindowType::WINDOW_TYPE_STATUS_BAR]); + if (statusBarNode != nullptr && statusBarNode->GetDisplayId() == displayId) { + auto statusBarHeight = statusBarNode->GetWindowRect().height_; + Rect newRect = { 0, 0, width, statusBarHeight }; + ResizeRect(sysBarWinId_[WindowType::WINDOW_TYPE_STATUS_BAR], newRect, WindowSizeChangeReason::ROTATION); + } + const auto& naviBarNode = windowRoot_->GetWindowNode(sysBarWinId_[WindowType::WINDOW_TYPE_NAVIGATION_BAR]); + if (naviBarNode != nullptr && naviBarNode->GetDisplayId() == displayId) { + auto naviBarHeight = naviBarNode->GetWindowRect().height_; + Rect newRect = { 0, static_cast(height - naviBarHeight), width, naviBarHeight }; + ResizeRect(sysBarWinId_[WindowType::WINDOW_TYPE_NAVIGATION_BAR], newRect, WindowSizeChangeReason::ROTATION); + } +} + +void WindowController::ProcessDisplayChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) +{ + if (displayInfo == nullptr) { + WLOGFE("get display failed"); + return; + } + auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayInfo->GetDisplayId()); + if (windowNodeContainer != nullptr) { + windowNodeContainer->BeforeProcessWindowAvoidAreaChangeWhenDisplayChange(); + windowNodeContainer->UpdateDisplayInfo(displayInfo); + } + switch (type) { + case DisplayStateChangeType::DISPLAY_COMPRESS: + ProcessDisplayCompression(defaultDisplayId, displayInfo); + [[fallthrough]]; + case DisplayStateChangeType::SIZE_CHANGE: + case DisplayStateChangeType::UPDATE_ROTATION: + windowRoot_->ProcessDisplayChange(defaultDisplayId, displayInfo, displayInfoMap, type); + ProcessSystemBarChange(displayInfo); + break; + case DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE: { + windowRoot_->ProcessDisplayChange(defaultDisplayId, displayInfo, displayInfoMap, type); + break; + } + default: { + WLOGFE("unknown DisplayStateChangeType:%{public}u", type); + return; + } + } + auto displayId = displayInfo->GetDisplayId(); + displayZoomController_->UpdateAllWindowsZoomInfo(displayId); + FlushWindowInfoWithDisplayId(displayId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(displayId, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + if (windowNodeContainer != nullptr) { + windowNodeContainer->ProcessWindowAvoidAreaChangeWhenDisplayChange(); + } +} + +void WindowController::ProcessDisplayCompression(DisplayId defaultDisplayId, const sptr& displayInfo) +{ + WLOGFD("Enter processDisplayCompress"); + DisplayId displayId = displayInfo->GetDisplayId(); + if (displayId != defaultDisplayId) { + WLOGFD("Not default display"); + return; + } + auto& dms = DisplayManagerServiceInner::GetInstance(); + if (!displayInfo->GetWaterfallDisplayCompressionStatus()) { + if (maskingSurfaceNode_ == nullptr) { + WLOGFD("MaskingSurfaceNode is not created"); + return; + } else { + WLOGFD("Remove maskingSurfaceNode"); + dms.UpdateRSTree(displayId, displayId, maskingSurfaceNode_, false, false); + maskingSurfaceNode_ = nullptr; + return; + } + } + WLOGFD("Add maskingSurfaceNode"); + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = "maskingSurface"; + maskingSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig); + if (maskingSurfaceNode_ == nullptr) { + WLOGFE("Create maskingSurfaceNode failed"); + return; + } + auto displayWidth = displayInfo->GetWidth(); + auto displayHeight = displayInfo->GetHeight(); + auto maskingSizeX = displayInfo->GetOffsetX(); + auto maskingSizeY = displayInfo->GetOffsetY(); + auto fullDisplayWidth = displayWidth + maskingSizeX * 2; // *2: Get full width. + auto fullDisplayHeight = displayHeight + maskingSizeY * 2; // *2: Get full height. + + Rect screenRect = Rect {0, 0, fullDisplayWidth, fullDisplayHeight}; + Rect transparentRect = Rect {maskingSizeX, maskingSizeY, displayWidth, displayHeight}; + WLOGFD("ScreenRect: fullDisplayWidth: %{public}d, fullDisplayHeight: %{public}d", + fullDisplayWidth, fullDisplayHeight); + WLOGFD("TransparentRect: X: %{public}u, Y: %{public}u, Width: %{public}d, Height: %{public}d", + maskingSizeX, maskingSizeY, displayWidth, displayHeight); + + maskingSurfaceNode_->SetPositionZ(MASKING_SURFACE_NODE_Z_ORDER); + + if (!SurfaceDraw::DrawMasking(maskingSurfaceNode_, screenRect, transparentRect)) { + WLOGFE("Draw masking surface failed"); + return; + } + maskingSurfaceNode_->SetBounds(0, 0, fullDisplayWidth, fullDisplayHeight); + dms.UpdateRSTree(displayId, displayId, maskingSurfaceNode_, true, false); +} + +void WindowController::StopBootAnimationIfNeed(const sptr& node) +{ + if (isBootAnimationStopped_) { + return; + } + if (node == nullptr) { + WLOGFE("could not find window"); + return; + } + if (node->GetDisplayId() != DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId()) { + return; + } + auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (windowNodeContainer == nullptr) { + WLOGFE("window node container is null"); + return; + } + std::vector> windowNodes; + windowNodeContainer->TraverseContainer(windowNodes); + WmOcclusion::Rect defaultDisplayRect = { defaultDisplayRect_.posX_, defaultDisplayRect_.posY_, + defaultDisplayRect_.posX_ + static_cast(defaultDisplayRect_.width_), + defaultDisplayRect_.posY_ + static_cast(defaultDisplayRect_.height_)}; + WmOcclusion::Region defaultDisplayRegion(defaultDisplayRect); + WmOcclusion::Region allRegion; // Counts the area of all shown windows + for (auto& node : windowNodes) { + if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) { + continue; + } + auto windowRect = node->GetWindowRect(); + WmOcclusion::Rect curRect = { windowRect.posX_, windowRect.posY_, + windowRect.posX_ + static_cast(windowRect.width_), + windowRect.posY_ + static_cast(windowRect.height_) }; + WmOcclusion::Region curRegion(curRect); + allRegion = curRegion.Or(allRegion); + WmOcclusion::Region subResult = defaultDisplayRegion.Sub(allRegion); + if (subResult.GetSize() == 0) { + WLOGFD("stop boot animation"); + system::SetParameter("bootevent.wms.fullscreen.ready", "true"); + isBootAnimationStopped_ = true; + RecordBootAnimationEvent(); + } + } +} + +void WindowController::RecordBootAnimationEvent() const +{ + uint64_t time = static_cast(std::chrono::time_point_cast + (std::chrono::steady_clock::now()).time_since_epoch().count()); + WLOGFD("boot animation done duration(s): %{public}" PRIu64"", time); + std::ostringstream os; + os << "boot animation done duration(s): " << time <<";"; + int32_t ret = OHOS::HiviewDFX::HiSysEvent::Write( + OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, + "WINDOW_BOOT_ANIMATION_DONE", + OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, + "MSG", os.str()); + if (ret != 0) { + WLOGFE("Write HiSysEvent error, ret:%{public}d", ret); + } +} + +WMError WindowController::SetWindowType(uint32_t windowId, WindowType type) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto property = node->GetWindowProperty(); + property->SetWindowType(type); + UpdateWindowAnimation(node); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_TYPE); + if (res != WMError::WM_OK) { + return res; + } + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + WLOGFD("SetWindowType end"); + return res; +} + +WMError WindowController::SetWindowFlags(uint32_t windowId, uint32_t flags) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto property = node->GetWindowProperty(); + uint32_t oldFlags = property->GetWindowFlags(); + property->SetWindowFlags(flags); + // only forbid_split_move flag change, just set property + if ((oldFlags ^ flags) == static_cast(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE)) { + return WMError::WM_OK; + } + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_FLAGS); + if (res != WMError::WM_OK) { + return res; + } + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + WLOGFD("SetWindowFlags end"); + return res; +} + +WMError WindowController::SetSystemBarProperty(uint32_t windowId, WindowType type, const SystemBarProperty& property) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + node->SetSystemBarProperty(type, property); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_OTHER_PROPS); + if (res != WMError::WM_OK) { + return res; + } + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + WLOGFD("SetSystemBarProperty end"); + return res; +} + +void WindowController::NotifySystemBarTints() +{ + windowRoot_->NotifySystemBarTints(); +} + +WMError WindowController::SetWindowAnimationController(const sptr& controller) +{ + return RemoteAnimation::SetWindowAnimationController(controller); +} + +AvoidArea WindowController::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) const +{ + return windowRoot_->GetAvoidAreaByType(windowId, avoidAreaType); +} + +WMError WindowController::ChangeMouseStyle(uint32_t windowId, sptr& moveDragProperty) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + if (node->GetWindowRect().width_ > node->GetWindowRect().height_) { + MMI::InputManager::GetInstance()->SetPointerStyle(windowId, MMI::MOUSE_ICON::NORTH_SOUTH); + } else { + MMI::InputManager::GetInstance()->SetPointerStyle(windowId, MMI::MOUSE_ICON::WEST_EAST); + } + return WMError::WM_OK; + } + MMI::InputManager::GetInstance()->SetPointerStyle(windowId, STYLEID_MAP.at(moveDragProperty->dragType_)); + return WMError::WM_OK; +} + +WMError WindowController::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& moveDragProperty) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFW("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (!node->currentVisibility_) { + WLOGFE("[NotifyServerReadyToMoveOrDrag] window is not visible, windowId: %{public}u", windowId); + return WMError::WM_ERROR_INVALID_OPERATION; + } + + // if start dragging or start moving dock_slice, need to update size change reason + if ((moveDragProperty->startMoveFlag_ && node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) || + moveDragProperty->startDragFlag_) { + WMError res = windowRoot_->UpdateSizeChangeReason(windowId, WindowSizeChangeReason::DRAG_START); + ChangeMouseStyle(windowId, moveDragProperty); + return res; + } + return WMError::WM_OK; +} + +WMError WindowController::ProcessPointDown(uint32_t windowId, bool isPointDown) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFW("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (!node->currentVisibility_) { + WLOGFE("[ProcessPointDown] window is not visible, windowId: %{public}u", windowId); + return WMError::WM_ERROR_INVALID_OPERATION; + } + + /* + * If not point down, no need to notify touch outside + */ + if (isPointDown) { + NotifyTouchOutside(node); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + windowRoot_->TakeWindowPairSnapshot(node->GetDisplayId()); + } + } + + WLOGFD("process point down, windowId: %{public}u", windowId); + WMError zOrderRes = windowRoot_->RaiseZOrderForAppWindow(node); + WMError focusRes = windowRoot_->RequestFocus(windowId); + windowRoot_->RequestActiveWindow(windowId); + windowRoot_->FocusFaultDetection(); + if (zOrderRes == WMError::WM_OK || focusRes == WMError::WM_OK) { + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId), + WindowUpdateType::WINDOW_UPDATE_FOCUSED); + WLOGFD("ProcessPointDown end"); + return WMError::WM_OK; + } + return WMError::WM_ERROR_INVALID_OPERATION; +} + +WMError WindowController::ProcessPointUp(uint32_t windowId) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFW("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + DisplayId displayId = node->GetDisplayId(); + if (windowRoot_->IsDockSliceInExitSplitModeArea(displayId)) { + windowRoot_->ExitSplitMode(displayId); + } else { + windowRoot_->ClearWindowPairSnapshot(node->GetDisplayId()); + auto property = node->GetWindowProperty(); + node->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG_END); + property->SetRequestRect(property->GetWindowRect()); + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_RECT); + if (res == WMError::WM_OK) { + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + } + } + } + WMError res = windowRoot_->UpdateSizeChangeReason(windowId, WindowSizeChangeReason::DRAG_END); + if (res != WMError::WM_OK) { + return res; + } + return WMError::WM_OK; +} + +WMError WindowController::InterceptInputEventToServer(uint32_t windowId) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFW("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto inputPidInServer = WindowInnerManager::GetInstance().GetPid(); + WLOGFD("InterceptInputEventToServer, windowId: %{public}u, inputPid: %{public}u", windowId, inputPidInServer); + node->SetInputEventCallingPid(static_cast(inputPidInServer)); + FlushWindowInfo(windowId); + return WMError::WM_OK; +} + +WMError WindowController::RecoverInputEventToClient(uint32_t windowId) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFW("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (node->GetInputEventCallingPid() == node->GetCallingPid()) { + WLOGFD("There is no need to recover input event to client"); + return WMError::WM_OK; + } + node->SetInputEventCallingPid(node->GetCallingPid()); + RecoverDefaultMouseStyle(windowId); + AsyncFlushInputInfo(windowId); + return WMError::WM_OK; +} + +void WindowController::AsyncFlushInputInfo(uint32_t windowId) +{ + WLOGFD("AsyncFlushWindowInfo"); + displayZoomController_->UpdateWindowZoomInfo(windowId); + RSTransaction::FlushImplicitTransaction(); + MMI::DisplayGroupInfo displayInfo_ = inputWindowMonitor_->GetDisplayInfo(windowId); + auto task = [this, displayInfo_]() { + MMI::InputManager::GetInstance()->UpdateDisplayInfo(displayInfo_); + }; + WindowInnerManager::GetInstance().PostTask(task, "UpdateDisplayInfo"); +} + +void WindowController::RecoverDefaultMouseStyle(uint32_t windowId) +{ + // asynchronously calls SetMouseStyle of MultiModalInput + auto task = [this, windowId]() { + MMI::InputManager::GetInstance()->SetPointerStyle(windowId, MMI::MOUSE_ICON::DEFAULT); + }; + WindowInnerManager::GetInstance().PostTask(task, "RecoverDefaultMouseStyle"); +} + +WMError WindowController::NotifyWindowClientPointUp(uint32_t windowId, + const std::shared_ptr& pointerEvent) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFW("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (node->GetWindowToken() != nullptr) { + WLOGFD("notify client when receive point_up event, windowId: %{public}u", windowId); + node->GetWindowToken()->NotifyWindowClientPointUp(pointerEvent); + } + return WMError::WM_OK; +} + +void WindowController::MinimizeAllAppWindows(DisplayId displayId) +{ + windowRoot_->MinimizeAllAppWindows(displayId); + if (RemoteAnimation::NotifyAnimationByHome() != WMError::WM_OK) { + MinimizeApp::ExecuteMinimizeAll(); + } +} + +WMError WindowController::ToggleShownStateForAllAppWindows() +{ + if (isScreenLocked_) { + return WMError::WM_DO_NOTHING; + } + return windowRoot_->ToggleShownStateForAllAppWindows(); +} + +WMError WindowController::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) +{ + return windowRoot_->GetTopWindowId(mainWinId, topWinId); +} + +void WindowController::FlushWindowInfo(uint32_t windowId) +{ + WLOGFD("FlushWindowInfo"); + displayZoomController_->UpdateWindowZoomInfo(windowId); + RSTransaction::FlushImplicitTransaction(); + inputWindowMonitor_->UpdateInputWindow(windowId); +} + +void WindowController::FlushWindowInfoWithDisplayId(DisplayId displayId) +{ + WLOGFD("FlushWindowInfoWithDisplayId, displayId: %{public}" PRIu64"", displayId); + RSTransaction::FlushImplicitTransaction(); + inputWindowMonitor_->UpdateInputWindowByDisplayId(displayId); +} + +void WindowController::UpdateWindowAnimation(const sptr& node) +{ + if (node == nullptr || (node->leashWinSurfaceNode_ == nullptr && node->surfaceNode_ == nullptr)) { + WLOGFE("windowNode or surfaceNode is nullptr"); + return; + } + const auto& windowAnimationConfig = WindowNodeContainer::GetAnimationConfigRef().windowAnimationConfig_; + + uint32_t animationFlag = node->GetWindowProperty()->GetAnimationFlag(); + uint32_t windowId = node->GetWindowProperty()->GetWindowId(); + WLOGFD("windowId: %{public}u, animationFlag: %{public}u", windowId, animationFlag); + std::shared_ptr effect = nullptr; + if (animationFlag == static_cast(WindowAnimation::DEFAULT)) { + effect = RSTransitionEffect::Create() + ->Scale(windowAnimationConfig.scale_) + ->Rotate(windowAnimationConfig.rotation_) + ->Translate(windowAnimationConfig.translate_) + ->Opacity(windowAnimationConfig.opacity_); + } else if (animationFlag == static_cast(WindowAnimation::INPUTE)) { + float translateY = static_cast(node->GetWindowRect().height_); + if (!node->GetWindowRect().height_) { + translateY = static_cast(node->GetRequestRect().height_); + } + effect = RSTransitionEffect::Create()->Translate(Vector3f(0, translateY, 0))->Opacity(0.0f); + }; + if (node->leashWinSurfaceNode_) { + node->leashWinSurfaceNode_->SetTransitionEffect(effect); + } + if (node->surfaceNode_) { + node->surfaceNode_->SetTransitionEffect(effect); + } +} + +WMError WindowController::SetWindowLayoutMode(WindowLayoutMode mode) +{ + WMError res = WMError::WM_OK; + auto displayIds = windowRoot_->GetAllDisplayIds(); + for (auto displayId : displayIds) { + res = windowRoot_->SetWindowLayoutMode(displayId, mode); + if (res != WMError::WM_OK) { + return res; + } + displayZoomController_->UpdateAllWindowsZoomInfo(displayId); + FlushWindowInfoWithDisplayId(displayId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(displayId, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + } + MinimizeApp::ExecuteMinimizeAll(); + return res; +} + +WMError WindowController::UpdateProperty(sptr& property, PropertyChangeAction action) +{ + if (property == nullptr) { + WLOGFE("property is invalid"); + return WMError::WM_ERROR_NULLPTR; + } + uint32_t windowId = property->GetWindowId(); + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("window is invalid"); + return WMError::WM_ERROR_NULLPTR; + } + WLOGFD("window: [%{public}s, %{public}u] update property for action: %{public}u", node->GetWindowName().c_str(), + node->GetWindowId(), static_cast(action)); + WMError ret = WMError::WM_OK; + switch (action) { + case PropertyChangeAction::ACTION_UPDATE_RECT: { + node->SetDecoStatus(property->GetDecoStatus()); + node->SetOriginRect(property->GetOriginRect()); + node->SetDragType(property->GetDragType()); + ret = ResizeRectAndFlush(windowId, property->GetRequestRect(), property->GetWindowSizeChangeReason()); + if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && ret == WMError::WM_OK && + callingWindowId_ == windowId && !WindowHelper::IsEmptyRect(callingWindowRestoringRect_)) { + if (property->GetWindowSizeChangeReason() != WindowSizeChangeReason::MOVE) { + callingWindowId_ = 0u; + callingWindowRestoringRect_ = { 0, 0, 0, 0 }; + } else { + auto windowRect = node->GetWindowRect(); + callingWindowRestoringRect_.posX_ = windowRect.posX_; + callingWindowRestoringRect_.posY_ = windowRect.posY_; + } + } + break; + } + case PropertyChangeAction::ACTION_UPDATE_MODE: { + ret = SetWindowMode(windowId, property->GetWindowMode()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_FLAGS: { + ret = SetWindowFlags(windowId, property->GetWindowFlags()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS: { + auto& props = property->GetSystemBarProperty(); + for (auto& iter : props) { + SetSystemBarProperty(windowId, iter.first, iter.second); + } + break; + } + case PropertyChangeAction::ACTION_UPDATE_FOCUSABLE: { + node->SetFocusable(property->GetFocusable()); + windowRoot_->UpdateFocusableProperty(windowId); + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + break; + } + case PropertyChangeAction::ACTION_UPDATE_TOUCHABLE: { + node->SetTouchable(property->GetTouchable()); + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + break; + } + case PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW: { + node->SetCallingWindow(property->GetCallingWindow()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_ORIENTATION: { + node->SetRequestedOrientation(property->GetRequestedOrientation()); + if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) { + DisplayManagerServiceInner::GetInstance(). + SetOrientationFromWindow(node->GetDisplayId(), property->GetRequestedOrientation()); + } + break; + } + case PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON: { + node->SetTurnScreenOn(property->IsTurnScreenOn()); + HandleTurnScreenOn(node); + break; + } + case PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON: { + node->SetKeepScreenOn(property->IsKeepScreenOn()); + windowRoot_->HandleKeepScreenOn(node->GetWindowId(), node->IsKeepScreenOn()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS: { + node->SetBrightness(property->GetBrightness()); + windowRoot_->SetBrightness(node->GetWindowId(), node->GetBrightness()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO: { + node->SetModeSupportInfo(property->GetModeSupportInfo()); + break; + } + case PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA: { + std::vector rects; + property->GetTouchHotAreas(rects); + ret = UpdateTouchHotAreas(node, rects); + break; + } + case PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG: { + node->GetWindowProperty()->SetAnimationFlag(property->GetAnimationFlag()); + UpdateWindowAnimation(node); + break; + } + case PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY: { + node->SetTransform(property->GetTransform()); + node->SetWindowSizeChangeReason(WindowSizeChangeReason::TRANSFORM); + node->GetWindowProperty()->SetAnimateWindowFlag(true); + ret = UpdateTransform(windowId); + break; + } + case PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE: { + node->GetWindowProperty()->SetPrivacyMode(property->GetPrivacyMode()); + break; + } + default: + break; + } + return ret; +} + +WMError WindowController::GetAccessibilityWindowInfo(std::vector>& infos) const +{ + accessibilityConnection_->GetAccessibilityWindowInfo(infos); + return WMError::WM_OK; +} + +WMError WindowController::GetVisibilityWindowInfo(std::vector>& infos) const +{ + windowRoot_->GetVisibilityWindowInfo(infos); + return WMError::WM_OK; +} + +WMError WindowController::GetModeChangeHotZones(DisplayId displayId, + ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config) +{ + return windowRoot_->GetModeChangeHotZones(displayId, hotZones, config); +} + +WMError WindowController::UpdateTouchHotAreas(const sptr& node, const std::vector& rects) +{ + std::ostringstream oss; + int index = 0; + for (const auto& rect : rects) { + oss << "[ " << rect.posX_ << ", " << rect.posY_ << ", " << rect.width_ << ", " << rect.height_ << " ]"; + index++; + if (index < static_cast(rects.size())) { + oss <<", "; + } + } + WLOGFD("windowId: %{public}u, size: %{public}d, rects: %{public}s", + node->GetWindowId(), static_cast(rects.size()), oss.str().c_str()); + if (rects.size() > TOUCH_HOT_AREA_MAX_NUM) { + WLOGFE("the number of touch hot areas exceeds the maximum"); + return WMError::WM_ERROR_INVALID_PARAM; + } + + std::vector touchHotAreas; + std::vector pointerHotAreas; + if (rects.empty()) { + touchHotAreas.emplace_back(node->GetEntireWindowTouchHotArea()); + pointerHotAreas.emplace_back(node->GetEntireWindowPointerHotArea()); + } else { + Rect windowRect = node->GetWindowRect(); + if (!WindowHelper::CalculateTouchHotAreas(windowRect, rects, touchHotAreas)) { + WLOGFE("the requested touch hot areas are incorrect"); + return WMError::WM_ERROR_INVALID_PARAM; + } + pointerHotAreas = touchHotAreas; + } + node->GetWindowProperty()->SetTouchHotAreas(rects); + node->SetTouchHotAreas(touchHotAreas); + node->SetPointerHotAreas(pointerHotAreas); + FlushWindowInfo(node->GetWindowId()); + accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY); + return WMError::WM_OK; +} + +WMError WindowController::UpdateTransform(uint32_t windowId) +{ + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_TRANSFORM); + if (res != WMError::WM_OK) { + return res; + } + FlushWindowInfo(windowId); + accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId), + WindowUpdateType::WINDOW_UPDATE_PROPERTY); + return WMError::WM_OK; +} + +void WindowController::NotifyTouchOutside(const sptr& node) +{ + auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (windowNodeContainer == nullptr) { + WLOGFE("window node container is null"); + return; + } + + std::vector> windowNodes; + windowNodeContainer->TraverseContainer(windowNodes); + uint32_t skipNodeId = GetEmbedNodeId(windowNodes, node); + for (const auto& windowNode : windowNodes) { + if (windowNode == nullptr || windowNode->GetWindowToken() == nullptr || + windowNode->GetWindowId() == skipNodeId || + windowNode->GetWindowId() == node->GetWindowId()) { + WLOGFD("continue %{public}s", windowNode == nullptr ? "nullptr" : windowNode->GetWindowName().c_str()); + continue; + } + WLOGFD("notify %{public}s id %{public}d", windowNode->GetWindowName().c_str(), windowNode->GetWindowId()); + windowNode->GetWindowToken()->NotifyTouchOutside(); + } +} + +uint32_t WindowController::GetEmbedNodeId(const std::vector>& windowNodes, + const sptr& node) +{ + if (node->GetWindowType() != WindowType::WINDOW_TYPE_APP_COMPONENT) { + return 0; + } + + Rect nodeRect = node->GetWindowRect(); + bool isSkip = true; + for (auto& windowNode : windowNodes) { + if (windowNode == nullptr) { + continue; + } + if (windowNode->GetWindowId() == node->GetWindowId()) { + isSkip = false; + continue; + } + if (isSkip) { + continue; + } + if (nodeRect.IsInsideOf(windowNode->GetWindowRect())) { + WLOGI("TouchOutside window type is component %{public}s windowNode %{public}d", + windowNode->GetWindowName().c_str(), windowNode->GetWindowId()); + return windowNode->GetWindowId(); + } + } + return 0; +} + +void WindowController::MinimizeWindowsByLauncher(std::vector& windowIds, bool isAnimated, + sptr& finishCallback) +{ + windowRoot_->MinimizeTargetWindows(windowIds); + auto func = []() { + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::GESTURE_ANIMATION); + }; + if (!isAnimated) { + func(); + } else { + finishCallback = RemoteAnimation::CreateAnimationFinishedCallback(func); + if (finishCallback == nullptr) { + return; + } + } +} + +void WindowController::OnScreenshot(DisplayId displayId) +{ + sptr windowNode; + WMError res = GetFocusWindowNode(displayId, windowNode); + if (res != WMError::WM_OK) { + return; + } + auto windowToken = windowNode->GetWindowToken(); + if (windowToken == nullptr) { + WLOGFE("notify screenshot failed: window token is null."); + return; + } + windowToken->NotifyScreenshot(); +} + +void WindowController::SetAnchorOffset(int32_t deltaX, int32_t deltaY) +{ + displayZoomController_->SetAnchorOffset(deltaX, deltaY); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + FlushWindowInfoWithDisplayId(displayId); +} + +void WindowController::OffWindowZoom() +{ + displayZoomController_->OffWindowZoom(); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + FlushWindowInfoWithDisplayId(displayId); +} + +void WindowController::SetAnchorAndScale(int32_t x, int32_t y, float scale) +{ + displayZoomController_->SetAnchorAndScale(x, y, scale); + DisplayId displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + FlushWindowInfoWithDisplayId(displayId); +} + +WMError WindowController::BindDialogTarget(uint32_t& windowId, sptr targetToken) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (windowRoot_->CheckMultiDialogWindows(node->GetWindowType(), targetToken)) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + + node->dialogTargetToken_ = targetToken; + + sptr parentNode = windowRoot_->FindDialogCallerNode(node->GetWindowType(), node->dialogTargetToken_); + if (parentNode != nullptr) { + auto position = parentNode->children_.end(); + for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) { + if ((*iter)->priority_ > node->priority_) { + position = iter; + break; + } + } + parentNode->children_.insert(position, node); + } + + return WMError::WM_OK; +} +} // namespace OHOS +} // namespace Rosen diff --git a/window_manager/wmserver/src/window_dumper.cpp b/window_manager/wmserver/src/window_dumper.cpp new file mode 100644 index 0000000..9dc301f --- /dev/null +++ b/window_manager/wmserver/src/window_dumper.cpp @@ -0,0 +1,286 @@ +/* + * 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 "window_dumper.h" + +#include +#include +#include +#include +#include + +#include "display_manager_service_inner.h" +#include "string_ex.h" +#include "unique_fd.h" +#include "window_manager_hilog.h" +#include "window_manager_service.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowDumper"}; + + constexpr int WINDOW_NAME_MAX_LENGTH = 20; + const std::string ARG_DUMP_HELP = "-h"; + const std::string ARG_DUMP_ALL = "-a"; + const std::string ARG_DUMP_WINDOW = "-w"; +} + +WMError WindowDumper::Dump(int fd, const std::vector& args) +{ + WLOGFI("Dump begin fd: %{public}d", fd); + if (fd < 0) { + return WMError::WM_ERROR_INVALID_PARAM; + } + (void) signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE crash + UniqueFd ufd = UniqueFd(fd); // auto close + fd = ufd.Get(); + std::vector params; + for (auto& arg : args) { + params.emplace_back(Str16ToStr8(arg)); + } + + std::string dumpInfo; + if (params.empty()) { + ShowHelpInfo(dumpInfo); + } else if (params.size() == 1 && params[0] == ARG_DUMP_HELP) { // 1: params num + ShowHelpInfo(dumpInfo); + } else { + WMError errCode = DumpWindowInfo(params, dumpInfo); + if (errCode != WMError::WM_OK) { + ShowIllegalArgsInfo(dumpInfo, errCode); + } + } + int ret = dprintf(fd, "%s\n", dumpInfo.c_str()); + if (ret < 0) { + WLOGFE("dprintf error"); + return WMError::WM_ERROR_INVALID_OPERATION; + } + WLOGFI("Dump end"); + return WMError::WM_OK; +} + +WMError WindowDumper::DumpScreenGroupWindowInfo(ScreenId screenGroupId, + const sptr& windowNodeContainer, std::string& dumpInfo) +{ + if (windowNodeContainer == nullptr) { + WLOGFE("windowNodeContainer is null"); + return WMError::WM_ERROR_NULLPTR; + } + std::ostringstream oss; + oss << "-------------------------------------ScreenGroup " << screenGroupId + << "-------------------------------------" + << std::endl; + oss << "WindowName DisplayId Pid WinId Type Mode Flag ZOrd Orientation [ x y w h ]" + << std::endl; + std::vector> windowNodes; + windowNodeContainer->TraverseContainer(windowNodes); + int zOrder = static_cast(windowNodes.size()); + windowRoot_->GetBackgroundNodesByScreenId(screenGroupId, windowNodes); + for (auto& windowNode : windowNodes) { + if (zOrder < 0) { + zOrder = 0; + } else if (zOrder == 0) { + oss << "---------------------------------------------------------------------------------------" + << std::endl; + } + if (windowNode == nullptr) { + --zOrder; + break; + } + Rect rect = windowNode->GetWindowRect(); + const std::string& windowName = windowNode->GetWindowName().size() <= WINDOW_NAME_MAX_LENGTH ? + windowNode->GetWindowName() : windowNode->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH); + // std::setw is used to set the output width and different width values are set to keep the format aligned. + oss << std::left << std::setw(21) << windowName + << std::left << std::setw(10) << windowNode->GetDisplayId() + << std::left << std::setw(8) << windowNode->GetCallingPid() + << std::left << std::setw(6) << windowNode->GetWindowId() + << std::left << std::setw(5) << static_cast(windowNode->GetWindowType()) + << std::left << std::setw(5) << static_cast(windowNode->GetWindowMode()) + << std::left << std::setw(5) << windowNode->GetWindowFlags() + << std::left << std::setw(5) << --zOrder + << std::left << std::setw(12) << static_cast(windowNode->GetRequestedOrientation()) + << "[ " + << std::left << std::setw(5) << rect.posX_ + << std::left << std::setw(5) << rect.posY_ + << std::left << std::setw(5) << rect.width_ + << std::left << std::setw(5) << rect.height_ + << "]" + << std::endl; + } + oss << "Focus window: " << windowNodeContainer->GetFocusWindow() << std::endl; + oss << "total window num: " << windowRoot_->GetTotalWindowNum()<< std::endl; + dumpInfo.append(oss.str()); + return WMError::WM_OK; +} + +WMError WindowDumper::DumpAllWindowInfo(std::string& dumpInfo) +{ + std::map> windowNodeContainers; + std::vector displayIds = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds(); + for (DisplayId displayId : displayIds) { + auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); + if (!windowNodeContainer) { + return WMError::WM_ERROR_NULLPTR; + } + ScreenId screenGroupId = DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(displayId); + if (windowNodeContainers.count(screenGroupId) == 0) { + windowNodeContainers.insert(std::make_pair(screenGroupId, windowNodeContainer)); + } + } + for (auto it = windowNodeContainers.begin(); it != windowNodeContainers.end(); it++) { + WMError ret = DumpScreenGroupWindowInfo(it->first, it->second, dumpInfo); + if (ret != WMError::WM_OK) { + return ret; + } + } + return WMError::WM_OK; +} + +bool WindowDumper::IsValidDigitString(const std::string& windowIdStr) +{ + if (windowIdStr.empty()) { + return false; + } + for (char ch : windowIdStr) { + if ((ch >= '0' && ch <= '9')) { + continue; + } + WLOGFE("invalid window id"); + return false; + } + return true; +} + +WMError WindowDumper::DumpSpecifiedWindowInfo(uint32_t windowId, const std::vector& params, + std::string& dumpInfo) +{ + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("invalid window"); + return WMError::WM_ERROR_NULLPTR; + } + Rect rect = node->GetWindowRect(); + std::string isShown_ = node->startingWindowShown_ ? "true" : "false"; + std::string isVisible = node->isVisible_ ? "true" : "false"; + std::ostringstream oss; + oss << "WindowName: " << node->GetWindowName() << std::endl; + oss << "DisplayId: " << node->GetDisplayId() << std::endl; + oss << "WinId: " << node->GetWindowId() << std::endl; + oss << "Pid: " << node->GetCallingPid() << std::endl; + oss << "Type: " << static_cast(node->GetWindowType()) << std::endl; + oss << "Mode: " << static_cast(node->GetWindowMode()) << std::endl; + oss << "Flag: " << node->GetWindowFlags() << std::endl; + oss << "Orientation: " << static_cast(node->GetRequestedOrientation()) << std::endl; + oss << "IsStartingWindow: " << isShown_ << std::endl; + oss << "FirstFrameCallbackCalled: " << node->firstFrameAvaliable_ << std::endl; + oss << "IsVisible: " << isVisible << std::endl; + oss << "WindowRect: " << "[ " + << rect.posX_ << ", " << rect.posY_ << ", " << rect.width_ << ", " << rect.height_ + << " ]" << std::endl; + oss << "TouchHotAreas: "; + std::vector touchHotAreas; + node->GetTouchHotAreas(touchHotAreas); + int index = 0; + for (const auto& area : touchHotAreas) { + oss << "[ " << area.posX_ << ", " << area.posY_ << ", " << area.width_ << ", " << area.height_ << " ]"; + index++; + if (index < static_cast(touchHotAreas.size())) { + oss <<", "; + } + } + oss << std::endl; + dumpInfo.append(oss.str()); + if (node->GetWindowToken() != nullptr) { + std::vector resetParams; + resetParams.assign(params.begin() + 2, params.end()); // 2: params num + if (resetParams.empty()) { + WLOGFI("do not dump ui info"); + return WMError::WM_OK; + } + dumpInfoFuture_.ResetLock({}); + node->GetWindowToken()->DumpInfo(resetParams); + auto infos = dumpInfoFuture_.GetResult(2000); // 2000: wait for 2000ms + for (auto& info: infos) { + dumpInfo.append(info).append("\n"); + } + } + return WMError::WM_OK; +} + +WMError WindowDumper::DumpWindowInfo(const std::vector& args, std::string& dumpInfo) +{ + if (args.empty()) { + return WMError::WM_ERROR_INVALID_PARAM; + } + if (args.size() == 1 && args[0] == ARG_DUMP_ALL) { // 1: params num + return DumpAllWindowInfo(dumpInfo); + } else if (args.size() >= 2 && args[0] == ARG_DUMP_WINDOW && IsValidDigitString(args[1])) { // 2: params num + uint32_t windowId = std::stoul(args[1]); + return DumpSpecifiedWindowInfo(windowId, args, dumpInfo); + } else { + return WMError::WM_ERROR_INVALID_PARAM; + } +} + +void WindowDumper::ShowIllegalArgsInfo(std::string& dumpInfo, WMError errCode) +{ + switch (errCode) { + case WMError::WM_ERROR_INVALID_PARAM: + dumpInfo.append("The arguments are illegal and you can enter '-h' for help."); + break; + case WMError::WM_ERROR_NULLPTR: + dumpInfo.append("The window is invalid, you can enter '-a' to get valid window id."); + break; + default: + break; + } +} + +void WindowDumper::ShowHelpInfo(std::string& dumpInfo) +{ + dumpInfo.append("Usage:\n") + .append(" -h ") + .append("|help text for the tool\n") + .append(" -a ") + .append("|dump all window information in the system\n") + .append(" -w {window id} [ArkUI Option] ") + .append("|dump specified window information\n") + .append(" ------------------------------------[ArkUI Option]------------------------------------ \n"); + ShowAceDumpHelp(dumpInfo); +} + +void WindowDumper::ShowAceDumpHelp(std::string& dumpInfo) +{ + auto node = windowRoot_->GetWindowForDumpAceHelpInfo(); + if (node == nullptr) { + WLOGFE("invalid window"); + return; + } + if (node->GetWindowToken() != nullptr) { + std::vector params; + params.emplace_back(ARG_DUMP_HELP); + dumpInfoFuture_.ResetLock({}); + node->GetWindowToken()->DumpInfo(params); + auto infos = dumpInfoFuture_.GetResult(2000); // 2000: wait for 2000ms + for (auto& info: infos) { + dumpInfo.append(info).append("\n"); + } + } +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/src/window_inner_manager.cpp b/window_manager/wmserver/src/window_inner_manager.cpp new file mode 100644 index 0000000..7471358 --- /dev/null +++ b/window_manager/wmserver/src/window_inner_manager.cpp @@ -0,0 +1,317 @@ +/* + * 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 "window_inner_manager.h" + +#include "ability_manager_client.h" +#include "memory_guard.h" +#include "window.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowInnerManager"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(WindowInnerManager) + +WindowInnerManager::WindowInnerManager() : eventHandler_(nullptr), eventLoop_(nullptr), + state_(InnerWMRunningState::STATE_NOT_START) +{ +} + +WindowInnerManager::~WindowInnerManager() +{ + Stop(); +} + +bool WindowInnerManager::Init() +{ + // create handler for inner command at server + eventLoop_ = AppExecFwk::EventRunner::Create(INNER_WM_THREAD_NAME); + if (eventLoop_ == nullptr) { + return false; + } + eventHandler_ = std::make_shared(eventLoop_); + if (eventHandler_ == nullptr) { + return false; + } + + eventHandler_->PostTask([]() { MemoryGuard cacheGuard; }, AppExecFwk::EventQueue::Priority::IMMEDIATE); + moveDragController_ = new MoveDragController(); + if (!moveDragController_->Init()) { + WLOGFE("Init window drag controller failed"); + return false; + } + + WLOGFI("init window inner manager service success."); + return true; +} + +void WindowInnerManager::Start(bool enableRecentholder) +{ + isRecentHolderEnable_ = enableRecentholder; + if (state_ == InnerWMRunningState::STATE_RUNNING) { + WLOGFI("window inner manager service has already started."); + } + if (!Init()) { + WLOGFI("failed to init window inner manager service."); + return; + } + state_ = InnerWMRunningState::STATE_RUNNING; + eventLoop_->Run(); + + pid_ = getpid(); + WLOGFI("window inner manager service start success."); +} + +void WindowInnerManager::Stop() +{ + WLOGFI("stop window inner manager service."); + if (eventLoop_ != nullptr) { + eventLoop_->Stop(); + eventLoop_.reset(); + } + if (eventHandler_ != nullptr) { + eventHandler_.reset(); + } + if (moveDragController_ != nullptr) { + moveDragController_->Stop(); + } + state_ = InnerWMRunningState::STATE_NOT_START; +} + +void WindowInnerManager::CreateInnerWindow(std::string name, DisplayId displayId, Rect rect, + WindowType type, WindowMode mode) +{ + bool recentHolderWindowFlag = isRecentHolderEnable_; + auto task = [name, displayId, rect, mode, type, recentHolderWindowFlag]() { + switch (type) { + case WindowType::WINDOW_TYPE_PLACEHOLDER: { + if (recentHolderWindowFlag) { + PlaceHolderWindow::GetInstance().Create(name, displayId, rect, mode); + } + break; + } + default: + break; + } + }; + PostTask(task, "CreateInnerWindow"); + return; +} + +void WindowInnerManager::DestroyInnerWindow(DisplayId displayId, WindowType type) +{ + bool recentHolderWindowFlag = isRecentHolderEnable_; + auto task = [type, recentHolderWindowFlag]() { + switch (type) { + case WindowType::WINDOW_TYPE_PLACEHOLDER: { + if (recentHolderWindowFlag) { + PlaceHolderWindow::GetInstance().Destroy(); + } + break; + } + default: + break; + } + }; + PostTask(task, "DestroyInnerWindow"); + return; +} + +void WindowInnerManager::UpdateInnerWindow(DisplayId displayId, WindowType type, uint32_t width, uint32_t height) +{ + bool recentHolderWindowFlag = isRecentHolderEnable_; + auto task = [type, width, height, recentHolderWindowFlag]() { + switch (type) { + case WindowType::WINDOW_TYPE_PLACEHOLDER: { + if (recentHolderWindowFlag) { + PlaceHolderWindow::GetInstance().Update(width, height); + } + break; + } + default: + break; + } + }; + PostTask(task, "UpdateInnerWindow"); + return; +} + +void WindowInnerManager::MinimizeAbility(const wptr &node, bool isFromUser) +{ + // asynchronously calls the MinimizeAbility of AbilityManager + auto weakNode = node.promote(); + if (weakNode == nullptr) { + WLOGFE("minimize ability failed."); + return; + } + wptr weakToken(weakNode->abilityToken_); + WLOGFD("minimize window %{public}u, isfromuser: %{public}d", weakNode->GetWindowId(), isFromUser); + auto task = [weakToken, isFromUser]() { + auto token = weakToken.promote(); + if (token == nullptr) { + WLOGE("minimize ability failed, because window token is nullptr."); + return; + } + AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(token, isFromUser); + }; + PostTask(task, "MinimizeAbility"); +} + +void WindowInnerManager::TerminateAbility(const wptr &node) +{ + // asynchronously calls the TerminateAbility of AbilityManager + auto weakNode = node.promote(); + if (weakNode == nullptr) { + WLOGFE("terminate ability failed."); + return; + } + wptr weakToken(weakNode->abilityToken_); + WLOGFD("terminate window %{public}u", weakNode->GetWindowId()); + auto task = [weakToken]() { + auto token = weakToken.promote(); + if (token == nullptr) { + WLOGE("terminate ability failed, because window token is nullptr."); + return; + } + AAFwk::Want resultWant; + AAFwk::AbilityManagerClient::GetInstance()->TerminateAbility(token, -1, &resultWant); + }; + PostTask(task, "TerminateAbility"); +} + +void WindowInnerManager::CloseAbility(const wptr &node) +{ + // asynchronously calls the CloseAbility of AbilityManager + auto weakNode = node.promote(); + if (weakNode == nullptr) { + WLOGFE("close ability failed."); + return; + } + wptr weakToken(weakNode->abilityToken_); + WLOGFD("close window %{public}u", weakNode->GetWindowId()); + auto task = [weakToken]() { + auto token = weakToken.promote(); + if (token == nullptr) { + WLOGE("close ability failed, because window token is nullptr."); + return; + } + AAFwk::Want resultWant; + AAFwk::AbilityManagerClient::GetInstance()->CloseAbility(token); + }; + PostTask(task, "CloseAbility"); +} + +void WindowInnerManager::CompleteFirstFrameDrawing(const wptr &node) +{ + // asynchronously calls the CloseAbility of AbilityManager + auto weakNode = node.promote(); + if (weakNode == nullptr) { + WLOGFE("CompleteFirstFrameDrawing failed."); + return; + } + wptr weakToken(weakNode->abilityToken_); + WLOGFD("CompleteFirstFrameDrawing %{public}u", weakNode->GetWindowId()); + auto task = [weakToken]() { + auto token = weakToken.promote(); + if (token == nullptr) { + WLOGE("CompleteFirstFrameDrawing failed, because window token is nullptr."); + return; + } + AAFwk::AbilityManagerClient::GetInstance()->CompleteFirstFrameDrawing(token); + }; + PostTask(task, "CompleteFirstFrameDrawing"); +} + +void WindowInnerManager::PostTask(InnerTask &&task, std::string name, EventPriority priority) +{ + if (eventHandler_ == nullptr) { + WLOGFE("listener handler is nullptr"); + return; + } + bool ret = eventHandler_->PostTask(task, name, 0, priority); // 0 is task delay time + if (!ret) { + WLOGFE("post listener callback task failed."); + return; + } + return; +} + +pid_t WindowInnerManager::GetPid() +{ + return pid_; +} + +void WindowInnerManager::SetInputEventConsumer() +{ + if (moveDragController_ == nullptr) { + return; + } + moveDragController_->SetInputEventConsumer(); +} + +void WindowInnerManager::NotifyDisplayChange(const std::map& displayRectMap) +{ + if (moveDragController_ == nullptr) { + return; + } + moveDragController_->HandleDisplayChange(displayRectMap); +} + +bool WindowInnerManager::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) +{ + if (moveDragController_->GetActiveWindowId() != INVALID_WINDOW_ID) { + WLOGFW("Is already in dragging or moving state, invalid operation"); + return false; + } + moveDragController_->HandleReadyToMoveOrDrag(windowId, windowProperty, moveDragProperty); + WLOGFI("NotifyServerReadyToMoveOrDrag, windowId: %{public}u", windowId); + return true; +} + +void WindowInnerManager::NotifyWindowEndUpMovingOrDragging(uint32_t windowId) +{ + if (moveDragController_->GetActiveWindowId() != windowId) { + return; + } + moveDragController_->HandleEndUpMovingOrDragging(windowId); + WLOGFI("NotifyWindowEndUpMovingOrDragging, windowId: %{public}u", windowId); +} + +void WindowInnerManager::NotifyWindowRemovedOrDestroyed(uint32_t windowId) +{ + if (moveDragController_->GetActiveWindowId() != windowId) { + return; + } + moveDragController_->HandleWindowRemovedOrDestroyed(windowId); + WLOGFI("NotifyWindowRemovedOrDestroyed, windowId: %{public}u", windowId); +} + +void WindowInnerManager::ConsumePointerEvent(const std::shared_ptr& pointerEvent) +{ + uint32_t windowId = static_cast(pointerEvent->GetAgentWindowId()); + if (moveDragController_->GetActiveWindowId() != windowId || + moveDragController_->GetActiveWindowId() == INVALID_WINDOW_ID) { + WLOGFE("active winId or inputEvent winId is invalid, windowId: %{public}u, activeWinId: %{public}u", + windowId, moveDragController_->GetActiveWindowId()); + return; + } + moveDragController_->ConsumePointerEvent(pointerEvent); +} +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/window_layout_policy.cpp b/window_manager/wmserver/src/window_layout_policy.cpp new file mode 100644 index 0000000..26f1edd --- /dev/null +++ b/window_manager/wmserver/src/window_layout_policy.cpp @@ -0,0 +1,1117 @@ +/* + * Copyright (c) 2021-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 "window_layout_policy.h" +#include "display_manager_service_inner.h" +#include "remote_animation.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowLayoutPolicy"}; +} + +uint32_t WindowLayoutPolicy::floatingBottomPosY_ = 0; + +WindowLayoutPolicy::WindowLayoutPolicy(const sptr& displayGroupInfo, + DisplayGroupWindowTree& displayGroupWindowTree) + : displayGroupInfo_(displayGroupInfo), displayGroupWindowTree_(displayGroupWindowTree) +{ +} + +void WindowLayoutPolicy::Launch() +{ + WLOGFD("WindowLayoutPolicy::Launch"); +} + +void WindowLayoutPolicy::Clean() +{ + WLOGFD("WindowLayoutPolicy::Clean"); +} + +void WindowLayoutPolicy::Reorder() +{ + WLOGFD("WindowLayoutPolicy::Reorder"); +} + +std::vector WindowLayoutPolicy::GetExitSplitPoints(DisplayId displayId) const +{ + return {}; +} + +void WindowLayoutPolicy::LimitWindowToBottomRightCorner(const sptr& node) +{ + Rect windowRect = node->GetRequestRect(); + Rect displayRect = displayGroupInfo_->GetDisplayRect(node->GetDisplayId()); + windowRect.posX_ = std::max(windowRect.posX_, displayRect.posX_); + windowRect.posY_ = std::max(windowRect.posY_, displayRect.posY_); + windowRect.width_ = std::min(windowRect.width_, displayRect.width_); + windowRect.height_ = std::min(windowRect.height_, displayRect.height_); + + if (windowRect.posX_ + static_cast(windowRect.width_) > + displayRect.posX_ + static_cast(displayRect.width_)) { + windowRect.posX_ = displayRect.posX_ + static_cast(displayRect.width_) - + static_cast(windowRect.width_); + } + + if (windowRect.posY_ + static_cast(windowRect.height_) > + displayRect.posY_ + static_cast(displayRect.height_)) { + windowRect.posY_ = displayRect.posY_ + static_cast(displayRect.height_) - + static_cast(windowRect.height_); + } + node->SetRequestRect(windowRect); + + WLOGFD("windowId: %{public}d, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]", + node->GetWindowId(), windowRect.posX_, windowRect.posY_, windowRect.width_, windowRect.height_); + + for (auto& childNode : node->children_) { + LimitWindowToBottomRightCorner(childNode); + } +} + +void WindowLayoutPolicy::UpdateDisplayGroupRect() +{ + Rect newDisplayGroupRect = { 0, 0, 0, 0 }; + // current multi-display is only support left-right combination, maxNum is two + for (auto& elem : displayGroupInfo_->GetAllDisplayRects()) { + newDisplayGroupRect.posX_ = std::min(displayGroupRect_.posX_, elem.second.posX_); + newDisplayGroupRect.posY_ = std::min(displayGroupRect_.posY_, elem.second.posY_); + newDisplayGroupRect.width_ += elem.second.width_; + int32_t maxHeight = std::max(newDisplayGroupRect.posY_ + static_cast(newDisplayGroupRect.height_), + elem.second.posY_+ static_cast(elem.second.height_)); + newDisplayGroupRect.height_ = maxHeight - newDisplayGroupRect.posY_; + } + displayGroupRect_ = newDisplayGroupRect; + WLOGFD("displayGroupRect_: [ %{public}d, %{public}d, %{public}d, %{public}d]", + displayGroupRect_.posX_, displayGroupRect_.posY_, displayGroupRect_.width_, displayGroupRect_.height_); +} + +void WindowLayoutPolicy::UpdateDisplayGroupLimitRect() +{ + auto firstDisplayLimitRect = limitRectMap_.begin()->second; + Rect newDisplayGroupLimitRect = { firstDisplayLimitRect.posX_, firstDisplayLimitRect.posY_, 0, 0 }; + for (auto& elem : limitRectMap_) { + newDisplayGroupLimitRect.posX_ = std::min(newDisplayGroupLimitRect.posX_, elem.second.posX_); + newDisplayGroupLimitRect.posY_ = std::min(newDisplayGroupLimitRect.posY_, elem.second.posY_); + + int32_t maxWidth = std::max(newDisplayGroupLimitRect.posX_ + + static_cast(newDisplayGroupLimitRect.width_), + elem.second.posX_+ static_cast(elem.second.width_)); + + int32_t maxHeight = std::max(newDisplayGroupLimitRect.posY_ + + static_cast(newDisplayGroupLimitRect.height_), + elem.second.posY_+ static_cast(elem.second.height_)); + newDisplayGroupLimitRect.width_ = static_cast(maxWidth - newDisplayGroupLimitRect.posX_); + newDisplayGroupLimitRect.height_ = static_cast(maxHeight - newDisplayGroupLimitRect.posY_); + } + displayGroupLimitRect_ = newDisplayGroupLimitRect; + WLOGFD("displayGroupLimitRect_: [ %{public}d, %{public}d, %{public}d, %{public}d]", + displayGroupLimitRect_.posX_, displayGroupLimitRect_.posY_, + displayGroupLimitRect_.width_, displayGroupLimitRect_.height_); +} + +void WindowLayoutPolicy::UpdateRectInDisplayGroup(const sptr& node, + const Rect& oriDisplayRect, + const Rect& newDisplayRect) +{ + Rect newRect = node->GetRequestRect(); + WLOGFD("before update rect in display group, windowId: %{public}d, rect: [%{public}d, %{public}d, " + "%{public}d, %{public}d]", node->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); + + newRect.posX_ = newRect.posX_ - oriDisplayRect.posX_ + newDisplayRect.posX_; + newRect.posY_ = newRect.posY_ - oriDisplayRect.posY_ + newDisplayRect.posY_; + node->SetRequestRect(newRect); + WLOGFD("after update rect in display group, windowId: %{public}d, newRect: [%{public}d, %{public}d, " + "%{public}d, %{public}d]", node->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); + + for (auto& childNode : node->children_) { + UpdateRectInDisplayGroup(childNode, oriDisplayRect, newDisplayRect); + } +} + +bool WindowLayoutPolicy::IsMultiDisplay() +{ + return isMultiDisplay_; +} + +void WindowLayoutPolicy::UpdateMultiDisplayFlag() +{ + if (displayGroupInfo_->GetAllDisplayRects().size() > 1) { + isMultiDisplay_ = true; + WLOGFD("current mode is multi-display"); + } else { + isMultiDisplay_ = false; + WLOGFD("current mode is not multi-display"); + } +} + +void WindowLayoutPolicy::UpdateRectInDisplayGroupForAllNodes(DisplayId displayId, + const Rect& oriDisplayRect, + const Rect& newDisplayRect) +{ + WLOGFD("displayId: %{public}" PRIu64", oriDisplayRect: [ %{public}d, %{public}d, %{public}d, %{public}d] " + "newDisplayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]", + displayId, oriDisplayRect.posX_, oriDisplayRect.posY_, oriDisplayRect.width_, oriDisplayRect.height_, + newDisplayRect.posX_, newDisplayRect.posY_, newDisplayRect.width_, newDisplayRect.height_); + + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + for (auto& iter : displayWindowTree) { + auto& nodeVector = *(iter.second); + for (auto& node : nodeVector) { + if (!node->isShowingOnMultiDisplays_) { + UpdateRectInDisplayGroup(node, oriDisplayRect, newDisplayRect); + } + if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + LimitWindowToBottomRightCorner(node); + } + } + WLOGFD("Recalculate window rect in display group, displayId: %{public}" PRIu64", rootType: %{public}d", + displayId, iter.first); + } +} + +void WindowLayoutPolicy::UpdateDisplayRectAndDisplayGroupInfo(const std::map& displayRectMap) +{ + for (auto& elem : displayRectMap) { + auto& displayId = elem.first; + auto& displayRect = elem.second; + displayGroupInfo_->SetDisplayRect(displayId, displayRect); + } +} + +void WindowLayoutPolicy::PostProcessWhenDisplayChange() +{ + displayGroupInfo_->UpdateLeftAndRightDisplayId(); + UpdateMultiDisplayFlag(); + UpdateDisplayGroupRect(); + Launch(); +} + +void WindowLayoutPolicy::ProcessDisplayCreate(DisplayId displayId, const std::map& displayRectMap) +{ + const auto& oriDisplayRectMap = displayGroupInfo_->GetAllDisplayRects(); + // check displayId and displayRectMap size + if (oriDisplayRectMap.find(displayId) == oriDisplayRectMap.end() || + displayRectMap.size() != oriDisplayRectMap.size()) { + WLOGFE("current display is exited or displayInfo map size is error, displayId: %{public}" PRIu64"", displayId); + return; + } + for (auto& elem : displayRectMap) { + auto iter = oriDisplayRectMap.find(elem.first); + if (iter != oriDisplayRectMap.end()) { + const auto& oriDisplayRect = iter->second; + const auto& newDisplayRect = elem.second; + UpdateRectInDisplayGroupForAllNodes(elem.first, oriDisplayRect, newDisplayRect); + } else { + if (elem.first != displayId) { + WLOGFE("Wrong display, displayId: %{public}" PRIu64"", displayId); + return; + } + } + } + UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); + PostProcessWhenDisplayChange(); + WLOGFD("Process display create, displayId: %{public}" PRIu64"", displayId); +} + +void WindowLayoutPolicy::ProcessDisplayDestroy(DisplayId displayId, const std::map& displayRectMap) +{ + const auto& oriDisplayRectMap = displayGroupInfo_->GetAllDisplayRects(); + // check displayId and displayRectMap size + if (oriDisplayRectMap.find(displayId) != oriDisplayRectMap.end() || + displayRectMap.size() != oriDisplayRectMap.size()) { + WLOGFE("can not find current display or displayInfo map size is error, displayId: %{public}" PRIu64"", + displayId); + return; + } + for (auto oriIter = oriDisplayRectMap.begin(); oriIter != oriDisplayRectMap.end();) { + auto newIter = displayRectMap.find(oriIter->first); + if (newIter != displayRectMap.end()) { + const auto& oriDisplayRect = oriIter->second; + const auto& newDisplayRect = newIter->second; + UpdateRectInDisplayGroupForAllNodes(oriIter->first, oriDisplayRect, newDisplayRect); + } else { + if (oriIter->first != displayId) { + WLOGFE("Wrong display, displayId: %{public}" PRIu64"", displayId); + return; + } + } + ++oriIter; + } + + UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); + PostProcessWhenDisplayChange(); + WLOGFD("Process display destroy, displayId: %{public}" PRIu64"", displayId); +} + +void WindowLayoutPolicy::ProcessDisplaySizeChangeOrRotation(DisplayId displayId, + const std::map& displayRectMap) +{ + const auto& oriDisplayRectMap = displayGroupInfo_->GetAllDisplayRects(); + // check displayId and displayRectMap size + if (oriDisplayRectMap.find(displayId) == oriDisplayRectMap.end() || + displayRectMap.size() != oriDisplayRectMap.size()) { + WLOGFE("can not find current display or displayInfo map size is error, displayId: %{public}" PRIu64"", + displayId); + return; + } + + for (auto& elem : displayRectMap) { + auto iter = oriDisplayRectMap.find(elem.first); + if (iter != oriDisplayRectMap.end()) { + UpdateRectInDisplayGroupForAllNodes(elem.first, iter->second, elem.second); + } + } + + UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); + PostProcessWhenDisplayChange(); + WLOGFD("Process display change, displayId: %{public}" PRIu64"", displayId); +} + +void WindowLayoutPolicy::LayoutWindowNodesByRootType(const std::vector>& nodeVec) +{ + if (nodeVec.empty()) { + WLOGE("The node vector is empty!"); + return; + } + for (auto& node : nodeVec) { + LayoutWindowNode(node); + } +} + +void WindowLayoutPolicy::NotifyAnimationSizeChangeIfNeeded() +{ + if (!RemoteAnimation::CheckAnimationController()) { + WLOGFD("no animation controller!"); + return; + } + std::vector fullScreenWinIds; + std::vector floatMainIds; + for (auto& iter : displayGroupWindowTree_) { + auto& displayWindowTree = iter.second; + auto& nodeVec = *(displayWindowTree[WindowRootNodeType::APP_WINDOW_NODE]); + if (nodeVec.empty()) { + WLOGE("The node vector is empty!"); + return; + } + for (auto& node : nodeVec) { + // just has one fullscreen app node on foreground + if (WindowHelper::IsMainFullScreenWindow(node->GetWindowType(), node->GetWindowMode())) { + fullScreenWinIds.emplace_back(node->GetWindowId()); + } + if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + floatMainIds.emplace_back(node->GetWindowId()); + } + } + } + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatMainIds); +} + +void WindowLayoutPolicy::LayoutWindowTree(DisplayId displayId) +{ + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + limitRectMap_[displayId] = displayGroupInfo_->GetDisplayRect(displayId); + // ensure that the avoid area windows are traversed first + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE])); + if (IsFullScreenRecentWindowExist(*(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE]))) { + WLOGFD("recent window on top, early exit layout tree"); + return; + } + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::APP_WINDOW_NODE])); + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::BELOW_WINDOW_NODE])); +} + +void WindowLayoutPolicy::LayoutWindowNode(const sptr& node) +{ + if (node == nullptr) { + return; + } + WLOGFD("LayoutWindowNode, window[%{public}u]", node->GetWindowId()); + if (node->parent_ != nullptr) { // isn't root node + if (!node->currentVisibility_) { + WLOGFD("window[%{public}u] currently not visible, no need layout", node->GetWindowId()); + return; + } + UpdateLayoutRect(node); + if (avoidTypes_.find(node->GetWindowType()) != avoidTypes_.end()) { + UpdateLimitRect(node, limitRectMap_[node->GetDisplayId()]); + UpdateDisplayGroupLimitRect(); + } + } + for (auto& childNode : node->children_) { + LayoutWindowNode(childNode); + } +} + +bool WindowLayoutPolicy::IsVerticalDisplay(DisplayId displayId) const +{ + return displayGroupInfo_->GetDisplayRect(displayId).width_ < displayGroupInfo_->GetDisplayRect(displayId).height_; +} + +void WindowLayoutPolicy::UpdateClientRect(const Rect& rect, const sptr& node, WindowSizeChangeReason reason) +{ + if (node->GetWindowToken()) { + WLOGFD("notify client id: %{public}d, windowRect:[%{public}d, %{public}d, %{public}u, %{public}u], reason: " + "%{public}u", node->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_, reason); + node->GetWindowToken()->UpdateWindowRect(rect, node->GetDecoStatus(), reason); + } + NotifyAnimationSizeChangeIfNeeded(); +} + +void WindowLayoutPolicy::UpdateClientRectAndResetReason(const sptr& node, const Rect& winRect) +{ + auto reason = node->GetWindowSizeChangeReason(); + UpdateClientRect(winRect, node, reason); + if ((reason != WindowSizeChangeReason::MOVE) && (node->GetWindowType() != WindowType::WINDOW_TYPE_DOCK_SLICE)) { + node->ResetWindowSizeChangeReason(); + } +} + +void WindowLayoutPolicy::RemoveWindowNode(const sptr& node) +{ + auto type = node->GetWindowType(); + // affect other windows, trigger off global layout + if (avoidTypes_.find(type) != avoidTypes_.end()) { + LayoutWindowTree(node->GetDisplayId()); + } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode + LayoutWindowTree(node->GetDisplayId()); + } + UpdateClientRect(node->GetRequestRect(), node, WindowSizeChangeReason::HIDE); +} + +void WindowLayoutPolicy::UpdateWindowNode(const sptr& node, bool isAddWindow) +{ + auto type = node->GetWindowType(); + // affect other windows, trigger off global layout + if (avoidTypes_.find(type) != avoidTypes_.end()) { + LayoutWindowTree(node->GetDisplayId()); + } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode + LayoutWindowTree(node->GetDisplayId()); + } else { // layout single window + LayoutWindowNode(node); + } +} + +void WindowLayoutPolicy::UpdateFloatingLayoutRect(Rect& limitRect, Rect& winRect) +{ + winRect.width_ = std::min(limitRect.width_, winRect.width_); + winRect.height_ = std::min(limitRect.height_, winRect.height_); + winRect.posX_ = std::max(limitRect.posX_, winRect.posX_); + winRect.posY_ = std::max(limitRect.posY_, winRect.posY_); + winRect.posX_ = std::min( + limitRect.posX_ + static_cast(limitRect.width_) - static_cast(winRect.width_), + winRect.posX_); + winRect.posY_ = std::min( + limitRect.posY_ + static_cast(limitRect.height_) - static_cast(winRect.height_), + winRect.posY_); +} + +void WindowLayoutPolicy::ComputeDecoratedRequestRect(const sptr& node) const +{ + auto property = node->GetWindowProperty(); + if (property == nullptr) { + WLOGE("window property is nullptr"); + return; + } + auto reqRect = property->GetRequestRect(); + if (!property->GetDecorEnable() || property->GetDecoStatus() || + node->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) { + return; + } + float virtualPixelRatio = GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * virtualPixelRatio); + uint32_t winTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + + Rect rect; + rect.posX_ = reqRect.posX_; + rect.posY_ = reqRect.posY_; + rect.width_ = reqRect.width_ + winFrameW + winFrameW; + rect.height_ = reqRect.height_ + winTitleBarH + winFrameW; + property->SetRequestRect(rect); + property->SetDecoStatus(true); +} + +Rect WindowLayoutPolicy::CalcEntireWindowHotZone(const sptr& node, const Rect& winRect, uint32_t hotZone, + float vpr, TransformHelper::Vector2 hotZoneScale) const +{ + Rect rect = winRect; + uint32_t hotZoneX = static_cast(hotZone * vpr / hotZoneScale.x_); + uint32_t hotZoneY = static_cast(hotZone * vpr / hotZoneScale.y_); + + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + if (rect.width_ < rect.height_) { + rect.posX_ -= static_cast(hotZoneX); + rect.width_ += (hotZoneX + hotZoneX); + } else { + rect.posY_ -= static_cast(hotZoneY); + rect.height_ += (hotZoneY + hotZoneY); + } + } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT) { + rect = displayGroupInfo_->GetDisplayRect(node->GetDisplayId()); + } else if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + rect.posX_ -= static_cast(hotZoneX); + rect.posY_ -= static_cast(hotZoneY); + rect.width_ += (hotZoneX + hotZoneX); + rect.height_ += (hotZoneY + hotZoneY); + } + return rect; +} + +void WindowLayoutPolicy::CalcAndSetNodeHotZone(const Rect& winRect, const sptr& node) const +{ + float virtualPixelRatio = GetVirtualPixelRatio(node->GetDisplayId()); + TransformHelper::Vector2 hotZoneScale(1, 1); + if (node->GetWindowProperty()->isNeedComputerTransform()) { + node->ComputeTransform(); + hotZoneScale = WindowHelper::CalculateHotZoneScale(node->GetWindowProperty()->GetTransformMat()); + } + + auto hotZoneRectTouch = CalcEntireWindowHotZone(node, winRect, HOTZONE_TOUCH, virtualPixelRatio, hotZoneScale); + auto hotZoneRectPointer = CalcEntireWindowHotZone(node, winRect, HOTZONE_POINTER, virtualPixelRatio, hotZoneScale); + + node->SetEntireWindowTouchHotArea(hotZoneRectTouch); + node->SetEntireWindowPointerHotArea(hotZoneRectPointer); + + std::vector requestedHotAreas; + node->GetWindowProperty()->GetTouchHotAreas(requestedHotAreas); + std::vector touchHotAreas; + std::vector pointerHotAreas; + if (requestedHotAreas.empty()) { + touchHotAreas.emplace_back(hotZoneRectTouch); + pointerHotAreas.emplace_back(hotZoneRectPointer); + } else { + if (!WindowHelper::CalculateTouchHotAreas(winRect, requestedHotAreas, touchHotAreas)) { + WLOGFW("some parameters in requestedHotAreas are abnormal"); + } + pointerHotAreas = touchHotAreas; + } + node->SetTouchHotAreas(touchHotAreas); + node->SetPointerHotAreas(pointerHotAreas); +} + +void WindowLayoutPolicy::FixWindowSizeByRatioIfDragBeyondLimitRegion(const sptr& node, Rect& winRect) +{ + const auto& sizeLimits = node->GetWindowUpdatedSizeLimits(); + if (sizeLimits.maxWidth_ == sizeLimits.minWidth_ && + sizeLimits.maxHeight_ == sizeLimits.minHeight_) { + WLOGFD("window rect can not be changed"); + return; + } + if (winRect.height_ == 0) { + WLOGFE("the height of window is zero"); + return; + } + float curRatio = static_cast(winRect.width_) / static_cast(winRect.height_); + if (sizeLimits.minRatio_ <= curRatio && curRatio <= sizeLimits.maxRatio_) { + WLOGFD("window ratio is satisfied with limit ratio, curRatio: %{public}f", curRatio); + return; + } + + float virtualPixelRatio = GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + Rect limitRect = isMultiDisplay_ ? displayGroupLimitRect_ : limitRectMap_[node->GetDisplayId()]; + int32_t limitMinPosX = limitRect.posX_ + static_cast(windowTitleBarH); + int32_t limitMaxPosX = limitRect.posX_ + static_cast(limitRect.width_ - windowTitleBarH); + int32_t limitMinPosY = limitRect.posY_; + int32_t limitMaxPosY = limitRect.posY_ + static_cast(limitRect.height_ - windowTitleBarH); + + Rect dockWinRect; + DockWindowShowState dockShownState = GetDockWindowShowState(node->GetDisplayId(), dockWinRect); + if (dockShownState == DockWindowShowState::SHOWN_IN_BOTTOM) { + WLOGFD("dock window show in bottom"); + limitMaxPosY = dockWinRect.posY_ - static_cast(windowTitleBarH); + } else if (dockShownState == DockWindowShowState::SHOWN_IN_LEFT) { + WLOGFD("dock window show in left"); + limitMinPosX = dockWinRect.posX_ + static_cast(dockWinRect.width_ + windowTitleBarH); + } else if (dockShownState == DockWindowShowState::SHOWN_IN_RIGHT) { + WLOGFD("dock window show in right"); + limitMaxPosX = dockWinRect.posX_ - static_cast(windowTitleBarH); + } + + float newRatio = curRatio < sizeLimits.minRatio_ ? sizeLimits.minRatio_ : sizeLimits.maxRatio_; + if ((winRect.posX_ + static_cast(winRect.width_) == limitMinPosX) || (winRect.posX_ == limitMaxPosX)) { + // height can not be changed + if (sizeLimits.maxHeight_ == sizeLimits.minHeight_) { + return; + } + winRect.height_ = static_cast(static_cast(winRect.width_) / newRatio); + } + + if ((winRect.posY_ == limitMinPosY) || (winRect.posX_ == limitMaxPosY)) { + // width can not be changed + if (sizeLimits.maxWidth_ == sizeLimits.minWidth_) { + return; + } + winRect.width_ = static_cast(static_cast(winRect.height_) * newRatio); + } + WLOGFD("After limit by ratio if beyond limit region, winRect: %{public}d %{public}d %{public}u %{public}u", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); +} + +WindowSizeLimits WindowLayoutPolicy::GetSystemSizeLimits(const sptr& node, + const Rect& displayRect, float virtualPixelRatio) +{ + WindowSizeLimits systemLimits; + systemLimits.maxWidth_ = static_cast(MAX_FLOATING_SIZE * virtualPixelRatio); + systemLimits.maxHeight_ = static_cast(MAX_FLOATING_SIZE * virtualPixelRatio); + + // Float camera window has a special limit: + // if display sw <= 600dp, portrait: min width = display sw * 30%, landscape: min width = sw * 50% + // if display sw > 600dp, portrait: min width = display sw * 12%, landscape: min width = sw * 30% + if (node->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + uint32_t smallWidth = displayRect.height_ <= displayRect.width_ ? displayRect.height_ : displayRect.width_; + float hwRatio = static_cast(displayRect.height_) / static_cast(displayRect.width_); + if (smallWidth <= static_cast(600 * virtualPixelRatio)) { // sw <= 600dp + if (displayRect.width_ <= displayRect.height_) { + systemLimits.minWidth_ = static_cast(smallWidth * 0.3); // min width = display sw * 0.3 + } else { + systemLimits.minWidth_ = static_cast(smallWidth * 0.5); // min width = display sw * 0.5 + } + } else { + if (displayRect.width_ <= displayRect.height_) { + systemLimits.minWidth_ = static_cast(smallWidth * 0.12); // min width = display sw * 0.12 + } else { + systemLimits.minWidth_ = static_cast(smallWidth * 0.3); // min width = display sw * 0.3 + } + } + systemLimits.minHeight_ = static_cast(systemLimits.minWidth_ * hwRatio); + } else { + systemLimits.minWidth_ = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + systemLimits.minHeight_ = static_cast(MIN_FLOATING_HEIGHT * virtualPixelRatio); + } + WLOGFD("[System SizeLimits] [maxWidth: %{public}u, minWidth: %{public}u, maxHeight: %{public}u, " + "minHeight: %{public}u]", systemLimits.maxWidth_, systemLimits.minWidth_, + systemLimits.maxHeight_, systemLimits.minHeight_); + return systemLimits; +} + +void WindowLayoutPolicy::UpdateWindowSizeLimits(const sptr& node) +{ + const auto& displayRect = displayGroupInfo_->GetDisplayRect(node->GetDisplayId()); + const auto& virtualPixelRatio = GetVirtualPixelRatio(node->GetDisplayId()); + const auto& systemLimits = GetSystemSizeLimits(node, displayRect, virtualPixelRatio); + const auto& customizedLimits = node->GetWindowSizeLimits(); + + WindowSizeLimits newLimits = systemLimits; + + // configured limits of floating window + uint32_t configuredMaxWidth = static_cast(customizedLimits.maxWidth_ * virtualPixelRatio); + uint32_t configuredMaxHeight = static_cast(customizedLimits.maxHeight_ * virtualPixelRatio); + uint32_t configuredMinWidth = static_cast(customizedLimits.minWidth_ * virtualPixelRatio); + uint32_t configuredMinHeight = static_cast(customizedLimits.minHeight_ * virtualPixelRatio); + + // calculate new limit size + if (systemLimits.minWidth_ <= configuredMaxWidth && configuredMaxWidth <= systemLimits.maxWidth_) { + newLimits.maxWidth_ = configuredMaxWidth; + } + if (systemLimits.minHeight_ <= configuredMaxHeight && configuredMaxHeight <= systemLimits.maxHeight_) { + newLimits.maxHeight_ = configuredMaxHeight; + } + if (systemLimits.minWidth_ <= configuredMinWidth && configuredMinWidth <= newLimits.maxWidth_) { + newLimits.minWidth_ = configuredMinWidth; + } + if (systemLimits.minHeight_ <= configuredMinHeight && configuredMinHeight <= newLimits.maxHeight_) { + newLimits.minHeight_ = configuredMinHeight; + } + + // calculate new limit ratio + newLimits.maxRatio_ = static_cast(newLimits.maxWidth_) / static_cast(newLimits.minHeight_); + newLimits.minRatio_ = static_cast(newLimits.minWidth_) / static_cast(newLimits.maxHeight_); + if (newLimits.minRatio_ <= customizedLimits.maxRatio_ && customizedLimits.maxRatio_ <= newLimits.maxRatio_) { + newLimits.maxRatio_ = customizedLimits.maxRatio_; + } + if (newLimits.minRatio_ <= customizedLimits.minRatio_ && customizedLimits.minRatio_ <= newLimits.maxRatio_) { + newLimits.minRatio_ = customizedLimits.minRatio_; + } + + // recalculate limit size by new ratio + uint32_t newMaxWidth = static_cast(static_cast(newLimits.maxHeight_) * newLimits.maxRatio_); + newLimits.maxWidth_ = std::min(newMaxWidth, newLimits.maxWidth_); + uint32_t newMinWidth = static_cast(static_cast(newLimits.minHeight_) * newLimits.minRatio_); + newLimits.minWidth_ = std::max(newMinWidth, newLimits.minWidth_); + uint32_t newMaxHeight = static_cast(static_cast(newLimits.maxWidth_) / newLimits.minRatio_); + newLimits.maxHeight_ = std::min(newMaxHeight, newLimits.maxHeight_); + uint32_t newMinHeight = static_cast(static_cast(newLimits.minWidth_) / newLimits.maxRatio_); + newLimits.minHeight_ = std::max(newMinHeight, newLimits.minHeight_); + + WLOGFD("[Update SizeLimits] winId: %{public}u, Width: [max:%{public}u, min:%{public}u], Height: [max:%{public}u, " + "min:%{public}u], Ratio: [max:%{public}f, min:%{public}f]", node->GetWindowId(), newLimits.maxWidth_, + newLimits.minWidth_, newLimits.maxHeight_, newLimits.minHeight_, newLimits.maxRatio_, newLimits.minRatio_); + node->SetWindowUpdatedSizeLimits(newLimits); +} + +void WindowLayoutPolicy::UpdateFloatingWindowSizeForStretchableWindow(const sptr& node, + const Rect& displayRect, Rect& winRect) const +{ + if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::DRAG) { + const Rect &originRect = node->GetOriginRect(); + if (originRect.height_ == 0 || originRect.width_ == 0) { + WLOGE("invalid originRect. window id: %{public}u", node->GetWindowId()); + return; + } + auto dragType = node->GetDragType(); + if (dragType == DragType::DRAG_BOTTOM_OR_TOP) { + // if drag height, use height to fix size. + winRect.width_ = winRect.height_ * originRect.width_ / originRect.height_; + } else if (dragType == DragType::DRAG_LEFT_TOP_CORNER || dragType == DragType::DRAG_RIGHT_TOP_CORNER || + dragType == DragType::DRAG_LEFT_OR_RIGHT) { + // if drag width or corner, use width to fix size. + winRect.height_ = winRect.width_ * originRect.height_ / originRect.width_; + } + } + // limit minimum size of window + + const auto& sizeLimits = node->GetWindowUpdatedSizeLimits(); + float scale = std::min(static_cast(winRect.width_) / sizeLimits.minWidth_, + static_cast(winRect.height_) / sizeLimits.minHeight_); + if (scale == 0) { + WLOGE("invalid sizeLimits"); + return; + } + if (scale < 1.0f) { + winRect.width_ = static_cast(static_cast(winRect.width_) / scale); + winRect.height_ = static_cast(static_cast(winRect.height_) / scale); + } +} + +void WindowLayoutPolicy::UpdateFloatingWindowSizeBySizeLimits(const sptr& node, + const Rect& displayRect, Rect& winRect) const +{ + // get new limit config with the settings of system and app + const auto& sizeLimits = node->GetWindowUpdatedSizeLimits(); + + // limit minimum size of floating (not system type) window + if (!WindowHelper::IsSystemWindow(node->GetWindowType()) || + node->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + winRect.width_ = std::max(sizeLimits.minWidth_, winRect.width_); + winRect.height_ = std::max(sizeLimits.minHeight_, winRect.height_); + } + winRect.width_ = std::min(sizeLimits.maxWidth_, winRect.width_); + winRect.height_ = std::min(sizeLimits.maxHeight_, winRect.height_); + WLOGFD("After limit by size, winRect: %{public}d %{public}d %{public}u %{public}u", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + + // width and height can not be changed + if (sizeLimits.maxWidth_ == sizeLimits.minWidth_ && + sizeLimits.maxHeight_ == sizeLimits.minHeight_) { + winRect.width_ = sizeLimits.maxWidth_; + winRect.height_ = sizeLimits.maxHeight_; + WLOGFD("window rect can not be changed"); + return; + } + + float curRatio = static_cast(winRect.width_) / static_cast(winRect.height_); + // there is no need to fix size by ratio if this is not main floating window + if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode()) || + (sizeLimits.minRatio_ <= curRatio && curRatio <= sizeLimits.maxRatio_)) { + WLOGFD("window is system window or ratio is satisfied with limits, curSize: [%{public}d, %{public}d], " + "curRatio: %{public}f", winRect.width_, winRect.height_, curRatio); + return; + } + + float newRatio = curRatio < sizeLimits.minRatio_ ? sizeLimits.minRatio_ : sizeLimits.maxRatio_; + if (sizeLimits.maxWidth_ == sizeLimits.minWidth_) { + winRect.height_ = static_cast(static_cast(winRect.width_) / newRatio); + return; + } + if (sizeLimits.maxHeight_ == sizeLimits.minHeight_) { + winRect.width_ = static_cast(static_cast(winRect.height_) * newRatio); + return; + } + + auto dragType = node->GetDragType(); + if (dragType == DragType::DRAG_BOTTOM_OR_TOP) { + // if drag height, use height to fix size. + winRect.width_ = static_cast(static_cast(winRect.height_) * newRatio); + } else { + // if drag width or corner, use width to fix size. + winRect.height_ = static_cast(static_cast(winRect.width_) / newRatio); + } + WLOGFD("After limit by customize config, winRect: %{public}d %{public}d %{public}u %{public}u", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); +} + +void WindowLayoutPolicy::LimitFloatingWindowSize(const sptr& node, + const Rect& displayRect, + Rect& winRect) const +{ + if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING + || node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) { + return; + } + Rect oriWinRect = winRect; + UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + if (node->GetStretchable() && + WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + } + + // fix size in case of moving window when dragging + const auto& lastWinRect = node->GetWindowRect(); + if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::DRAG) { + if (oriWinRect.posX_ != lastWinRect.posX_) { + winRect.posX_ = oriWinRect.posX_ + static_cast(oriWinRect.width_) - + static_cast(winRect.width_); + } + if (oriWinRect.posY_ != lastWinRect.posY_) { + winRect.posY_ = oriWinRect.posY_ + static_cast(oriWinRect.height_) - + static_cast(winRect.height_); + } + } +} + +void WindowLayoutPolicy::LimitMainFloatingWindowPosition(const sptr& node, Rect& winRect) const +{ + if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + return; + } + + auto reason = node->GetWindowSizeChangeReason(); + // if drag or move window, limit size and position + if (reason == WindowSizeChangeReason::DRAG) { + LimitWindowPositionWhenDrag(node, winRect); + if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + const_cast(this)->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, winRect); + } + } else { + // Limit window position, such as init window rect when show + LimitWindowPositionWhenInitRectOrMove(node, winRect); + } +} + +void WindowLayoutPolicy::LimitWindowPositionWhenDrag(const sptr& node, + Rect& winRect) const +{ + float virtualPixelRatio = GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + const Rect& lastRect = node->GetWindowRect(); + Rect oriWinRect = winRect; + + Rect limitRect = isMultiDisplay_ ? displayGroupLimitRect_ : limitRectMap_[node->GetDisplayId()]; + int32_t limitMinPosX = limitRect.posX_ + static_cast(windowTitleBarH); + int32_t limitMaxPosX = limitRect.posX_ + static_cast(limitRect.width_ - windowTitleBarH); + int32_t limitMinPosY = limitRect.posY_; + int32_t limitMaxPosY = limitRect.posY_ + static_cast(limitRect.height_ - windowTitleBarH); + + Rect dockWinRect; + DockWindowShowState dockShownState = GetDockWindowShowState(node->GetDisplayId(), dockWinRect); + if (dockShownState == DockWindowShowState::SHOWN_IN_BOTTOM) { + WLOGFD("dock window show in bottom"); + limitMaxPosY = dockWinRect.posY_ - static_cast(windowTitleBarH); + } else if (dockShownState == DockWindowShowState::SHOWN_IN_LEFT) { + WLOGFD("dock window show in left"); + limitMinPosX = dockWinRect.posX_ + static_cast(dockWinRect.width_ + windowTitleBarH); + } else if (dockShownState == DockWindowShowState::SHOWN_IN_RIGHT) { + WLOGFD("dock window show in right"); + limitMaxPosX = dockWinRect.posX_ - static_cast(windowTitleBarH); + } + + // limitMinPosX is minimum (x + width) + if (oriWinRect.posX_ + static_cast(oriWinRect.width_) < limitMinPosX) { + if (oriWinRect.width_ != lastRect.width_) { + winRect.width_ = static_cast(limitMinPosX - oriWinRect.posX_); + } + } + // maximum position x + if (oriWinRect.posX_ > limitMaxPosX) { + winRect.posX_ = limitMaxPosX; + if (oriWinRect.width_ != lastRect.width_) { + winRect.width_ = static_cast( + oriWinRect.posX_ + static_cast(oriWinRect.width_) - winRect.posX_); + } + } + // minimum position y + if (oriWinRect.posY_ < limitMinPosY) { + winRect.posY_ = limitMinPosY; + if (oriWinRect.height_ != lastRect.height_) { + winRect.height_ = static_cast( + oriWinRect.posY_ + static_cast(oriWinRect.height_) - winRect.posY_); + } + } + // maximum position y + if (winRect.posY_ > limitMaxPosY) { + winRect.posY_ = limitMaxPosY; + if (oriWinRect.height_ != lastRect.height_) { + winRect.height_ = static_cast( + oriWinRect.posY_ + static_cast(oriWinRect.height_) - winRect.posY_); + } + } + WLOGFD("After limit by position, winRect: %{public}d %{public}d %{public}u %{public}u", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); +} + +void WindowLayoutPolicy::LimitWindowPositionWhenInitRectOrMove(const sptr& node, Rect& winRect) const +{ + float virtualPixelRatio = GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + + Rect limitRect; + // if is cross-display window, the limit rect should be full limitRect + if (node->isShowingOnMultiDisplays_) { + limitRect = displayGroupLimitRect_; + } else { + limitRect = limitRectMap_[node->GetDisplayId()]; + } + + // limit position of the main floating window(window which support dragging) + if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + Rect dockWinRect; + DockWindowShowState dockShownState = GetDockWindowShowState(node->GetDisplayId(), dockWinRect); + winRect.posY_ = std::max(limitRect.posY_, winRect.posY_); + winRect.posY_ = std::min(limitRect.posY_ + static_cast(limitRect.height_ - windowTitleBarH), + winRect.posY_); + if (dockShownState == DockWindowShowState::SHOWN_IN_BOTTOM) { + WLOGFD("dock window show in bottom"); + winRect.posY_ = std::min(dockWinRect.posY_ - static_cast(windowTitleBarH), + winRect.posY_); + } + winRect.posX_ = std::max(limitRect.posX_ + static_cast(windowTitleBarH - winRect.width_), + winRect.posX_); + if (dockShownState == DockWindowShowState::SHOWN_IN_LEFT) { + WLOGFD("dock window show in left"); + winRect.posX_ = std::max(static_cast(dockWinRect.width_ + windowTitleBarH - winRect.width_), + winRect.posX_); + } + winRect.posX_ = std::min(limitRect.posX_ + static_cast(limitRect.width_ - windowTitleBarH), + winRect.posX_); + if (dockShownState == DockWindowShowState::SHOWN_IN_RIGHT) { + WLOGFD("dock window show in right"); + winRect.posX_ = std::min(dockWinRect.posX_ - static_cast(windowTitleBarH), + winRect.posX_); + } + auto reason = node->GetWindowSizeChangeReason(); + // if init window on pc, limit position + if (floatingBottomPosY_ != 0 && reason == WindowSizeChangeReason::UNDEFINED) { + uint32_t bottomPosY = static_cast(floatingBottomPosY_ * virtualPixelRatio); + if (winRect.posY_ + static_cast(winRect.height_) >= bottomPosY) { + winRect.posY_ = limitRect.posY_; + } + } + } + WLOGFD("After limit by position if init or move, winRect: %{public}d %{public}d %{public}u %{public}u", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); +} + +DockWindowShowState WindowLayoutPolicy::GetDockWindowShowState(DisplayId displayId, Rect& dockWinRect) const +{ + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + auto& nodeVec = *(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE]); + for (auto& node : nodeVec) { + if (node->GetWindowType() != WindowType::WINDOW_TYPE_LAUNCHER_DOCK) { + continue; + } + + dockWinRect = node->GetWindowRect(); + auto displayRect = displayGroupInfo_->GetDisplayRect(displayId); + WLOGFD("begin dockWinRect :[%{public}d, %{public}d, %{public}u, %{public}u]", + dockWinRect.posX_, dockWinRect.posY_, dockWinRect.width_, dockWinRect.height_); + if (dockWinRect.height_ < dockWinRect.width_) { + if (static_cast(dockWinRect.posY_) + dockWinRect.height_ == displayRect.height_) { + return DockWindowShowState::SHOWN_IN_BOTTOM; + } else { + return DockWindowShowState::NOT_SHOWN; + } + } else { + if (dockWinRect.posX_ == 0) { + return DockWindowShowState::SHOWN_IN_LEFT; + } else if (static_cast(dockWinRect.posX_) + dockWinRect.width_ == displayRect.width_) { + return DockWindowShowState::SHOWN_IN_RIGHT; + } else { + return DockWindowShowState::NOT_SHOWN; + } + } + } + return DockWindowShowState::NOT_SHOWN; +} + +AvoidPosType WindowLayoutPolicy::GetAvoidPosType(const Rect& rect, DisplayId displayId) const +{ + const auto& displayRectMap = displayGroupInfo_->GetAllDisplayRects(); + if (displayRectMap.find(displayId) == std::end(displayRectMap)) { + WLOGFE("GetAvoidPosType fail. Get display fail. displayId: %{public}" PRIu64"", displayId); + return AvoidPosType::AVOID_POS_UNKNOWN; + } + const auto& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + return WindowHelper::GetAvoidPosType(rect, displayRect); +} + +void WindowLayoutPolicy::UpdateLimitRect(const sptr& node, Rect& limitRect) +{ + const auto& layoutRect = node->GetWindowRect(); + int32_t limitH = static_cast(limitRect.height_); + int32_t limitW = static_cast(limitRect.width_); + int32_t layoutH = static_cast(layoutRect.height_); + int32_t layoutW = static_cast(layoutRect.width_); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR || + node->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR) { + auto avoidPosType = GetAvoidPosType(layoutRect, node->GetDisplayId()); + int32_t offsetH = 0; + int32_t offsetW = 0; + switch (avoidPosType) { + case AvoidPosType::AVOID_POS_TOP: + offsetH = layoutRect.posY_ + layoutH - limitRect.posY_; + limitRect.posY_ += offsetH; + limitH -= offsetH; + break; + case AvoidPosType::AVOID_POS_BOTTOM: + offsetH = limitRect.posY_ + limitH - layoutRect.posY_; + limitH -= offsetH; + break; + case AvoidPosType::AVOID_POS_LEFT: + offsetW = layoutRect.posX_ + layoutW - limitRect.posX_; + limitRect.posX_ += offsetW; + limitW -= offsetW; + break; + case AvoidPosType::AVOID_POS_RIGHT: + offsetW = limitRect.posX_ + limitW - layoutRect.posX_; + limitW -= offsetW; + break; + default: + WLOGFE("invalid avoidPosType: %{public}d", avoidPosType); + } + } + limitRect.height_ = static_cast(limitH < 0 ? 0 : limitH); + limitRect.width_ = static_cast(limitW < 0 ? 0 : limitW); + WLOGFD("Type: %{public}d, limitRect: %{public}d %{public}d %{public}u %{public}u", + node->GetWindowType(), limitRect.posX_, limitRect.posY_, limitRect.width_, limitRect.height_); +} + +void WindowLayoutPolicy::Reset() +{ +} + +float WindowLayoutPolicy::GetVirtualPixelRatio(DisplayId displayId) const +{ + float virtualPixelRatio = displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId); + WLOGFD("GetVirtualPixel success. displayId:%{public}" PRIu64", vpr:%{public}f", displayId, virtualPixelRatio); + return virtualPixelRatio; +} + +bool WindowLayoutPolicy::IsFullScreenRecentWindowExist(const std::vector>& nodeVec) const +{ + for (auto& node : nodeVec) { + if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT && + node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) { + return true; + } + } + return false; +} + +static void SetBounds(const sptr& node, const Rect& winRect, const Rect& preRect) +{ + if (node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT || + node->GetWindowSizeChangeReason() == WindowSizeChangeReason::TRANSFORM) { + WLOGFD("not need to update bounds"); + return; + } + // set surface node gravity based on WindowSizeChangeReason + if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::DRAG_START || + node->GetWindowSizeChangeReason() == WindowSizeChangeReason::DRAG || + node->GetWindowSizeChangeReason() == WindowSizeChangeReason::ROTATION) { + if (node->surfaceNode_) { + node->surfaceNode_->SetFrameGravity(Gravity::RESIZE); + } + } else { + if (node->surfaceNode_) { + node->surfaceNode_->SetFrameGravity(Gravity::TOP_LEFT); + } + } + WLOGFD("name:%{public}s id:%{public}u preRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + node->GetWindowName().c_str(), node->GetWindowId(), + preRect.posX_, preRect.posY_, preRect.width_, preRect.height_); + WLOGFD("name:%{public}s id:%{public}u winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + node->GetWindowName().c_str(), node->GetWindowId(), + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + if (node->leashWinSurfaceNode_) { + if (winRect != preRect) { + // avoid animation interpreted when client coming + node->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + } + if (node->startingWinSurfaceNode_) { + node->startingWinSurfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_); + } + if (node->surfaceNode_) { + node->surfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_); + } + } else if (node->surfaceNode_) { + node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + } +} + +void WindowLayoutPolicy::UpdateSurfaceBounds(const sptr& node, const Rect& winRect, const Rect& preRect) +{ + wptr weakNode = node; + auto SetBoundsFunc = [weakNode, winRect, preRect]() { + auto winNode = weakNode.promote(); + if (winNode == nullptr) { + WLOGFD("winNode is nullptr"); + return; + } + SetBounds(winNode, winRect, preRect); + }; + + switch (node->GetWindowSizeChangeReason()) { + case WindowSizeChangeReason::MAXIMIZE: + [[fallthrough]]; + case WindowSizeChangeReason::RECOVER: { + const RSAnimationTimingProtocol timingProtocol(400); // animation time + RSNode::Animate(timingProtocol, RSAnimationTimingCurve::EASE_OUT, SetBoundsFunc); + break; + } + case WindowSizeChangeReason::ROTATION: { + const RSAnimationTimingProtocol timingProtocol(600); // animation time + const RSAnimationTimingCurve curve_ = RSAnimationTimingCurve::CreateCubicCurve( + 0.2, 0.0, 0.2, 1.0); // animation curve: cubic [0.2, 0.0, 0.2, 1.0] + RSNode::Animate(timingProtocol, curve_, SetBoundsFunc); + break; + } + case WindowSizeChangeReason::UNDEFINED: + [[fallthrough]]; + default: + SetBoundsFunc(); + } +} + +Rect WindowLayoutPolicy::GetDisplayGroupRect() const +{ + return displayGroupRect_; +} + +void WindowLayoutPolicy::SetSplitRatioConfig(const SplitRatioConfig& splitRatioConfig) +{ + splitRatioConfig_ = splitRatioConfig; +} + +Rect WindowLayoutPolicy::GetDividerRect(DisplayId displayId) const +{ + return INVALID_EMPTY_RECT; +} + +bool WindowLayoutPolicy::IsTileRectSatisfiedWithSizeLimits(const sptr& node) +{ + return true; +} + +void WindowLayoutPolicy::SetCascadeRectBottomPosYLimit(uint32_t floatingBottomPosY) +{ + floatingBottomPosY_ = floatingBottomPosY; +} +} +} diff --git a/window_manager/wmserver/src/window_layout_policy_cascade.cpp b/window_manager/wmserver/src/window_layout_policy_cascade.cpp new file mode 100644 index 0000000..f4b9076 --- /dev/null +++ b/window_manager/wmserver/src/window_layout_policy_cascade.cpp @@ -0,0 +1,671 @@ +/* + * 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 "window_layout_policy_cascade.h" + +#include + +#include "minimize_app.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowLayoutPolicyCascade"}; +} + +WindowLayoutPolicyCascade::WindowLayoutPolicyCascade(const sptr& displayGroupInfo, + DisplayGroupWindowTree& displayGroupWindowTree) + : WindowLayoutPolicy(displayGroupInfo, displayGroupWindowTree) +{ + LayoutRects cascadeRects { + .primaryRect_ = {0, 0, 0, 0}, + .secondaryRect_ = {0, 0, 0, 0}, + .primaryLimitRect_ = {0, 0, 0, 0}, + .secondaryLimitRect_ = {0, 0, 0, 0}, + .dividerRect_ = {0, 0, 0, 0}, + .firstCascadeRect_ = {0, 0, 0, 0}, + }; + for (auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + cascadeRectsMap_.insert(std::make_pair(iter.first, cascadeRects)); + } +} + +void WindowLayoutPolicyCascade::Launch() +{ + InitAllRects(); + for (const auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + DisplayId displayId = iter.first; + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::APP_WINDOW_NODE])); + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::BELOW_WINDOW_NODE])); + } + WLOGFD("WindowLayoutPolicyCascade::Launch"); +} + +void WindowLayoutPolicyCascade::Clean() +{ + WLOGFD("WindowLayoutPolicyCascade::Clean"); +} + +void WindowLayoutPolicyCascade::Reset() +{ + const auto& displayRectMap = displayGroupInfo_->GetAllDisplayRects(); + // reset split and limit rects + for (auto& iter : displayRectMap) { + InitSplitRects(iter.first); + InitLimitRects(iter.first); + } + displayGroupLimitRect_ = displayGroupRect_; +} + +void WindowLayoutPolicyCascade::InitAllRects() +{ + const auto& displayRectMap = displayGroupInfo_->GetAllDisplayRects(); + for (auto& iter : displayRectMap) { + // init split and limit rects + InitSplitRects(iter.first); + InitLimitRects(iter.first); + // init full displayRect + displayGroupLimitRect_ = displayGroupRect_; + // init cascade rect + auto& displayWindowTree = displayGroupWindowTree_[iter.first]; + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE])); + InitCascadeRect(iter.first); + } +} + +void WindowLayoutPolicyCascade::LayoutWindowNode(const sptr& node) +{ + if (node == nullptr) { + return; + } + if (node->parent_ != nullptr) { // isn't root node + if (!node->currentVisibility_) { + WLOGFD("window[%{public}u] currently not visible, no need layout", node->GetWindowId()); + return; + } + UpdateLayoutRect(node); + if (avoidTypes_.find(node->GetWindowType()) != avoidTypes_.end()) { + const DisplayId& displayId = node->GetDisplayId(); + Rect& primaryLimitRect = cascadeRectsMap_[displayId].primaryLimitRect_; + Rect& secondaryLimitRect = cascadeRectsMap_[displayId].secondaryLimitRect_; + UpdateLimitRect(node, limitRectMap_[displayId]); + UpdateSplitLimitRect(limitRectMap_[displayId], primaryLimitRect); + UpdateSplitLimitRect(limitRectMap_[displayId], secondaryLimitRect); + UpdateSplitRatioPoints(displayId); + UpdateDisplayGroupLimitRect(); + WLOGFD("priLimitRect: %{public}d %{public}d %{public}u %{public}u, " \ + "secLimitRect: %{public}d %{public}d %{public}u %{public}u", primaryLimitRect.posX_, + primaryLimitRect.posY_, primaryLimitRect.width_, primaryLimitRect.height_, secondaryLimitRect.posX_, + secondaryLimitRect.posY_, secondaryLimitRect.width_, secondaryLimitRect.height_); + } + } + for (auto& childNode : node->children_) { + LayoutWindowNode(childNode); + } +} + +void WindowLayoutPolicyCascade::LayoutWindowTree(DisplayId displayId) +{ + InitLimitRects(displayId); + WindowLayoutPolicy::LayoutWindowTree(displayId); +} + +void WindowLayoutPolicyCascade::RemoveWindowNode(const sptr& node) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + auto type = node->GetWindowType(); + // affect other windows, trigger off global layout + if (avoidTypes_.find(type) != avoidTypes_.end()) { + LayoutWindowTree(node->GetDisplayId()); + } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode + InitSplitRects(node->GetDisplayId()); + LayoutWindowTree(node->GetDisplayId()); + } + UpdateClientRect(node->GetRequestRect(), node, WindowSizeChangeReason::HIDE); +} + +std::vector WindowLayoutPolicyCascade::GetExitSplitPoints(DisplayId displayId) const +{ + return cascadeRectsMap_[displayId].exitSplitPoints_; +} + +bool WindowLayoutPolicyCascade::SpecialReasonProcess(const sptr& node, bool isAddWindow) const +{ + const DisplayId& displayId = node->GetDisplayId(); + if ((node->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) || + (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::RESIZE)) { + if ((node->GetRequestRect() == node->GetWindowRect()) && (!isAddWindow)) { + return false; + } + } + if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::ROTATION) { + const auto& windowNodeVecSptrs = displayGroupWindowTree_[displayId]; + for (const auto& windowNodeVecSptr : windowNodeVecSptrs) { + const auto& windowNodeVec = *(windowNodeVecSptr.second); + for (auto& childNode : windowNodeVec) { + childNode->SetWindowSizeChangeReason(WindowSizeChangeReason::ROTATION); + } + } + } + return true; +} + +void WindowLayoutPolicyCascade::UpdateWindowNode(const sptr& node, bool isAddWindow) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + auto type = node->GetWindowType(); + const DisplayId& displayId = node->GetDisplayId(); + UpdateWindowNodeRectOffset(node); + // affect other windows, trigger off global layout + if (avoidTypes_.find(type) != avoidTypes_.end()) { + bool ret = SpecialReasonProcess(node, isAddWindow); + if (ret != true) { + return; + } + LayoutWindowTree(displayId); + } else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode + UpdateLayoutRect(node); + auto splitDockerRect = node->GetWindowRect(); + SetSplitRect(splitDockerRect, displayId); // calculate primary/secondary depend on divider rect + WLOGFD("UpdateDividerRects WinId: %{public}u, Rect: %{public}d %{public}d %{public}u %{public}u", + node->GetWindowId(), splitDockerRect.posX_, splitDockerRect.posY_, + splitDockerRect.width_, splitDockerRect.height_); + if (!isAddWindow) { + const auto& appWindowNodeVec = *(displayGroupWindowTree_[displayId][WindowRootNodeType::APP_WINDOW_NODE]); + for (auto& childNode : appWindowNodeVec) { // update split node size change reason + if (childNode->IsSplitMode()) { + childNode->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG); + } + } + } + LayoutWindowTree(displayId); + } else if (node->IsSplitMode()) { + LayoutWindowTree(displayId); + } else { // layout single window + LayoutWindowNode(node); + } +} + +void WindowLayoutPolicyCascade::AddWindowNode(const sptr& node) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + auto property = node->GetWindowProperty(); + if (property == nullptr) { + WLOGFE("window property is nullptr."); + return; + } + + if (WindowHelper::IsEmptyRect(property->GetRequestRect())) { + SetCascadeRect(node); + } + UpdateWindowNodeRectOffset(node); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + node->SetRequestRect(cascadeRectsMap_[node->GetDisplayId()].dividerRect_); // init divider bar + DisplayId displayId = node->GetDisplayId(); + if (!WindowHelper::IsEmptyRect(restoringDividerWindowRects_[displayId])) { + node->SetRequestRect(restoringDividerWindowRects_[displayId]); + } + restoringDividerWindowRects_.erase(displayId); + } + UpdateWindowNode(node, true); // currently, update and add do the same process +} + +void WindowLayoutPolicyCascade::SetSplitDividerWindowRects(std::map dividerWindowRects) +{ + restoringDividerWindowRects_ = dividerWindowRects; +} + +void WindowLayoutPolicyCascade::LimitDividerMoveBounds(Rect& rect, DisplayId displayId) const +{ + const Rect& limitRect = limitRectMap_[displayId]; + if (rect.width_ < rect.height_) { + if (rect.posX_ < limitRect.posX_) { + rect.posX_ = limitRect.posX_; + } else if (rect.posX_ + static_cast(rect.width_) > + limitRect.posX_ + static_cast(limitRect.width_)) { + rect.posX_ = limitRect.posX_ + static_cast(limitRect.width_ - rect.width_); + } + } else { + if (rect.posY_ < limitRect.posY_) { + rect.posY_ = limitRect.posY_; + } else if (rect.posY_ + static_cast(rect.height_) > + limitRect.posY_ + static_cast(limitRect.height_)) { + rect.posY_ = limitRect.posY_ + static_cast(limitRect.height_ - rect.height_); + } + } + WLOGFD("limit divider move bounds:[%{public}d, %{public}d, %{public}u, %{public}u]", + rect.posX_, rect.posY_, rect.width_, rect.height_); +} + +void WindowLayoutPolicyCascade::InitCascadeRect(DisplayId displayId) +{ + constexpr uint32_t half = 2; + constexpr float ratio = DEFAULT_ASPECT_RATIO; + + /* + * Calculate default width and height, if width or height is + * smaller than minWidth or minHeight, use the minimum limits + */ + const auto& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + auto vpr = displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId); + uint32_t defaultW = std::max(static_cast(displayRect.width_ * ratio), + static_cast(MIN_FLOATING_WIDTH * vpr)); + uint32_t defaultH = std::max(static_cast(displayRect.height_ * ratio), + static_cast(MIN_FLOATING_HEIGHT * vpr)); + + // calculate default x and y + Rect resRect = {0, 0, defaultW, defaultH}; + const Rect& limitRect = limitRectMap_[displayId]; + if (defaultW <= limitRect.width_ && defaultH <= limitRect.height_) { + int32_t centerPosX = limitRect.posX_ + static_cast(limitRect.width_ / half); + resRect.posX_ = centerPosX - static_cast(defaultW / half); + + int32_t centerPosY = limitRect.posY_ + static_cast(limitRect.height_ / half); + resRect.posY_ = centerPosY - static_cast(defaultH / half); + } + WLOGFD("init CascadeRect :[%{public}d, %{public}d, %{public}d, %{public}d]", + resRect.posX_, resRect.posY_, resRect.width_, resRect.height_); + cascadeRectsMap_[displayId].firstCascadeRect_ = resRect; +} + +void WindowLayoutPolicyCascade::ApplyWindowRectConstraints(const sptr& node, Rect& winRect) const +{ + WLOGFD("Before apply constraints winRect:[%{public}d, %{public}d, %{public}u, %{public}u]", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + auto reason = node->GetWindowSizeChangeReason(); + DisplayId displayId = node->GetDisplayId(); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + // make sure the divider is entirely within display + LimitDividerMoveBounds(winRect, displayId); + if (reason == WindowSizeChangeReason::DRAG_END) { + if (!IsVerticalDisplay(displayId)) { + UpdateDockSlicePosition(displayId, winRect.posX_); + } else { + UpdateDockSlicePosition(displayId, winRect.posY_); + } + } + /* + * use the layout orientation of the window and the layout orientation of the screen + * to determine whether the screen is rotating + */ + if ((!WindowHelper::IsLandscapeRect(winRect) && IsVerticalDisplay(displayId)) || + (WindowHelper::IsLandscapeRect(winRect) && !IsVerticalDisplay(displayId))) { + // resets the rect of the divider window when the screen is rotating + WLOGFD("Reset divider when display rotate rect:[%{public}d, %{public}d, %{public}u, %{public}u]", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + winRect = cascadeRectsMap_[displayId].dividerRect_; + node->SetRequestRect(winRect); + } + } + LimitFloatingWindowSize(node, displayGroupInfo_->GetDisplayRect(node->GetDisplayId()), winRect); + LimitMainFloatingWindowPosition(node, winRect); + WLOGFD("After apply constraints winRect:[%{public}d, %{public}d, %{public}u, %{public}u]", + winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); +} + +void WindowLayoutPolicyCascade::UpdateLayoutRect(const sptr& node) +{ + auto type = node->GetWindowType(); + auto mode = node->GetWindowMode(); + auto property = node->GetWindowProperty(); + if (property == nullptr) { + WLOGFE("window property is nullptr."); + return; + } + UpdateWindowSizeLimits(node); + bool needAvoid = (node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + bool parentLimit = (node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT)); + bool subWindow = WindowHelper::IsSubWindow(type) || WindowHelper::IsSystemSubWindow(type); + bool floatingWindow = (mode == WindowMode::WINDOW_MODE_FLOATING); + const Rect lastWinRect = node->GetWindowRect(); + Rect displayRect = GetDisplayRect(mode, node->GetDisplayId()); + Rect limitRect = displayRect; + ComputeDecoratedRequestRect(node); + Rect winRect = property->GetRequestRect(); + + WLOGFD("Id:%{public}u, avoid:%{public}d parLimit:%{public}d floating:%{public}d, sub:%{public}d, " \ + "deco:%{public}d, type:%{public}d, requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]", + node->GetWindowId(), needAvoid, parentLimit, floatingWindow, subWindow, property->GetDecorEnable(), + static_cast(type), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + if (needAvoid) { + limitRect = GetLimitRect(mode, node->GetDisplayId()); + } + + if (!floatingWindow) { // fullscreen window + winRect = limitRect; + } else { // floating window + if (subWindow && parentLimit && node->parent_) { // subwindow and limited by parent + limitRect = node->parent_->GetWindowRect(); + UpdateFloatingLayoutRect(limitRect, winRect); + } + } + ApplyWindowRectConstraints(node, winRect); + node->SetWindowRect(winRect); + CalcAndSetNodeHotZone(winRect, node); + // update node bounds before reset reason + UpdateSurfaceBounds(node, winRect, lastWinRect); + UpdateClientRectAndResetReason(node, winRect); +} + +void WindowLayoutPolicyCascade::InitLimitRects(DisplayId displayId) +{ + limitRectMap_[displayId] = displayGroupInfo_->GetDisplayRect(displayId); + cascadeRectsMap_[displayId].primaryLimitRect_ = cascadeRectsMap_[displayId].primaryRect_; + cascadeRectsMap_[displayId].secondaryLimitRect_ = cascadeRectsMap_[displayId].secondaryRect_; + UpdateSplitRatioPoints(displayId); +} + +Rect WindowLayoutPolicyCascade::GetLimitRect(const WindowMode mode, DisplayId displayId) const +{ + if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + return cascadeRectsMap_[displayId].primaryLimitRect_; + } else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + return cascadeRectsMap_[displayId].secondaryLimitRect_; + } else { + return limitRectMap_[displayId]; + } +} + +Rect WindowLayoutPolicyCascade::GetDisplayRect(const WindowMode mode, DisplayId displayId) const +{ + if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + return cascadeRectsMap_[displayId].primaryRect_; + } else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + return cascadeRectsMap_[displayId].secondaryRect_; + } else { + return displayGroupInfo_->GetDisplayRect(displayId); + } +} + +void WindowLayoutPolicyCascade::UpdateSplitRatioPoints(DisplayId displayId) +{ + LayoutRects& cascadeRects = cascadeRectsMap_[displayId]; + cascadeRects.exitSplitPoints_.clear(); + cascadeRects.splitRatioPoints_.clear(); + cascadeRects.exitSplitPoints_.push_back(GetSplitRatioPoint(splitRatioConfig_.exitSplitStartRatio, displayId)); + cascadeRects.exitSplitPoints_.push_back(GetSplitRatioPoint(splitRatioConfig_.exitSplitEndRatio, displayId)); + for (const auto& ratio : splitRatioConfig_.splitRatios) { + cascadeRects.splitRatioPoints_.push_back(GetSplitRatioPoint(ratio, displayId)); + } +} + +void WindowLayoutPolicyCascade::UpdateDockSlicePosition(DisplayId displayId, int32_t& origin) const +{ + const LayoutRects& cascadeRects = cascadeRectsMap_[displayId]; + if (cascadeRects.splitRatioPoints_.size() == 0) { + return; + } + uint32_t minDiff = std::max(limitRectMap_[displayId].width_, limitRectMap_[displayId].height_); + int32_t closestPoint = origin; + for (const auto& elem : cascadeRects.splitRatioPoints_) { + uint32_t diff = (origin > elem) ? static_cast(origin - elem) : static_cast(elem - origin); + if (diff < minDiff) { + closestPoint = elem; + minDiff = diff; + } + } + origin = closestPoint; +} + +void WindowLayoutPolicyCascade::UpdateSplitLimitRect(const Rect& limitRect, Rect& limitSplitRect) +{ + Rect curLimitRect = limitSplitRect; + limitSplitRect.posX_ = std::max(limitRect.posX_, curLimitRect.posX_); + limitSplitRect.posY_ = std::max(limitRect.posY_, curLimitRect.posY_); + limitSplitRect.width_ = std::min(limitRect.posX_ + limitRect.width_, + curLimitRect.posX_ + curLimitRect.width_) - + limitSplitRect.posX_; + limitSplitRect.height_ = std::min(limitRect.posY_ + limitRect.height_, + curLimitRect.posY_ + curLimitRect.height_) - + limitSplitRect.posY_; +} + +void WindowLayoutPolicyCascade::InitSplitRects(DisplayId displayId) +{ + float virtualPixelRatio = GetVirtualPixelRatio(displayId); + uint32_t dividerWidth = static_cast(DIVIDER_WIDTH * virtualPixelRatio); + auto& dividerRect = cascadeRectsMap_[displayId].dividerRect_; + const auto& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + if (!IsVerticalDisplay(displayId)) { + dividerRect = { static_cast((displayRect.width_ - dividerWidth) * DEFAULT_SPLIT_RATIO), 0, + dividerWidth, displayRect.height_ }; + } else { + dividerRect = { 0, static_cast((displayRect.height_ - dividerWidth) * DEFAULT_SPLIT_RATIO), + displayRect.width_, dividerWidth }; + } + WLOGFD("init dividerRect :[%{public}d, %{public}d, %{public}u, %{public}u]", + dividerRect.posX_, dividerRect.posY_, dividerRect.width_, dividerRect.height_); + SetSplitRect(dividerRect, displayId); +} + +int32_t WindowLayoutPolicyCascade::GetSplitRatioPoint(float ratio, DisplayId displayId) +{ + auto dividerRect = cascadeRectsMap_[displayId].dividerRect_; + auto displayRect = displayGroupInfo_->GetDisplayRect(displayId); + if (!IsVerticalDisplay(displayId)) { + return displayRect.posX_ + + static_cast((displayRect.width_ - dividerRect.width_) * ratio); + } else { + return displayRect.posY_ + + static_cast((displayRect.height_ - dividerRect.height_) * ratio); + } +} + +void WindowLayoutPolicyCascade::SetSplitRect(const Rect& divRect, DisplayId displayId) +{ + auto& dividerRect = cascadeRectsMap_[displayId].dividerRect_; + auto& primaryRect = cascadeRectsMap_[displayId].primaryRect_; + auto& secondaryRect = cascadeRectsMap_[displayId].secondaryRect_; + const auto& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + + dividerRect.width_ = divRect.width_; + dividerRect.height_ = divRect.height_; + if (!IsVerticalDisplay(displayId)) { + primaryRect.posX_ = displayRect.posX_; + primaryRect.posY_ = displayRect.posY_; + primaryRect.width_ = divRect.posX_; + primaryRect.height_ = displayRect.height_; + + secondaryRect.posX_ = divRect.posX_ + static_cast(dividerRect.width_); + secondaryRect.posY_ = displayRect.posY_; + secondaryRect.width_ = static_cast(static_cast(displayRect.width_) - secondaryRect.posX_); + secondaryRect.height_ = displayRect.height_; + } else { + primaryRect.posX_ = displayRect.posX_; + primaryRect.posY_ = displayRect.posY_; + primaryRect.height_ = divRect.posY_; + primaryRect.width_ = displayRect.width_; + + secondaryRect.posX_ = displayRect.posX_; + secondaryRect.posY_ = divRect.posY_ + static_cast(dividerRect.height_); + secondaryRect.height_ = static_cast(static_cast(displayRect.height_) - secondaryRect.posY_); + secondaryRect.width_ = displayRect.width_; + } +} + +void WindowLayoutPolicyCascade::Reorder() +{ + WLOGFD("Cascade reorder start"); + for (const auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + DisplayId displayId = iter.first; + Rect rect = cascadeRectsMap_[displayId].firstCascadeRect_; + bool isFirstReorderedWindow = true; + const auto& appWindowNodeVec = *(displayGroupWindowTree_[displayId][WindowRootNodeType::APP_WINDOW_NODE]); + for (auto nodeIter = appWindowNodeVec.begin(); nodeIter != appWindowNodeVec.end(); nodeIter++) { + auto node = *nodeIter; + if (node == nullptr || node->GetWindowType() != WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { + WLOGFD("get node failed or not app window."); + continue; + } + // if window don't support floating mode, or default rect of cascade is not satisfied with limits + if (!WindowHelper::IsWindowModeSupported(node->GetModeSupportInfo(), WindowMode::WINDOW_MODE_FLOATING) || + !WindowHelper::IsRectSatisfiedWithSizeLimits(rect, node->GetWindowUpdatedSizeLimits())) { + MinimizeApp::AddNeedMinimizeApp(node, MinimizeReason::LAYOUT_CASCADE); + continue; + } + if (isFirstReorderedWindow) { + isFirstReorderedWindow = false; + } else { + rect = StepCascadeRect(rect, displayId); + } + node->SetRequestRect(rect); + node->SetDecoStatus(true); + if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) { + node->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + if (node->GetWindowToken()) { + node->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); + } + } + WLOGFD("Cascade reorder Id: %{public}d, rect:[%{public}d, %{public}d, %{public}d, %{public}d]", + node->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); + } + LayoutWindowTree(displayId); + } + WLOGFD("Reorder end"); +} + +Rect WindowLayoutPolicyCascade::GetCurCascadeRect(const sptr& node) const +{ + Rect cascadeRect = {0, 0, 0, 0}; + const DisplayId& displayId = node->GetDisplayId(); + const auto& appWindowNodeVec = *(const_cast(this)-> + displayGroupWindowTree_[displayId][WindowRootNodeType::APP_WINDOW_NODE]); + const auto& aboveAppWindowNodeVec = *(const_cast(this)-> + displayGroupWindowTree_[displayId][WindowRootNodeType::ABOVE_WINDOW_NODE]); + + std::vector>> roots = { aboveAppWindowNodeVec, appWindowNodeVec }; + for (auto& root : roots) { + for (auto iter = root.rbegin(); iter != root.rend(); iter++) { + if ((*iter)->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && + (*iter)->GetWindowId() != node->GetWindowId()) { + auto property = (*iter)->GetWindowProperty(); + if (property != nullptr) { + cascadeRect = ((*iter)->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING ? + property->GetWindowRect() : property->GetRequestRect()); + } + WLOGFD("Get current cascadeRect: %{public}u [%{public}d, %{public}d, %{public}u, %{public}u]", + (*iter)->GetWindowId(), cascadeRect.posX_, cascadeRect.posY_, + cascadeRect.width_, cascadeRect.height_); + break; + } + } + } + + if (WindowHelper::IsEmptyRect(cascadeRect)) { + WLOGFD("cascade rect is empty use first cascade rect"); + return cascadeRectsMap_[displayId].firstCascadeRect_; + } + return StepCascadeRect(cascadeRect, displayId); +} + +Rect WindowLayoutPolicyCascade::StepCascadeRect(Rect rect, DisplayId displayId) const +{ + float virtualPixelRatio = GetVirtualPixelRatio(displayId); + uint32_t cascadeWidth = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + uint32_t cascadeHeight = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + + const Rect& limitRect = limitRectMap_[displayId]; + Rect cascadeRect = {0, 0, 0, 0}; + cascadeRect.width_ = rect.width_; + cascadeRect.height_ = rect.height_; + cascadeRect.posX_ = (rect.posX_ + static_cast(cascadeWidth) >= limitRect.posX_) && + (rect.posX_ + static_cast(rect.width_ + cascadeWidth) <= + (limitRect.posX_ + static_cast(limitRect.width_))) ? + (rect.posX_ + static_cast(cascadeWidth)) : limitRect.posX_; + cascadeRect.posY_ = (rect.posY_ + static_cast(cascadeHeight) >= limitRect.posY_) && + (rect.posY_ + static_cast(rect.height_ + cascadeHeight) <= + (limitRect.posY_ + static_cast(limitRect.height_))) ? + (rect.posY_ + static_cast(cascadeHeight)) : limitRect.posY_; + WLOGFD("step cascadeRect :[%{public}d, %{public}d, %{public}u, %{public}u]", + cascadeRect.posX_, cascadeRect.posY_, cascadeRect.width_, cascadeRect.height_); + return cascadeRect; +} + +void WindowLayoutPolicyCascade::SetCascadeRect(const sptr& node) +{ + static bool isFirstAppWindow = true; + Rect rect; + auto property = node->GetWindowProperty(); + if (property == nullptr) { + WLOGFE("window property is nullptr."); + return; + } + if (WindowHelper::IsAppWindow(property->GetWindowType()) && isFirstAppWindow) { + WLOGFD("set first app window cascade rect"); + rect = cascadeRectsMap_[node->GetDisplayId()].firstCascadeRect_; + isFirstAppWindow = false; + } else if (WindowHelper::IsAppWindow(property->GetWindowType()) && !isFirstAppWindow) { + WLOGFD("set other app window cascade rect"); + rect = GetCurCascadeRect(node); + } else { + // system window + WLOGFD("set system window cascade rect"); + rect = cascadeRectsMap_[node->GetDisplayId()].firstCascadeRect_; + } + WLOGFD("set cascadeRect :[%{public}d, %{public}d, %{public}u, %{public}u]", + rect.posX_, rect.posY_, rect.width_, rect.height_); + node->SetRequestRect(rect); + node->SetDecoStatus(true); +} +Rect WindowLayoutPolicyCascade::GetDividerRect(DisplayId displayId) const +{ + Rect dividerRect = {0, 0, 0, 0}; + if (cascadeRectsMap_.find(displayId) != std::end(cascadeRectsMap_)) { + dividerRect = cascadeRectsMap_[displayId].dividerRect_; + } + return dividerRect; +} + +void WindowLayoutPolicyCascade::UpdateWindowNodeRectOffset(const sptr& node) const +{ + WLOGFD("UpdateWindowNodeRectOffset, windowId: %{public}u", node->GetWindowId()); + auto displayId = node->GetDisplayId(); + const Rect& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + auto displayInfo = displayGroupInfo_->GetDisplayInfo(displayId); + auto type = node->GetWindowType(); + Rect rect = node->GetRequestRect(); + WLOGFD("RequestRect before, width: %{public}u, height: %{public}u, posX:%{public}d, posY:%{public}d", + rect.width_, rect.height_, rect.posX_, rect.posY_); + switch (type) { + case WindowType::WINDOW_TYPE_STATUS_BAR: { + rect.posY_ = displayRect.posY_; + break; + } + case WindowType::WINDOW_TYPE_NAVIGATION_BAR: { + rect.posY_ = static_cast(displayRect.height_) + displayRect.posY_ - + static_cast(rect.height_); + break; + } + default: { + if (displayInfo->GetWaterfallDisplayCompressionStatus()) { + if (rect.posY_ < displayRect.posY_) { + rect.posY_ = displayRect.posY_; + } else if (rect.posY_ > displayRect.posY_ + static_cast(displayRect.height_)) { + rect.posY_ = displayRect.posY_ + static_cast(displayRect.height_); + } + } + } + } + node->SetRequestRect(rect); + WLOGFD("RequestRect after, width: %{public}u, height: %{public}u, posX:%{public}d, posY:%{public}d", + rect.width_, rect.height_, rect.posX_, rect.posY_); +} + +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/window_layout_policy_tile.cpp b/window_manager/wmserver/src/window_layout_policy_tile.cpp new file mode 100644 index 0000000..b580f86 --- /dev/null +++ b/window_manager/wmserver/src/window_layout_policy_tile.cpp @@ -0,0 +1,374 @@ +/* + * 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 "window_layout_policy_tile.h" +#include +#include + +#include "minimize_app.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowLayoutPolicyTile"}; + constexpr uint32_t EDGE_INTERVAL = 48; + constexpr uint32_t MID_INTERVAL = 24; +} + +WindowLayoutPolicyTile::WindowLayoutPolicyTile(const sptr& displayGroupInfo, + DisplayGroupWindowTree& displayGroupWindowTree) + : WindowLayoutPolicy(displayGroupInfo, displayGroupWindowTree) +{ + for (auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + maxTileWinNumMap_.insert(std::make_pair(iter.first, static_cast(1))); + } +} + +void WindowLayoutPolicyTile::Launch() +{ + // compute limit rect + InitAllRects(); + // select app min win in queue, and minimize others + InitForegroundNodeQueue(); + for (const auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + DisplayId displayId = iter.first; + AssignNodePropertyForTileWindows(displayId); + LayoutForegroundNodeQueue(displayId); + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::BELOW_WINDOW_NODE])); + } + WLOGFI("WindowLayoutPolicyTile::Launch"); +} + +void WindowLayoutPolicyTile::InitAllRects() +{ + displayGroupLimitRect_ = displayGroupRect_; + for (const auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + DisplayId displayId = iter.first; + limitRectMap_[displayId] = iter.second; + auto& displayWindowTree = displayGroupWindowTree_[displayId]; + LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE])); + InitTileWindowRects(displayId); + } +} + +uint32_t WindowLayoutPolicyTile::GetMaxTileWinNum(DisplayId displayId) const +{ + float virtualPixelRatio = GetVirtualPixelRatio(displayId); + constexpr uint32_t half = 2; + uint32_t edgeIntervalVp = static_cast(EDGE_INTERVAL * half * virtualPixelRatio); + uint32_t midIntervalVp = static_cast(MID_INTERVAL * virtualPixelRatio); + uint32_t minFloatingW = static_cast(MIN_FLOATING_WIDTH * virtualPixelRatio); + uint32_t drawableW = limitRectMap_[displayId].width_ - edgeIntervalVp + midIntervalVp; + return static_cast(drawableW / (minFloatingW + midIntervalVp)); +} + +void WindowLayoutPolicyTile::InitTileWindowRects(DisplayId displayId) +{ + float virtualPixelRatio = GetVirtualPixelRatio(displayId); + uint32_t edgeIntervalVp = static_cast(EDGE_INTERVAL * virtualPixelRatio); + uint32_t midIntervalVp = static_cast(MID_INTERVAL * virtualPixelRatio); + + constexpr float ratio = DEFAULT_ASPECT_RATIO; + const Rect& limitRect = limitRectMap_[displayId]; + const Rect& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + constexpr int half = 2; + maxTileWinNumMap_[displayId] = GetMaxTileWinNum(displayId); + WLOGFI("set max tile window num %{public}u", maxTileWinNumMap_[displayId]); + auto& presetRects = presetRectsMap_[displayId]; + presetRects.clear(); + uint32_t w = displayRect.width_ * ratio; + uint32_t h = displayRect.height_ * ratio; + w = w > limitRect.width_ ? limitRect.width_ : w; + h = h > limitRect.height_ ? limitRect.height_ : h; + int x = limitRect.posX_ + ((limitRect.width_ - w) / half); + int y = limitRect.posY_ + ((limitRect.height_ - h) / half); + + std::vector single = {{ x, y, w, h }}; + presetRects.emplace_back(single); + for (uint32_t num = 2; num <= maxTileWinNumMap_[displayId]; num++) { // start calc preset with 2 windows + w = (limitRect.width_ - edgeIntervalVp * half - midIntervalVp * (num - 1)) / num; + std::vector curLevel; + for (uint32_t i = 0; i < num; i++) { + int curX = limitRect.posX_ + edgeIntervalVp + i * (w + midIntervalVp); + Rect curRect = { curX, y, w, h }; + WLOGFI("presetRects: level %{public}u, id %{public}u, [%{public}d %{public}d %{public}u %{public}u]", + num, i, curX, y, w, h); + curLevel.emplace_back(curRect); + } + presetRects.emplace_back(curLevel); + } +} + +bool WindowLayoutPolicyTile::IsTileRectSatisfiedWithSizeLimits(const sptr& node) +{ + if (!WindowHelper::IsMainWindow(node->GetWindowType())) { + return true; + } + const auto& displayId = node->GetDisplayId(); + auto& foregroundNodes = foregroundNodesMap_[displayId]; + auto num = foregroundNodes.size(); + if (num > maxTileWinNumMap_[displayId] || maxTileWinNumMap_[displayId] == 0) { + return false; + } + + UpdateWindowSizeLimits(node); + + // find if node already exits in foreground nodes map + auto iter = std::find_if(foregroundNodes.begin(), foregroundNodes.end(), + [node](sptr foregroundNode) { + return foregroundNode->GetWindowId() == node->GetWindowId(); + }); + if (iter != foregroundNodes.end()) { + return true; + } + + const auto& presetRects = presetRectsMap_[displayId]; + Rect tileRect; + // if size of foreground nodes is equal to or more than max tile window number + if (num == maxTileWinNumMap_[displayId]) { + tileRect = *(presetRects[num - 1].begin()); + } else { // if size of foreground nodes is less than max tile window number + tileRect = *(presetRects[num].begin()); + } + WLOGFI("id %{public}u, tileRect: [%{public}d %{public}d %{public}u %{public}u]", + node->GetWindowId(), tileRect.posX_, tileRect.posY_, tileRect.width_, tileRect.height_); + return WindowHelper::IsRectSatisfiedWithSizeLimits(tileRect, node->GetWindowUpdatedSizeLimits()); +} + +void WindowLayoutPolicyTile::AddWindowNode(const sptr& node) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + DisplayId displayId = node->GetDisplayId(); + ForegroundNodeQueuePushBack(node, displayId); + AssignNodePropertyForTileWindows(displayId); + LayoutForegroundNodeQueue(displayId); + } else { + UpdateWindowNode(node); // currently, update and add do the same process + } +} + +void WindowLayoutPolicyTile::UpdateWindowNode(const sptr& node, bool isAddWindow) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + WindowLayoutPolicy::UpdateWindowNode(node); + if (avoidTypes_.find(node->GetWindowType()) != avoidTypes_.end()) { + DisplayId displayId = node->GetDisplayId(); + InitTileWindowRects(displayId); + AssignNodePropertyForTileWindows(displayId); + LayoutForegroundNodeQueue(displayId); + } +} + +void WindowLayoutPolicyTile::RemoveWindowNode(const sptr& node) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + WLOGFI("RemoveWindowNode %{public}u in tile", node->GetWindowId()); + auto type = node->GetWindowType(); + auto displayId = node->GetDisplayId(); + // affect other windows, trigger off global layout + if (avoidTypes_.find(type) != avoidTypes_.end()) { + LayoutWindowTree(displayId); + } else { + ForegroundNodeQueueRemove(node); + AssignNodePropertyForTileWindows(displayId); + LayoutForegroundNodeQueue(displayId); + } + UpdateClientRect(node->GetRequestRect(), node, WindowSizeChangeReason::HIDE); +} + +void WindowLayoutPolicyTile::LayoutForegroundNodeQueue(DisplayId displayId) +{ + for (auto& node : foregroundNodesMap_[displayId]) { + Rect winRect = node->GetRequestRect(); + Rect lastRect = node->GetWindowRect(); + node->SetWindowRect(winRect); + CalcAndSetNodeHotZone(winRect, node); + UpdateClientRect(winRect, node, node->GetWindowSizeChangeReason()); + UpdateSurfaceBounds(node, winRect, lastRect); + for (auto& childNode : node->children_) { + LayoutWindowNode(childNode); + } + } +} + +void WindowLayoutPolicyTile::InitForegroundNodeQueue() +{ + for (const auto& iter : displayGroupInfo_->GetAllDisplayRects()) { + DisplayId displayId = iter.first; + foregroundNodesMap_[displayId].clear(); + const auto& appWindowNodes = *(displayGroupWindowTree_[displayId][WindowRootNodeType::APP_WINDOW_NODE]); + for (auto& node : appWindowNodes) { + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + ForegroundNodeQueuePushBack(node, displayId); + } + } + } +} + +void WindowLayoutPolicyTile::ForegroundNodeQueuePushBack(const sptr& node, DisplayId displayId) +{ + if (node == nullptr) { + return; + } + auto& foregroundNodes = foregroundNodesMap_[displayId]; + auto iter = std::find_if(foregroundNodes.begin(), foregroundNodes.end(), + [node](sptr foregroundNode) { + return foregroundNode->GetWindowId() == node->GetWindowId(); + }); + if (iter != foregroundNodes.end()) { + return; + } + + if (!WindowHelper::IsWindowModeSupported(node->GetModeSupportInfo(), WindowMode::WINDOW_MODE_FLOATING)) { + WLOGFD("window don't support tile mode, winId: %{public}d", node->GetWindowId()); + MinimizeApp::AddNeedMinimizeApp(node, MinimizeReason::LAYOUT_TILE); + return; + } + WLOGFI("add win in tile, displayId: %{public}" PRIu64", winId: %{public}d", displayId, node->GetWindowId()); + while (!foregroundNodes.empty() && foregroundNodes.size() >= maxTileWinNumMap_[displayId]) { + auto removeNode = foregroundNodes.front(); + foregroundNodes.pop_front(); + WLOGFI("pop win in queue head for add new win, windowId: %{public}d", removeNode->GetWindowId()); + MinimizeApp::AddNeedMinimizeApp(removeNode, MinimizeReason::LAYOUT_TILE); + } + foregroundNodes.push_back(node); +} + +void WindowLayoutPolicyTile::ForegroundNodeQueueRemove(const sptr& node) +{ + if (node == nullptr) { + return; + } + DisplayId displayId = node->GetDisplayId(); + auto& foregroundNodes = foregroundNodesMap_[displayId]; + 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); + } +} + +void WindowLayoutPolicyTile::AssignNodePropertyForTileWindows(DisplayId displayId) +{ + // set rect for foreground windows + auto& foregroundNodes = foregroundNodesMap_[displayId]; + uint32_t num = foregroundNodes.size(); + auto& presetRects = presetRectsMap_[displayId]; + if (num > maxTileWinNumMap_[displayId] || num > presetRects.size() || num == 0) { + WLOGE("invalid tile queue"); + return; + } + std::vector& presetRect = presetRects[num - 1]; + if (presetRect.size() != num) { + WLOGE("invalid preset rects"); + return; + } + auto rectIt = presetRect.begin(); + std::vector> needMinimizeNodes; + std::vector> needRecoverNodes; + for (auto node : foregroundNodes) { + auto& rect = (*rectIt); + if (WindowHelper::IsWindowModeSupported(node->GetModeSupportInfo(), WindowMode::WINDOW_MODE_FLOATING) && + WindowHelper::IsRectSatisfiedWithSizeLimits(rect, node->GetWindowUpdatedSizeLimits())) { + node->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + if (node->GetWindowToken()) { + node->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); + } + node->SetRequestRect(rect); + node->SetDecoStatus(true); + WLOGFI("set rect for qwin id: %{public}d [%{public}d %{public}d %{public}d %{public}d]", + node->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); + rectIt++; + } else { + // if foreground nodes is equal to max tileWinNum, means need recover one node before minimize cur node + if (num == maxTileWinNumMap_[displayId]) { + auto recoverNode = MinimizeApp::GetRecoverdNodeFromMinimizeList(); + if (recoverNode != nullptr) { + needRecoverNodes.push_back(recoverNode); + } + } + needMinimizeNodes.push_back(node); + MinimizeApp::AddNeedMinimizeApp(node, MinimizeReason::LAYOUT_TILE); + } + } + for (auto& miniNode : needMinimizeNodes) { + auto iter = std::find(foregroundNodes.begin(), foregroundNodes.end(), miniNode); + if (iter != foregroundNodes.end()) { + foregroundNodes.erase(iter); + } + } + needMinimizeNodes.clear(); + + for (auto& recNode : needRecoverNodes) { + foregroundNodes.push_back(recNode); + } + needRecoverNodes.clear(); +} + +void WindowLayoutPolicyTile::UpdateLayoutRect(const sptr& node) +{ + auto type = node->GetWindowType(); + auto mode = node->GetWindowMode(); + auto flags = node->GetWindowFlags(); + auto property = node->GetWindowProperty(); + if (property == nullptr) { + WLOGFE("window property is nullptr."); + return; + } + UpdateWindowSizeLimits(node); + auto decorEnable = property->GetDecorEnable(); + bool needAvoid = (flags & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + bool parentLimit = (flags & static_cast(WindowFlag::WINDOW_FLAG_PARENT_LIMIT)); + bool subWindow = WindowHelper::IsSubWindow(type) || WindowHelper::IsSystemSubWindow(type); + bool floatingWindow = (mode == WindowMode::WINDOW_MODE_FLOATING); + const Rect lastRect = node->GetWindowRect(); + Rect limitRect = displayGroupInfo_->GetDisplayRect(node->GetDisplayId()); + ComputeDecoratedRequestRect(node); + Rect winRect = node->GetRequestRect(); + + WLOGFI("Id:%{public}u, avoid:%{public}d parLimit:%{public}d floating:%{public}d, sub:%{public}d, " \ + "deco:%{public}d, type:%{public}u, requestRect:[%{public}d, %{public}d, %{public}u, %{public}u]", + node->GetWindowId(), needAvoid, parentLimit, floatingWindow, subWindow, decorEnable, + static_cast(type), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + if (needAvoid) { + limitRect = limitRectMap_[node->GetDisplayId()]; + } + + if (!floatingWindow) { // fullscreen window + winRect = limitRect; + } else { // floating window + if (subWindow && parentLimit && node->parent_) { // subwindow and limited by parent + limitRect = node->parent_->GetWindowRect(); + UpdateFloatingLayoutRect(limitRect, winRect); + } + } + + LimitFloatingWindowSize(node, displayGroupInfo_->GetDisplayRect(node->GetDisplayId()), winRect); + LimitMainFloatingWindowPosition(node, winRect); + + node->SetWindowRect(winRect); + CalcAndSetNodeHotZone(winRect, node); + // update Node Bounds before reset Reason + UpdateSurfaceBounds(node, winRect, lastRect); + UpdateClientRectAndResetReason(node, winRect); +} +} // Rosen +} // OHOS diff --git a/window_manager/wmserver/src/window_manager_agent_controller.cpp b/window_manager/wmserver/src/window_manager_agent_controller.cpp new file mode 100644 index 0000000..58d56de --- /dev/null +++ b/window_manager/wmserver/src/window_manager_agent_controller.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-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 "window_manager_agent_controller.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerAgentController"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(WindowManagerAgentController) + +bool WindowManagerAgentController::RegisterWindowManagerAgent(const sptr& windowManagerAgent, + WindowManagerAgentType type) +{ + return wmAgentContainer_.RegisterAgent(windowManagerAgent, type); +} + +bool WindowManagerAgentController::UnregisterWindowManagerAgent(const sptr& windowManagerAgent, + WindowManagerAgentType type) +{ + return wmAgentContainer_.UnregisterAgent(windowManagerAgent, type); +} + +void WindowManagerAgentController::UpdateFocusChangeInfo(const sptr& focusChangeInfo, bool focused) +{ + for (auto& agent : wmAgentContainer_.GetAgentsByType(WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_FOCUS)) { + agent->UpdateFocusChangeInfo(focusChangeInfo, focused); + } +} + +void WindowManagerAgentController::UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) +{ + WLOGFD("tints size: %{public}u", static_cast(tints.size())); + if (tints.empty()) { + return; + } + for (auto& agent : wmAgentContainer_.GetAgentsByType( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR)) { + agent->UpdateSystemBarRegionTints(displayId, tints); + } +} + +void WindowManagerAgentController::NotifyAccessibilityWindowInfo( + const std::vector>& infos, WindowUpdateType type) +{ + WLOGFD("NotifyAccessibilityWindowInfo"); + for (auto& agent : wmAgentContainer_.GetAgentsByType( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_UPDATE)) { + agent->NotifyAccessibilityWindowInfo(infos, 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); + } +} + +void WindowManagerAgentController::UpdateCameraFloatWindowStatus(uint32_t accessTokenId, bool isShowing) +{ + for (auto& agent : wmAgentContainer_.GetAgentsByType( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT)) { + agent->UpdateCameraFloatWindowStatus(accessTokenId, isShowing); + } +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/window_manager_config.cpp b/window_manager/wmserver/src/window_manager_config.cpp new file mode 100644 index 0000000..e004dc4 --- /dev/null +++ b/window_manager/wmserver/src/window_manager_config.cpp @@ -0,0 +1,292 @@ +/* + * 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 "window_manager_config.h" +#include "config_policy_utils.h" +#include "window_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerConfig"}; +} + +WindowManagerConfig::ConfigItem WindowManagerConfig::config_; +const std::map WindowManagerConfig::configItemTypeMap_ = { + { "maxAppWindowNumber", WindowManagerConfig::ValueType::INTS }, + { "maxUniRenderAppWindowNumber", WindowManagerConfig::ValueType::INTS }, + { "modeChangeHotZones", WindowManagerConfig::ValueType::INTS }, + { "duration", WindowManagerConfig::ValueType::INTS }, + { "durationIn", WindowManagerConfig::ValueType::INTS }, + { "durationOut", WindowManagerConfig::ValueType::INTS }, + { "defaultWindowMode", WindowManagerConfig::ValueType::INTS }, + { "floatingBottomPosY", WindowManagerConfig::ValueType::INTS }, + { "defaultFloatingWindow", WindowManagerConfig::ValueType::INTS }, + { "windowAnimation", WindowManagerConfig::ValueType::MAP }, + { "keyboardAnimation", WindowManagerConfig::ValueType::MAP }, + { "timing", WindowManagerConfig::ValueType::MAP }, + { "windowEffect", WindowManagerConfig::ValueType::MAP }, + { "appWindows", WindowManagerConfig::ValueType::MAP }, + { "cornerRadius", WindowManagerConfig::ValueType::MAP }, + { "shadow", WindowManagerConfig::ValueType::MAP }, + { "focused", WindowManagerConfig::ValueType::MAP }, + { "unfocused", WindowManagerConfig::ValueType::MAP }, + { "curve", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "splitRatios", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "exitSplitRatios", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "scale", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "opacity", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "elevation", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "alpha", WindowManagerConfig::ValueType::POSITIVE_FLOATS }, + { "rotation", WindowManagerConfig::ValueType::FLOATS }, + { "translate", WindowManagerConfig::ValueType::FLOATS }, + { "offsetX", WindowManagerConfig::ValueType::FLOATS }, + { "offsetY", WindowManagerConfig::ValueType::FLOATS }, + { "fullScreen", WindowManagerConfig::ValueType::STRING }, + { "split", WindowManagerConfig::ValueType::STRING }, + { "float", WindowManagerConfig::ValueType::STRING }, + { "color", WindowManagerConfig::ValueType::STRING }, + { "decor", WindowManagerConfig::ValueType::UNDIFINED }, + { "minimizeByOther", WindowManagerConfig::ValueType::UNDIFINED }, + { "stretchable", WindowManagerConfig::ValueType::UNDIFINED }, + { "remoteAnimation", WindowManagerConfig::ValueType::UNDIFINED }, +}; + +std::vector WindowManagerConfig::ReadNumberStrings(const xmlNodePtr& node) +{ + xmlChar* context = xmlNodeGetContent(node); + if (context == nullptr) { + WLOGFE("[WmConfig] read xml node error: nodeName:(%{public}s)", node->name); + return std::vector(); + } + + std::string numbersStr = reinterpret_cast(context); + xmlFree(context); + if (numbersStr.size() == 0) { + return std::vector(); + } + return WindowHelper::Split(numbersStr, " "); +} + +std::string WindowManagerConfig::GetConfigPath(const std::string& configFileName) +{ + char buf[PATH_MAX + 1]; + char* configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1); + char tmpPath[PATH_MAX + 1] = { 0 }; + if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) { + WLOGFI("[WmConfig] can not get customization config file"); + return "/system/" + configFileName; + } + return std::string(tmpPath); +} + +void WindowManagerConfig::ReadConfig(const xmlNodePtr& rootPtr, std::map& mapValue) +{ + for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { + if (!IsValidNode(*curNodePtr)) { + WLOGFE("[WmConfig]: invalid node!"); + continue; + } + std::string nodeName = reinterpret_cast(curNodePtr->name); + if (configItemTypeMap_.count(nodeName)) { + std::map p; + ReadProperty(curNodePtr, p); + if (p.size() > 0) { + mapValue[reinterpret_cast(curNodePtr->name)].SetProperty(p); + } + switch (configItemTypeMap_.at(nodeName)) { + case ValueType::INTS: { + std::vector v; + ReadIntNumbersConfigInfo(curNodePtr, v); + mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); + break; + } + case ValueType::POSITIVE_FLOATS: { + std::vector v; + ReadFloatNumbersConfigInfo(curNodePtr, v, false); + mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); + break; + } + case ValueType::FLOATS: { + std::vector v; + ReadFloatNumbersConfigInfo(curNodePtr, v, true); + mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); + break; + } + case ValueType::MAP: { + std::map v; + ReadConfig(curNodePtr, v); + mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); + break; + } + case ValueType::STRING: { + std::string v; + ReadStringConfigInfo(curNodePtr, v); + mapValue[reinterpret_cast(curNodePtr->name)].SetValue(v); + break; + } + default: + break; + } + } + } +} + +bool WindowManagerConfig::LoadConfigXml() +{ + auto configFilePath = GetConfigPath("etc/window/resources/window_manager_config.xml"); + xmlDocPtr docPtr = nullptr; + { + std::lock_guard lock(mutex_); + docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS); + } + WLOGFI("[WmConfig] filePath: %{public}s", configFilePath.c_str()); + if (docPtr == nullptr) { + WLOGFE("[WmConfig] load xml error!"); + return false; + } + + xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); + if (rootPtr == nullptr || rootPtr->name == nullptr || + xmlStrcmp(rootPtr->name, reinterpret_cast("Configs"))) { + WLOGFE("[WmConfig] get root element failed!"); + xmlFreeDoc(docPtr); + return false; + } + + std::map configMap; + config_.SetValue(configMap); + ReadConfig(rootPtr, *config_.mapValue_); + + xmlFreeDoc(docPtr); + return true; +} + +bool WindowManagerConfig::IsValidNode(const xmlNode& currNode) +{ + if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) { + return false; + } + return true; +} + +void WindowManagerConfig::ReadProperty(const xmlNodePtr& currNode, + std::map& property) +{ + xmlChar* prop = xmlGetProp(currNode, reinterpret_cast("enable")); + if (prop != nullptr) { + if (!xmlStrcmp(prop, reinterpret_cast("true"))) { + property["enable"].SetValue(true); + } else if (!xmlStrcmp(prop, reinterpret_cast("false"))) { + property["enable"].SetValue(false); + } + xmlFree(prop); + } + + prop = xmlGetProp(currNode, reinterpret_cast("name")); + if (prop != nullptr) { + property["name"].SetValue(std::string(reinterpret_cast(prop))); + xmlFree(prop); + } +} + +void WindowManagerConfig::ReadIntNumbersConfigInfo(const xmlNodePtr& currNode, std::vector& intsValue) +{ + auto numbers = ReadNumberStrings(currNode); + for (auto& num : numbers) { + if (!WindowHelper::IsNumber(num)) { + WLOGFE("[WmConfig] read int number error: nodeName:(%{public}s)", currNode->name); + return; + } + intsValue.push_back(std::stoi(num)); + } +} + +void WindowManagerConfig::ReadFloatNumbersConfigInfo(const xmlNodePtr& currNode, + std::vector& floatsValue, bool allowNeg) +{ + auto numbers = ReadNumberStrings(currNode); + for (auto& num : numbers) { + if (!WindowHelper::IsFloatingNumber(num, allowNeg)) { + WLOGFE("[WmConfig] read float number error: nodeName:(%{public}s)", currNode->name); + return; + } + floatsValue.push_back(std::stof(num)); + } +} + +void WindowManagerConfig::ReadStringConfigInfo(const xmlNodePtr& currNode, std::string& stringValue) +{ + xmlChar* context = xmlNodeGetContent(currNode); + if (context == nullptr) { + WLOGFE("[WmConfig] read xml node error: nodeName:(%{public}s)", currNode->name); + return; + } + + stringValue = std::string(reinterpret_cast(context)); + xmlFree(context); +} + +void WindowManagerConfig::DumpConfig(const std::map& config) +{ + for (auto& conf : config) { + WLOGFI("[WmConfig] %{public}s", conf.first.c_str()); + std::map propMap; + if (conf.second.property_) { + propMap = *conf.second.property_; + } + for (auto prop : propMap) { + switch (prop.second.type_) { + case ValueType::BOOL: + WLOGFI("[WmConfig] Prop: %{public}s %{public}u", prop.first.c_str(), prop.second.boolValue_); + break; + case ValueType::STRING: + WLOGFI("[WmConfig] Prop: %{public}s %{public}s", prop.first.c_str(), + prop.second.stringValue_.c_str()); + break; + default: + break; + } + } + switch (conf.second.type_) { + case ValueType::MAP: + if (conf.second.mapValue_) { + DumpConfig(*conf.second.mapValue_); + } + break; + case ValueType::BOOL: + WLOGFI("[WmConfig] %{public}u", conf.second.boolValue_); + break; + case ValueType::STRING: + WLOGFI("[WmConfig] %{public}s", conf.second.stringValue_.c_str()); + break; + case ValueType::INTS: + for (auto& num : *conf.second.intsValue_) { + WLOGFI("[WmConfig] Num: %{public}d", num); + } + break; + case ValueType::FLOATS: + for (auto& num : *conf.second.floatsValue_) { + WLOGFI("[WmConfig] Num: %{public}f", num); + } + break; + default: + break; + } + } +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/window_manager_service.cpp b/window_manager/wmserver/src/window_manager_service.cpp new file mode 100644 index 0000000..691e676 --- /dev/null +++ b/window_manager/wmserver/src/window_manager_service.cpp @@ -0,0 +1,1222 @@ +/* + * Copyright (c) 2021-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 "window_manager_service.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xcollie/watchdog.h" + +#include "color_parser.h" +#include "display_manager_service_inner.h" +#include "dm_common.h" +#include "drag_controller.h" +#include "memory_guard.h" +#include "minimize_app.h" +#include "permission.h" +#include "remote_animation.h" +#include "singleton_container.h" +#include "starting_window.h" +#include "ui/rs_ui_director.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_layout_policy.h" +#include "window_manager_agent_controller.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#include "wm_math.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerService"}; +} +WM_IMPLEMENT_SINGLE_INSTANCE(WindowManagerService) + +const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&SingletonContainer::Get()); + +WindowManagerService::WindowManagerService() : SystemAbility(WINDOW_MANAGER_SERVICE_ID, true), + rsInterface_(RSInterfaces::GetInstance()), + windowShowPerformReport_(new PerformReporter("SHOW_WINDOW_TIME", {20, 35, 50})) +{ + windowRoot_ = new WindowRoot( + [this](Event event, const sptr& remoteObject) { OnWindowEvent(event, remoteObject); }); + inputWindowMonitor_ = new InputWindowMonitor(windowRoot_); + windowController_ = new WindowController(windowRoot_, inputWindowMonitor_); + dragController_ = new DragController(windowRoot_); + windowDumper_ = new WindowDumper(windowRoot_); + freezeDisplayController_ = new FreezeController(); + windowCommonEvent_ = std::make_shared(); + startingOpen_ = system::GetParameter("persist.window.sw.enabled", "1") == "1"; // startingWin default enabled + runner_ = AppExecFwk::EventRunner::Create(name_); + handler_ = std::make_shared(runner_); + snapshotController_ = new SnapshotController(windowRoot_, handler_); + int ret = HiviewDFX::Watchdog::GetInstance().AddThread(name_, handler_); + if (ret != 0) { + WLOGFE("Add watchdog thread failed"); + } + handler_->PostTask([]() { MemoryGuard cacheGuard; }, AppExecFwk::EventQueue::Priority::IMMEDIATE); + // init RSUIDirector, it will handle animation callback + rsUiDirector_ = RSUIDirector::Create(); + rsUiDirector_->SetUITaskRunner([this](const std::function& task) { PostAsyncTask(task); }); + rsUiDirector_->Init(false); +} + +void WindowManagerService::OnStart() +{ + WLOGFI("start"); + if (!Init()) { + WLOGFE("Init failed"); + return; + } + WindowInnerManager::GetInstance().Start(system::GetParameter("persist.window.holder.enable", "0") == "1"); + sptr listener = new DisplayChangeListener(); + DisplayManagerServiceInner::GetInstance().RegisterDisplayChangeListener(listener); + + sptr windowInfoQueriedListener = new WindowInfoQueriedListener(); + DisplayManagerServiceInner::GetInstance().RegisterWindowInfoQueriedListener(windowInfoQueriedListener); + + PostAsyncTask([this]() { + sptr rSScreenChangeListener = new IRSScreenChangeListener(); + rSScreenChangeListener->onConnected_ + = std::bind(&WindowManagerService::OnRSScreenConnected, this); + rSScreenChangeListener->onDisconnected_ + = std::bind(&WindowManagerService::OnRSScreenDisconnected, this); + WLOGFI("RegisterRSScreenChangeListener"); + DisplayManagerServiceInner::GetInstance().RegisterRSScreenChangeListener(rSScreenChangeListener); + }); + + AddSystemAbilityListener(RENDER_SERVICE); + AddSystemAbilityListener(ABILITY_MGR_SERVICE_ID); + AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); + + if (!Publish(this)) { + WLOGFE("Publish failed"); + } + WLOGFI("end"); +} + +void WindowManagerService::PostAsyncTask(Task task) +{ + if (handler_) { + bool ret = handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + if (!ret) { + WLOGFE("EventHandler PostTask Failed"); + } + } +} + +void WindowManagerService::PostVoidSyncTask(Task task) +{ + if (handler_) { + bool ret = handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + if (!ret) { + WLOGFE("EventHandler PostVoidSyncTask Failed"); + } + } +} + +void WindowManagerService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) +{ + WLOGFI("systemAbilityId: %{public}d, start", systemAbilityId); + switch (systemAbilityId) { + case RENDER_SERVICE: + WLOGFI("RENDER_SERVICE"); + InitWithRanderServiceAdded(); + break; + case ABILITY_MGR_SERVICE_ID: + WLOGFI("ABILITY_MGR_SERVICE_ID"); + InitWithAbilityManagerServiceAdded(); + break; + case COMMON_EVENT_SERVICE_ID: + WLOGFI("COMMON_EVENT_SERVICE_ID"); + windowCommonEvent_->SubscriberEvent(); + break; + default: + WLOGFW("unhandled sysabilityId: %{public}d", systemAbilityId); + break; + } + WLOGFI("systemAbilityId: %{public}d, end", systemAbilityId); +} + +void WindowManagerService::OnAccountSwitched(int accountId) +{ + PostAsyncTask([this, accountId]() { + windowRoot_->RemoveSingleUserWindowNodes(accountId); + }); + WLOGFI("called"); +} + +void WindowManagerService::WindowVisibilityChangeCallback(std::shared_ptr occlusionData) +{ + WLOGFD("NotifyWindowVisibilityChange: enter"); + std::weak_ptr weak(occlusionData); + PostVoidSyncTask([this, weak]() { + auto weakOcclusionData = weak.lock(); + if (weakOcclusionData == nullptr) { + WLOGFE("weak occlusionData is nullptr"); + return; + } + windowRoot_->NotifyWindowVisibilityChange(weakOcclusionData); + }); +} + +void WindowManagerService::InitWithRanderServiceAdded() +{ + auto windowVisibilityChangeCb = std::bind(&WindowManagerService::WindowVisibilityChangeCallback, this, + std::placeholders::_1); + WLOGFI("RegisterWindowVisibilityChangeCallback"); + if (rsInterface_.RegisterOcclusionChangeCallback(windowVisibilityChangeCb) != WM_OK) { + WLOGFE("RegisterWindowVisibilityChangeCallback failed"); + } + RenderModeChangeCallback renderModeChangeCb + = std::bind(&WindowManagerService::OnRenderModeChanged, this, std::placeholders::_1); + WLOGFI("SetRenderModeChangeCallback"); + if (rsInterface_.SetRenderModeChangeCallback(renderModeChangeCb) != WM_OK) { + WLOGFE("SetRenderModeChangeCallback failed"); + } + + if (windowRoot_->GetMaxUniRenderAppWindowNumber() <= 0) { + rsInterface_.UpdateRenderMode(false); + } +} + +void WindowManagerService::InitWithAbilityManagerServiceAdded() +{ + if (snapshotController_ == nullptr) { + snapshotController_ = new SnapshotController(windowRoot_, handler_); + } + WLOGFI("RegisterSnapshotHandler"); + if (AAFwk::AbilityManagerClient::GetInstance()->RegisterSnapshotHandler(snapshotController_) != ERR_OK) { + WLOGFE("RegisterSnapshotHandler failed"); + } + + if (wmsHandler_ == nullptr) { + wmsHandler_ = new WindowManagerServiceHandler(); + } + WLOGFI("RegisterWindowManagerServiceHandler"); + if (AAFwk::AbilityManagerClient::GetInstance()->RegisterWindowManagerServiceHandler(wmsHandler_) != ERR_OK) { + WLOGFE("RegisterWindowManagerServiceHandler failed"); + } +} + +void WindowManagerServiceHandler::NotifyWindowTransition( + sptr from, sptr to) +{ + sptr fromInfo = nullptr; + sptr toInfo = nullptr; + if (from) { // if exists, transition to window transition info + fromInfo = new WindowTransitionInfo(from); + } + if (to) { + toInfo = new WindowTransitionInfo(to); + } + WindowManagerService::GetInstance().NotifyWindowTransition(fromInfo, toInfo, false); +} + +int32_t WindowManagerServiceHandler::GetFocusWindow(sptr& abilityToken) +{ + return static_cast(WindowManagerService::GetInstance().GetFocusWindowInfo(abilityToken)); +} + +void WindowManagerServiceHandler::StartingWindow( + sptr info, std::shared_ptr pixelMap) +{ + sptr windowInfo = new WindowTransitionInfo(info); + WLOGFI("hot start is called"); + WindowManagerService::GetInstance().StartingWindow(windowInfo, pixelMap, false); +} + +void WindowManagerServiceHandler::StartingWindow( + sptr info, std::shared_ptr pixelMap, uint32_t bgColor) +{ + sptr windowInfo = new WindowTransitionInfo(info); + WLOGFI("cold start is called"); + WindowManagerService::GetInstance().StartingWindow(windowInfo, pixelMap, true, bgColor); +} + +void WindowManagerServiceHandler::CancelStartingWindow(sptr abilityToken) +{ + WLOGFI("WindowManagerServiceHandler CancelStartingWindow!"); + WindowManagerService::GetInstance().CancelStartingWindow(abilityToken); +} + +bool WindowManagerService::Init() +{ + WLOGFI("Init start"); + if (WindowManagerConfig::LoadConfigXml()) { + if (WindowManagerConfig::GetConfig().IsMap()) { + WindowManagerConfig::DumpConfig(*WindowManagerConfig::GetConfig().mapValue_); + } + ConfigureWindowManagerService(); + } + WLOGFI("Init success"); + return true; +} + +int WindowManagerService::Dump(int fd, const std::vector& args) +{ + if (windowDumper_ == nullptr) { + windowDumper_ = new WindowDumper(windowRoot_); + } + + return PostSyncTask([this, fd, &args]() { + return static_cast(windowDumper_->Dump(fd, args)); + }); +} + +void WindowManagerService::ConfigureWindowManagerService() +{ + const auto& config = WindowManagerConfig::GetConfig(); + WindowManagerConfig::ConfigItem item = config["decor"].GetProp("enable"); + if (item.IsBool()) { + systemConfig_.isSystemDecorEnable_ = item.boolValue_; + } + item = config["minimizeByOther"].GetProp("enable"); + if (item.IsBool()) { + MinimizeApp::SetMinimizedByOtherConfig(item.boolValue_); + } + item = config["stretchable"].GetProp("enable"); + if (item.IsBool()) { + systemConfig_.isStretchable_ = item.boolValue_; + } + item = config["defaultWindowMode"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1 && + (numbers[0] == static_cast(WindowMode::WINDOW_MODE_FULLSCREEN) || + numbers[0] == static_cast(WindowMode::WINDOW_MODE_FLOATING))) { + systemConfig_.defaultWindowMode_ = static_cast(static_cast(numbers[0])); + StartingWindow::SetDefaultWindowMode(systemConfig_.defaultWindowMode_); + } + } + item = config["remoteAnimation"].GetProp("enable"); + if (item.IsBool()) { + RemoteAnimation::isRemoteAnimationEnable_ = item.boolValue_; + } + item = config["maxAppWindowNumber"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1 && numbers[0] > 0) { + windowRoot_->SetMaxAppWindowNumber(static_cast(numbers[0])); + } + } + item = config["maxUniRenderAppWindowNumber"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1 && numbers[0] > 0) { + windowRoot_->SetMaxUniRenderAppWindowNumber(static_cast(numbers[0])); + } + } + item = config["modeChangeHotZones"]; + if (item.IsInts()) { + ConfigHotZones(*item.intsValue_); + } + item = config["splitRatios"]; + if (item.IsFloats()) { + windowRoot_->SetSplitRatios(*item.floatsValue_); + } + item = config["exitSplitRatios"]; + if (item.IsFloats()) { + windowRoot_->SetExitSplitRatios(*item.floatsValue_); + } + item = config["windowAnimation"]; + if (item.IsMap()) { + ConfigWindowAnimation(item); + } + item = config["keyboardAnimation"]; + if (item.IsMap()) { + ConfigKeyboardAnimation(item); + } + item = config["windowEffect"]; + if (item.IsMap()) { + ConfigWindowEffect(item); + } + item = config["floatingBottomPosY"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1 && numbers[0] > 0) { + WindowLayoutPolicy::SetCascadeRectBottomPosYLimit(static_cast(numbers[0])); + } + } +} + +void WindowManagerService::ConfigHotZones(const std::vector& numbers) +{ + if (numbers.size() == 3) { // 3 hot zones + hotZonesConfig_.fullscreenRange_ = static_cast(numbers[0]); // 0 fullscreen + hotZonesConfig_.primaryRange_ = static_cast(numbers[1]); // 1 primary + hotZonesConfig_.secondaryRange_ = static_cast(numbers[2]); // 2 secondary + hotZonesConfig_.isModeChangeHotZoneConfigured_ = true; + } +} + +void WindowManagerService::ConfigWindowAnimation(const WindowManagerConfig::ConfigItem& animeConfig) +{ + auto& windowAnimationConfig = WindowNodeContainer::GetAnimationConfigRef().windowAnimationConfig_; + WindowManagerConfig::ConfigItem item = animeConfig["timing"]; + if (item.IsMap() && item.mapValue_->count("curve")) { + windowAnimationConfig.animationTiming_.timingCurve_ = CreateCurve(item["curve"]); + } + item = animeConfig["timing"]["duration"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1) { // duration + windowAnimationConfig.animationTiming_.timingProtocol_ = + RSAnimationTimingProtocol(numbers[0]); + } + } + item = animeConfig["scale"]; + if (item.IsFloats()) { + auto numbers = *item.floatsValue_; + if (numbers.size() == 1) { // 1 xy scale + windowAnimationConfig.scale_.x_ = + windowAnimationConfig.scale_.y_ = numbers[0]; // 0 xy scale + } else if (numbers.size() == 2) { // 2 x,y sclae + windowAnimationConfig.scale_.x_ = numbers[0]; // 0 x scale + windowAnimationConfig.scale_.y_ = numbers[1]; // 1 y scale + } else if (numbers.size() == 3) { // 3 x,y,z scale + windowAnimationConfig.scale_ = Vector3f(&numbers[0]); + } + } + item = animeConfig["rotation"]; + if (item.IsFloats() && item.floatsValue_->size() == 4) { // 4 (axix,angle) + windowAnimationConfig.rotation_ = Vector4f(item.floatsValue_->data()); + } + item = animeConfig["translate"]; + if (item.IsFloats()) { + auto numbers = *item.floatsValue_; + if (numbers.size() == 2) { // 2 translate xy + windowAnimationConfig.translate_.x_ = numbers[0]; // 0 translate x + windowAnimationConfig.translate_.y_ = numbers[1]; // 1 translate y + } else if (numbers.size() == 3) { // 3 translate xyz + windowAnimationConfig.translate_.x_ = numbers[0]; // 0 translate x + windowAnimationConfig.translate_.y_ = numbers[1]; // 1 translate y + windowAnimationConfig.translate_.z_ = numbers[2]; // 2 translate z + } + } + item = animeConfig["opacity"]; + if (item.IsFloats()) { + auto numbers = *item.floatsValue_; + numbers.size() == 1 ? (windowAnimationConfig.opacity_ = numbers[0]) : float(); + } +} + +void WindowManagerService::ConfigKeyboardAnimation(const WindowManagerConfig::ConfigItem& animeConfig) +{ + auto& animationConfig = WindowNodeContainer::GetAnimationConfigRef(); + WindowManagerConfig::ConfigItem item = animeConfig["timing"]; + if (item.IsMap() && item.mapValue_->count("curve")) { + animationConfig.keyboardAnimationConfig_.curve_ = CreateCurve(item["curve"]); + } + item = animeConfig["timing"]["durationIn"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1) { // duration + animationConfig.keyboardAnimationConfig_.durationIn_ = + RSAnimationTimingProtocol(numbers[0]); + } + } + item = animeConfig["timing"]["durationOut"]; + if (item.IsInts()) { + auto numbers = *item.intsValue_; + if (numbers.size() == 1) { // duration + animationConfig.keyboardAnimationConfig_.durationOut_ = + RSAnimationTimingProtocol(numbers[0]); + } + } +} + +bool WindowManagerService::ConfigAppWindowCornerRadius(const WindowManagerConfig::ConfigItem& item, float& out) +{ + std::map stringToCornerRadius = { + {"off", 0.0f}, {"defaultCornerRadiusXS", 4.0f}, {"defaultCornerRadiusS", 8.0f}, + {"defaultCornerRadiusM", 12.0f}, {"defaultCornerRadiusL", 16.0f}, {"defaultCornerRadiusXL", 24.0f} + }; + + if (item.IsString()) { + auto value = item.stringValue_; + if (stringToCornerRadius.find(value) != stringToCornerRadius.end()) { + out = stringToCornerRadius[value]; + return true; + } + } + return false; +} + +bool WindowManagerService::ConfigAppWindowShadow(const WindowManagerConfig::ConfigItem& shadowConfig, + WindowShadowParameters& outShadow) +{ + WindowManagerConfig::ConfigItem item = shadowConfig["elevation"]; + if (item.IsFloats()) { + auto elevation = *item.floatsValue_; + if (elevation.size() != 1 || MathHelper::LessNotEqual(elevation[0], 0.0)) { + return false; + } + outShadow.elevation_ = elevation[0]; + } + + item = shadowConfig["color"]; + if (item.IsString()) { + auto color = item.stringValue_; + uint32_t colorValue; + if (!ColorParser::Parse(color, colorValue)) { + return false; + } + outShadow.color_ = color; + } + + item = shadowConfig["offsetX"]; + if (item.IsFloats()) { + auto offsetX = *item.floatsValue_; + if (offsetX.size() != 1) { + return false; + } + outShadow.offsetX_ = offsetX[0]; + } + + item = shadowConfig["offsetY"]; + if (item.IsFloats()) { + auto offsetY = *item.floatsValue_; + if (offsetY.size() != 1) { + return false; + } + outShadow.offsetY_ = offsetY[0]; + } + + item = shadowConfig["alpha"]; + if (item.IsFloats()) { + auto alpha = *item.floatsValue_; + if (alpha.size() != 1 || (alpha.size() == 1 && + MathHelper::LessNotEqual(alpha[0], 0.0) && MathHelper::GreatNotEqual(alpha[0], 1.0))) { + return false; + } + outShadow.alpha_ = alpha[0]; + } + return true; +} + +void WindowManagerService::ConfigWindowEffect(const WindowManagerConfig::ConfigItem& effectConfig) +{ + AppWindowEffectConfig config; + + // config corner radius + WindowManagerConfig::ConfigItem item = effectConfig["appWindows"]["cornerRadius"]; + if (item.IsMap()) { + if (ConfigAppWindowCornerRadius(item["fullScreen"], config.fullScreenCornerRadius_) && + ConfigAppWindowCornerRadius(item["split"], config.splitCornerRadius_) && + ConfigAppWindowCornerRadius(item["float"], config.floatCornerRadius_)) { + systemConfig_.effectConfig_ = config; + } + } + + // config shadow + item = effectConfig["appWindows"]["shadow"]["focused"]; + if (item.IsMap()) { + if (ConfigAppWindowShadow(item, config.focusedShadow_)) { + systemConfig_.effectConfig_.focusedShadow_ = config.focusedShadow_; + } + } + + item = effectConfig["appWindows"]["shadow"]["unfocused"]; + if (item.IsMap()) { + if (ConfigAppWindowShadow(item, config.unfocusedShadow_)) { + systemConfig_.effectConfig_.unfocusedShadow_ = config.unfocusedShadow_; + } + } +} + +RSAnimationTimingCurve WindowManagerService::CreateCurve(const WindowManagerConfig::ConfigItem& curveConfig) +{ + const auto& nameItem = curveConfig.GetProp("name"); + if (nameItem.IsString()) { + std::string name = nameItem.stringValue_; + if (name == "easeOut") { + return RSAnimationTimingCurve::EASE_OUT; + } else if (name == "ease") { + return RSAnimationTimingCurve::EASE; + } else if (name == "easeIn") { + return RSAnimationTimingCurve::EASE_IN; + } else if (name == "easeInOut") { + return RSAnimationTimingCurve::EASE_IN_OUT; + } else if (name == "default") { + return RSAnimationTimingCurve::DEFAULT; + } else if (name == "linear") { + return RSAnimationTimingCurve::LINEAR; + } else if (name == "spring") { + return RSAnimationTimingCurve::SPRING; + } else if (name == "interactiveSpring") { + return RSAnimationTimingCurve::INTERACTIVE_SPRING; + } else if (name == "cubic" && curveConfig.IsFloats() && + curveConfig.floatsValue_->size() == 4) { // 4 curve parameter + const auto& numbers = *curveConfig.floatsValue_; + return RSAnimationTimingCurve::CreateCubicCurve(numbers[0], // 0 ctrlX1 + numbers[1], // 1 ctrlY1 + numbers[2], // 2 ctrlX2 + numbers[3]); // 3 ctrlY2 + } + } + return RSAnimationTimingCurve::EASE_OUT; +} + +void WindowManagerService::OnStop() +{ + windowCommonEvent_->UnSubscriberEvent(); + WindowInnerManager::GetInstance().Stop(); + WLOGFI("ready to stop service."); +} + +WMError WindowManagerService::NotifyWindowTransition( + sptr& fromInfo, sptr& toInfo, bool isFromClient) +{ + if (!isFromClient) { + WLOGFI("NotifyWindowTransition asynchronously."); + PostAsyncTask([this, fromInfo, toInfo]() mutable { + return windowController_->NotifyWindowTransition(fromInfo, toInfo); + }); + return WMError::WM_OK; + } else { + WLOGFI("NotifyWindowTransition synchronously."); + return PostSyncTask([this, &fromInfo, &toInfo]() { + return windowController_->NotifyWindowTransition(fromInfo, toInfo); + }); + } +} + +WMError WindowManagerService::GetFocusWindowInfo(sptr& abilityToken) +{ + return PostSyncTask([this, &abilityToken]() { + return windowController_->GetFocusWindowInfo(abilityToken); + }); +} + +void WindowManagerService::StartingWindow(sptr info, std::shared_ptr pixelMap, + bool isColdStart, uint32_t bkgColor) +{ + if (!startingOpen_) { + WLOGFI("startingWindow not open!"); + return; + } + PostAsyncTask([this, info, pixelMap, isColdStart, bkgColor]() { + windowController_->StartingWindow(info, pixelMap, bkgColor, isColdStart); + }); +} + +void WindowManagerService::CancelStartingWindow(sptr abilityToken) +{ + WLOGFI("begin CancelStartingWindow!"); + if (!startingOpen_) { + WLOGFI("startingWindow not open!"); + return; + } + PostAsyncTask([this, abilityToken]() { + windowController_->CancelStartingWindow(abilityToken); + }); +} + +bool WindowManagerService::CheckAnimationPermission(const sptr& property) const +{ + if (property->GetAnimationFlag() == static_cast(WindowAnimation::CUSTOM) + && !Permission::IsSystemCalling()) { + WLOGFD("check animation permission failed"); + return false; + } + return true; +} + +bool WindowManagerService::CheckSystemWindowPermission(const sptr& property) const +{ + WindowType type = property->GetWindowType(); + if (!WindowHelper::IsSystemWindow(type)) { + // type is not system + return true; + } + if (type == WindowType::WINDOW_TYPE_DRAGGING_EFFECT || type == WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW || + type == WindowType::WINDOW_TYPE_TOAST) { + // some system types counld be created by normal app + return true; + } + if (type == WindowType::WINDOW_TYPE_FLOAT && + Permission::CheckCallingPermission("ohos.permission.SYSTEM_FLOAT_WINDOW")) { + // WINDOW_TYPE_FLOAT counld be created by normal app with the corresponding permission + WLOGFD("check create permission success, normal app create float window with request permission."); + return true; + } + if (Permission::IsSystemCalling()) { + WLOGFD("check create permission success, create with system calling."); + return true; + } + WLOGFD("check system window permission failed."); + return false; +} + +WMError WindowManagerService::CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, uint32_t& windowId, sptr token) +{ + if (!window || property == nullptr || surfaceNode == nullptr || !window->AsObject()) { + WLOGFE("window is invalid"); + return WMError::WM_ERROR_NULLPTR; + } + if (!CheckSystemWindowPermission(property)) { + WLOGFE("create system window permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + int pid = IPCSkeleton::GetCallingPid(); + int uid = IPCSkeleton::GetCallingUid(); + WMError ret = PostSyncTask([this, pid, uid, &window, &property, &surfaceNode, &windowId, &token]() { + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:CreateWindow(%u)", windowId); + return windowController_->CreateWindow(window, property, surfaceNode, windowId, token, pid, uid); + }); + accessTokenIdMaps_.insert(std::pair(windowId, IPCSkeleton::GetCallingTokenID())); + return ret; +} + +WMError WindowManagerService::AddWindow(sptr& property) +{ + if (property == nullptr) { + WLOGFE("property is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + if (!CheckSystemWindowPermission(property) || !CheckAnimationPermission(property)) { + WLOGFE("add window permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + return PostSyncTask([this, &property]() { + windowShowPerformReport_->start(); + Rect rect = property->GetRequestRect(); + uint32_t windowId = property->GetWindowId(); + WLOGFI("[WMS] Add: %{public}5d %{public}4d %{public}4d %{public}4d [%{public}4d %{public}4d " \ + "%{public}4d %{public}4d]", windowId, property->GetWindowType(), property->GetWindowMode(), + property->GetWindowFlags(), rect.posX_, rect.posY_, rect.width_, rect.height_); + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:AddWindow(%u)", windowId); + WMError res = windowController_->AddWindowNode(property); + if (property->GetWindowType() == WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { + dragController_->StartDrag(windowId); + } + if (res == WMError::WM_OK) { + windowShowPerformReport_->end(); + } + return res; + }); +} + +WMError WindowManagerService::RemoveWindow(uint32_t windowId) +{ + return PostSyncTask([this, windowId]() { + WLOGFI("[WMS] Remove: %{public}u", windowId); + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:RemoveWindow(%u)", windowId); + WindowInnerManager::GetInstance().NotifyWindowRemovedOrDestroyed(windowId); + WMError res = windowController_->RecoverInputEventToClient(windowId); + if (res != WMError::WM_OK) { + return res; + } + return windowController_->RemoveWindowNode(windowId); + }); +} + +WMError WindowManagerService::DestroyWindow(uint32_t windowId, bool onlySelf) +{ + if (!accessTokenIdMaps_.isExistAndRemove(windowId, IPCSkeleton::GetCallingTokenID())) { + WLOGFI("Operation rejected"); + return WMError::WM_ERROR_INVALID_OPERATION; + } + return PostSyncTask([this, windowId, onlySelf]() { + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + node->stateMachine_.SetDestroyTaskParam(onlySelf); + auto func = [this, windowId]() { + WLOGFI("[WMS] Destroy: %{public}u", windowId); + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:DestroyWindow(%u)", windowId); + WindowInnerManager::GetInstance().NotifyWindowRemovedOrDestroyed(windowId); + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + return WMError::WM_OK; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { + dragController_->FinishDrag(windowId); + } + return windowController_->DestroyWindow(windowId, node->stateMachine_.GetDestroyTaskParam()); + }; + if (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsRemoteAnimationPlaying()) { + WLOGFI("SetDestroyTask id:%{public}u", node->GetWindowId()); + node->stateMachine_.SetDestroyTask(func); + return WMError::WM_OK; + } + WLOGFI("DestroyWindow windowId: %{public}u, name:%{public}s state: %{public}u", + node->GetWindowId(), node->GetWindowName().c_str(), + static_cast(node->stateMachine_.GetCurrentState())); + return func(); + }); +} + +WMError WindowManagerService::RequestFocus(uint32_t windowId) +{ + return PostSyncTask([this, windowId]() { + WLOGFI("[WMS] RequestFocus: %{public}u", windowId); + return windowController_->RequestFocus(windowId); + }); +} + +AvoidArea WindowManagerService::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) +{ + return PostSyncTask([this, windowId, avoidAreaType]() { + WLOGFI("[WMS] GetAvoidAreaByType: %{public}u, Type: %{public}u", windowId, + static_cast(avoidAreaType)); + return windowController_->GetAvoidAreaByType(windowId, avoidAreaType); + }); +} + +bool WindowManagerService::RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("register windowManager agent permission denied!"); + return false; + } + if ((windowManagerAgent == nullptr) || (windowManagerAgent->AsObject() == nullptr)) { + WLOGFE("windowManagerAgent is null"); + return false; + } + return PostSyncTask([this, &windowManagerAgent, type]() { + bool ret = WindowManagerAgentController::GetInstance().RegisterWindowManagerAgent(windowManagerAgent, type); + if (type == WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR) { // if system bar, notify once + windowController_->NotifySystemBarTints(); + } + return ret; + }); +} + +bool WindowManagerService::UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("unregister windowManager agent permission denied!"); + return false; + } + if ((windowManagerAgent == nullptr) || (windowManagerAgent->AsObject() == nullptr)) { + WLOGFE("windowManagerAgent is null"); + return false; + } + return PostSyncTask([this, &windowManagerAgent, type]() { + return WindowManagerAgentController::GetInstance().UnregisterWindowManagerAgent(windowManagerAgent, type); + }); +} + +WMError WindowManagerService::SetWindowAnimationController(const sptr& controller) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set window animation controller permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + if (controller == nullptr) { + WLOGFE("RSWindowAnimation: Failed to set window animation controller, controller is null!"); + return WMError::WM_ERROR_NULLPTR; + } + + sptr deathRecipient = new AgentDeathRecipient( + [this](sptr& remoteObject) { + PostVoidSyncTask([&remoteObject]() { + RemoteAnimation::OnRemoteDie(remoteObject); + }); + } + ); + controller->AsObject()->AddDeathRecipient(deathRecipient); + RemoteAnimation::SetWindowControllerAndRoot(windowController_, windowRoot_); + RemoteAnimation::SetMainTaskHandler(handler_); + return PostSyncTask([this, &controller]() { + WMError ret = windowController_->SetWindowAnimationController(controller); + RemoteAnimation::SetAnimationFirst(system::GetParameter("persist.window.af.enabled", "1") == "1"); + return ret; + }); +} + +void WindowManagerService::OnWindowEvent(Event event, const sptr& remoteObject) +{ + if (event == Event::REMOTE_DIED) { + PostVoidSyncTask([this, &remoteObject]() { + uint32_t windowId = windowRoot_->GetWindowIdByObject(remoteObject); + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFD("window node is nullptr, REMOTE_DIED no need to destroy"); + return; + } + WLOGI("window %{public}u received REMOTE_DIED", windowId); + node->stateMachine_.SetDestroyTaskParam(true); + auto func = [this, windowId]() { + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFD("window node is nullptr"); + return; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DRAGGING_EFFECT) { + dragController_->FinishDrag(windowId); + } + WindowInnerManager::GetInstance().NotifyWindowRemovedOrDestroyed(windowId); + windowController_->DestroyWindow(windowId, node->stateMachine_.GetDestroyTaskParam()); + }; + + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + RemoteAnimation::OnRemoteDie(remoteObject); + } + if (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsRemoteAnimationPlaying()) { + WLOGFI("set destroy task windowId:%{public}u", node->GetWindowId()); + node->stateMachine_.SetDestroyTask(func); + handler_->PostTask(func, "destroyTimeOutTask", 6000); // 6000 is time out 6s + return; + } + func(); + }); + } +} + +void WindowManagerService::NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:NotifyDisplayStateChange(%u)", type); + DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId(); + if (type == DisplayStateChangeType::FREEZE) { + freezeDisplayController_->FreezeDisplay(displayId); + } else if (type == DisplayStateChangeType::UNFREEZE) { + freezeDisplayController_->UnfreezeDisplay(displayId); + /* + * Set 'InnerInputManager Listener' to MMI, ensure that the listener + * for move/drag won't be replaced by freeze-display-window + */ + WindowInnerManager::GetInstance().SetInputEventConsumer(); + } else { + PostAsyncTask([this, defaultDisplayId, displayInfo, displayInfoMap, type]() mutable { + windowController_->NotifyDisplayStateChange(defaultDisplayId, displayInfo, displayInfoMap, type); + }); + } +} + +void DisplayChangeListener::OnDisplayStateChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) +{ + WindowManagerService::GetInstance().NotifyDisplayStateChange(defaultDisplayId, displayInfo, displayInfoMap, type); +} + +void DisplayChangeListener::OnScreenshot(DisplayId displayId) +{ + WindowManagerService::GetInstance().OnScreenshot(displayId); +} + +void WindowManagerService::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) +{ + if (windowProperty == nullptr || moveDragProperty == nullptr) { + WLOGFE("windowProperty or moveDragProperty is invalid"); + return; + } + + PostAsyncTask([this, windowId, windowProperty, moveDragProperty]() mutable { + if (moveDragProperty->startDragFlag_ || moveDragProperty->startMoveFlag_) { + bool res = WindowInnerManager::GetInstance().NotifyServerReadyToMoveOrDrag(windowId, + windowProperty, moveDragProperty); + if (!res) { + WLOGFE("invalid operation"); + return; + } + windowController_->InterceptInputEventToServer(windowId); + } + windowController_->NotifyServerReadyToMoveOrDrag(windowId, moveDragProperty); + }); +} + +void WindowManagerService::ProcessPointDown(uint32_t windowId, bool isPointDown) +{ + PostAsyncTask([this, windowId, isPointDown]() { + windowController_->ProcessPointDown(windowId, isPointDown); + }); +} + +void WindowManagerService::ProcessPointUp(uint32_t windowId) +{ + PostAsyncTask([this, windowId]() { + WindowInnerManager::GetInstance().NotifyWindowEndUpMovingOrDragging(windowId); + windowController_->RecoverInputEventToClient(windowId); + windowController_->ProcessPointUp(windowId); + }); +} + +void WindowManagerService::NotifyWindowClientPointUp(uint32_t windowId, + const std::shared_ptr& pointerEvent) +{ + PostAsyncTask([this, windowId, pointerEvent]() mutable { + windowController_->NotifyWindowClientPointUp(windowId, pointerEvent); + }); +} + +void WindowManagerService::MinimizeAllAppWindows(DisplayId displayId) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("minimize all appWindows permission denied!"); + return; + } + PostAsyncTask([this, displayId]() { + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:MinimizeAllAppWindows(%" PRIu64")", displayId); + WLOGFI("displayId %{public}" PRIu64"", displayId); + windowController_->MinimizeAllAppWindows(displayId); + }); +} + +WMError WindowManagerService::ToggleShownStateForAllAppWindows() +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("toggle shown state for all appwindows permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + PostAsyncTask([this]() { + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:ToggleShownStateForAllAppWindows"); + return windowController_->ToggleShownStateForAllAppWindows(); + }); + return WMError::WM_OK; +} + +WMError WindowManagerService::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) +{ + return PostSyncTask([this, &topWinId, mainWinId]() { + return windowController_->GetTopWindowId(mainWinId, topWinId); + }); +} + +WMError WindowManagerService::SetWindowLayoutMode(WindowLayoutMode mode) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("set window layout mode permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + return PostSyncTask([this, mode]() { + WLOGFI("layoutMode: %{public}u", mode); + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:SetWindowLayoutMode"); + return windowController_->SetWindowLayoutMode(mode); + }); +} + +WMError WindowManagerService::UpdateProperty(sptr& windowProperty, PropertyChangeAction action, + bool isAsyncTask) +{ + if (windowProperty == nullptr) { + WLOGFE("windowProperty is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + if ((windowProperty->GetWindowFlags() == static_cast(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE) || + action == PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY) && + !Permission::IsSystemCalling()) { + WLOGFE("SetForbidSplitMove or SetShowWhenLocked or SetTranform or SetTurnScreenOn permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + + if (action == PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY) { + return PostSyncTask([this, windowProperty, action]() mutable { + windowController_->UpdateProperty(windowProperty, action); + return WMError::WM_OK; + }); + } + + if (isAsyncTask || action == PropertyChangeAction::ACTION_UPDATE_RECT) { + PostAsyncTask([this, windowProperty, action]() mutable { + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:UpdateProperty"); + WMError res = windowController_->UpdateProperty(windowProperty, action); + if (action == PropertyChangeAction::ACTION_UPDATE_RECT && res == WMError::WM_OK && + windowProperty->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) { + dragController_->UpdateDragInfo(windowProperty->GetWindowId()); + } + }); + return WMError::WM_OK; + } + + return PostSyncTask([this, &windowProperty, action]() { + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:UpdateProperty"); + WMError res = windowController_->UpdateProperty(windowProperty, action); + if (action == PropertyChangeAction::ACTION_UPDATE_RECT && res == WMError::WM_OK && + windowProperty->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) { + dragController_->UpdateDragInfo(windowProperty->GetWindowId()); + } + return res; + }); +} + +WMError WindowManagerService::GetAccessibilityWindowInfo(std::vector>& infos) +{ + if (!Permission::IsSystemServiceCalling()) { + WLOGFE("get accessibility window info permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + return PostSyncTask([this, &infos]() { + return windowController_->GetAccessibilityWindowInfo(infos); + }); +} + +WMError WindowManagerService::GetVisibilityWindowInfo(std::vector>& infos) +{ + return PostSyncTask([this, &infos]() { + return windowController_->GetVisibilityWindowInfo(infos); + }); +} + +std::shared_ptr WindowManagerService::GetSnapshot(int32_t windowId) +{ + return nullptr; +} + +void WindowManagerService::NotifyDumpInfoResult(const std::vector& info) +{ + if (windowDumper_) { + windowDumper_->dumpInfoFuture_.SetValue(info); + } +} + +WMError WindowManagerService::GetSystemConfig(SystemConfig& systemConfig) +{ + systemConfig = systemConfig_; + return WMError::WM_OK; +} + +WMError WindowManagerService::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) +{ + if (!hotZonesConfig_.isModeChangeHotZoneConfigured_) { + return WMError::WM_DO_NOTHING; + } + + return windowController_->GetModeChangeHotZones(displayId, hotZones, hotZonesConfig_); +} + +void WindowManagerService::MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("minimize windows by launcher permission denied!"); + return; + } + PostVoidSyncTask([this, windowIds, isAnimated, &finishCallback]() mutable { + windowController_->MinimizeWindowsByLauncher(windowIds, isAnimated, finishCallback); + }); +} + +WMError WindowManagerService::UpdateAvoidAreaListener(uint32_t windowId, bool haveAvoidAreaListener) +{ + return PostSyncTask([this, windowId, haveAvoidAreaListener]() { + sptr node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("get window node failed. win %{public}u", windowId); + return WMError::WM_DO_NOTHING; + } + sptr container = windowRoot_->GetWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("get container failed. win %{public}u display %{public}" PRIu64"", windowId, node->GetDisplayId()); + return WMError::WM_DO_NOTHING; + } + container->UpdateAvoidAreaListener(node, haveAvoidAreaListener); + return WMError::WM_OK; + }); +} + +void WindowManagerService::SetAnchorAndScale(int32_t x, int32_t y, float scale) +{ + PostAsyncTask([this, x, y, scale]() { + windowController_->SetAnchorAndScale(x, y, scale); + }); +} + +void WindowManagerService::SetAnchorOffset(int32_t deltaX, int32_t deltaY) +{ + PostAsyncTask([this, deltaX, deltaY]() { + windowController_->SetAnchorOffset(deltaX, deltaY); + }); +} + +void WindowManagerService::OffWindowZoom() +{ + PostAsyncTask([this]() { + windowController_->OffWindowZoom(); + }); +} + +WMError WindowManagerService::UpdateRsTree(uint32_t windowId, bool isAdd) +{ + return PostSyncTask([this, windowId, isAdd]() { + return windowRoot_->UpdateRsTree(windowId, isAdd); + }); +} + +void WindowManagerService::OnScreenshot(DisplayId displayId) +{ + PostAsyncTask([this, displayId]() { + windowController_->OnScreenshot(displayId); + }); +} + +WMError WindowManagerService::BindDialogTarget(uint32_t& windowId, sptr targetToken) +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("bind dialog target permission denied!"); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + return PostSyncTask([this, &windowId, targetToken]() { + return windowController_->BindDialogTarget(windowId, targetToken); + }); +} + +void WindowManagerService::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + PostVoidSyncTask([this, displayId, &hasPrivateWindow]() mutable { + hasPrivateWindow = windowRoot_->HasPrivateWindow(displayId); + }); + WLOGFI("called %{public}u", hasPrivateWindow); +} + +void WindowInfoQueriedListener::HasPrivateWindow(DisplayId displayId, bool& hasPrivateWindow) +{ + WLOGFI("called"); + WindowManagerService::GetInstance().HasPrivateWindow(displayId, hasPrivateWindow); +} + +void WindowManagerService::OnRSScreenConnected() +{ + PostAsyncTask([this]() { + windowRoot_->SwitchRenderModeIfNeeded(); + }); +} + +void WindowManagerService::OnRSScreenDisconnected() +{ + PostAsyncTask([this]() { + windowRoot_->SwitchRenderModeIfNeeded(); + }); +} + +void WindowManagerService::OnRenderModeChanged(bool isUniRender) +{ + PostAsyncTask([this, isUniRender]() { + windowRoot_->OnRenderModeChanged(isUniRender); + }); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/window_node.cpp b/window_manager/wmserver/src/window_node.cpp new file mode 100644 index 0000000..fe1fc72 --- /dev/null +++ b/window_manager/wmserver/src/window_node.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2021-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 "window_node.h" +#include "window_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowNode"}; +} + +WindowNode::~WindowNode() +{ + WLOGFI("~WindowNode id:%{public}u", GetWindowId()); +} + +void WindowNode::SetDisplayId(DisplayId displayId) +{ + property_->SetDisplayId(displayId); +} + +void WindowNode::SetEntireWindowTouchHotArea(const Rect& rect) +{ + entireWindowTouchHotArea_ = rect; +} + +void WindowNode::SetEntireWindowPointerHotArea(const Rect& rect) +{ + entireWindowPointerHotArea_ = rect; +} + +void WindowNode::SetWindowRect(const Rect& rect) +{ + property_->SetWindowRect(rect); +} + +void WindowNode::SetDecoStatus(bool status) +{ + property_->SetDecoStatus(status); +} + +void WindowNode::SetRequestRect(const Rect& rect) +{ + property_->SetRequestRect(rect); +} + +void WindowNode::SetWindowProperty(const sptr& property) +{ + property_ = property; +} + +void WindowNode::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) +{ + property_->SetSystemBarProperty(type, property); +} + +void WindowNode::SetWindowMode(WindowMode mode) +{ + property_->SetWindowMode(mode); +} + +void WindowNode::SetBrightness(float brightness) +{ + property_->SetBrightness(brightness); +} + +void WindowNode::SetFocusable(bool focusable) +{ + property_->SetFocusable(focusable); +} + +void WindowNode::SetTouchable(bool touchable) +{ + property_->SetTouchable(touchable); +} + +void WindowNode::SetTurnScreenOn(bool turnScreenOn) +{ + property_->SetTurnScreenOn(turnScreenOn); +} + +void WindowNode::SetKeepScreenOn(bool keepScreenOn) +{ + property_->SetKeepScreenOn(keepScreenOn); +} + +void WindowNode::SetCallingWindow(uint32_t windowId) +{ + property_->SetCallingWindow(windowId); +} + +uint32_t WindowNode::GetCallingWindow() const +{ + return property_->GetCallingWindow(); +} + +void WindowNode::SetWindowSizeChangeReason(WindowSizeChangeReason reason) +{ + windowSizeChangeReason_ = reason; +} + +void WindowNode::SetRequestedOrientation(Orientation orientation) +{ + property_->SetRequestedOrientation(orientation); +} + +void WindowNode::SetShowingDisplays(const std::vector& displayIdVec) +{ + showingDisplays_.clear(); + showingDisplays_.assign(displayIdVec.begin(), displayIdVec.end()); +} + +void WindowNode::SetModeSupportInfo(uint32_t modeSupportInfo) +{ + property_->SetModeSupportInfo(modeSupportInfo); +} + +void WindowNode::ResetWindowSizeChangeReason() +{ + windowSizeChangeReason_ = WindowSizeChangeReason::UNDEFINED; +} + +const sptr& WindowNode::GetWindowToken() const +{ + return windowToken_; +} + +void WindowNode::SetWindowToken(sptr window) +{ + windowToken_ = window; +} + +void WindowNode::SetInputEventCallingPid(int32_t pid) +{ + inputCallingPid_ = pid; +} + +void WindowNode::SetCallingPid(int32_t pid) +{ + callingPid_ = pid; + SetInputEventCallingPid(pid); +} + +void WindowNode::SetCallingUid(int32_t uid) +{ + callingUid_ = uid; +} + +void WindowNode::SetDragType(DragType dragType) +{ + property_->SetDragType(dragType); +} + +void WindowNode::SetOriginRect(const Rect& rect) +{ + property_->SetOriginRect(rect); +} + +void WindowNode::SetTouchHotAreas(const std::vector& rects) +{ + touchHotAreas_ = rects; +} + +void WindowNode::SetPointerHotAreas(const std::vector& rects) +{ + pointerHotAreas_ = rects; +} + +void WindowNode::SetWindowSizeLimits(const WindowSizeLimits& sizeLimits) +{ + property_->SetSizeLimits(sizeLimits); +} + +void WindowNode::SetWindowUpdatedSizeLimits(const WindowSizeLimits& sizeLimits) +{ + property_->SetUpdatedSizeLimits(sizeLimits); +} + +void WindowNode::ComputeTransform() +{ + property_->ComputeTransform(); +} + +void WindowNode::SetTransform(const Transform& trans) +{ + property_->SetTransform(trans); +} + +Transform WindowNode::GetZoomTransform() const +{ + return property_->GetZoomTransform(); +} + +void WindowNode::UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) +{ + property_->SetZoomTransform(trans); + property_->SetDisplayZoomState(isDisplayZoomOn); + if (windowToken_) { + windowToken_->UpdateZoomTransform(trans, isDisplayZoomOn); + } +} + +WindowSizeLimits WindowNode::GetWindowSizeLimits() const +{ + return property_->GetSizeLimits(); +} + +WindowSizeLimits WindowNode::GetWindowUpdatedSizeLimits() const +{ + return property_->GetUpdatedSizeLimits(); +} + +DragType WindowNode::GetDragType() const +{ + return property_->GetDragType(); +} + +bool WindowNode::GetStretchable() const +{ + return property_->GetStretchable(); +} + +const Rect& WindowNode::GetOriginRect() const +{ + return property_->GetOriginRect(); +} + +DisplayId WindowNode::GetDisplayId() const +{ + return property_->GetDisplayId(); +} + +const std::string& WindowNode::GetWindowName() const +{ + return property_->GetWindowName(); +} + +uint32_t WindowNode::GetWindowId() const +{ + return property_->GetWindowId(); +} + +uint32_t WindowNode::GetParentId() const +{ + return property_->GetParentId(); +} + +Rect WindowNode::GetEntireWindowTouchHotArea() const +{ + return entireWindowTouchHotArea_; +} + +Rect WindowNode::GetEntireWindowPointerHotArea() const +{ + return entireWindowPointerHotArea_; +} + +Rect WindowNode::GetWindowRect() const +{ + return property_->GetWindowRect(); +} + +bool WindowNode::GetDecoStatus() const +{ + return property_->GetDecoStatus(); +} + +Rect WindowNode::GetRequestRect() const +{ + return property_->GetRequestRect(); +} + +WindowType WindowNode::GetWindowType() const +{ + return property_->GetWindowType(); +} + +WindowMode WindowNode::GetWindowMode() const +{ + return property_->GetWindowMode(); +} + +bool WindowNode::EnableDefaultAnimation(bool animationPlayed) +{ + // system config enabled && not in remote animation && not custom animation && not crash + bool defaultAnimation = property_->GetAnimationFlag() == (static_cast(WindowAnimation::DEFAULT)); + return ((!animationPlayed) && (defaultAnimation) && (!isAppCrash_)); +} + +float WindowNode::GetBrightness() const +{ + return property_->GetBrightness(); +} + +bool WindowNode::IsTurnScreenOn() const +{ + return property_->IsTurnScreenOn(); +} + +bool WindowNode::IsKeepScreenOn() const +{ + return property_->IsKeepScreenOn(); +} + +uint32_t WindowNode::GetWindowFlags() const +{ + return property_->GetWindowFlags(); +} + +const sptr& WindowNode::GetWindowProperty() const +{ + return property_; +} + +int32_t WindowNode::GetInputEventCallingPid() const +{ + return inputCallingPid_; +} + +int32_t WindowNode::GetCallingPid() const +{ + return callingPid_; +} + +int32_t WindowNode::GetCallingUid() const +{ + return callingUid_; +} + +const std::unordered_map& WindowNode::GetSystemBarProperty() const +{ + return property_->GetSystemBarProperty(); +} + +bool WindowNode::IsSplitMode() const +{ + return (property_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + property_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY); +} + +WindowSizeChangeReason WindowNode::GetWindowSizeChangeReason() const +{ + return windowSizeChangeReason_; +} + +Orientation WindowNode::GetRequestedOrientation() const +{ + return property_->GetRequestedOrientation(); +} + +std::vector WindowNode::GetShowingDisplays() const +{ + return showingDisplays_; +} + +uint32_t WindowNode::GetModeSupportInfo() const +{ + return property_->GetModeSupportInfo(); +} + +void WindowNode::GetTouchHotAreas(std::vector& rects) const +{ + rects = touchHotAreas_; +} + +void WindowNode::GetPointerHotAreas(std::vector& rects) const +{ + rects = pointerHotAreas_; +} + +uint32_t WindowNode::GetAccessTokenId() const +{ + return property_->GetAccessTokenId(); +} + +void WindowNode::SetSnapshot(std::shared_ptr pixelMap) +{ + snapshot_ = pixelMap; +} + +std::shared_ptr WindowNode::GetSnapshot() +{ + return snapshot_; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/window_node_container.cpp b/window_manager/wmserver/src/window_node_container.cpp new file mode 100644 index 0000000..1a14ae9 --- /dev/null +++ b/window_manager/wmserver/src/window_node_container.cpp @@ -0,0 +1,2178 @@ +/* + * Copyright (c) 2021-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 "window_node_container.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_event_manager.h" +#include "dm_common.h" +#include "remote_animation.h" +#include "starting_window.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_manager_hilog.h" +#include "window_manager_service.h" +#include "wm_common.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowNodeContainer"}; + constexpr int WINDOW_NAME_MAX_LENGTH = 10; + constexpr uint32_t MAX_BRIGHTNESS = 255; + constexpr uint32_t SPLIT_WINDOWS_CNT = 2; + constexpr uint32_t EXIT_SPLIT_POINTS_NUMBER = 2; + constexpr int UID_TRANSFROM_DIVISOR = 200000; + constexpr int UID_MIN = 100; +} +AnimationConfig WindowNodeContainer::animationConfig_; + +WindowNodeContainer::WindowNodeContainer(const sptr& displayInfo, ScreenId displayGroupId) +{ + DisplayId displayId = displayInfo->GetDisplayId(); + + // create and displayGroupInfo and displayGroupController + displayGroupInfo_ = new DisplayGroupInfo(displayGroupId, displayInfo); + displayGroupController_ = new DisplayGroupController(this, displayGroupInfo_); + displayGroupController_->InitNewDisplay(displayId); + + // init layout policy + layoutPolicies_[WindowLayoutMode::CASCADE] = new WindowLayoutPolicyCascade(displayGroupInfo_, + displayGroupController_->displayGroupWindowTree_); + layoutPolicies_[WindowLayoutMode::TILE] = new WindowLayoutPolicyTile(displayGroupInfo_, + displayGroupController_->displayGroupWindowTree_); + layoutPolicy_ = layoutPolicies_[WindowLayoutMode::CASCADE]; + layoutPolicy_->Launch(); + + Rect initalDividerRect = layoutPolicies_[WindowLayoutMode::CASCADE]->GetDividerRect(displayId); + displayGroupController_->SetDividerRect(displayId, initalDividerRect); + // init avoidAreaController + avoidController_ = new AvoidAreaController(focusedWindow_); +} + +WindowNodeContainer::~WindowNodeContainer() +{ + Destroy(); +} + +uint32_t WindowNodeContainer::GetWindowCountByType(WindowType windowType) +{ + uint32_t windowNumber = 0; + auto counter = [&windowNumber, &windowType](sptr& windowNode) { + if (windowNode->GetWindowType() == windowType && !windowNode->startingWindowShown_) ++windowNumber; + }; + std::for_each(belowAppWindowNode_->children_.begin(), belowAppWindowNode_->children_.end(), counter); + std::for_each(appWindowNode_->children_.begin(), appWindowNode_->children_.end(), counter); + std::for_each(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), counter); + return windowNumber; +} + +WMError WindowNodeContainer::AddWindowNodeOnWindowTree(sptr& node, const sptr& parentNode) +{ + sptr root = FindRoot(node->GetWindowType()); + if (root == nullptr && !(WindowHelper::IsSystemSubWindow(node->GetWindowType()) && + parentNode != nullptr)) { + WLOGFE("root is nullptr!"); + return WMError::WM_ERROR_NULLPTR; + } + node->requestedVisibility_ = true; + if (parentNode != nullptr) { // subwindow + if (WindowHelper::IsSystemSubWindow(node->GetWindowType()) || + node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) { + if (WindowHelper::IsSubWindow(parentNode->GetWindowType()) || + WindowHelper::IsSystemSubWindow(parentNode->GetWindowType()) || + parentNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT || + parentNode->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) { + // some times, dialog is a child window, so exclude + WLOGFE("the parent of window cannot be any sub window"); + return WMError::WM_ERROR_INVALID_PARAM; + } + } else { + if (parentNode->parent_ != root && + !((parentNode->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) && + (parentNode->parent_ == aboveAppWindowNode_))) { + WLOGFE("window type and parent window not match \ + or try to add subwindow to subwindow, which is forbidden"); + return WMError::WM_ERROR_INVALID_PARAM; + } + } + node->currentVisibility_ = parentNode->currentVisibility_; + node->parent_ = parentNode; + } else { // mainwindow + node->parent_ = root; + node->currentVisibility_ = true; + for (auto& child : node->children_) { + child->currentVisibility_ = child->requestedVisibility_; + } + if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) { + displayGroupController_->sysBarNodeMaps_[node->GetDisplayId()][node->GetWindowType()] = node; + } + } + return WMError::WM_OK; +} + +WMError WindowNodeContainer::ShowStartingWindow(sptr& node) +{ + if (node->currentVisibility_) { + WLOGFE("current window is visible, windowId: %{public}u", node->GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + + WMError res = AddWindowNodeOnWindowTree(node, nullptr); + if (res != WMError::WM_OK) { + return res; + } + UpdateWindowTree(node); + displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ADDED); + StartingWindow::AddNodeOnRSTree(node, animationConfig_, layoutPolicy_->IsMultiDisplay()); + AssignZOrder(); + layoutPolicy_->AddWindowNode(node); + WLOGFD("ShowStartingWindow windowId: %{public}u end", node->GetWindowId()); + return WMError::WM_OK; +} + +WMError WindowNodeContainer::IsTileRectSatisfiedWithSizeLimits(sptr& node) +{ + if (layoutMode_ == WindowLayoutMode::TILE && + !layoutPolicy_->IsTileRectSatisfiedWithSizeLimits(node)) { + WLOGFE("layoutMode is tile, default rect is not satisfied with size limits of window, windowId: %{public}u", + node->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE; + } + return WMError::WM_OK; +} + +AnimationConfig& WindowNodeContainer::GetAnimationConfigRef() +{ + return animationConfig_; +} + +void WindowNodeContainer::LayoutWhenAddWindowNode(sptr& node, bool afterAnimation) +{ + if (afterAnimation) { + layoutPolicy_->AddWindowNode(node); + return; + } + WLOGFD("AddWindowNode windowId:%{public}u, name:%{public}s currState:%{public}u", + node->GetWindowId(), node->GetWindowName().c_str(), + static_cast(node->stateMachine_.GetCurrentState())); + if (WindowHelper::IsMainWindow(node->GetWindowType()) && + RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsShowAnimationPlaying()) { + // for first frame callback + auto winRect = node->GetWindowRect(); + if (node->surfaceNode_) { + node->surfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_); + WLOGFD("notify client and SetBounds id:%{public}u, rect:[%{public}d, %{public}d, %{public}u, %{public}u]", + node->GetWindowId(), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); + layoutPolicy_->UpdateClientRect(node->GetWindowRect(), node, WindowSizeChangeReason::UNDEFINED); + } + } else { + if (node->GetWindowProperty()->GetAnimationFlag() == static_cast(WindowAnimation::CUSTOM) && + WindowHelper::IsSystemWindow(node->GetWindowType())) { + node->SetWindowSizeChangeReason(WindowSizeChangeReason::CUSTOM_ANIMATION_SHOW); + } + layoutPolicy_->AddWindowNode(node); + } +} + +WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr& parentNode, bool afterAnimation) +{ + if (!node->startingWindowShown_) { // window except main Window + WMError res = AddWindowNodeOnWindowTree(node, parentNode); + if (res != WMError::WM_OK) { + return res; + } + UpdateWindowTree(node); + displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ADDED); + // add node on RSTree + for (auto& displayId : node->GetShowingDisplays()) { + AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ADDED, + node->isPlayAnimationShow_); + } + } else { // only main app window has starting window + node->isPlayAnimationShow_ = false; + node->startingWindowShown_ = false; + AddAppSurfaceNodeOnRSTree(node); + ReZOrderShowWhenLockedWindowIfNeeded(node); + RaiseZOrderForAppWindow(node, parentNode); + } + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId()); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + windowPair->UpdateIfSplitRelated(node); + if (node->IsSplitMode()) { + // raise the z-order of window pair + RaiseSplitRelatedWindowToTop(node); + } + AssignZOrder(); + LayoutWhenAddWindowNode(node, afterAnimation); + NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_ADD); + DumpScreenWindowTree(); + UpdateCameraFloatWindowStatus(node, true); + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + backupWindowIds_.clear(); + } + + if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { + isScreenLocked_ = true; + SetBelowScreenlockVisible(node, false); + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) { + RemoteAnimation::NotifyAnimationUpdateWallpaper(node); + } + WLOGFD("AddWindowNode windowId: %{public}u end", node->GetWindowId()); + RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum()); + return WMError::WM_OK; +} + +void WindowNodeContainer::UpdateRSTreeWhenShowingDisplaysChange(sptr& node, + const std::vector& lastShowingDisplays) +{ + if (!layoutPolicy_->IsMultiDisplay()) { + return; + } + + // Update RSTree + auto curShowingDisplays = node->GetShowingDisplays(); + for (auto& displayId : lastShowingDisplays) { + if (std::find(curShowingDisplays.begin(), curShowingDisplays.end(), displayId) == curShowingDisplays.end()) { + RemoveNodeFromRSTree(node, displayId, *(curShowingDisplays.begin()), + WindowUpdateType::WINDOW_UPDATE_ACTIVE); + WLOGFD("remove from RSTree : %{public}" PRIu64"", displayId); + } + } + + for (auto& displayId : curShowingDisplays) { + if (std::find(lastShowingDisplays.begin(), lastShowingDisplays.end(), displayId) == lastShowingDisplays.end()) { + AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE); + WLOGFD("add on RSTree : %{public}" PRIu64"", displayId); + } + } +} + +WMError WindowNodeContainer::UpdateWindowNode(sptr& node, WindowUpdateReason reason) +{ + // Get last displayId and last showing displays before layout + auto lastShowingDisplays = node->GetShowingDisplays(); + + // PreProcess window node and layout node + displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ACTIVE); + if (WindowHelper::IsMainWindow(node->GetWindowType()) && WindowHelper::IsSwitchCascadeReason(reason)) { + SwitchLayoutPolicy(WindowLayoutMode::CASCADE, node->GetDisplayId()); + } + layoutPolicy_->UpdateWindowNode(node); + displayGroupController_->PostProcessWindowNode(node); + // Get current displayId and showing displays, update RSTree and displayGroupWindowTree + UpdateRSTreeWhenShowingDisplaysChange(node, lastShowingDisplays); + NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_UPDATE); + DumpScreenWindowTree(); + WLOGFD("UpdateWindowNode windowId: %{public}u end", node->GetWindowId()); + return WMError::WM_OK; +} + +void WindowNodeContainer::RemoveWindowNodeFromWindowTree(sptr& node) +{ + // remove this node from parent + auto iter = std::find(node->parent_->children_.begin(), node->parent_->children_.end(), node); + if (iter != node->parent_->children_.end()) { + node->parent_->children_.erase(iter); + } else { + WLOGFE("can't find this node in parent"); + } + node->parent_ = nullptr; +} + +void WindowNodeContainer::RemoveFromRsTreeWhenRemoveWindowNode(sptr& node, bool fromAnimation) +{ + if (fromAnimation || (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) && + node->stateMachine_.IsHideAnimationPlaying())) { + WLOGFD("not remove from rs tree id:%{public}u", node->GetWindowId()); + return; + } + // When RemoteAnimation exists, remove node from rs tree after animation + WLOGFD("remove from rs tree id:%{public}u, node->isPlayAnimationHide_:%{public}u", node->GetWindowId(), + static_cast(node->isPlayAnimationHide_)); + // subwindow or no remote animation also exit with animation + for (auto& displayId : node->GetShowingDisplays()) { + RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_REMOVED, + node->isPlayAnimationHide_); + } +} + +void WindowNodeContainer::SetSurfaceNodeVisible(sptr& node, int32_t topPriority, bool visible) +{ + if (node == nullptr) { + return; + } + if (node->parent_ != nullptr && node->currentVisibility_) { + if (node->priority_ < topPriority && !WindowHelper::IsShowWhenLocked(node->GetWindowFlags()) && + !WindowHelper::IsShowWhenLocked(node->parent_->GetWindowFlags())) { + auto surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_; + if (surfaceNode) { + surfaceNode->SetVisible(visible); + } + } + } + for (auto& childNode : node->children_) { + SetSurfaceNodeVisible(childNode, topPriority, visible); + } +} + +void WindowNodeContainer::SetBelowScreenlockVisible(sptr& node, bool visible) +{ + int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD); + std::vector> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ }; + for (auto& node : rootNodes) { + SetSurfaceNodeVisible(node, topPriority, visible); + } +} + +WMError WindowNodeContainer::RemoveWindowNode(sptr& node, bool fromAnimation) +{ + if (node == nullptr) { + WLOGFE("window node or surface node is nullptr, invalid"); + return WMError::WM_ERROR_DESTROYED_OBJECT; + } + if (node->parent_ == nullptr) { + WLOGFW("can't find parent of this node"); + } else { + RemoveWindowNodeFromWindowTree(node); + } + + node->requestedVisibility_ = false; + node->currentVisibility_ = false; + RemoveFromRsTreeWhenRemoveWindowNode(node, fromAnimation); + node->isPlayAnimationHide_ = false; + displayGroupController_->UpdateDisplayGroupWindowTree(); + + layoutPolicy_->RemoveWindowNode(node); + WindowMode lastMode = node->GetWindowMode(); + if (HandleRemoveWindow(node) != WMError::WM_OK) { + return WMError::WM_ERROR_NULLPTR; + } + if (!WindowHelper::IsFloatingWindow(lastMode)) { + NotifyDockWindowStateChanged(node, true); + } + NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_REMOVE); + DumpScreenWindowTree(); + UpdateCameraFloatWindowStatus(node, false); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { + isScreenLocked_ = false; + SetBelowScreenlockVisible(node, true); + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) { + DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled(); + } + WLOGFD("RemoveWindowNode windowId: %{public}u end", node->GetWindowId()); + RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum()); + return WMError::WM_OK; +} + +uint32_t WindowNodeContainer::GetAppWindowNum() +{ + uint32_t num = 0; + for (auto& child : appWindowNode_->children_) { + if (WindowHelper::IsAppWindow(child->GetWindowType())) { + num++; + } + } + return num; +} + +WMError WindowNodeContainer::HandleRemoveWindow(sptr& node) +{ + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId()); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + windowPair->HandleRemoveWindow(node); + auto dividerWindow = windowPair->GetDividerWindow(); + auto type = node->GetWindowType(); + if ((type == WindowType::WINDOW_TYPE_STATUS_BAR || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR) && + dividerWindow != nullptr) { + UpdateWindowNode(dividerWindow, WindowUpdateReason::UPDATE_RECT); + } + return WMError::WM_OK; +} + +WMError WindowNodeContainer::DestroyWindowNode(sptr& node, std::vector& windowIds) +{ + WMError ret = RemoveWindowNode(node); + if (ret != WMError::WM_OK) { + WLOGFE("RemoveWindowNode failed"); + return ret; + } + StartingWindow::ReleaseStartWinSurfaceNode(node); + node->surfaceNode_ = nullptr; + windowIds.push_back(node->GetWindowId()); + for (auto& child : node->children_) { // destroy sub window if exists + windowIds.push_back(child->GetWindowId()); + child->parent_ = nullptr; + if (child->surfaceNode_ != nullptr) { + WLOGFD("child surfaceNode set nullptr"); + child->surfaceNode_ = nullptr; + } + } + + // clear vector cache completely, swap with empty vector + auto emptyVector = std::vector>(); + node->children_.swap(emptyVector); + if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) { + RemoteAnimation::NotifyAnimationUpdateWallpaper(nullptr); + } + WLOGFD("DestroyWindowNode windowId: %{public}u end", node->GetWindowId()); + return WMError::WM_OK; +} + +void WindowNodeContainer::UpdateSizeChangeReason(sptr& node, WindowSizeChangeReason reason) +{ + if (!node->GetWindowToken()) { + WLOGFE("windowToken is null"); + return; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + for (auto& childNode : appWindowNode_->children_) { + if (childNode->IsSplitMode()) { + layoutPolicy_->UpdateClientRect(childNode->GetWindowRect(), childNode, reason); + childNode->ResetWindowSizeChangeReason(); + WLOGFD("Notify split window that the drag action is start or end, windowId: %{public}d, " + "reason: %{public}u", childNode->GetWindowId(), reason); + } + } + } else { + layoutPolicy_->UpdateClientRect(node->GetWindowRect(), node, reason); + node->ResetWindowSizeChangeReason(); + WLOGFD("Notify window that the drag action is start or end, windowId: %{public}d, " + "reason: %{public}u", node->GetWindowId(), reason); + } +} + +void WindowNodeContainer::UpdateWindowTree(sptr& node) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + node->priority_ = zorderPolicy_->GetWindowPriority(node->GetWindowType()); + RaiseInputMethodWindowPriorityIfNeeded(node); + RaiseShowWhenLockedWindowIfNeeded(node); + auto parentNode = node->parent_; + if (parentNode == nullptr) { + WLOGFD("Current window node has no parent: %{public}u", node->GetWindowId()); + return; + } + auto iter = std::find(parentNode->children_.begin(), parentNode->children_.end(), node); + if (iter != parentNode->children_.end()) { + WLOGFD("node %{public}u is already on window tree, no need to update!", node->GetWindowId()); + return; + } + auto position = parentNode->children_.end(); + int splitWindowCnt = 0; + for (auto child = parentNode->children_.begin(); child < parentNode->children_.end(); ++child) { + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE && splitWindowCnt == SPLIT_WINDOWS_CNT) { + position = child; + break; + } + if (WindowHelper::IsSplitWindowMode((*child)->GetWindowMode())) { + splitWindowCnt++; + } + if ((*child)->priority_ > node->priority_) { + position = child; + break; + } + } + parentNode->children_.insert(position, node); +} + +bool WindowNodeContainer::AddAppSurfaceNodeOnRSTree(sptr& node) +{ + /* + * App main window must has starting window, and show after starting window + * Starting Window has already update leashWindowSurfaceNode and starting window surfaceNode on RSTree + * Just need add appSurface Node as child of leashWindowSurfaceNode + */ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "AddAppSurfaceNodeOnRSTree"); + if (!WindowHelper::IsMainWindow(node->GetWindowType())) { + WLOGFE("id:%{public}u not main app window but has start window", node->GetWindowId()); + return false; + } + if (!node->leashWinSurfaceNode_ || !node->surfaceNode_) { + WLOGFE("id:%{public}u leashWinSurfaceNode or surfaceNode is null but has start window!", node->GetWindowId()); + return false; + } + WLOGFD("AddAppSurfaceNodeOnRSTree windowId: %{public}d", node->GetWindowId()); + if (!node->currentVisibility_) { + WLOGFD("window: %{public}d is invisible, do not need update RS tree", node->GetWindowId()); + return false; + } + node->leashWinSurfaceNode_->AddChild(node->surfaceNode_, -1); + return true; +} + +bool WindowNodeContainer::AddNodeOnRSTree(sptr& node, DisplayId displayId, DisplayId parentDisplayId, + WindowUpdateType type, bool animationPlayed) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + if (node->GetWindowProperty()->GetAnimationFlag() == static_cast(WindowAnimation::CUSTOM) || + node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) { + WLOGFD("not need to update RSTree"); + return true; + } + bool isMultiDisplay = layoutPolicy_->IsMultiDisplay(); + WLOGFD("AddNodeOnRSTree windowId: %{public}d, displayId: %{public}" PRIu64", parentDisplayId: %{public}" PRIu64", " + "isMultiDisplay: %{public}d, animationPlayed: %{public}d", + node->GetWindowId(), displayId, parentDisplayId, isMultiDisplay, animationPlayed); + auto updateRSTreeFunc = [&]() { + auto& dms = DisplayManagerServiceInner::GetInstance(); + if (!node->currentVisibility_) { + WLOGFD("window: %{public}d is invisible, do not need update RS tree", node->GetWindowId()); + return; + } + auto& surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_; + dms.UpdateRSTree(displayId, parentDisplayId, surfaceNode, true, isMultiDisplay); + for (auto& child : node->children_) { + if (child->currentVisibility_) { + dms.UpdateRSTree(displayId, parentDisplayId, child->surfaceNode_, true, isMultiDisplay); + } + } + }; + + if (type != WindowUpdateType::WINDOW_UPDATE_ADDED && type != WindowUpdateType::WINDOW_UPDATE_REMOVED) { + updateRSTreeFunc(); + return true; + } + + if (node->EnableDefaultAnimation(animationPlayed)) { + WLOGFD("add window with animation"); + StartTraceArgs(HITRACE_TAG_WINDOW_MANAGER, "Animate(%u)", node->GetWindowId()); + RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_, + animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc); + FinishTrace(HITRACE_TAG_WINDOW_MANAGER); + } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT && + !animationPlayed) { // add keyboard with animation + ProcessInputMethodWindowAddAnimation(node, updateRSTreeFunc); + } else { + WLOGFD("add window without animation"); + updateRSTreeFunc(); + } + return true; +} + +void WindowNodeContainer::ProcessInputMethodWindowAddAnimation(sptr& node, + std::function updateRSTreeFunc) +{ + static sptr imeNode = nullptr; + if (imeNode == node && imeNode != nullptr && imeNode->surfaceNode_ != nullptr) { + WLOGFD("imeNode SetAppFreeze(true)"); + imeNode->surfaceNode_->SetAppFreeze(true); + } + sptr launcherNode = nullptr; + for (auto& windowNode : belowAppWindowNode_->children_) { + if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + launcherNode = windowNode; + break; + } + } + if (launcherNode != nullptr && launcherNode->surfaceNode_ != nullptr) { + WLOGFD("launcherNode SetAppFreeze(true)"); + launcherNode->surfaceNode_->SetAppFreeze(true); + } + auto timingProtocol = animationConfig_.keyboardAnimationConfig_.durationIn_; + RSNode::Animate(timingProtocol, animationConfig_.keyboardAnimationConfig_.curve_, updateRSTreeFunc, + [ime = imeNode, node, launcherNode]() { + if (ime == node && ime != nullptr && ime->surfaceNode_ != nullptr) { + WLOGFD("imeNode SetAppFreeze(false)"); + ime->surfaceNode_->SetAppFreeze(false); + } + if (launcherNode != nullptr && launcherNode->surfaceNode_ != nullptr) { + WLOGFD("launcherNode SetAppFreeze(false)"); + launcherNode->surfaceNode_->SetAppFreeze(false); + } + auto transactionProxy = RSTransactionProxy::GetInstance(); + if (transactionProxy != nullptr) { + transactionProxy->FlushImplicitTransaction(); + } + }); + imeNode = node; +} + +bool WindowNodeContainer::RemoveNodeFromRSTree(sptr& node, DisplayId displayId, DisplayId parentDisplayId, + WindowUpdateType type, bool animationPlayed) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + if (node->GetWindowProperty()->GetAnimationFlag() == static_cast(WindowAnimation::CUSTOM) || + node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) { + WLOGFD("not need to update RSTree"); + return true; + } + bool isMultiDisplay = layoutPolicy_->IsMultiDisplay(); + WLOGFD("RemoveNodeFromRSTree windowId: %{public}d, displayId: %{public}" PRIu64", isMultiDisplay: %{public}d, " + "parentDisplayId: %{public}" PRIu64", animationPlayed: %{public}d", + node->GetWindowId(), displayId, isMultiDisplay, parentDisplayId, animationPlayed); + auto updateRSTreeFunc = [&]() { + auto& dms = DisplayManagerServiceInner::GetInstance(); + auto& surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_; + dms.UpdateRSTree(displayId, parentDisplayId, surfaceNode, false, isMultiDisplay); + for (auto& child : node->children_) { + if (child->currentVisibility_) { + dms.UpdateRSTree(displayId, parentDisplayId, child->surfaceNode_, false, isMultiDisplay); + } + } + }; + + if (type != WindowUpdateType::WINDOW_UPDATE_ADDED && type != WindowUpdateType::WINDOW_UPDATE_REMOVED) { + updateRSTreeFunc(); + return true; + } + + if (node->EnableDefaultAnimation(animationPlayed)) { + WLOGFD("remove window with animation"); + StartTraceArgs(HITRACE_TAG_WINDOW_MANAGER, "Animate(%u)", node->GetWindowId()); + if (node->surfaceNode_) { + node->surfaceNode_->SetAppFreeze(true); + } + wptr weakNode(node); + RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_, + animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc, [weakNode]() { + auto weakWindow = weakNode.promote(); + if (weakWindow && weakWindow->surfaceNode_) { + weakWindow->surfaceNode_->SetAppFreeze(false); + } + }); + FinishTrace(HITRACE_TAG_WINDOW_MANAGER); + } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT && + !animationPlayed) { // remove keyboard with animation + auto timingProtocol = animationConfig_.keyboardAnimationConfig_.durationOut_; + RSNode::Animate(timingProtocol, animationConfig_.keyboardAnimationConfig_.curve_, updateRSTreeFunc); + } else { + WLOGFD("remove window without animation"); + updateRSTreeFunc(); + } + return true; +} + +const std::vector& WindowNodeContainer::Destroy() +{ + // clear vector cache completely, swap with empty vector + auto emptyVector = std::vector(); + removedIds_.swap(emptyVector); + for (auto& node : belowAppWindowNode_->children_) { + DestroyWindowNode(node, removedIds_); + } + for (auto& node : appWindowNode_->children_) { + DestroyWindowNode(node, removedIds_); + } + for (auto& node : aboveAppWindowNode_->children_) { + DestroyWindowNode(node, removedIds_); + } + return removedIds_; +} + +sptr WindowNodeContainer::FindRoot(WindowType type) const +{ + if (WindowHelper::IsAppWindow(type) || type == WindowType::WINDOW_TYPE_DOCK_SLICE || + type == WindowType::WINDOW_TYPE_APP_COMPONENT || type == WindowType::WINDOW_TYPE_PLACEHOLDER || + type == WindowType::WINDOW_TYPE_DIALOG) { + return appWindowNode_; + } + if (WindowHelper::IsBelowSystemWindow(type)) { + return belowAppWindowNode_; + } + if (WindowHelper::IsAboveSystemWindow(type)) { + return aboveAppWindowNode_; + } + return nullptr; +} + +sptr WindowNodeContainer::FindWindowNodeById(uint32_t id) const +{ + std::vector> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ }; + for (const auto& rootNode : rootNodes) { + for (auto& node : rootNode->children_) { + if (node->GetWindowId() == id) { + return node; + } + for (auto& subNode : node->children_) { + if (subNode->GetWindowId() == id) { + return subNode; + } + } + } + } + return nullptr; +} + +void WindowNodeContainer::UpdateFocusStatus(uint32_t id, bool focused) +{ + auto node = FindWindowNodeById(id); + if (node == nullptr) { + WLOGFW("cannot find focused window id:%{public}d", id); + return; + } + if (focused) { + focusedPid_ = node->GetCallingPid(); + } + + if (node->GetCallingPid() == 0) { + WLOGFW("focused window is starting window, no need notify"); + return; + } + + if (focused && node->GetWindowProperty() != nullptr) { + AbilityInfo info = node->GetWindowProperty()->GetAbilityInfo(); + WLOGFW("current focus window: windowId: %{public}d, windowName: %{public}s, bundleName: %{public}s," + " abilityName: %{public}s, pid: %{public}d, uid: %{public}d", id, + node->GetWindowProperty()->GetWindowName().c_str(), info.bundleName_.c_str(), info.abilityName_.c_str(), + node->GetCallingPid(), node->GetCallingUid()); + FocusAppInfo appInfo = { node->GetCallingPid(), node->GetCallingUid(), info.bundleName_, info.abilityName_ }; + RSInterfaces::GetInstance().SetFocusAppInfo(appInfo); + } + if (node->GetWindowToken()) { + node->GetWindowToken()->UpdateFocusStatus(focused); + } + if (node->abilityToken_ == nullptr) { + WLOGFD("abilityToken is null, window : %{public}d", id); + } + sptr focusChangeInfo = new FocusChangeInfo(node->GetWindowId(), node->GetDisplayId(), + node->GetCallingPid(), node->GetCallingUid(), node->GetWindowType(), node->abilityToken_); + WindowManagerAgentController::GetInstance().UpdateFocusChangeInfo( + focusChangeInfo, focused); +} + +void WindowNodeContainer::UpdateActiveStatus(uint32_t id, bool isActive) +{ + auto node = FindWindowNodeById(id); + if (node == nullptr) { + WLOGFE("cannot find active window id: %{public}d", id); + return; + } + if (isActive) { + activePid_ = node->GetCallingPid(); + } + if (node->GetWindowToken()) { + node->GetWindowToken()->UpdateActiveStatus(isActive); + } +} + +void WindowNodeContainer::UpdateBrightness(uint32_t id, bool byRemoved) +{ + auto node = FindWindowNodeById(id); + if (node == nullptr) { + WLOGFE("cannot find active window id: %{public}d", id); + return; + } + + if (!byRemoved) { + if (!WindowHelper::IsAppWindow(node->GetWindowType())) { + return; + } + } + WLOGFD("brightness: [%{public}f, %{public}f]", GetDisplayBrightness(), node->GetBrightness()); + if (std::fabs(node->GetBrightness() - UNDEFINED_BRIGHTNESS) < std::numeric_limits::min()) { + if (GetDisplayBrightness() != node->GetBrightness()) { + WLOGFD("adjust brightness with default value"); + DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().RestoreBrightness(); + SetDisplayBrightness(UNDEFINED_BRIGHTNESS); // UNDEFINED_BRIGHTNESS means system default brightness + } + SetBrightnessWindow(INVALID_WINDOW_ID); + } else { + if (GetDisplayBrightness() != node->GetBrightness()) { + WLOGFD("adjust brightness with value: %{public}u", ToOverrideBrightness(node->GetBrightness())); + DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().OverrideBrightness( + ToOverrideBrightness(node->GetBrightness())); + SetDisplayBrightness(node->GetBrightness()); + } + SetBrightnessWindow(node->GetWindowId()); + } +} + +void WindowNodeContainer::AssignZOrder() +{ + zOrder_ = 0; + WindowNodeOperationFunc func = [this](sptr node) { + if (!node->leashWinSurfaceNode_ && !node->surfaceNode_ && !node->startingWinSurfaceNode_) { + ++zOrder_; + WLOGFE("Id: %{public}u has no surface nodes", node->GetWindowId()); + return false; + } + if (node->leashWinSurfaceNode_ != nullptr) { + ++zOrder_; + node->leashWinSurfaceNode_->SetPositionZ(zOrder_); + } + + if (node->surfaceNode_ != nullptr) { + ++zOrder_; + node->surfaceNode_->SetPositionZ(zOrder_); + node->zOrder_ = zOrder_; + } + // make sure starting window above app + if (node->startingWinSurfaceNode_ != nullptr) { + ++zOrder_; + node->startingWinSurfaceNode_->SetPositionZ(zOrder_); + } + return false; + }; + TraverseWindowTree(func, false); + displayGroupController_->UpdateDisplayGroupWindowTree(); +} + +WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId) +{ + if (focusedWindow_ == windowId) { + WLOGFD("focused window no change, id: %{public}u, %{public}d", windowId, focusedPid_); + // StartingWindow can be focused and this pid is 0, then notify info in UpdateFocusStatus. + // This info is invalid, so we must notify again when first frame callback. + if (focusedPid_ == 0) { + UpdateFocusStatus(windowId, true); + } + return WMError::WM_DO_NOTHING; + } + UpdateFocusStatus(focusedWindow_, false); + focusedWindow_ = windowId; + UpdateFocusStatus(focusedWindow_, true); + return WMError::WM_OK; +} + +uint32_t WindowNodeContainer::GetFocusWindow() const +{ + return focusedWindow_; +} + +WMError WindowNodeContainer::SetActiveWindow(uint32_t windowId, bool byRemoved) +{ + if (activeWindow_ == windowId) { + WLOGFD("active window not change, id: %{public}u, %{public}d", windowId, activePid_); + if (activePid_ == 0) { + UpdateActiveStatus(windowId, true); + } + return WMError::WM_DO_NOTHING; + } + UpdateActiveStatus(activeWindow_, false); + activeWindow_ = windowId; + UpdateActiveStatus(activeWindow_, true); + UpdateBrightness(activeWindow_, byRemoved); + return WMError::WM_OK; +} + +void WindowNodeContainer::SetDisplayBrightness(float brightness) +{ + displayBrightness_ = brightness; +} + +float WindowNodeContainer::GetDisplayBrightness() const +{ + return displayBrightness_; +} + +void WindowNodeContainer::SetBrightnessWindow(uint32_t windowId) +{ + brightnessWindow_ = windowId; +} + +uint32_t WindowNodeContainer::GetBrightnessWindow() const +{ + return brightnessWindow_; +} + +uint32_t WindowNodeContainer::ToOverrideBrightness(float brightness) +{ + return static_cast(brightness * MAX_BRIGHTNESS); +} + +uint32_t WindowNodeContainer::GetActiveWindow() const +{ + return activeWindow_; +} + +sptr WindowNodeContainer::GetLayoutPolicy() const +{ + return layoutPolicy_; +} + +sptr WindowNodeContainer::GetAvoidController() const +{ + return avoidController_; +} + +sptr WindowNodeContainer::GetMultiDisplayController() const +{ + return displayGroupController_; +} + +sptr WindowNodeContainer::GetRootNode(WindowRootNodeType type) const +{ + if (type == WindowRootNodeType::ABOVE_WINDOW_NODE) { + return aboveAppWindowNode_; + } else if (type == WindowRootNodeType::APP_WINDOW_NODE) { + return appWindowNode_; + } else if (type == WindowRootNodeType::BELOW_WINDOW_NODE) { + return belowAppWindowNode_; + } + return nullptr; +} + +void WindowNodeContainer::HandleKeepScreenOn(const sptr& node, bool requireLock) +{ + if (requireLock && node->keepScreenLock_ == nullptr) { + // reset ipc identity + std::string identity = IPCSkeleton::ResetCallingIdentity(); + node->keepScreenLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock(node->GetWindowName(), + PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN); + // set ipc identity to raw + IPCSkeleton::SetCallingIdentity(identity); + } + if (node->keepScreenLock_ == nullptr) { + return; + } + WLOGFD("handle keep screen on: [%{public}s, %{public}d]", node->GetWindowName().c_str(), requireLock); + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "container:HandleKeepScreenOn(%s, %d)", + node->GetWindowName().c_str(), requireLock); + ErrCode res; + // reset ipc identity + std::string identity = IPCSkeleton::ResetCallingIdentity(); + if (requireLock) { + res = node->keepScreenLock_->Lock(); + } else { + res = node->keepScreenLock_->UnLock(); + } + // set ipc identity to raw + IPCSkeleton::SetCallingIdentity(identity); + if (res != ERR_OK) { + WLOGFE("handle keep screen running lock failed: [operation: %{public}d, err: %{public}d]", requireLock, res); + } +} + +bool WindowNodeContainer::IsAboveSystemBarNode(sptr node) const +{ + int32_t curPriority = zorderPolicy_->GetWindowPriority(node->GetWindowType()); + if ((curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_STATUS_BAR)) && + (curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_NAVIGATION_BAR))) { + return true; + } + return false; +} + +bool WindowNodeContainer::IsSplitImmersiveNode(sptr node) const +{ + auto type = node->GetWindowType(); + return node->IsSplitMode() || type == WindowType::WINDOW_TYPE_DOCK_SLICE; +} + +std::unordered_map WindowNodeContainer::GetExpectImmersiveProperty() const +{ + std::unordered_map sysBarPropMap { + { WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarProperty() }, + { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarProperty() }, + }; + + std::vector> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ }; + for (const auto& node : rootNodes) { + for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); ++iter) { + auto& sysBarPropMapNode = (*iter)->GetSystemBarProperty(); + if (IsAboveSystemBarNode(*iter)) { + continue; + } + if (WindowHelper::IsFullScreenWindow((*iter)->GetWindowMode()) + && (*iter)->GetWindowType() != WindowType::WINDOW_TYPE_PANEL) { + WLOGFD("Top immersive window id: %{public}d. Use full immersive prop", (*iter)->GetWindowId()); + for (auto it : sysBarPropMap) { + sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second; + } + return sysBarPropMap; + } else if (IsSplitImmersiveNode(*iter)) { + WLOGFD("Top split window id: %{public}d. Use split immersive prop", (*iter)->GetWindowId()); + for (auto it : sysBarPropMap) { + sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second; + sysBarPropMap[it.first].enable_ = false; + } + return sysBarPropMap; + } + } + } + + WLOGFD("No immersive window on top. Use default systembar Property"); + return sysBarPropMap; +} + +void WindowNodeContainer::NotifyIfAvoidAreaChanged(const sptr& node, + const AvoidControlType avoidType) const +{ + auto checkFunc = [this](sptr node) { + return CheckWindowNodeWhetherInWindowTree(node); + }; + avoidController_->ProcessWindowChange(node, avoidType, checkFunc); + if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) { + NotifyIfSystemBarRegionChanged(node->GetDisplayId()); + } else { + NotifyIfSystemBarTintChanged(node->GetDisplayId()); + } + + NotifyIfKeyboardRegionChanged(node, avoidType); +} + +void WindowNodeContainer::BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const +{ + avoidController_->SetFlagForProcessWindowChange(true); +} + +void WindowNodeContainer::ProcessWindowAvoidAreaChangeWhenDisplayChange() const +{ + avoidController_->SetFlagForProcessWindowChange(false); + auto checkFunc = [this](sptr node) { + return CheckWindowNodeWhetherInWindowTree(node); + }; + WindowNodeOperationFunc func = [avoidController = avoidController_, &checkFunc](sptr node) { + avoidController->ProcessWindowChange(node, AvoidControlType::AVOID_NODE_UPDATE, checkFunc); + return false; + }; + TraverseWindowTree(func, true); +} + +void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) const +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + auto expectSystemBarProp = GetExpectImmersiveProperty(); + SystemBarRegionTints tints; + SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId]; + for (auto it : sysBarTintMap) { + auto expectProp = expectSystemBarProp.find(it.first)->second; + if (it.second.prop_ == expectProp) { + continue; + } + WLOGFD("System bar prop update, Type: %{public}d, Visible: %{public}d, Color: %{public}x | %{public}x", + static_cast(it.first), expectProp.enable_, expectProp.backgroundColor_, expectProp.contentColor_); + sysBarTintMap[it.first].prop_ = expectProp; + sysBarTintMap[it.first].type_ = it.first; + tints.emplace_back(sysBarTintMap[it.first]); + } + WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); +} + +void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) const +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + SystemBarRegionTints tints; + SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId]; + SysBarNodeMap& sysBarNodeMap = displayGroupController_->sysBarNodeMaps_[displayId]; + for (auto it : sysBarTintMap) { // split screen mode not support yet + auto sysNode = sysBarNodeMap[it.first]; + if (sysNode == nullptr || it.second.region_ == sysNode->GetWindowRect()) { + continue; + } + const Rect& newRegion = sysNode->GetWindowRect(); + sysBarTintMap[it.first].region_ = newRegion; + sysBarTintMap[it.first].type_ = it.first; + tints.emplace_back(sysBarTintMap[it.first]); + WLOGFD("system bar region update, type: %{public}d" \ + "region: [%{public}d, %{public}d, %{public}d, %{public}d]", + static_cast(it.first), newRegion.posX_, newRegion.posY_, newRegion.width_, newRegion.height_); + } + WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); +} + +void WindowNodeContainer::NotifyIfKeyboardRegionChanged(const sptr& node, + const AvoidControlType avoidType) const +{ + if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { + WLOGFD("windowType: %{public}u", node->GetWindowType()); + return; + } + + auto callingWindow = FindWindowNodeById(node->GetCallingWindow()); + if (callingWindow == nullptr) { + WLOGFD("callingWindow: %{public}u does not be set", node->GetCallingWindow()); + callingWindow = FindWindowNodeById(GetFocusWindow()); + } + if (callingWindow == nullptr || callingWindow->GetWindowToken() == nullptr) { + WLOGFE("does not have correct callingWindow for input method window"); + return; + } + const WindowMode callingWindowMode = callingWindow->GetWindowMode(); + if (callingWindowMode == WindowMode::WINDOW_MODE_FULLSCREEN || + callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + const Rect keyRect = node->GetWindowRect(); + const Rect callingRect = callingWindow->GetWindowRect(); + if (WindowHelper::IsEmptyRect(WindowHelper::GetOverlap(callingRect, keyRect, 0, 0))) { + WLOGFD("no overlap between two windows"); + return; + } + Rect overlapRect = { 0, 0, 0, 0 }; + if (avoidType == AvoidControlType::AVOID_NODE_ADD || avoidType == AvoidControlType::AVOID_NODE_UPDATE) { + overlapRect = WindowHelper::GetOverlap(keyRect, callingRect, callingRect.posX_, callingRect.posY_); + } + + WLOGFD("keyboard size change callingWindow: [%{public}s, %{public}u], " \ + "overlap rect: [%{public}d, %{public}d, %{public}u, %{public}u]", + callingWindow->GetWindowName().c_str(), callingWindow->GetWindowId(), + overlapRect.posX_, overlapRect.posY_, overlapRect.width_, overlapRect.height_); + sptr info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT, overlapRect); + callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info); + return; + } + WLOGFE("does not have correct callingWindowMode for input method window"); +} + +void WindowNodeContainer::NotifySystemBarTints(std::vector displayIdVec) +{ + if (displayIdVec.size() != displayGroupController_->sysBarTintMaps_.size()) { + WLOGE("[Immersive] the number of display is error"); + } + + for (auto displayId : displayIdVec) { + SystemBarRegionTints tints; + SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId]; + for (auto it : sysBarTintMap) { + WLOGFD("[Immersive] system bar cur notify, T: %{public}d, " \ + "V: %{public}d, C: %{public}x | %{public}x, " \ + "R: [%{public}d, %{public}d, %{public}d, %{public}d]", + static_cast(it.first), + sysBarTintMap[it.first].prop_.enable_, + sysBarTintMap[it.first].prop_.backgroundColor_, sysBarTintMap[it.first].prop_.contentColor_, + sysBarTintMap[it.first].region_.posX_, sysBarTintMap[it.first].region_.posY_, + sysBarTintMap[it.first].region_.width_, sysBarTintMap[it.first].region_.height_); + tints.push_back(sysBarTintMap[it.first]); + } + WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); + } +} + +void WindowNodeContainer::NotifyDockWindowStateChanged(sptr& node, bool isEnable) +{ + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + WLOGFD("[Immersive] begin isEnable: %{public}d", isEnable); + if (isEnable) { + for (auto& windowNode : appWindowNode_->children_) { + if (windowNode->GetWindowId() == node->GetWindowId()) { + continue; + } + if (!WindowHelper::IsFloatingWindow(windowNode->GetWindowMode())) { + return; + } + } + } + SystemBarProperty prop; + prop.enable_ = isEnable; + SystemBarRegionTint tint; + tint.type_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + tint.prop_ = prop; + SystemBarRegionTints tints; + tints.push_back(tint); + WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(node->GetDisplayId(), tints); +} + +void WindowNodeContainer::UpdateAvoidAreaListener(sptr& windowNode, bool haveAvoidAreaListener) +{ + avoidController_->UpdateAvoidAreaListener(windowNode, haveAvoidAreaListener); +} + +bool WindowNodeContainer::IsTopWindow(uint32_t windowId, sptr& rootNode) const +{ + if (rootNode->children_.empty()) { + WLOGFE("root does not have any node"); + return false; + } + auto node = *(rootNode->children_.rbegin()); + if (node == nullptr) { + WLOGFE("window tree does not have any node"); + return false; + } + + for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); iter++) { + if ((*iter)->priority_ > 0) { + return (*iter)->GetWindowId() == windowId; + } else { + break; + } + } + return node->GetWindowId() == windowId; +} + +void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector>& orderedNodes, + std::vector>& windowNodes) +{ + for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end();) { + uint32_t wid = (*iter)->GetWindowId(); + auto orderedIter = std::find_if(orderedNodes.begin(), orderedNodes.end(), + [wid] (sptr orderedNode) { return orderedNode->GetWindowId() == wid; }); + if (orderedIter != orderedNodes.end()) { + iter = windowNodes.erase(iter); + } else { + iter++; + } + } + for (auto iter = orderedNodes.begin(); iter != orderedNodes.end(); iter++) { + UpdateWindowTree(*iter); + } + return; +} + +void WindowNodeContainer::RaiseWindowToTop(uint32_t windowId, std::vector>& windowNodes) +{ + if (windowNodes.empty()) { + WLOGFE("windowNodes is empty!"); + return; + } + auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), + [windowId](sptr node) { + return node->GetWindowId() == windowId; + }); + // raise app node window to top + if (iter != windowNodes.end()) { + sptr node = *iter; + windowNodes.erase(iter); + UpdateWindowTree(node); + WLOGFD("raise window to top %{public}u", node->GetWindowId()); + } +} + +void WindowNodeContainer::TraverseContainer(std::vector>& windowNodes) const +{ + for (auto& node : belowAppWindowNode_->children_) { + TraverseWindowNode(node, windowNodes); + } + for (auto& node : appWindowNode_->children_) { + TraverseWindowNode(node, windowNodes); + } + for (auto& node : aboveAppWindowNode_->children_) { + TraverseWindowNode(node, windowNodes); + } + std::reverse(windowNodes.begin(), windowNodes.end()); +} + +void WindowNodeContainer::TraverseWindowNode(sptr& node, std::vector>& windowNodes) const +{ + if (node == nullptr) { + return; + } + auto iter = node->children_.begin(); + for (; iter < node->children_.end(); ++iter) { + if ((*iter)->priority_ < 0) { + windowNodes.emplace_back(*iter); + } else { + break; + } + } + windowNodes.emplace_back(node); + for (; iter < node->children_.end(); ++iter) { + windowNodes.emplace_back(*iter); + } +} + +AvoidArea WindowNodeContainer::GetAvoidAreaByType(const sptr& node, AvoidAreaType avoidAreaType) const +{ + if (CheckWindowNodeWhetherInWindowTree(node)) { + return avoidController_->GetAvoidAreaByType(node, avoidAreaType); + } + return {}; +} + +bool WindowNodeContainer::CheckWindowNodeWhetherInWindowTree(const sptr& node) const +{ + bool isInWindowTree = false; + WindowNodeOperationFunc func = [&node, &isInWindowTree](sptr windowNode) { + if (node->GetWindowId() == windowNode->GetWindowId()) { + isInWindowTree = true; + return true; + } + return false; + }; + TraverseWindowTree(func, true); + return isInWindowTree; +} + +void WindowNodeContainer::DumpScreenWindowTree() +{ + WLOGFD("-------- dump window info begin---------"); + WLOGFD("WindowName DisplayId WinId Type Mode Flag ZOrd Orientation abilityToken [ x y w h]"); + uint32_t zOrder = zOrder_; + WindowNodeOperationFunc func = [&zOrder](sptr node) { + Rect rect = node->GetWindowRect(); + const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ? + node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH); + WLOGFD("DumpScreenWindowTree: %{public}10s %{public}9" PRIu64" %{public}5u %{public}4u %{public}4u %{public}4u " + "%{public}4u %{public}11u %{public}12d [%{public}4d %{public}4d %{public}4u %{public}4u]", + windowName.c_str(), node->GetDisplayId(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(), + node->GetWindowFlags(), --zOrder, static_cast(node->GetRequestedOrientation()), + node->abilityToken_ != nullptr, rect.posX_, rect.posY_, rect.width_, rect.height_); + return false; + }; + TraverseWindowTree(func, true); + WLOGFD("-------- dump window info end ---------"); +} + +Rect WindowNodeContainer::GetDisplayRect(DisplayId displayId) const +{ + return displayGroupInfo_->GetDisplayRect(displayId); +} + +bool WindowNodeContainer::IsVerticalDisplay(DisplayId displayId) const +{ + return displayGroupInfo_->GetDisplayRect(displayId).width_ < displayGroupInfo_->GetDisplayRect(displayId).height_; +} + +void WindowNodeContainer::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason) +{ + switch (reason) { + case WindowStateChangeReason::KEYGUARD: { + int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD); + TraverseAndUpdateWindowState(state, topPriority); + break; + } + default: + return; + } +} + +void WindowNodeContainer::TraverseAndUpdateWindowState(WindowState state, int32_t topPriority) +{ + std::vector> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ }; + for (auto& node : rootNodes) { + UpdateWindowState(node, topPriority, state); + } +} + +void WindowNodeContainer::UpdateWindowState(sptr node, int32_t topPriority, WindowState state) +{ + if (node == nullptr) { + return; + } + if (node->parent_ != nullptr && node->currentVisibility_) { + if (node->priority_ < topPriority && !WindowHelper::IsShowWhenLocked(node->GetWindowFlags()) && + !WindowHelper::IsShowWhenLocked(node->parent_->GetWindowFlags())) { + if (node->GetWindowToken()) { + node->GetWindowToken()->UpdateWindowState(state); + } + HandleKeepScreenOn(node, state); + } + } + for (auto& childNode : node->children_) { + UpdateWindowState(childNode, topPriority, state); + } +} + +void WindowNodeContainer::HandleKeepScreenOn(const sptr& node, WindowState state) +{ + if (node == nullptr) { + WLOGFE("window is invalid"); + return; + } + if (state == WindowState::STATE_FROZEN) { + HandleKeepScreenOn(node, false); + } else if (state == WindowState::STATE_UNFROZEN) { + HandleKeepScreenOn(node, node->IsKeepScreenOn()); + } else { + // do nothing + } +} + +sptr WindowNodeContainer::FindDividerNode() const +{ + for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end(); iter++) { + if ((*iter)->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + return *iter; + } + } + return nullptr; +} + +void WindowNodeContainer::RaiseSplitRelatedWindowToTop(sptr& node) +{ + if (node == nullptr) { + return; + } + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId()); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return; + } + std::vector> orderedPair = windowPair->GetOrderedPair(node); + RaiseOrderedWindowToTop(orderedPair, appWindowNode_->children_); + AssignZOrder(); + return; +} + +WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr& node, sptr& parentNode) +{ + if (node == nullptr) { + return WMError::WM_ERROR_NULLPTR; + } + if (IsTopWindow(node->GetWindowId(), appWindowNode_) || IsTopWindow(node->GetWindowId(), aboveAppWindowNode_)) { + WLOGFD("it is already top app window, id: %{public}u", node->GetWindowId()); + return WMError::WM_ERROR_INVALID_TYPE; + } + + if (WindowHelper::IsSubWindow(node->GetWindowType()) || + (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) { + if (parentNode == nullptr) { + WLOGFE("window type is invalid"); + return WMError::WM_ERROR_NULLPTR; + } + RaiseWindowToTop(node->GetWindowId(), parentNode->children_); // raise itself + if (parentNode->IsSplitMode()) { + RaiseSplitRelatedWindowToTop(parentNode); + } else if (parentNode->parent_ != nullptr) { + RaiseWindowToTop(parentNode->GetWindowId(), parentNode->parent_->children_); // raise parent window + } + } else if (WindowHelper::IsMainWindow(node->GetWindowType())) { + if (node->IsSplitMode()) { + RaiseSplitRelatedWindowToTop(node); + } else { + // remote animation continuous start and exit allow parent is nullptr + if (node->parent_ == nullptr) { + WLOGFW("node parent is nullptr"); + return WMError::WM_OK; + } + RaiseWindowToTop(node->GetWindowId(), node->parent_->children_); + } + } else { + // do nothing + } + AssignZOrder(); + WLOGFD("RaiseZOrderForAppWindow finished"); + DumpScreenWindowTree(); + return WMError::WM_OK; +} + +sptr WindowNodeContainer::GetNextFocusableWindow(uint32_t windowId) const +{ + sptr nextFocusableWindow; + bool previousFocusedWindowFound = false; + WindowNodeOperationFunc func = [windowId, &nextFocusableWindow, &previousFocusedWindowFound]( + sptr node) { + if (previousFocusedWindowFound && node->GetWindowProperty()->GetFocusable() && node->currentVisibility_) { + nextFocusableWindow = node; + return true; + } + if (node->GetWindowId() == windowId) { + previousFocusedWindowFound = true; + } + return false; + }; + TraverseWindowTree(func, true); + return nextFocusableWindow; +} + +sptr WindowNodeContainer::GetNextRotatableWindow(uint32_t windowId) const +{ + sptr nextRotatableWindow; + WindowNodeOperationFunc func = [windowId, &nextRotatableWindow]( + sptr node) { + if (windowId != node->GetWindowId() && + WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) { + nextRotatableWindow = node; + return true; + } + return false; + }; + TraverseWindowTree(func, true); + return nextRotatableWindow; +} + +sptr WindowNodeContainer::GetNextActiveWindow(uint32_t windowId) const +{ + auto currentNode = FindWindowNodeById(windowId); + if (currentNode == nullptr) { + WLOGFE("cannot find window id: %{public}u by tree", windowId); + return nullptr; + } + WLOGFD("current window: [%{public}u, %{public}u]", windowId, static_cast(currentNode->GetWindowType())); + if (WindowHelper::IsSystemWindow(currentNode->GetWindowType())) { + for (auto& node : appWindowNode_->children_) { + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + continue; + } + return node; + } + for (auto& node : belowAppWindowNode_->children_) { + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + return node; + } + } + } else if (WindowHelper::IsAppWindow(currentNode->GetWindowType())) { + 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()) { + WLOGFE("could not find this window"); + return nullptr; + } + int index = std::distance(windowNodes.begin(), iter); + for (size_t i = static_cast(index) + 1; i < windowNodes.size(); i++) { + if (windowNodes[i]->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE + || !windowNodes[i]->currentVisibility_) { + continue; + } + return windowNodes[i]; + } + } else { + // do nothing + } + WLOGFE("could not get next active window"); + return nullptr; +} + +bool WindowNodeContainer::IsForbidDockSliceMove(DisplayId displayId) const +{ + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr) { + WLOGFE("window pair is nullptr"); + return true; + } + if (windowPair->IsForbidDockSliceMove()) { + return true; + } + return false; +} + +bool WindowNodeContainer::IsDockSliceInExitSplitModeArea(DisplayId displayId) const +{ + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr) { + WLOGFE("window pair is nullptr"); + return false; + } + std::vector exitSplitPoints = layoutPolicy_->GetExitSplitPoints(displayId); + if (exitSplitPoints.size() != EXIT_SPLIT_POINTS_NUMBER) { + return false; + } + return windowPair->IsDockSliceInExitSplitModeArea(exitSplitPoints); +} + +void WindowNodeContainer::ExitSplitMode(DisplayId displayId) +{ + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr) { + WLOGFE("window pair is nullptr"); + return; + } + windowPair->ExitSplitMode(); +} + +void WindowNodeContainer::MinimizeAllAppWindows(DisplayId displayId) +{ + WMError ret = MinimizeAppNodeExceptOptions(MinimizeReason::MINIMIZE_ALL); + SwitchLayoutPolicy(WindowLayoutMode::CASCADE, displayId); + if (ret != WMError::WM_OK) { + WLOGFE("Minimize all app window failed"); + } + return; +} + +sptr WindowNodeContainer::GetDeskTopWindow() +{ + sptr deskTop; + WindowNodeOperationFunc findDeskTopFunc = [this, &deskTop](sptr node) { + if (node->GetWindowProperty()->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { + deskTop = node; + return true; + } + return false; + }; + TraverseWindowTree(findDeskTopFunc, false); + return deskTop; +} + +bool WindowNodeContainer::HasPrivateWindow() +{ + std::vector> windowNodes; + TraverseContainer(windowNodes); + for (const auto& node : windowNodes) { + if (node->isVisible_ && node->GetWindowProperty()->GetPrivacyMode()) { + WLOGFD("window name %{public}s", node->GetWindowName().c_str()); + return true; + } + } + return false; +} + +void WindowNodeContainer::MinimizeOldestAppWindow() +{ + for (auto& appNode : appWindowNode_->children_) { + if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { + MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT); + return; + } + } + for (auto& appNode : aboveAppWindowNode_->children_) { + if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { + MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT); + return; + } + } + WLOGFD("no window needs to minimize"); +} + +WMError WindowNodeContainer::ToggleShownStateForAllAppWindows( + std::function restoreFunc, bool restore) +{ + WLOGFD("ToggleShownStateForAllAppWindows"); + for (auto node : aboveAppWindowNode_->children_) { + if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT && + node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && restore) { + return WMError::WM_DO_NOTHING; + } + } + // to do, backup reentry: 1.ToggleShownStateForAllAppWindows fast; 2.this display should reset backupWindowIds_. + if (!restore && appWindowNode_->children_.empty() && !backupWindowIds_.empty()) { + backupWindowIds_.clear(); + backupWindowMode_.clear(); + backupDisplaySplitWindowMode_.clear(); + backupDividerWindowRect_.clear(); + } + if (!restore && !appWindowNode_->children_.empty() && backupWindowIds_.empty()) { + WLOGFD("backup"); + BackUpAllAppWindows(); + } else if (restore && !backupWindowIds_.empty()) { + WLOGFD("restore"); + RestoreAllAppWindows(restoreFunc); + } else { + WLOGFD("do nothing because shown app windows is empty or backup windows is empty."); + } + return WMError::WM_OK; +} + +void WindowNodeContainer::BackUpAllAppWindows() +{ + std::set displayIdSet; + backupWindowMode_.clear(); + backupDisplaySplitWindowMode_.clear(); + std::vector> children = appWindowNode_->children_; + for (auto& appNode : children) { + if (!WindowHelper::IsMainWindow(appNode->GetWindowType())) { + continue; + } + auto windowMode = appNode->GetWindowMode(); + backupWindowMode_[appNode->GetWindowId()] = windowMode; + if (WindowHelper::IsSplitWindowMode(windowMode)) { + backupDisplaySplitWindowMode_[appNode->GetDisplayId()].insert(windowMode); + } + displayIdSet.insert(appNode->GetDisplayId()); + } + for (auto& appNode : children) { + // exclude exceptional window + if (!WindowHelper::IsMainWindow(appNode->GetWindowType())) { + WLOGFE("is not main window, windowId:%{public}u", appNode->GetWindowId()); + continue; + } + // minimize window + WLOGFD("minimize window, windowId:%{public}u", appNode->GetWindowId()); + backupWindowIds_.emplace_back(appNode->GetWindowId()); + WindowManagerService::GetInstance().RemoveWindow(appNode->GetWindowId()); + wptr abilityToken = appNode->abilityToken_; + WindowInnerManager::GetInstance().PostTask([abilityToken]() { + auto token = abilityToken.promote(); + if (token == nullptr) { + WLOGFW("Ability token is null"); + return; + } + AAFwk::AbilityManagerClient::GetInstance()->DoAbilityBackground(token, + static_cast(WindowStateChangeReason::TOGGLING)); + }); + } + backupDividerWindowRect_.clear(); + for (auto displayId : displayIdSet) { + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr || windowPair->GetDividerWindow() == nullptr) { + continue; + } + backupDividerWindowRect_[displayId] = windowPair->GetDividerWindow()->GetWindowRect(); + } +} + +void WindowNodeContainer::RestoreAllAppWindows(std::function restoreFunc) +{ + std::vector backupWindowIds(backupWindowIds_); + auto displayIds = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds(); + std::vector> windowPairs; + for (auto displayId : displayIds) { + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair != nullptr) { + if (backupDisplaySplitWindowMode_[displayId].count(WindowMode::WINDOW_MODE_SPLIT_PRIMARY) > 0 && + backupDisplaySplitWindowMode_[displayId].count(WindowMode::WINDOW_MODE_SPLIT_SECONDARY) > 0) { + windowPair->SetAllSplitAppWindowsRestoring(true); + } + windowPairs.emplace_back(windowPair); + } + } + for (auto windowId: backupWindowIds) { + if (!restoreFunc(windowId, backupWindowMode_[windowId])) { + WLOGFE("restore %{public}u failed", windowId); + continue; + } + WLOGFD("restore %{public}u", windowId); + } + for (auto windowPair : windowPairs) { + windowPair->SetAllSplitAppWindowsRestoring(false); + } + layoutPolicy_->SetSplitDividerWindowRects(backupDividerWindowRect_); + backupWindowIds_.clear(); + backupWindowMode_.clear(); + backupDividerWindowRect_.clear(); +} + +bool WindowNodeContainer::IsAppWindowsEmpty() const +{ + return appWindowNode_->children_.empty(); +} + +WMError WindowNodeContainer::MinimizeAppNodeExceptOptions(MinimizeReason reason, + const std::vector &exceptionalIds, const std::vector &exceptionalModes) +{ + if (appWindowNode_->children_.empty()) { + return WMError::WM_OK; + } + for (auto& appNode : appWindowNode_->children_) { + // exclude exceptional window + if (std::find(exceptionalIds.begin(), exceptionalIds.end(), appNode->GetWindowId()) != exceptionalIds.end() || + std::find(exceptionalModes.begin(), exceptionalModes.end(), + appNode->GetWindowMode()) != exceptionalModes.end() || + appNode->GetWindowType() != WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { + continue; + } + MinimizeApp::AddNeedMinimizeApp(appNode, reason); + } + return WMError::WM_OK; +} + +WMError WindowNodeContainer::MinimizeStructuredAppWindowsExceptSelf(const sptr& node) +{ + std::vector exceptionalIds = { node->GetWindowId() }; + std::vector exceptionalModes = { WindowMode::WINDOW_MODE_FLOATING, WindowMode::WINDOW_MODE_PIP }; + return MinimizeAppNodeExceptOptions(MinimizeReason::OTHER_WINDOW, exceptionalIds, exceptionalModes); +} + +void WindowNodeContainer::ResetLayoutPolicy() +{ + layoutPolicy_->Reset(); +} + +WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, DisplayId displayId, bool reorder) +{ + WLOGFD("SwitchLayoutPolicy src: %{public}d dst: %{public}d, reorder: %{public}d, displayId: %{public}" PRIu64"", + static_cast(layoutMode_), static_cast(dstMode), static_cast(reorder), displayId); + if (dstMode < WindowLayoutMode::BASE || dstMode >= WindowLayoutMode::END) { + WLOGFE("invalid layout mode"); + return WMError::WM_ERROR_INVALID_PARAM; + } + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + if (layoutMode_ != dstMode) { + if (layoutMode_ == WindowLayoutMode::CASCADE) { + layoutPolicy_->Reset(); + windowPair->Clear(); + } + layoutMode_ = dstMode; + layoutPolicy_->Clean(); + layoutPolicy_ = layoutPolicies_[dstMode]; + layoutPolicy_->Launch(); + DumpScreenWindowTree(); + } else { + WLOGFD("Current layout mode is already: %{public}d", static_cast(dstMode)); + } + if (reorder) { + windowPair->Clear(); + layoutPolicy_->Reorder(); + DumpScreenWindowTree(); + } + NotifyIfSystemBarTintChanged(displayId); + return WMError::WM_OK; +} + +void WindowNodeContainer::UpdateModeSupportInfoWhenKeyguardChange(const sptr& node, bool up) +{ + if (!WindowHelper::IsWindowModeSupported(node->GetWindowProperty()->GetRequestModeSupportInfo(), + WindowMode::WINDOW_MODE_SPLIT_PRIMARY)) { + WLOGFD("window doesn't support split mode, winId: %{public}d", node->GetWindowId()); + return; + } + uint32_t modeSupportInfo; + if (up) { + modeSupportInfo = node->GetModeSupportInfo() & (~WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY); + } else { + modeSupportInfo = node->GetModeSupportInfo() | WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY; + } + node->SetModeSupportInfo(modeSupportInfo); + if (node->GetWindowToken() != nullptr) { + node->GetWindowToken()->UpdateWindowModeSupportInfo(modeSupportInfo); + } +} + +void WindowNodeContainer::RaiseInputMethodWindowPriorityIfNeeded(const sptr& node) const +{ + if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT || !isScreenLocked_) { + return; + } + + WLOGFD("raise input method float window priority."); + node->priority_ = zorderPolicy_->GetWindowPriority( + WindowType::WINDOW_TYPE_KEYGUARD) + 2; // 2: higher than keyguard and show when locked window +} + +void WindowNodeContainer::ReZOrderShowWhenLockedWindows(bool up) +{ + WLOGFD("Keyguard change %{public}u, re-zorder showWhenLocked window", up); + std::vector> needReZOrderNodes; + auto& srcRoot = up ? appWindowNode_ : aboveAppWindowNode_; + auto& dstRoot = up ? aboveAppWindowNode_ : appWindowNode_; + + auto dstPriority = up ? zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1 : + zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + + for (auto iter = srcRoot->children_.begin(); iter != srcRoot->children_.end();) { + if ((*iter)->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) { + needReZOrderNodes.emplace_back(*iter); + iter = srcRoot->children_.erase(iter); + } else { + iter++; + } + } + + for (auto& needReZOrderNode : needReZOrderNodes) { + needReZOrderNode->priority_ = dstPriority; + needReZOrderNode->parent_ = dstRoot; + auto parentNode = needReZOrderNode->parent_; + auto position = parentNode->children_.end(); + for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) { + if ((*iter)->priority_ > needReZOrderNode->priority_) { + position = iter; + break; + } + } + + UpdateModeSupportInfoWhenKeyguardChange(needReZOrderNode, up); + + parentNode->children_.insert(position, needReZOrderNode); + if (up && WindowHelper::IsSplitWindowMode(needReZOrderNode->GetWindowMode())) { + needReZOrderNode->GetWindowProperty()->ResumeLastWindowMode(); + if (needReZOrderNode->GetWindowToken() != nullptr) { + needReZOrderNode->GetWindowToken()->UpdateWindowMode(needReZOrderNode->GetWindowMode()); + } + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(needReZOrderNode->GetDisplayId()); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return; + } + windowPair->UpdateIfSplitRelated(needReZOrderNode); + } + WLOGFD("window %{public}u re-zorder when keyguard change %{public}u", needReZOrderNode->GetWindowId(), up); + } +} + +void WindowNodeContainer::ReZOrderShowWhenLockedWindowIfNeeded(const sptr& node) +{ + if (!(node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) || + !isScreenLocked_) { + return; + } + + WLOGFD("ShowWhenLocked window %{public}u re-zorder to up", node->GetWindowId()); + ReZOrderShowWhenLockedWindows(true); +} + +void WindowNodeContainer::RaiseShowWhenLockedWindowIfNeeded(const sptr& node) +{ + // if keyguard window show, raise show when locked windows + if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { + ReZOrderShowWhenLockedWindows(true); + return; + } + + // if show when locked window show, raise itself when exist keyguard + if (!(node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) || + !isScreenLocked_) { + return; + } + + WLOGFD("ShowWhenLocked window %{public}u raise itself", node->GetWindowId()); + node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1; + node->parent_ = aboveAppWindowNode_; + if (WindowHelper::IsSplitWindowMode(node->GetWindowMode())) { + node->GetWindowProperty()->ResumeLastWindowMode(); + if (node->GetWindowToken() != nullptr) { + node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode()); + } + } +} + +void WindowNodeContainer::DropShowWhenLockedWindowIfNeeded(const sptr& node) +{ + // if keyguard window hide, drop show when locked windows + if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { + ReZOrderShowWhenLockedWindows(false); + AssignZOrder(); + } +} + +void WindowNodeContainer::TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const +{ + std::vector> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ }; + if (isFromTopToBottom) { + std::reverse(rootNodes.begin(), rootNodes.end()); + } + + for (const 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; + } + } + } + } +} + +bool WindowNodeContainer::TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const +{ + 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; +} + +bool WindowNodeContainer::TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const +{ + 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; +} + +float WindowNodeContainer::GetVirtualPixelRatio(DisplayId displayId) const +{ + return layoutPolicy_->GetVirtualPixelRatio(displayId); +} + +Rect WindowNodeContainer::GetDisplayGroupRect() const +{ + return layoutPolicy_->GetDisplayGroupRect(); +} + +WMError WindowNodeContainer::SetWindowMode(sptr& node, WindowMode dstMode) +{ + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + WindowMode srcMode = node->GetWindowMode(); + if (srcMode == dstMode) { + return WMError::WM_OK; + } + + if (WindowHelper::IsSplitWindowMode(dstMode) && isScreenLocked_ && + (node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) { + return WMError::WM_ERROR_INVALID_PARAM; + } + + WMError res = WMError::WM_OK; + if ((srcMode == WindowMode::WINDOW_MODE_FULLSCREEN) && (dstMode == WindowMode::WINDOW_MODE_FLOATING)) { + node->SetWindowSizeChangeReason(WindowSizeChangeReason::RECOVER); + } else if (dstMode == WindowMode::WINDOW_MODE_FULLSCREEN) { + node->SetWindowSizeChangeReason(WindowSizeChangeReason::MAXIMIZE); + if (srcMode == WindowMode::WINDOW_MODE_FLOATING) { + node->SetRequestRect(node->GetWindowRect()); + } + } else { + node->SetWindowSizeChangeReason(WindowSizeChangeReason::RESIZE); + } + node->SetWindowMode(dstMode); + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId()); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + windowPair->UpdateIfSplitRelated(node); + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + if (WindowHelper::IsFloatingWindow(node->GetWindowMode())) { + NotifyDockWindowStateChanged(node, true); + } else { + NotifyDockWindowStateChanged(node, false); + } + } + + if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && + WindowHelper::IsAppWindow(node->GetWindowType())) { + // minimize other app window + res = MinimizeStructuredAppWindowsExceptSelf(node); + if (res != WMError::WM_OK) { + return res; + } + } + if (node->GetWindowToken() != nullptr) { + node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode()); + } + res = UpdateWindowNode(node, WindowUpdateReason::UPDATE_MODE); + if (res != WMError::WM_OK) { + WLOGFE("Set window mode failed, update node failed"); + return res; + } + return WMError::WM_OK; +} + +void WindowNodeContainer::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones, + const ModeChangeHotZonesConfig& config) +{ + const auto& displayRect = displayGroupInfo_->GetDisplayRect(displayId); + + hotZones.fullscreen_.width_ = displayRect.width_; + hotZones.fullscreen_.height_ = config.fullscreenRange_; + + hotZones.primary_.width_ = config.primaryRange_; + hotZones.primary_.height_ = displayRect.height_; + + hotZones.secondary_.posX_ = static_cast(displayRect.width_) - config.secondaryRange_; + hotZones.secondary_.width_ = config.secondaryRange_; + hotZones.secondary_.height_ = displayRect.height_; +} + +float WindowNodeContainer::GetDisplayVirtualPixelRatio(DisplayId displayId) const +{ + return displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId); +} + +sptr WindowNodeContainer::GetDisplayInfo(DisplayId displayId) +{ + return displayGroupInfo_->GetDisplayInfo(displayId); +} + +void WindowNodeContainer::UpdateDisplayInfo(sptr displayInfo) +{ + displayGroupInfo_->UpdateDisplayInfo(displayInfo); +} + +std::vector> WindowNodeContainer::GetAllDisplayInfo() +{ + return displayGroupInfo_->GetAllDisplayInfo(); +} + +void WindowNodeContainer::UpdateCameraFloatWindowStatus(const sptr& node, bool isShowing) +{ + if (node->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { + WindowManagerAgentController::GetInstance().UpdateCameraFloatWindowStatus(node->GetAccessTokenId(), isShowing); + } +} + +WindowLayoutMode WindowNodeContainer::GetCurrentLayoutMode() const +{ + return layoutMode_; +} + +void WindowNodeContainer::RemoveSingleUserWindowNodes(int accountId) +{ + std::vector> windowNodes; + TraverseContainer(windowNodes); + WLOGFD("%{public}d", accountId); + for (auto& windowNode : windowNodes) { + int windowAccountId = windowNode->GetCallingUid() / UID_TRANSFROM_DIVISOR; + if (windowAccountId < UID_MIN || windowAccountId == accountId) { + WLOGFD("skiped window %{public}s, windowId %{public}d uid %{public}d", + windowNode->GetWindowName().c_str(), windowNode->GetWindowId(), windowNode->GetCallingUid()); + continue; + } + WLOGFD("remove window %{public}s, windowId %{public}d uid %{public}d", + windowNode->GetWindowName().c_str(), windowNode->GetWindowId(), windowNode->GetCallingUid()); + windowNode->GetWindowProperty()->SetAnimationFlag(static_cast(WindowAnimation::NONE)); + if (windowNode->GetWindowToken()) { + if (windowNode->surfaceNode_ != nullptr) { + windowNode->surfaceNode_->SetVisible(true); + } + windowNode->GetWindowToken()->UpdateWindowState(WindowState::STATE_HIDDEN); + } + } +} + +bool WindowNodeContainer::TakeWindowPairSnapshot(DisplayId displayId) +{ + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + return windowPair == nullptr ? false : windowPair->TakePairSnapshot(); +} + +void WindowNodeContainer::ClearWindowPairSnapshot(DisplayId displayId) +{ + auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr) { + WLOGFE("Window pair is nullptr"); + return; + } + windowPair->ClearPairSnapshot(); +} + +bool WindowNodeContainer::IsScreenLocked() +{ + return isScreenLocked_; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/window_node_state_machine.cpp b/window_manager/wmserver/src/window_node_state_machine.cpp new file mode 100644 index 0000000..d2f0bc3 --- /dev/null +++ b/window_manager/wmserver/src/window_node_state_machine.cpp @@ -0,0 +1,158 @@ +/* + * 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 "window_node_state_machine.h" + +#include "parameters.h" +#include "remote_animation.h" +#include "window_helper.h" +#include "window_manager_hilog.h" +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowNodeStateMachine"}; +} // namespace + +WindowNodeStateMachine::WindowNodeStateMachine() +{ +} + +WindowNodeStateMachine::~WindowNodeStateMachine() +{ +} + +void WindowNodeStateMachine::SetDestroyTaskParam(bool onlySelf) +{ + destroyOnlySelf_ = destroyOnlySelf_ && onlySelf; +} + +bool WindowNodeStateMachine::GetDestroyTaskParam() +{ + return destroyOnlySelf_; +} + +bool WindowNodeStateMachine::GetDestroyTask(StateTask& task) +{ + if (!RemoteAnimation::IsAnimationFirst()) { + return false; + } + std::lock_guard lock(mutex_); + if (destroyTask_ != nullptr) { + task = destroyTask_; + WLOGFI("GetDestroyTask success:%{public}u", windowId_); + return true; + } + return false; +} + +void WindowNodeStateMachine::SetDestroyTask(StateTask task) +{ + std::lock_guard lock(mutex_); + destroyTask_ = task; +} + +void WindowNodeStateMachine::TransitionTo(WindowNodeState state) +{ + std::lock_guard lock(mutex_); + if (WindowHelper::IsSystemWindow(type_)) { + WLOGFI("system window no need to use stateMachine"); + return; + } + currState_ = state; +} + +void WindowNodeStateMachine::UpdateAnimationTaskCount(bool isAdd) +{ + if (!RemoteAnimation::IsAnimationFirst()) { + WLOGFI("not animation first!"); + return; + } + std::lock_guard lock(mutex_); + if (isAdd) { + taskCount_++; + count1++; + WLOGFD("after add UpdateAnimationTaskCount1: %{public}u id:%{public}u", count1, windowId_); + } else { + taskCount_--; + count2++; + WLOGFD("after sub UpdateAnimationTaskCount1: %{public}u id:%{public}u", count2, windowId_); + } +} + +void WindowNodeStateMachine::ResetAnimationTaskCount(int32_t taskCount) +{ + std::lock_guard lock(mutex_); + taskCount_ = taskCount; +} + +int32_t WindowNodeStateMachine::GetAnimationCount() +{ + std::lock_guard lock(mutex_); + return taskCount_; +} + +bool WindowNodeStateMachine::IsRemoteAnimationPlaying() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsRemoteAnimationPlaying id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + if (currState_ == WindowNodeState::SHOW_ANIMATION_PLAYING || + currState_ == WindowNodeState::HIDE_ANIMATION_PLAYING) { + return true; + } + return false; +} + +bool WindowNodeStateMachine::IsShowAnimationPlaying() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsShowAnimationPlaying id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + return currState_ == WindowNodeState::SHOW_ANIMATION_PLAYING; +} + +bool WindowNodeStateMachine::IsHideAnimationPlaying() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsHideAnimationPlaying id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + return currState_ == WindowNodeState::HIDE_ANIMATION_PLAYING; +} + +bool WindowNodeStateMachine::IsWindowNodeShownOrShowing() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsWindowNodeShownOrShowing id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + if (currState_ == WindowNodeState::SHOW_ANIMATION_PLAYING || + currState_ == WindowNodeState::SHOW_ANIMATION_DONE || currState_ == WindowNodeState::SHOWN) { + return true; // not play show animation again when + } + return false; +} + +bool WindowNodeStateMachine::IsWindowNodeHiddenOrHiding() +{ + std::lock_guard lock(mutex_); + WLOGFD("IsWindowNodeHiddenOrHiding id:%{public}u state:%{public}u", windowId_, static_cast(currState_)); + if (currState_ == WindowNodeState::HIDE_ANIMATION_PLAYING || + currState_ == WindowNodeState::HIDE_ANIMATION_DONE || currState_ == WindowNodeState::HIDDEN) { + return true; // not play show animation again when + } + return false; +} + +WindowNodeState WindowNodeStateMachine::GetCurrentState() +{ + return currState_; +} +} // Rosen +} // OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/window_pair.cpp b/window_manager/wmserver/src/window_pair.cpp new file mode 100644 index 0000000..0255d86 --- /dev/null +++ b/window_manager/wmserver/src/window_pair.cpp @@ -0,0 +1,489 @@ +/* + * 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 "window_pair.h" + +#include +#include "common_event_manager.h" +#include "minimize_app.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "window_helper.h" +#include "surface_draw.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowPair"}; + const std::string SPLIT_SCREEN_EVENT_NAME = "common.event.SPLIT_SCREEN"; + const std::map splitEventDataMap { + {SplitEventMsgType::MSG_SHOW_PRIMARY, "Primary"}, + {SplitEventMsgType::MSG_SHOW_SECONDARY, "Secondary"}, + {SplitEventMsgType::MSG_SHOW_DIVIDER, "common.event.SPLIT_SCREEN.data.show.divider"}, + {SplitEventMsgType::MSG_DESTROY_DIVIDER, "common.event.SPLIT_SCREEN.data.destroy.divider"} + }; +} + +WindowPair::~WindowPair() +{ + WLOGD("~WindowPair"); + Clear(); +} + +void WindowPair::SendSplitScreenCommonEvent(SplitEventMsgType msgType, int32_t missionId) +{ + std::string data = splitEventDataMap.at(msgType); + std::string identity = IPCSkeleton::ResetCallingIdentity(); + AAFwk::Want want; + want.SetAction(SPLIT_SCREEN_EVENT_NAME); + want.SetParam("windowMode", data); + want.SetParam("missionId", missionId); + EventFwk::CommonEventData commonEventData; + commonEventData.SetWant(want); + EventFwk::CommonEventManager::PublishCommonEvent(commonEventData); + // set ipc identity to raw + IPCSkeleton::SetCallingIdentity(identity); + WLOGD("Send split screen event: %{public}s", data.c_str()); +} + +void WindowPair::NotifyShowRecent(sptr node) +{ + if (node == nullptr) { + return; + } + auto msgType = (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) ? + SplitEventMsgType::MSG_SHOW_PRIMARY : SplitEventMsgType::MSG_SHOW_SECONDARY; + SendSplitScreenCommonEvent(msgType, node->abilityInfo_.missionId_); +} + +void WindowPair::NotifyCreateOrDestroyDivider(sptr node, bool isDestroy) +{ + if (node == nullptr) { + return; + } + auto msgType = isDestroy ? SplitEventMsgType::MSG_DESTROY_DIVIDER : SplitEventMsgType::MSG_SHOW_DIVIDER; + SendSplitScreenCommonEvent(msgType, node->abilityInfo_.missionId_); +} + +sptr WindowPair::Find(sptr& node) +{ + if (node == nullptr) { + return nullptr; + } + if (primary_ != nullptr && primary_->GetWindowId() == node->GetWindowId()) { + return primary_; + } else if (secondary_ != nullptr && secondary_->GetWindowId() == node->GetWindowId()) { + return secondary_; + } else if (divider_ != nullptr && divider_->GetWindowId() == node->GetWindowId()) { + return divider_; + } + return nullptr; +} + +bool WindowPair::IsPaired() const +{ + if (primary_ == nullptr || secondary_ == nullptr) { + return false; + } + if (primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY && + secondary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY && + divider_ != nullptr) { + return true; + } + return false; +} + +void WindowPair::SetSplitRatio(float ratio) +{ + ratio_ = ratio; +} + +float WindowPair::GetSplitRatio() const +{ + return ratio_; +} + +WindowPairStatus WindowPair::GetPairStatus() const +{ + return status_; +} + +sptr WindowPair::GetDividerWindow() const +{ + return divider_; +} + +bool WindowPair::IsForbidDockSliceMove() const +{ + if (status_ != WindowPairStatus::STATUS_PAIRED_DONE) { + return false; + } + uint32_t flag = static_cast(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE); + if (primary_ != nullptr && !(primary_->GetWindowFlags() & flag) && secondary_ != nullptr && + !(secondary_->GetWindowFlags() & flag)) { + return false; + } + return true; +} + +bool WindowPair::IsDockSliceInExitSplitModeArea(const std::vector& exitSplitPoints) +{ + if (!IsPaired()) { + return false; + } + int32_t dividerOrigin; + Rect rect = divider_->GetWindowRect(); + if (rect.width_ < rect.height_) { + dividerOrigin = rect.posX_; + } else { + dividerOrigin = rect.posY_; // vertical display + } + if (dividerOrigin < exitSplitPoints[0] || dividerOrigin > exitSplitPoints[1]) { + return true; + } + return false; +} + +void WindowPair::ExitSplitMode() +{ + if (!IsPaired()) { + return; + } + Rect dividerRect = divider_->GetWindowRect(); + sptr hideNode, recoveryNode; + bool isVertical = (dividerRect.height_ < dividerRect.width_) ? true : false; + if ((isVertical && (primary_->GetWindowRect().height_ < secondary_->GetWindowRect().height_)) || + (!isVertical && (primary_->GetWindowRect().width_ < secondary_->GetWindowRect().width_))) { + hideNode = primary_; + recoveryNode = secondary_; + } else { + hideNode = secondary_; + recoveryNode = primary_; + } + if (recoveryNode != nullptr) { + recoveryNode->SetSnapshot(nullptr); + } + MinimizeApp::AddNeedMinimizeApp(hideNode, MinimizeReason::SPLIT_QUIT); + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_QUIT); + WLOGFD("Exit Split Mode, Minimize Window %{public}u", hideNode->GetWindowId()); +} + +void WindowPair::Clear() +{ + WLOGI("Clear window pair."); + DumpPairInfo(); + auto splitModeInfo = (WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | + WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY); + if (primary_ != nullptr && primary_->GetWindowProperty() != nullptr && + primary_->GetWindowToken() != nullptr) { + if (primary_->GetModeSupportInfo() == splitModeInfo) { + MinimizeApp::AddNeedMinimizeApp(primary_, MinimizeReason::SPLIT_QUIT); + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_QUIT); + } else { + primary_->GetWindowProperty()->ResumeLastWindowMode(); + primary_->GetWindowToken()->UpdateWindowMode(primary_->GetWindowMode()); + } + } + if (secondary_ != nullptr && secondary_->GetWindowProperty() != nullptr && + secondary_->GetWindowToken() != nullptr) { + if (secondary_->GetModeSupportInfo() == splitModeInfo) { + MinimizeApp::AddNeedMinimizeApp(secondary_, MinimizeReason::SPLIT_QUIT); + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_QUIT); + } else { + secondary_->GetWindowProperty()->ResumeLastWindowMode(); + secondary_->GetWindowToken()->UpdateWindowMode(secondary_->GetWindowMode()); + } + } + + primary_ = nullptr; + secondary_ = nullptr; + if (divider_ != nullptr) { + NotifyCreateOrDestroyDivider(divider_, true); + divider_ = nullptr; + } + status_ = WindowPairStatus::STATUS_EMPTY; +} + +bool WindowPair::IsSplitRelated(sptr& node) const +{ + if (node == nullptr) { + return false; + } + return WindowHelper::IsSplitWindowMode((node->GetWindowMode())) || + (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE); +} + +std::vector> WindowPair::GetOrderedPair(sptr& node) +{ + WLOGI("Get paired node in Z order"); + std::vector> orderedPair; + if (node == nullptr || Find(node) == nullptr) { + return orderedPair; + } + if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY || + node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + // primary secondary + if (primary_ != nullptr && WindowHelper::IsAppWindow(primary_->GetWindowType())) { + orderedPair.push_back(primary_); + } + if (secondary_ != nullptr && WindowHelper::IsAppWindow(secondary_->GetWindowType())) { + orderedPair.push_back(secondary_); + } + } else if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + // secondary primary divider + if (secondary_ != nullptr && WindowHelper::IsAppWindow(secondary_->GetWindowType())) { + orderedPair.push_back(secondary_); + } + if (primary_ != nullptr && WindowHelper::IsAppWindow(primary_->GetWindowType())) { + orderedPair.push_back(primary_); + } + } + if (divider_ != nullptr) { + orderedPair.push_back(divider_); + } + return orderedPair; +} + +std::vector> WindowPair::GetPairedWindows() +{ + WLOGD("Get primary and secondary of window pair"); + std::vector> pairWindows; + if (status_ == WindowPairStatus::STATUS_PAIRED_DONE && primary_ != nullptr && secondary_ != nullptr) { + pairWindows = {primary_, secondary_}; + } + return pairWindows; +} + +void WindowPair::UpdateIfSplitRelated(sptr& node) +{ + if (node == nullptr) { + return; + } + if (Find(node) == nullptr && !IsSplitRelated(node)) { + WLOGI("Window id: %{public}u is not split related and paired.", node->GetWindowId()); + return; + } + if ((node->GetWindowType() == WindowType::WINDOW_TYPE_PLACEHOLDER) && + ((primary_ != nullptr && primary_->GetWindowMode() == node->GetWindowMode()) || + (secondary_ != nullptr && secondary_->GetWindowMode() == node->GetWindowMode()))) { + WindowInnerManager::GetInstance().DestroyInnerWindow(displayId_, WindowType::WINDOW_TYPE_PLACEHOLDER); + return; + } + WLOGI("Current status: %{public}u, window id: %{public}u mode: %{public}u", + status_, node->GetWindowId(), node->GetWindowMode()); + if (status_ == WindowPairStatus::STATUS_EMPTY) { + Insert(node); + if (!isAllSplitAppWindowsRestoring_) { + WindowMode holderMode = node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ? + WindowMode::WINDOW_MODE_SPLIT_SECONDARY : WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + WindowInnerManager::GetInstance().CreateInnerWindow("place_holder", displayId_, DEFAULT_PLACE_HOLDER_RECT, + WindowType::WINDOW_TYPE_PLACEHOLDER, holderMode); + // notity systemui to create divider window + NotifyShowRecent(node); + } + } else { + if (Find(node) == nullptr) { + // add new split related node to pair + Insert(node); + } else { + // handle paired nodes change + HandlePairedNodesChange(); + } + } +} + +void WindowPair::UpdateWindowPairStatus() +{ + WLOGI("Update window pair status."); + WindowPairStatus prevStatus = status_; + if (primary_ != nullptr && secondary_ != nullptr && divider_ != nullptr) { + status_ = WindowPairStatus::STATUS_PAIRED_DONE; + } else if (primary_ != nullptr && secondary_ != nullptr && divider_ == nullptr) { + status_ = WindowPairStatus::STATUS_PAIRING; + } else if (primary_ != nullptr && secondary_ == nullptr) { + status_ = WindowPairStatus::STATUS_SINGLE_PRIMARY; + } else if (primary_ == nullptr && secondary_ != nullptr) { + status_ = WindowPairStatus::STATUS_SINGLE_SECONDARY; + } else { + status_ = WindowPairStatus::STATUS_EMPTY; + } + if ((prevStatus == WindowPairStatus::STATUS_SINGLE_PRIMARY || + prevStatus == WindowPairStatus::STATUS_SINGLE_SECONDARY || prevStatus == WindowPairStatus::STATUS_EMPTY) && + status_ == WindowPairStatus::STATUS_PAIRING) { + // notify systemui to create divider + NotifyCreateOrDestroyDivider(primary_, false); + } else if ((prevStatus == WindowPairStatus::STATUS_PAIRED_DONE || prevStatus == WindowPairStatus::STATUS_PAIRING) && + (status_ != WindowPairStatus::STATUS_PAIRED_DONE && status_ != WindowPairStatus::STATUS_PAIRING)) { + // clear pair + Clear(); + } + DumpPairInfo(); +} + +void WindowPair::SwitchPosition() +{ + if (primary_ == nullptr || secondary_ == nullptr) { + return; + } + WLOGFD("Switch the pair pos, pri: %{public}u pri-mode: %{public}u, sec: %{public}u sec-mode: %{public}u,", + primary_->GetWindowId(), primary_->GetWindowMode(), secondary_->GetWindowId(), secondary_->GetWindowMode()); + if (primary_->GetWindowMode() == secondary_->GetWindowMode() && + primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + primary_->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + if (primary_->GetWindowToken() != nullptr) { + primary_->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + } + std::swap(primary_, secondary_); + } else if (primary_->GetWindowMode() == secondary_->GetWindowMode() && + primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + secondary_->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + if (secondary_->GetWindowToken() != nullptr) { + secondary_->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + } + std::swap(primary_, secondary_); + } +} + +void WindowPair::HandlePairedNodesChange() +{ + WLOGI("Update pair node."); + if (primary_ != nullptr && !primary_->IsSplitMode()) { + primary_ = nullptr; + } + if (secondary_ != nullptr && !secondary_->IsSplitMode()) { + secondary_ = nullptr; + } + // paired node mode change + if (primary_ != nullptr && secondary_ == nullptr && + primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + std::swap(primary_, secondary_); + } else if (primary_ == nullptr && secondary_ != nullptr && + secondary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + std::swap(primary_, secondary_); + } else if (primary_ != nullptr && secondary_ != nullptr && + primary_->GetWindowMode() == secondary_->GetWindowMode()) { + // switch position + SwitchPosition(); + } + UpdateWindowPairStatus(); +} + +void WindowPair::Insert(sptr& node) +{ + if (node == nullptr) { + return; + } + WLOGI("Insert a window to pair id: %{public}u", node->GetWindowId()); + sptr pairedNode; + if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) { + pairedNode = primary_; + primary_ = node; + } else if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + pairedNode = secondary_; + secondary_ = node; + } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + pairedNode = divider_; + divider_ = node; + } + // minimize invalid paired window + if (pairedNode != nullptr && pairedNode->abilityToken_ != nullptr) { + MinimizeApp::AddNeedMinimizeApp(pairedNode, MinimizeReason::SPLIT_REPLACE); + } + UpdateWindowPairStatus(); +} + +void WindowPair::DumpPairInfo() +{ + if (primary_ != nullptr) { + WLOGI("[DumpPairInfo] primary id: %{public}u mode: %{public}u", primary_->GetWindowId(), + primary_->GetWindowMode()); + } + if (secondary_ != nullptr) { + WLOGI("[DumpPairInfo] secondary id: %{public}u mode: %{public}u", secondary_->GetWindowId(), + secondary_->GetWindowMode()); + } + if (divider_ != nullptr) { + WLOGI("[DumpPairInfo] divider id: %{public}u mode: %{public}u", divider_->GetWindowId(), + divider_->GetWindowMode()); + } + WLOGI("[DumpPairInfo] pair status %{public}u", status_); +} + +void WindowPair::HandleRemoveWindow(sptr& node) +{ + if (node == nullptr) { + return; + } + if (Find(node) == nullptr && node->IsSplitMode()) { + WLOGI("Resume unpaired split related window id: %{public}u", node->GetWindowId()); + if (node->GetWindowProperty() != nullptr && node->GetWindowToken() != nullptr) { + node->GetWindowProperty()->ResumeLastWindowMode(); + node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode()); + } + // target node is not in window pair, need resume mode when remove + return; + } else if (Find(node) != nullptr) { + WLOGI("Pairing window id: %{public}u is remove, clear window pair", node->GetWindowId()); + Clear(); + } +} + +void WindowPair::RotateDividerWindow(const Rect& rect) +{ + dividerRect_ = rect; + // rotate divider when display orientation changed + if (divider_ == nullptr) { + WLOGE("Rotate divider failed because divider is null"); + return; + } + WLOGFD("Rotate divider when display rotate rect:[%{public}d, %{public}d, %{public}u, %{public}u]", + rect.posX_, rect.posY_, rect.width_, rect.height_); +} + +void WindowPair::SetDividerRect(const Rect& rect) +{ + dividerRect_ = rect; +} + +bool WindowPair::TakePairSnapshot() +{ + if (status_ == WindowPairStatus::STATUS_PAIRED_DONE && primary_ != nullptr && secondary_ != nullptr) { + WLOGD("Take pair snapshot id:[%{public}u, %{public}u]", primary_->GetWindowId(), secondary_->GetWindowId()); + std::shared_ptr pixelMap; + // get pixelmap time out 2000ms + if (SurfaceDraw::GetSurfaceSnapshot(primary_->surfaceNode_, pixelMap, 2000)) { + primary_->SetSnapshot(pixelMap); + } + // get pixelmap time out 2000ms + if (SurfaceDraw::GetSurfaceSnapshot(secondary_->surfaceNode_, pixelMap, 2000)) { + secondary_->SetSnapshot(pixelMap); + } + return true; + } + return false; +} + +void WindowPair::ClearPairSnapshot() +{ + WLOGD("Clear window pair snapshot"); + if (primary_ != nullptr) { + primary_->SetSnapshot(nullptr); + } + if (secondary_ != nullptr) { + secondary_->SetSnapshot(nullptr); + } +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/window_root.cpp b/window_manager/wmserver/src/window_root.cpp new file mode 100644 index 0000000..73438cd --- /dev/null +++ b/window_manager/wmserver/src/window_root.cpp @@ -0,0 +1,1763 @@ +/* + * Copyright (c) 2021-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 "window_root.h" +#include +#include +#include +#include +#include +#include + +#include "display_manager_service_inner.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_hilog.h" +#include "window_manager_service.h" +#include "window_manager_agent_controller.h" +#include "permission.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowRoot"}; +} + +uint32_t WindowRoot::GetTotalWindowNum() const +{ + return static_cast(windowNodeMap_.size()); +} + +sptr WindowRoot::GetWindowForDumpAceHelpInfo() const +{ + for (auto& iter : windowNodeMap_) { + if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP || + iter.second->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR || + iter.second->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR || + iter.second->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { + return iter.second; + } + } + return nullptr; +} + +ScreenId WindowRoot::GetScreenGroupId(DisplayId displayId, bool& isRecordedDisplay) +{ + for (auto iter : displayIdMap_) { + auto displayIdVec = iter.second; + if (std::find(displayIdVec.begin(), displayIdVec.end(), displayId) != displayIdVec.end()) { + isRecordedDisplay = true; + return iter.first; + } + } + isRecordedDisplay = false; + WLOGFE("Current display is not be recorded, displayId: %{public}" PRIu64 "", displayId); + return DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(displayId); +} + +sptr WindowRoot::GetOrCreateWindowNodeContainer(DisplayId displayId) +{ + auto container = GetWindowNodeContainer(displayId); + if (container != nullptr) { + return container; + } + + // In case of have no container for default display, create container + WLOGFD("Create container for current display, displayId: %{public}" PRIu64 "", displayId); + sptr displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); + return CreateWindowNodeContainer(displayInfo); +} + +sptr WindowRoot::GetWindowNodeContainer(DisplayId displayId) +{ + bool isRecordedDisplay; + ScreenId displayGroupId = GetScreenGroupId(displayId, isRecordedDisplay); + auto iter = windowNodeContainerMap_.find(displayGroupId); + if (iter != windowNodeContainerMap_.end()) { + // if container exist for screenGroup and display is not be recorded, process expand display + if (!isRecordedDisplay) { + sptr displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); + // add displayId in displayId vector + displayIdMap_[displayGroupId].push_back(displayId); + auto displayRectMap = GetAllDisplayRectsByDMS(displayInfo); + DisplayId defaultDisplayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + ProcessExpandDisplayCreate(defaultDisplayId, displayInfo, displayRectMap); + } + return iter->second; + } + return nullptr; +} + +sptr WindowRoot::CreateWindowNodeContainer(sptr displayInfo) +{ + if (displayInfo == nullptr || !CheckDisplayInfo(displayInfo)) { + WLOGFE("get display failed or get invalid display info"); + return nullptr; + } + + DisplayId displayId = displayInfo->GetDisplayId(); + ScreenId displayGroupId = displayInfo->GetScreenGroupId(); + WLOGFD("create new container for display, width: %{public}d, height: %{public}d, " + "displayGroupId:%{public}" PRIu64", displayId:%{public}" PRIu64"", displayInfo->GetWidth(), + displayInfo->GetHeight(), displayGroupId, displayId); + sptr container = new WindowNodeContainer(displayInfo, displayGroupId); + windowNodeContainerMap_.insert(std::make_pair(displayGroupId, container)); + std::vector displayVec = { displayId }; + displayIdMap_.insert(std::make_pair(displayGroupId, displayVec)); + if (container == nullptr) { + WLOGFE("create container failed, displayId :%{public}" PRIu64 "", displayId); + return nullptr; + } + container->GetLayoutPolicy()->SetSplitRatioConfig(splitRatioConfig_); + return container; +} + +bool WindowRoot::CheckDisplayInfo(const sptr& display) +{ + const int32_t minWidth = 50; + const int32_t minHeight = 50; + const int32_t maxWidth = 7680; + const int32_t maxHeight = 7680; // 8k resolution + if (display->GetWidth() < minWidth || display->GetWidth() > maxWidth || + display->GetHeight() < minHeight || display->GetHeight() > maxHeight) { + return false; + } + return true; +} + +sptr WindowRoot::GetWindowNode(uint32_t windowId) const +{ + auto iter = windowNodeMap_.find(windowId); + if (iter == windowNodeMap_.end()) { + return nullptr; + } + return iter->second; +} + +void WindowRoot::GetBackgroundNodesByScreenId(ScreenId screenGroupId, std::vector>& windowNodes) const +{ + for (const auto& it : windowNodeMap_) { + if (it.second && screenGroupId == DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId( + it.second->GetDisplayId()) && !it.second->currentVisibility_) { + windowNodes.push_back(it.second); + } + } +} + +sptr WindowRoot::FindWindowNodeWithToken(const sptr& token) const +{ + if (token == nullptr) { + WLOGFE("token is null"); + return nullptr; + } + auto iter = std::find_if(windowNodeMap_.begin(), windowNodeMap_.end(), + [token](const std::map>::value_type& pair) { + if (!(WindowHelper::IsSubWindow(pair.second->GetWindowType()))) { + return pair.second->abilityToken_ == token; + } + return false; + }); + if (iter == windowNodeMap_.end()) { + WLOGFD("cannot find windowNode"); + return nullptr; + } + return iter->second; +} + +void WindowRoot::AddDeathRecipient(sptr node) +{ + if (node == nullptr) { + WLOGFE("AddDeathRecipient failed, node is nullptr"); + return; + } + WLOGFD("Add for window: %{public}u", node->GetWindowId()); + + auto remoteObject = node->GetWindowToken()->AsObject(); + windowIdMap_.insert(std::make_pair(remoteObject, node->GetWindowId())); + + if (windowDeath_ == nullptr) { + WLOGFD("failed to create death Recipient ptr WindowDeathRecipient"); + return; + } + if (!remoteObject->AddDeathRecipient(windowDeath_)) { + WLOGFD("failed to add death recipient"); + } +} + +WMError WindowRoot::SaveWindow(const sptr& node) +{ + if (node == nullptr) { + WLOGFE("add window failed, node is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + + WLOGFD("save windowId %{public}u", node->GetWindowId()); + windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node)); + if (node->surfaceNode_ != nullptr) { + surfaceIdWindowNodeMap_.insert(std::make_pair(node->surfaceNode_->GetId(), node)); + } + if (node->GetWindowToken()) { + AddDeathRecipient(node); + } + // Register FirstFrame Callback to rs, inform ability to get snapshot + wptr weak = node; + auto firstFrameCompleteCallback = [weak]() { + auto weakNode = weak.promote(); + if (weakNode == nullptr) { + WLOGFE("windowNode is nullptr"); + return; + } + WindowInnerManager::GetInstance().CompleteFirstFrameDrawing(weakNode); + }; + if (node->surfaceNode_ && WindowHelper::IsMainWindow(node->GetWindowType())) { + node->surfaceNode_->SetBufferAvailableCallback(firstFrameCompleteCallback); + } + return WMError::WM_OK; +} + +WMError WindowRoot::MinimizeStructuredAppWindowsExceptSelf(sptr& node) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "root:MinimizeStructuredAppWindowsExceptSelf"); + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("MinimizeAbility failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + return container->MinimizeStructuredAppWindowsExceptSelf(node); +} + +void WindowRoot::MinimizeTargetWindows(std::vector& windowIds) +{ + for (auto& windowId : windowIds) { + if (windowNodeMap_.count(windowId) != 0) { + auto windowNode = windowNodeMap_[windowId]; + if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { + MinimizeApp::AddNeedMinimizeApp(windowNode, MinimizeReason::GESTURE_ANIMATION); + } else { + WLOGFE("Minimize window failed id: %{public}u, type: %{public}u", + windowNode->GetWindowId(), static_cast(windowNode->GetWindowType())); + } + } + } +} + +std::vector> WindowRoot::GetSplitScreenWindowNodes(DisplayId displayId) +{ + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + return {}; + } + auto displayGroupController = container->GetMultiDisplayController(); + if (displayGroupController == nullptr) { + return {}; + } + auto windowPair = displayGroupController->GetWindowPairByDisplayId(displayId); + if (windowPair == nullptr) { + return {}; + } + return windowPair->GetPairedWindows(); +} + +bool WindowRoot::IsForbidDockSliceMove(DisplayId displayId) const +{ + auto container = const_cast(this)->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("can't find container"); + return true; + } + return container->IsForbidDockSliceMove(displayId); +} + +bool WindowRoot::IsDockSliceInExitSplitModeArea(DisplayId displayId) const +{ + auto container = const_cast(this)->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("can't find container"); + return false; + } + return container->IsDockSliceInExitSplitModeArea(displayId); +} + +void WindowRoot::ExitSplitMode(DisplayId displayId) +{ + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("can't find container"); + return; + } + container->ExitSplitMode(displayId); +} + +void WindowRoot::AddSurfaceNodeIdWindowNodePair(uint64_t surfaceNodeId, sptr node) +{ + surfaceIdWindowNodeMap_.insert(std::make_pair(surfaceNodeId, node)); +} + +void WindowRoot::GetVisibilityWindowInfo(std::vector>& infos) const +{ + if (!Permission::IsSystemCalling()) { + WLOGFE("Get Visible Window Permission Denied"); + } + VisibleData& VisibleWindow = lastOcclusionData_->GetVisibleData(); + for (auto surfaceId : VisibleWindow) { + auto iter = surfaceIdWindowNodeMap_.find(surfaceId); + if (iter == surfaceIdWindowNodeMap_.end()) { + continue; + } + sptr node = iter->second; + if (node == nullptr) { + continue; + } + infos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(), + node->GetCallingUid(), true, node->GetWindowType())); + } +} + +std::vector> WindowRoot::GetWindowVisibilityChangeInfo( + std::shared_ptr occlusionData) +{ + std::vector> visibilityChangeInfo; + VisibleData& currentVisibleWindow = occlusionData->GetVisibleData(); + std::sort(currentVisibleWindow.begin(), currentVisibleWindow.end()); + VisibleData& lastVisibleWindow = lastOcclusionData_->GetVisibleData(); + uint32_t i, j; + i = j = 0; + for (; i < lastVisibleWindow.size() && j < currentVisibleWindow.size();) { + if (lastVisibleWindow[i] < currentVisibleWindow[j]) { + visibilityChangeInfo.emplace_back(lastVisibleWindow[i], false); + i++; + } else if (lastVisibleWindow[i] > currentVisibleWindow[j]) { + visibilityChangeInfo.emplace_back(currentVisibleWindow[j], true); + j++; + } else { + i++; + j++; + } + } + for (; i < lastVisibleWindow.size(); ++i) { + visibilityChangeInfo.emplace_back(lastVisibleWindow[i], false); + } + for (; j < currentVisibleWindow.size(); ++j) { + visibilityChangeInfo.emplace_back(currentVisibleWindow[j], true); + } + lastOcclusionData_ = occlusionData; + return visibilityChangeInfo; +} + +void WindowRoot::NotifyWindowVisibilityChange(std::shared_ptr occlusionData) +{ + std::vector> visibilityChangeInfo = GetWindowVisibilityChangeInfo(occlusionData); + std::vector> windowVisibilityInfos; + bool hasAppWindowChange = false; + for (const auto& elem : visibilityChangeInfo) { + uint64_t surfaceId = elem.first; + bool isVisible = elem.second; + auto iter = surfaceIdWindowNodeMap_.find(surfaceId); + if (iter == surfaceIdWindowNodeMap_.end()) { + continue; + } + sptr node = iter->second; + if (node == nullptr) { + continue; + } + node->isVisible_ = isVisible; + WindowType winType = node->GetWindowType(); + hasAppWindowChange = (winType >= WindowType::APP_WINDOW_BASE && winType < WindowType::APP_WINDOW_END); + windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(), + node->GetCallingUid(), isVisible, node->GetWindowType())); + WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d", + node->GetWindowId(), isVisible); + } + if (hasAppWindowChange) { + SwitchRenderModeIfNeeded(); + } + + if (windowVisibilityInfos.size() != 0) { + WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos); + } +} + +AvoidArea WindowRoot::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) +{ + AvoidArea avoidArea; + sptr node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return avoidArea; + } + sptr container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("add window failed, window container could not be found"); + return avoidArea; + } + return container->GetAvoidAreaByType(node, avoidAreaType); +} + +void WindowRoot::MinimizeAllAppWindows(DisplayId displayId) +{ + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("can't find window node container, failed!"); + return; + } + return container->MinimizeAllAppWindows(displayId); +} + +WMError WindowRoot::ToggleShownStateForAllAppWindows() +{ + std::vector displays = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds(); + std::vector> containers; + bool isAllAppWindowsEmpty = true; + for (auto displayId : displays) { + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("can't find window node container, failed!"); + continue; + } + containers.emplace_back(container); + isAllAppWindowsEmpty = isAllAppWindowsEmpty && container->IsAppWindowsEmpty(); + } + WMError res = WMError::WM_OK; + std::for_each(containers.begin(), containers.end(), + [this, isAllAppWindowsEmpty, &res] (sptr container) { + auto restoreFunc = [this](uint32_t windowId, WindowMode mode) { + auto windowNode = GetWindowNode(windowId); + if (windowNode == nullptr) { + return false; + } + if (!windowNode->GetWindowToken()) { + return false; + } + auto property = windowNode->GetWindowToken()->GetWindowProperty(); + if (property == nullptr) { + return false; + } + if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || + mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + property->SetWindowMode(mode); + windowNode->GetWindowToken()->RestoreSplitWindowMode(static_cast(mode)); + } + windowNode->GetWindowToken()->UpdateWindowState(WindowState::STATE_SHOWN); + WindowManagerService::GetInstance().AddWindow(property); + return true; + }; + WMError tmpRes = tmpRes = container->ToggleShownStateForAllAppWindows(restoreFunc, isAllAppWindowsEmpty); + res = (res == WMError::WM_OK) ? tmpRes : res; + }); + return res; +} + +void WindowRoot::DestroyLeakStartingWindow() +{ + WLOGFD("DestroyLeakStartingWindow is called"); + std::vector destroyIds; + for (auto& iter : windowNodeMap_) { + if (iter.second->startingWindowShown_ && !iter.second->GetWindowToken()) { + destroyIds.push_back(iter.second->GetWindowId()); + } + } + for (auto& id : destroyIds) { + WLOGFD("Destroy Window id:%{public}u", id); + DestroyWindow(id, false); + } +} + +WMError WindowRoot::PostProcessAddWindowNode(sptr& node, sptr& parentNode, + sptr& container) +{ + if (!node->currentVisibility_) { + WLOGFD("window is invisible, do not need process"); + return WMError::WM_DO_NOTHING; + } + if (WindowHelper::IsSubWindow(node->GetWindowType())) { + if (parentNode == nullptr) { + WLOGFE("window type is invalid"); + return WMError::WM_ERROR_INVALID_TYPE; + } + sptr parent = nullptr; + container->RaiseZOrderForAppWindow(parentNode, parent); + } + if (node->GetWindowProperty()->GetFocusable()) { + // when launcher reboot, the focus window should not change with showing a full screen window. + sptr focusWin = GetWindowNode(container->GetFocusWindow()); + if (focusWin == nullptr || + !(WindowHelper::IsFullScreenWindow(focusWin->GetWindowMode()) && focusWin->zOrder_ > node->zOrder_)) { + container->SetFocusWindow(node->GetWindowId()); + needCheckFocusWindow = true; + } + } + if (!WindowHelper::IsSystemBarWindow(node->GetWindowType())) { + container->SetActiveWindow(node->GetWindowId(), false); + } + + for (auto& child : node->children_) { + if (child == nullptr || !child->currentVisibility_) { + break; + } + HandleKeepScreenOn(child->GetWindowId(), child->IsKeepScreenOn()); + } + HandleKeepScreenOn(node->GetWindowId(), node->IsKeepScreenOn()); + WLOGFD("windowId:%{public}u, name:%{public}s, orientation:%{public}u, type:%{public}u, isMainWindow:%{public}d", + node->GetWindowId(), node->GetWindowName().c_str(), static_cast(node->GetRequestedOrientation()), + node->GetWindowType(), WindowHelper::IsMainWindow(node->GetWindowType())); + if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) { + DisplayManagerServiceInner::GetInstance(). + SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation()); + } + return WMError::WM_OK; +} + +bool WindowRoot::NeedToStopAddingNode(sptr& node, const sptr& container) +{ + if (!WindowHelper::IsMainWindow(node->GetWindowType())) { + return false; + } + // intercept the node which doesn't support floating mode at tile mode + if (WindowHelper::IsInvalidWindowInTileLayoutMode(node->GetModeSupportInfo(), container->GetCurrentLayoutMode())) { + WLOGFE("window doesn't support floating mode in tile, windowId: %{public}u", node->GetWindowId()); + return true; + } + // intercept the node that the tile rect can't be applied to + WMError res = container->IsTileRectSatisfiedWithSizeLimits(node); + if (res != WMError::WM_OK) { + return true; + } + return false; +} + +Rect WindowRoot::GetDisplayRectWithoutSystemBarAreas(DisplayId displayId) +{ + std::map> systemBarRects; + for (const auto& it : windowNodeMap_) { + auto& node = it.second; + if (node && (node->GetDisplayId() == displayId) && + WindowHelper::IsSystemBarWindow(node->GetWindowType())) { + systemBarRects[node->GetWindowType()] = std::make_pair(node->currentVisibility_, node->GetWindowRect()); + } + } + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("GetDisplayRectWithoutSystemBarAreas failed, window container could not be found"); + return {0, 0, 0, 0}; // empty rect + } + auto displayRect = container->GetDisplayRect(displayId); + Rect targetRect = displayRect; + bool isStatusShow = true; + if (systemBarRects.count(WindowType::WINDOW_TYPE_STATUS_BAR)) { + isStatusShow = systemBarRects[WindowType::WINDOW_TYPE_STATUS_BAR].first; + targetRect.posY_ = displayRect.posY_ + static_cast( + systemBarRects[WindowType::WINDOW_TYPE_STATUS_BAR].second.height_); + targetRect.height_ -= systemBarRects[WindowType::WINDOW_TYPE_STATUS_BAR].second.height_; + WLOGFD("after status bar winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + targetRect.posX_, targetRect.posY_, targetRect.width_, targetRect.height_); + } + if (systemBarRects.count(WindowType::WINDOW_TYPE_NAVIGATION_BAR)) { + if (isStatusShow && !(systemBarRects[WindowType::WINDOW_TYPE_NAVIGATION_BAR].first)) { + return targetRect; + } + targetRect.height_ -= systemBarRects[WindowType::WINDOW_TYPE_NAVIGATION_BAR].second.height_; + WLOGFD("after navi bar winRect:[x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d]", + targetRect.posX_, targetRect.posY_, targetRect.width_, targetRect.height_); + } + return targetRect; +} + +void WindowRoot::GetAllAnimationPlayingNodes(std::vector>& windowNodes) +{ + for (const auto& it : windowNodeMap_) { + if (it.second) { + if (!WindowHelper::IsMainWindow(it.second->GetWindowType())) { + continue; + } + WLOGFD("id:%{public}u state:%{public}u", + it.second->GetWindowId(), static_cast(it.second->stateMachine_.GetCurrentState())); + if (it.second->stateMachine_.IsRemoteAnimationPlaying() || + it.second->stateMachine_.GetAnimationCount() > 0) { + windowNodes.emplace_back(it.second); + } + } + } +} + +void WindowRoot::LayoutWhenAddWindowNode(sptr& node, bool afterAnimation) +{ + if (node == nullptr) { + WLOGFE("LayoutWhenAddWindowNode failed, node is nullptr"); + return; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("add window failed, window container could not be found"); + return; + } + container->LayoutWhenAddWindowNode(node, afterAnimation); + return; +} + +WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, bool fromStartingWin) +{ + if (node == nullptr) { + WLOGFE("add window failed, node is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("add window failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + + if (NeedToStopAddingNode(node, container)) { // true means stop adding + return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE; + } + + if (fromStartingWin) { + if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && + WindowHelper::IsAppWindow(node->GetWindowType()) && !node->isPlayAnimationShow_) { + container->NotifyDockWindowStateChanged(node, false); + WMError res = MinimizeStructuredAppWindowsExceptSelf(node); + if (res != WMError::WM_OK) { + WLOGFE("Minimize other structured window failed"); + MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); + return res; + } + } + WMError res = container->ShowStartingWindow(node); + if (res != WMError::WM_OK) { + MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); + } + SwitchRenderModeIfNeeded(); + return res; + } + // limit number of main window + uint32_t mainWindowNumber = container->GetWindowCountByType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + if (mainWindowNumber >= maxAppWindowNumber_ && node->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { + container->MinimizeOldestAppWindow(); + } + + auto parentNode = GetWindowNode(parentId); + + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) { + sptr callerNode = FindDialogCallerNode(node->GetWindowType(), node->dialogTargetToken_); + parentNode = (callerNode != nullptr) ? callerNode : nullptr; + } + + WMError res = container->AddWindowNode(node, parentNode); + if (res != WMError::WM_OK) { + WLOGFE("AddWindowNode failed with ret: %{public}u", static_cast(res)); + return res; + } + SwitchRenderModeIfNeeded(); + return PostProcessAddWindowNode(node, parentNode, container); +} + +WMError WindowRoot::RemoveWindowNode(uint32_t windowId, bool fromAnimation) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("remove window failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + container->DropShowWhenLockedWindowIfNeeded(node); + UpdateFocusWindowWithWindowRemoved(node, container); + UpdateActiveWindowWithWindowRemoved(node, container); + UpdateBrightnessWithWindowRemoved(windowId, container); + WMError res = container->RemoveWindowNode(node, fromAnimation); + if (res == WMError::WM_OK) { + for (auto& child : node->children_) { + if (child == nullptr) { + break; + } + HandleKeepScreenOn(child->GetWindowId(), false); + } + HandleKeepScreenOn(windowId, false); + SwitchRenderModeIfNeeded(); + } + auto nextRotatableWindow = container->GetNextRotatableWindow(windowId); + if (nextRotatableWindow != nullptr) { + DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(nextRotatableWindow->GetDisplayId(), + nextRotatableWindow->GetRequestedOrientation()); + } + return res; +} + +WMError WindowRoot::UpdateWindowNode(uint32_t windowId, WindowUpdateReason reason) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("update window failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + return container->UpdateWindowNode(node, reason); +} + +WMError WindowRoot::UpdateSizeChangeReason(uint32_t windowId, WindowSizeChangeReason reason) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("update window size change reason failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + container->UpdateSizeChangeReason(node, reason); + return WMError::WM_OK; +} + +void WindowRoot::SetBrightness(uint32_t windowId, float brightness) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("set brightness failed, window container could not be found"); + return; + } + if (!WindowHelper::IsAppWindow(node->GetWindowType())) { + WLOGFD("non app window does not support set brightness"); + return; + } + if (windowId == container->GetActiveWindow()) { + if (container->GetDisplayBrightness() != brightness) { + WLOGFD("set brightness with value: %{public}u", container->ToOverrideBrightness(brightness)); + DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().OverrideBrightness( + container->ToOverrideBrightness(brightness)); + container->SetDisplayBrightness(brightness); + } + container->SetBrightnessWindow(windowId); + } +} + +void WindowRoot::HandleKeepScreenOn(uint32_t windowId, bool requireLock) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("handle keep screen on failed, window container could not be found"); + return; + } + container->HandleKeepScreenOn(node, requireLock); +} + +void WindowRoot::UpdateFocusableProperty(uint32_t windowId) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("handle focusable failed, window container could not be found"); + return; + } + + if (windowId != container->GetFocusWindow() || node->GetWindowProperty()->GetFocusable()) { + return; + } + auto nextFocusableWindow = container->GetNextFocusableWindow(windowId); + if (nextFocusableWindow != nullptr) { + WLOGFD("adjust focus window, next focus window id: %{public}u", nextFocusableWindow->GetWindowId()); + container->SetFocusWindow(nextFocusableWindow->GetWindowId()); + } +} + +WMError WindowRoot::SetWindowMode(sptr& node, WindowMode dstMode) +{ + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("set window mode failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + WindowMode curWinMode = node->GetWindowMode(); + auto res = container->SetWindowMode(node, dstMode); + if (res == WMError::WM_OK + && (WindowHelper::IsSplitWindowMode(curWinMode) || WindowHelper::IsSplitWindowMode(dstMode))) { + WLOGFD("SwitchRender: split mode changed"); + SwitchRenderModeIfNeeded(); + } + if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) { + DisplayManagerServiceInner::GetInstance(). + SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation()); + } + auto nextRotatableWindow = container->GetNextRotatableWindow(0); + if (nextRotatableWindow != nullptr) { + DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(nextRotatableWindow->GetDisplayId(), + nextRotatableWindow->GetRequestedOrientation()); + } + return res; +} + +WMError WindowRoot::DestroyWindowSelf(sptr& node, const sptr& container) +{ + for (auto& child : node->children_) { + if (child == nullptr) { + continue; + } + child->parent_ = nullptr; + if ((child->GetWindowToken() != nullptr) && (child->abilityToken_ != node->abilityToken_) && + (child->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) { + child->GetWindowToken()->NotifyDestroy(); + } + } + WMError res = container->RemoveWindowNode(node); + if (res != WMError::WM_OK) { + WLOGFE("RemoveWindowNode failed"); + } + SwitchRenderModeIfNeeded(); + return DestroyWindowInner(node); +} + +WMError WindowRoot::DestroyWindowWithChild(sptr& node, const sptr& container) +{ + auto token = node->abilityToken_; + std::vector windowIds; + WMError res = container->DestroyWindowNode(node, windowIds); + for (auto id : windowIds) { + node = GetWindowNode(id); + if (!node) { + continue; + } + HandleKeepScreenOn(id, false); + DestroyWindowInner(node); + if ((node->GetWindowToken() != nullptr) && (node->abilityToken_ != token) && + (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) { + node->GetWindowToken()->NotifyDestroy(); + } + } + SwitchRenderModeIfNeeded(); + return res; +} + +WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("destroy window failed, because window node is not exist."); + return WMError::WM_ERROR_NULLPTR; + } + WLOGFD("destroy window %{public}u, onlySelf:%{public}u.", windowId, onlySelf); + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (!container) { + WLOGFW("destroy window failed, window container could not be found"); + return DestroyWindowInner(node); + } + + UpdateFocusWindowWithWindowRemoved(node, container); + UpdateActiveWindowWithWindowRemoved(node, container); + UpdateBrightnessWithWindowRemoved(windowId, container); + HandleKeepScreenOn(windowId, false); + if (onlySelf) { + return DestroyWindowSelf(node, container); + } else { + return DestroyWindowWithChild(node, container); + } +} + +WMError WindowRoot::DestroyWindowInner(sptr& node) +{ + if (node == nullptr) { + WLOGFE("window has been destroyed"); + return WMError::WM_ERROR_DESTROYED_OBJECT; + } + + if (node->isVisible_) { + std::vector> windowVisibilityInfos; + node->isVisible_ = false; + windowVisibilityInfos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(), + node->GetCallingUid(), false, node->GetWindowType())); + WLOGFD("NotifyWindowVisibilityChange: covered status changed window:%{public}u, isVisible:%{public}d", + node->GetWindowId(), node->isVisible_); + WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(windowVisibilityInfos); + } + + auto cmpFunc = [node](const std::map>::value_type& pair) { + if (pair.second == nullptr) { + return false; + } + if (pair.second->GetWindowId() == node->GetWindowId()) { + return true; + } + return false; + }; + auto iter = std::find_if(surfaceIdWindowNodeMap_.begin(), surfaceIdWindowNodeMap_.end(), cmpFunc); + if (iter != surfaceIdWindowNodeMap_.end()) { + surfaceIdWindowNodeMap_.erase(iter); + } + + sptr window = node->GetWindowToken(); + if ((window != nullptr) && (window->AsObject() != nullptr)) { + if (windowIdMap_.count(window->AsObject()) == 0) { + WLOGFD("window remote object has been destroyed"); + return WMError::WM_ERROR_DESTROYED_OBJECT; + } + + if (window->AsObject() != nullptr) { + window->AsObject()->RemoveDeathRecipient(windowDeath_); + } + windowIdMap_.erase(window->AsObject()); + } + windowNodeMap_.erase(node->GetWindowId()); + WLOGFD("destroy window node use_count:%{public}d", node->GetSptrRefCount()); + return WMError::WM_OK; +} + +void WindowRoot::UpdateFocusWindowWithWindowRemoved(const sptr& node, + const sptr& container) const +{ + if (node == nullptr || container == nullptr) { + WLOGFE("window is invalid"); + return; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + WLOGFD("window is divider, do not get next focus window."); + return; + } + uint32_t windowId = node->GetWindowId(); + uint32_t focusedWindowId = container->GetFocusWindow(); + WLOGFD("current window: %{public}u, focus window: %{public}u", windowId, focusedWindowId); + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + if (windowId != focusedWindowId) { + auto iter = std::find_if(node->children_.begin(), node->children_.end(), + [focusedWindowId](sptr node) { + return node->GetWindowId() == focusedWindowId; + }); + if (iter == node->children_.end()) { + return; + } + } + if (!node->children_.empty()) { + auto firstChild = node->children_.front(); + if (firstChild->priority_ < 0) { + windowId = firstChild->GetWindowId(); + } + } + } else { + if (windowId != focusedWindowId) { + return; + } + } + auto nextFocusableWindow = container->GetNextFocusableWindow(windowId); + if (nextFocusableWindow != nullptr) { + WLOGFD("adjust focus window, next focus window id: %{public}u", nextFocusableWindow->GetWindowId()); + container->SetFocusWindow(nextFocusableWindow->GetWindowId()); + } +} + +void WindowRoot::UpdateActiveWindowWithWindowRemoved(const sptr& node, + const sptr& container) const +{ + if (node == nullptr || container == nullptr) { + WLOGFE("window is invalid"); + return; + } + uint32_t windowId = node->GetWindowId(); + uint32_t activeWindowId = container->GetActiveWindow(); + WLOGFD("current window: %{public}u, active window: %{public}u", windowId, activeWindowId); + if (WindowHelper::IsMainWindow(node->GetWindowType())) { + if (windowId != activeWindowId) { + auto iter = std::find_if(node->children_.begin(), node->children_.end(), + [activeWindowId](sptr node) { + return node->GetWindowId() == activeWindowId; + }); + if (iter == node->children_.end()) { + return; + } + } + if (!node->children_.empty()) { + auto firstChild = node->children_.front(); + if (firstChild->priority_ < 0) { + windowId = firstChild->GetWindowId(); + } + } + } else { + if (windowId != activeWindowId) { + return; + } + } + auto nextActiveWindow = container->GetNextActiveWindow(windowId); + if (nextActiveWindow != nullptr) { + WLOGFD("adjust active window, next active window id: %{public}u", nextActiveWindow->GetWindowId()); + container->SetActiveWindow(nextActiveWindow->GetWindowId(), true); + } +} + +void WindowRoot::UpdateBrightnessWithWindowRemoved(uint32_t windowId, const sptr& container) const +{ + if (container == nullptr) { + WLOGFE("window container could not be found"); + return; + } + if (windowId == container->GetBrightnessWindow()) { + WLOGFD("adjust brightness window with active window: %{public}u", container->GetActiveWindow()); + container->UpdateBrightness(container->GetActiveWindow(), true); + } +} + +bool WindowRoot::IsVerticalDisplay(sptr& node) const +{ + auto container = const_cast(this)->GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("get display direction failed, window container could not be found"); + return false; + } + return container->IsVerticalDisplay(node->GetDisplayId()); +} + +WMError WindowRoot::RequestFocus(uint32_t windowId) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (!node->currentVisibility_) { + WLOGFE("could not request focus before it does not be shown"); + return WMError::WM_ERROR_INVALID_OPERATION; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + if (node->GetWindowProperty()->GetFocusable()) { + return container->SetFocusWindow(windowId); + } + return WMError::WM_ERROR_INVALID_OPERATION; +} + +WMError WindowRoot::RequestActiveWindow(uint32_t windowId) +{ + auto node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) { + WLOGFE("window could not be active window"); + return WMError::WM_ERROR_INVALID_TYPE; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + auto res = container->SetActiveWindow(windowId, false); + WLOGFD("windowId:%{public}u, name:%{public}s, orientation:%{public}u, type:%{public}u, isMainWindow:%{public}d", + windowId, node->GetWindowName().c_str(), static_cast(node->GetRequestedOrientation()), + node->GetWindowType(), WindowHelper::IsMainWindow(node->GetWindowType())); + if (res == WMError::WM_OK && + WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) { + DisplayManagerServiceInner::GetInstance(). + SetOrientationFromWindow(node->GetDisplayId(), node->GetRequestedOrientation()); + } + return res; +} + +void WindowRoot::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason) +{ + for (auto& elem : windowNodeContainerMap_) { + if (elem.second == nullptr) { + continue; + } + elem.second->ProcessWindowStateChange(state, reason); + } +} + +void WindowRoot::NotifySystemBarTints() +{ + WLOGFD("notify current system bar tints"); + for (auto& it : windowNodeContainerMap_) { + if (it.second != nullptr) { + it.second->NotifySystemBarTints(displayIdMap_[it.first]); + } + } +} + +WMError WindowRoot::RaiseZOrderForAppWindow(sptr& node) +{ + if (node == nullptr) { + WLOGFW("add window failed, node is nullptr"); + return WMError::WM_ERROR_NULLPTR; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFW("window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + container->RaiseSplitRelatedWindowToTop(node); + return WMError::WM_OK; + } + if (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) { + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFW("window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + sptr parentNode = FindDialogCallerNode(node->GetWindowType(), node->dialogTargetToken_); + if (parentNode != nullptr) { + container->RaiseZOrderForAppWindow(node, parentNode); + } + return WMError::WM_OK; + } + + if (!WindowHelper::IsAppWindow(node->GetWindowType())) { + WLOGFW("window is not app window"); + return WMError::WM_ERROR_INVALID_TYPE; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFW("add window failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + + auto parentNode = GetWindowNode(node->GetParentId()); + return container->RaiseZOrderForAppWindow(node, parentNode); +} + +uint32_t WindowRoot::GetWindowIdByObject(const sptr& remoteObject) +{ + auto iter = windowIdMap_.find(remoteObject); + return iter == std::end(windowIdMap_) ? INVALID_WINDOW_ID : iter->second; +} + +void WindowRoot::OnRemoteDied(const sptr& remoteObject) +{ + callback_(Event::REMOTE_DIED, remoteObject); +} + +WMError WindowRoot::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) +{ + if (windowNodeMap_.find(mainWinId) == windowNodeMap_.end()) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + auto node = windowNodeMap_[mainWinId]; + if (!node->currentVisibility_) { + return WMError::WM_ERROR_INVALID_WINDOW; + } + if (!node->children_.empty()) { + auto iter = node->children_.rbegin(); + if (WindowHelper::IsSubWindow((*iter)->GetWindowType()) || + WindowHelper::IsSystemSubWindow((*iter)->GetWindowType())) { + topWinId = (*iter)->GetWindowId(); + return WMError::WM_OK; + } + } + topWinId = mainWinId; + return WMError::WM_OK; +} + +WMError WindowRoot::SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mode) +{ + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + WMError ret = container->SwitchLayoutPolicy(mode, displayId, true); + if (ret != WMError::WM_OK) { + WLOGFW("set window layout mode failed displayId: %{public}" PRIu64 ", ret: %{public}d", displayId, ret); + } + return ret; +} + +std::vector WindowRoot::GetAllDisplayIds() const +{ + std::vector displayIds; + for (auto& it : windowNodeContainerMap_) { + if (!it.second) { + return {}; + } + std::vector& displayIdVec = const_cast(this)->displayIdMap_[it.first]; + for (auto displayId : displayIdVec) { + displayIds.push_back(displayId); + } + } + return displayIds; +} + +std::string WindowRoot::GenAllWindowsLogInfo() const +{ + std::ostringstream os; + WindowNodeOperationFunc func = [&os](sptr node) { + if (node == nullptr) { + WLOGE("WindowNode is nullptr"); + return false; + } + os<<"window_name:"<GetWindowName()<<",id:"<GetWindowId()<< + ",focusable:"<GetWindowProperty()->GetFocusable()<<";"; + return false; + }; + + for (auto& elem : windowNodeContainerMap_) { + if (elem.second == nullptr) { + continue; + } + std::vector& displayIdVec = const_cast(this)->displayIdMap_[elem.first]; + for (const auto& displayId : displayIdVec) { + os << "Display " << displayId << ":"; + } + elem.second->TraverseWindowTree(func, true); + } + return os.str(); +} + +void WindowRoot::FocusFaultDetection() const +{ + if (!needCheckFocusWindow) { + return; + } + bool needReport = true; + uint32_t focusWinId = INVALID_WINDOW_ID; + for (auto& elem : windowNodeContainerMap_) { + if (elem.second == nullptr) { + continue; + } + focusWinId = elem.second->GetFocusWindow(); + if (focusWinId != INVALID_WINDOW_ID) { + needReport = false; + sptr windowNode = GetWindowNode(focusWinId); + if (windowNode == nullptr || !windowNode->currentVisibility_) { + needReport = true; + WLOGFE("The focus windowNode is nullptr or is invisible, focusWinId: %{public}u", focusWinId); + break; + } + } + } + if (needReport) { + std::string windowLog(GenAllWindowsLogInfo()); + WLOGFE("The focus window is faulty, focusWinId:%{public}u, %{public}s", focusWinId, windowLog.c_str()); + int32_t ret = OHOS::HiviewDFX::HiSysEvent::Write( + OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, + "NO_FOCUS_WINDOW", + OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, + "PID", getpid(), + "UID", getuid(), + "PACKAGE_NAME", "foundation", + "PROCESS_NAME", "foundation", + "MSG", windowLog); + if (ret != 0) { + WLOGFE("Write HiSysEvent error, ret:%{public}d", ret); + } + } +} + +void WindowRoot::ProcessExpandDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, + std::map& displayRectMap) +{ + if (displayInfo == nullptr || !CheckDisplayInfo(displayInfo)) { + WLOGFE("get display failed or get invalid display info"); + return; + } + DisplayId displayId = displayInfo->GetDisplayId(); + ScreenId displayGroupId = displayInfo->GetScreenGroupId(); + auto container = windowNodeContainerMap_[displayGroupId]; + if (container == nullptr) { + WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId); + return; + } + + WLOGFD("[Display Create] before add new display, displayId: %{public}" PRIu64"", displayId); + container->GetMultiDisplayController()->ProcessDisplayCreate(defaultDisplayId, displayInfo, displayRectMap); + WLOGFD("[Display Create] Container exist, add new display, displayId: %{public}" PRIu64"", displayId); +} + +std::map> WindowRoot::GetAllDisplayInfos(const std::vector& displayIdVec) +{ + std::map> displayInfoMap; + for (auto& displayId : displayIdVec) { + const sptr displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); + displayInfoMap.insert(std::make_pair(displayId, displayInfo)); + WLOGFD("Get latest displayInfo, displayId: %{public}" PRIu64"", displayId); + } + return displayInfoMap; +} + +std::map WindowRoot::GetAllDisplayRectsByDMS(sptr displayInfo) +{ + std::map displayRectMap; + + if (displayInfo == nullptr) { + return displayRectMap; + } + + for (auto& displayId : displayIdMap_[displayInfo->GetScreenGroupId()]) { + auto info = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId); + Rect displayRect = { info->GetOffsetX(), info->GetOffsetY(), info->GetWidth(), info->GetHeight() }; + displayRectMap.insert(std::make_pair(displayId, displayRect)); + + WLOGFD("displayId: %{public}" PRIu64", displayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]", + displayId, displayRect.posX_, displayRect.posY_, displayRect.width_, displayRect.height_); + } + return displayRectMap; +} + +std::map WindowRoot::GetAllDisplayRectsByDisplayInfo( + const std::map>& displayInfoMap) +{ + std::map displayRectMap; + + for (const auto& iter : displayInfoMap) { + auto id = iter.first; + auto info = iter.second; + Rect displayRect = { info->GetOffsetX(), info->GetOffsetY(), info->GetWidth(), info->GetHeight() }; + displayRectMap.insert(std::make_pair(id, displayRect)); + + WLOGFD("displayId: %{public}" PRIu64", displayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]", + id, displayRect.posX_, displayRect.posY_, displayRect.width_, displayRect.height_); + } + return displayRectMap; +} + +void WindowRoot::ProcessDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap) +{ + DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId(); + ScreenId displayGroupId = (displayInfo == nullptr) ? SCREEN_ID_INVALID : displayInfo->GetScreenGroupId(); + auto iter = windowNodeContainerMap_.find(displayGroupId); + if (iter == windowNodeContainerMap_.end()) { + CreateWindowNodeContainer(displayInfo); + WLOGFD("[Display Create] Create new container for display, displayId: %{public}" PRIu64"", displayId); + } else { + auto& displayIdVec = displayIdMap_[displayGroupId]; + if (std::find(displayIdVec.begin(), displayIdVec.end(), displayId) != displayIdVec.end()) { + WLOGFD("[Display Create] Current display is already exist, displayId: %{public}" PRIu64"", displayId); + return; + } + // add displayId in displayId vector + displayIdMap_[displayGroupId].push_back(displayId); + auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap); + ProcessExpandDisplayCreate(defaultDisplayId, displayInfo, displayRectMap); + } +} + +void WindowRoot::MoveNotShowingWindowToDefaultDisplay(DisplayId defaultDisplayId, DisplayId displayId) +{ + for (auto& elem : windowNodeMap_) { + auto& windowNode = elem.second; + if (windowNode->GetDisplayId() == displayId && !windowNode->currentVisibility_) { + std::vector newShowingDisplays = { defaultDisplayId }; + windowNode->SetShowingDisplays(newShowingDisplays); + windowNode->isShowingOnMultiDisplays_ = false; + if (windowNode->GetWindowToken()) { + windowNode->GetWindowToken()->UpdateDisplayId(windowNode->GetDisplayId(), defaultDisplayId); + } + windowNode->SetDisplayId(defaultDisplayId); + } + } +} + +void WindowRoot::ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap) +{ + DisplayId displayId = (displayInfo == nullptr) ? DISPLAY_ID_INVALID : displayInfo->GetDisplayId(); + ScreenId displayGroupId = (displayInfo == nullptr) ? SCREEN_ID_INVALID : displayInfo->GetScreenGroupId(); + auto& displayIdVec = displayIdMap_[displayGroupId]; + + auto iter = windowNodeContainerMap_.find(displayGroupId); + if (iter == windowNodeContainerMap_.end() || + std::find(displayIdVec.begin(), displayIdVec.end(), displayId) == displayIdVec.end() || + displayInfoMap.find(displayId) == displayInfoMap.end()) { + WLOGFE("[Display Destroy] could not find display, destroy failed, displayId: %{public}" PRIu64"", displayId); + return; + } + + // erase displayId in displayIdMap + auto displayIter = std::remove(displayIdVec.begin(), displayIdVec.end(), displayId); + displayIdVec.erase(displayIter, displayIdVec.end()); + + // container process display destroy + auto container = iter->second; + if (container == nullptr) { + WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId); + return; + } + WLOGFD("[Display Destroy] displayId: %{public}" PRIu64"", displayId); + + std::vector needDestroyWindows; + auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap); + // erase displayId in displayRectMap + auto displayRectIter = displayRectMap.find(displayId); + if (displayRectIter == displayRectMap.end()) { + return; + } + displayRectMap.erase(displayRectIter); + container->GetMultiDisplayController()->ProcessDisplayDestroy( + defaultDisplayId, displayInfo, displayRectMap, needDestroyWindows); + for (auto id : needDestroyWindows) { + auto node = GetWindowNode(id); + if (node != nullptr) { + DestroyWindowInner(node); + } + } + // move window which is not showing on destroyed display to default display + MoveNotShowingWindowToDefaultDisplay(defaultDisplayId, displayId); + WLOGFD("[Display Destroy] displayId: %{public}" PRIu64" ", displayId); +} + +void WindowRoot::ProcessDisplayChange(DisplayId defaultDisplayId, sptr displayInfo, + const std::map>& displayInfoMap, DisplayStateChangeType type) +{ + if (displayInfo == nullptr) { + WLOGFE("get display failed"); + return; + } + DisplayId displayId = displayInfo->GetDisplayId(); + ScreenId displayGroupId = displayInfo->GetScreenGroupId(); + auto& displayIdVec = displayIdMap_[displayGroupId]; + auto iter = windowNodeContainerMap_.find(displayGroupId); + if (iter == windowNodeContainerMap_.end() || std::find(displayIdVec.begin(), + displayIdVec.end(), displayId) == displayIdVec.end()) { + WLOGFE("[Display Change] could not find display, change failed, displayId: %{public}" PRIu64"", displayId); + return; + } + // container process display change + auto container = iter->second; + if (container == nullptr) { + WLOGFE("window node container is nullptr, displayId :%{public}" PRIu64 "", displayId); + return; + } + + auto displayRectMap = GetAllDisplayRectsByDisplayInfo(displayInfoMap); + container->GetMultiDisplayController()->ProcessDisplayChange(defaultDisplayId, displayInfo, displayRectMap, type); +} + +float WindowRoot::GetVirtualPixelRatio(DisplayId displayId) const +{ + auto container = const_cast(this)->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("window container could not be found"); + return 1.0; // Use DefaultVPR 1.0 + } + return container->GetDisplayVirtualPixelRatio(displayId); +} + +Rect WindowRoot::GetDisplayGroupRect(DisplayId displayId) const +{ + Rect fullDisplayRect; + auto container = const_cast(this)->GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("window container could not be found"); + return fullDisplayRect; + } + return container->GetDisplayGroupRect(); +} + +bool WindowRoot::HasPrivateWindow(DisplayId displayId) +{ + auto container = GetWindowNodeContainer(displayId); + return container != nullptr ? container->HasPrivateWindow() : false; +} + +void WindowRoot::SetMaxAppWindowNumber(uint32_t windowNum) +{ + maxAppWindowNumber_ = windowNum; +} + +void WindowRoot::SetMaxUniRenderAppWindowNumber(uint32_t uniAppWindowNum) +{ + maxUniRenderAppWindowNumber_ = uniAppWindowNum; +} + +uint32_t WindowRoot::GetMaxUniRenderAppWindowNumber() const +{ + return maxUniRenderAppWindowNumber_; +} + +void WindowRoot::SetSplitRatios(const std::vector& splitRatioNumbers) +{ + auto& splitRatios = splitRatioConfig_.splitRatios; + splitRatios.clear(); + splitRatios = splitRatioNumbers; + for (auto iter = splitRatios.begin(); iter != splitRatios.end();) { + if (*iter > 0 && *iter < 1) { // valid ratio range (0, 1) + iter++; + } else { + iter = splitRatios.erase(iter); + } + } + std::sort(splitRatios.begin(), splitRatios.end()); + auto iter = std::unique(splitRatios.begin(), splitRatios.end()); + splitRatios.erase(iter, splitRatios.end()); // remove duplicate ratios +} + +void WindowRoot::SetExitSplitRatios(const std::vector& exitSplitRatios) +{ + if (exitSplitRatios.size() != 2) { + return; + } + if (exitSplitRatios[0] > 0 && exitSplitRatios[0] < DEFAULT_SPLIT_RATIO) { + splitRatioConfig_.exitSplitStartRatio = exitSplitRatios[0]; + } + if (exitSplitRatios[1] > DEFAULT_SPLIT_RATIO && exitSplitRatios[1] < 1) { + splitRatioConfig_.exitSplitEndRatio = exitSplitRatios[1]; + } +} + +WMError WindowRoot::GetModeChangeHotZones(DisplayId displayId, + ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config) +{ + auto container = GetOrCreateWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("GetModeChangeHotZones failed, window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + container->GetModeChangeHotZones(displayId, hotZones, config); + return WMError::WM_OK; +} + +void WindowRoot::RemoveSingleUserWindowNodes(int accountId) +{ + std::vector displayIds = GetAllDisplayIds(); + for (auto id : displayIds) { + sptr container = GetOrCreateWindowNodeContainer(id); + if (container == nullptr) { + WLOGFD("get container failed %{public}" PRIu64"", id); + continue; + } + container->RemoveSingleUserWindowNodes(accountId); + } +} + +WMError WindowRoot::UpdateRsTree(uint32_t windowId, bool isAdd) +{ + sptr node = GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_ERROR_NULLPTR; + } + auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId()); + if (container == nullptr) { + WLOGFE("window container could not be found"); + return WMError::WM_ERROR_NULLPTR; + } + for (auto& displayId : node->GetShowingDisplays()) { + if (isAdd) { + container->AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE); + } else { + container->RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE); + } + } + RSTransaction::FlushImplicitTransaction(); + return WMError::WM_OK; +} + +sptr WindowRoot::FindDialogCallerNode(WindowType type, sptr token) +{ + if (type != WindowType::WINDOW_TYPE_DIALOG) { + return nullptr; + } + + auto iter = std::find_if(windowNodeMap_.begin(), windowNodeMap_.end(), + [token](const std::map>::value_type& pair) { + if (WindowHelper::IsMainWindow(pair.second->GetWindowType())) { + return pair.second->abilityToken_ == token; + } + return false; + }); + if (iter == windowNodeMap_.end()) { + WLOGFD("cannot find windowNode"); + return nullptr; + } + return iter->second; +} + +bool WindowRoot::CheckMultiDialogWindows(WindowType type, sptr token) +{ + if (type != WindowType::WINDOW_TYPE_DIALOG) { + return false; + } + + sptr newCaller, oriCaller; + + newCaller = FindDialogCallerNode(type, token); + if (newCaller == nullptr) { + return false; + } + + for (auto& iter : windowNodeMap_) { + if (iter.second->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) { + oriCaller = FindDialogCallerNode(iter.second->GetWindowType(), iter.second->dialogTargetToken_); + if (oriCaller == newCaller) { + return true; + } + } + } + + return false; +} + +void WindowRoot::OnRenderModeChanged(bool isUniRender) +{ + WLOGFD("SwitchRender: render mode of RS has changed from %{public}u to %{public}s", + static_cast(renderMode_), std::to_string(isUniRender).c_str()); + if (isUniRender) { + switch (renderMode_) { + case RenderMode::SEPARATED: + case RenderMode::UNIFYING: + renderMode_ = RenderMode::UNIFIED; + break; + case RenderMode::SEPARATING: + RSInterfaces::GetInstance().UpdateRenderMode(false); + break; + default: + WLOGFE("SwitchRender: impossible code"); + break; + } + } else { + switch (renderMode_) { + case RenderMode::UNIFIED: + case RenderMode::SEPARATING: + renderMode_ = RenderMode::SEPARATED; + break; + case RenderMode::UNIFYING: + RSInterfaces::GetInstance().UpdateRenderMode(true); + break; + default: + WLOGFE("SwitchRender: impossible code"); + break; + } + } +} + +void WindowRoot::SwitchRenderModeIfNeeded() +{ + if (displayIdMap_.empty()) { + WLOGFE("WindowRoot::SwitchRenderModeIfNeeded: displayIdMap_ is empty"); + return; + } + if (displayIdMap_.size() != 1) { + WLOGFE("WindowRoot::SwitchRenderModeIfNeeded: invalid screenGroup number"); + return; + } + uint32_t displayNum = displayIdMap_.begin()->second.size(); + if (displayNum > 1) { + // switch to sperate render mode + ChangeRSRenderModeIfNeeded(false); + return; + } + + bool exceed = IsAppWindowExceed(); + if (exceed) { + // switch to sperate render mode + ChangeRSRenderModeIfNeeded(false); + } else { + // switch to unified render mode + ChangeRSRenderModeIfNeeded(true); + } +} + +void WindowRoot::ChangeRSRenderModeIfNeeded(bool isToUnified) +{ + switch (renderMode_) { + case RenderMode::SEPARATED: + if (isToUnified) { + WLOGFD("SwitchRender: notify RS from separated to be unifying"); + renderMode_ = RenderMode::UNIFYING; + RSInterfaces::GetInstance().UpdateRenderMode(true); + } + break; + case RenderMode::UNIFIED: + if (!isToUnified) { + WLOGFD("SwitchRender: notify RS from unified to be separating"); + renderMode_ = RenderMode::SEPARATING; + RSInterfaces::GetInstance().UpdateRenderMode(false); + } + break; + case RenderMode::SEPARATING: + if (isToUnified) { + WLOGFD("SwitchRender: notify RS from separating to be unifying"); + renderMode_ = RenderMode::UNIFYING; + } + break; + case RenderMode::UNIFYING: + if (!isToUnified) { + WLOGFD("SwitchRender: notify RS from unifying to be separating"); + renderMode_ = RenderMode::SEPARATING; + } + break; + default: + WLOGE("SwitchRender: impossible code"); + break; + } +} + +bool WindowRoot::IsAppWindowExceed() const +{ + uint32_t appWindowNum = 0; + for (const auto& it : windowNodeMap_) { + WindowType winType = it.second->GetWindowType(); + WindowMode winMode = it.second->GetWindowMode(); + if (winMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || winMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { + return false; + } + if (winType >= WindowType::APP_WINDOW_BASE && winType < WindowType::APP_WINDOW_END && + it.second->currentVisibility_) { + appWindowNum++; + } + } + WLOGFD("SwitchRender: the number of app window is %{public}u", maxUniRenderAppWindowNumber_); + return (appWindowNum > maxUniRenderAppWindowNumber_); +} + +sptr WindowRoot::GetWindowNodeByAbilityToken(const sptr& abilityToken) +{ + for (const auto& iter : windowNodeMap_) { + if (iter.second != nullptr && iter.second->abilityToken_ == abilityToken) { + return iter.second; + } + } + WLOGFE("could not find required abilityToken!"); + return nullptr; +} + +bool WindowRoot::TakeWindowPairSnapshot(DisplayId displayId) +{ + auto container = GetWindowNodeContainer(displayId); + return container == nullptr ? false : container->TakeWindowPairSnapshot(displayId); +} + +void WindowRoot::ClearWindowPairSnapshot(DisplayId displayId) +{ + auto container = GetWindowNodeContainer(displayId); + if (container == nullptr) { + WLOGFE("clear window pair snapshot failed, because container in null"); + return; + } + return container->ClearWindowPairSnapshot(displayId); +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/src/window_snapshot/snapshot_controller.cpp b/window_manager/wmserver/src/window_snapshot/snapshot_controller.cpp new file mode 100644 index 0000000..65eed33 --- /dev/null +++ b/window_manager/wmserver/src/window_snapshot/snapshot_controller.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021-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 "snapshot_controller.h" + +#include + +#include "surface_capture_future.h" +#include "surface_draw.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SnapshotController"}; +} + +int32_t SnapshotController::GetSnapshot(const sptr &token, Snapshot& snapshot) +{ + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:GetSnapshot"); + if (token == nullptr) { + WLOGFE("Get snapshot failed, because token is null."); + return static_cast(WMError::WM_ERROR_NULLPTR); + } + if (handler_ == nullptr || windowRoot_ == nullptr) { + WLOGFE("Get snapshot failed, because handler/root is null."); + return static_cast(WMError::WM_ERROR_NULLPTR); + } + + performReport_->start(); + // get snapshot cache in wms main handler + std::shared_ptr pixelMap; + std::shared_ptr surfaceNode; + auto task = [this, &pixelMap, &surfaceNode, token] () { + auto targetNode = windowRoot_->GetWindowNodeByAbilityToken(token); + if (targetNode != nullptr) { + pixelMap = targetNode->GetSnapshot(); + targetNode->SetSnapshot(nullptr); // reset window snapshot after use + surfaceNode = targetNode->surfaceNode_; + } + }; + handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE); + + // do snapshot if no cache + if (pixelMap == nullptr) { + bool snapSucc = SurfaceDraw::GetSurfaceSnapshot(surfaceNode, pixelMap, 300); // snapshot time out 300ms + if (!snapSucc) { + return static_cast(WMError::WM_ERROR_NULLPTR); + } + } + + // success to snapshot + snapshot.SetPixelMap(pixelMap); + performReport_->end(); + return static_cast(WM_OK); +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/window_snapshot/snapshot_proxy.cpp b/window_manager/wmserver/src/window_snapshot/snapshot_proxy.cpp new file mode 100644 index 0000000..3843eb8 --- /dev/null +++ b/window_manager/wmserver/src/window_snapshot/snapshot_proxy.cpp @@ -0,0 +1,53 @@ +/* + * 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 "snapshot_proxy.h" +#include "ipc_types.h" +#include "pixel_map.h" +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SnapshotProxy"}; +} + +int32_t SnapshotProxy::GetSnapshot(const sptr &token, AAFwk::Snapshot& snapshot) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return static_cast(WMError::WM_ERROR_IPC_FAILED); + } + + if (!data.WriteRemoteObject(token)) { + WLOGFE("Write ability token failed"); + return static_cast(WMError::WM_ERROR_IPC_FAILED); + } + + if (Remote()->SendRequest(TRANS_ID_GET_SNAPSHOT, data, reply, option) != ERR_NONE) { + return static_cast(WMError::WM_ERROR_IPC_FAILED); + } + + std::shared_ptr pixelMap(reply.ReadParcelable()); + snapshot.SetPixelMap(pixelMap); + return reply.ReadInt32(); +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/src/window_snapshot/snapshot_stub.cpp b/window_manager/wmserver/src/window_snapshot/snapshot_stub.cpp new file mode 100644 index 0000000..d2ca4a7 --- /dev/null +++ b/window_manager/wmserver/src/window_snapshot/snapshot_stub.cpp @@ -0,0 +1,56 @@ +/* + * 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 "snapshot_stub.h" +#include +#include "window_manager_hilog.h" +#include "wm_common.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SnapshotStub"}; +} + +int32_t SnapshotStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + WLOGFI("SnapshotStub::OnRemoteRequest code is %{public}u", code); + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed!"); + return -1; + } + switch (code) { + case TRANS_ID_GET_SNAPSHOT : { + AAFwk::Snapshot snapshot_; + sptr abilityObject = data.ReadRemoteObject(); + int32_t ret = GetSnapshot(abilityObject, snapshot_); + if (snapshot_.GetPixelMap() == nullptr) { + reply.WriteParcelable(nullptr); + reply.WriteInt32(static_cast(WMError::WM_ERROR_NULLPTR)); + break; + } + reply.WriteParcelable(snapshot_.GetPixelMap().get()); + reply.WriteInt32(ret); + break; + } + default: + WLOGFW("unknown transaction code"); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return 0; +} +} +} diff --git a/window_manager/wmserver/src/window_zorder_policy.cpp b/window_manager/wmserver/src/window_zorder_policy.cpp new file mode 100644 index 0000000..8b68172 --- /dev/null +++ b/window_manager/wmserver/src/window_zorder_policy.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021-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 "window_manager_hilog.h" +#include "window_zorder_policy.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowZorderPolicy"}; +} + +int32_t WindowZorderPolicy::GetWindowPriority(WindowType type) const +{ + if (windowPriorityMap_.count(type) == 0) { + WLOGFE("invalid window type"); + return windowPriorityMap_.at(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + } + return windowPriorityMap_.at(type); +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/src/zidl/ressched_report.cpp b/window_manager/wmserver/src/zidl/ressched_report.cpp new file mode 100644 index 0000000..56d7a0a --- /dev/null +++ b/window_manager/wmserver/src/zidl/ressched_report.cpp @@ -0,0 +1,57 @@ +/* + * 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 "zidl/ressched_report.h" +#include + +namespace OHOS::Rosen { +namespace { +#ifdef __aarch64__ + const std::string RES_SCHED_CLIENT_SO = "/system/lib64/libressched_client.z.so"; +#else + const std::string RES_SCHED_CLIENT_SO = "/system/lib/libressched_client.z.so"; +#endif +} + +ReportDataFunc LoadReportDataFunc() +{ + auto handle = dlopen(RES_SCHED_CLIENT_SO.c_str(), RTLD_NOW); + if (handle == nullptr) { + return nullptr; + } + auto func = reinterpret_cast(dlsym(handle, "ReportData")); + if (func == nullptr) { + dlclose(handle); + return nullptr; + } + return func; +} + +ResSchedReport& ResSchedReport::GetInstance() +{ + static ResSchedReport instance; + return instance; +} + +void ResSchedReport::ResSchedDataReport(uint32_t resType, int32_t value, + const std::unordered_map& payload) +{ + if (reportDataFunc_ == nullptr) { + reportDataFunc_ = LoadReportDataFunc(); + } + if (reportDataFunc_ != nullptr) { + reportDataFunc_(resType, value, payload); + } +} +} // namespace OHOS::Rosen \ No newline at end of file diff --git a/window_manager/wmserver/src/zidl/window_manager_proxy.cpp b/window_manager/wmserver/src/zidl/window_manager_proxy.cpp new file mode 100644 index 0000000..17099ea --- /dev/null +++ b/window_manager/wmserver/src/zidl/window_manager_proxy.cpp @@ -0,0 +1,840 @@ +/* + * Copyright (c) 2021-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 "zidl/window_manager_proxy.h" +#include +#include + +#include "marshalling_helper.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerProxy"}; +} + + +WMError WindowManagerProxy::CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, uint32_t& windowId, sptr token) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteRemoteObject(window->AsObject())) { + WLOGFE("Write IWindow failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteParcelable(property.GetRefPtr())) { + WLOGFE("Write windowProperty failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (surfaceNode == nullptr || !surfaceNode->Marshalling(data)) { + WLOGFE("Write windowProperty failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (token != nullptr) { + if (!data.WriteRemoteObject(token)) { + WLOGFE("Write abilityToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_CREATE_WINDOW), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + windowId = reply.ReadUint32(); + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::AddWindow(sptr& property) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteParcelable(property.GetRefPtr())) { + WLOGFE("Write windowProperty failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_ADD_WINDOW), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::RemoveWindow(uint32_t windowId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_REMOVE_WINDOW), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::DestroyWindow(uint32_t windowId, bool /* onlySelf */) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_DESTROY_WINDOW), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::RequestFocus(uint32_t windowId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_REQUEST_FOCUS), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +AvoidArea WindowManagerProxy::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + AvoidArea avoidArea; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return avoidArea; + } + + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return avoidArea; + } + + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write AvoidAreaType failed"); + return avoidArea; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_AVOID_AREA), + data, reply, option) != ERR_NONE) { + return avoidArea; + } + sptr area = reply.ReadParcelable(); + if (area == nullptr) { + return avoidArea; + } + return *area; +} + +bool WindowManagerProxy::RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write type failed"); + return false; + } + + if (!data.WriteRemoteObject(windowManagerAgent->AsObject())) { + WLOGFE("Write IWindowManagerAgent failed"); + return false; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_REGISTER_WINDOW_MANAGER_AGENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return false; + } + + return reply.ReadBool(); +} + +bool WindowManagerProxy::UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return false; + } + + if (!data.WriteUint32(static_cast(type))) { + WLOGFE("Write type failed"); + return false; + } + + if (!data.WriteRemoteObject(windowManagerAgent->AsObject())) { + WLOGFE("Write IWindowManagerAgent failed"); + return false; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_UNREGISTER_WINDOW_MANAGER_AGENT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return false; + } + + return reply.ReadBool(); +} + +WMError WindowManagerProxy::SetWindowAnimationController(const sptr& controller) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (controller == nullptr) { + WLOGFE("RSWindowAnimation Failed to set window animation controller, controller is null!"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("RSWindowAnimation Failed to WriteInterfaceToken!"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteRemoteObject(controller->AsObject())) { + WLOGFE("RSWindowAnimation Failed to write controller!"); + return WMError::WM_ERROR_IPC_FAILED; + } + + auto error = Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_ANIMATION_SET_CONTROLLER), + data, reply, option); + if (error != ERR_NONE) { + WLOGFE("RSWindowAnimation Send request error: %{public}d", error); + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +void WindowManagerProxy::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return; + } + if (!data.WriteParcelable(windowProperty.GetRefPtr())) { + WLOGFE("Failed to write windowProperty!"); + return; + } + if (!data.WriteParcelable(moveDragProperty.GetRefPtr())) { + WLOGFE("Failed to write moveDragProperty!"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_NOTIFY_READY_MOVE_OR_DRAG), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerProxy::ProcessPointDown(uint32_t windowId, bool isPointDown) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return; + } + if (!data.WriteBool(isPointDown)) { + WLOGFE("Write isPointDown failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_PROCESS_POINT_DOWN), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerProxy::ProcessPointUp(uint32_t windowId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_PROCESS_POINT_UP), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerProxy::MinimizeAllAppWindows(DisplayId displayId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint64(displayId)) { + WLOGFE("Write displayId failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_MINIMIZE_ALL_APP_WINDOWS), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +WMError WindowManagerProxy::ToggleShownStateForAllAppWindows() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest( + static_cast(WindowManagerMessage::TRANS_ID_TOGGLE_SHOWN_STATE_FOR_ALL_APP_WINDOWS), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + int32_t ret; + if (!reply.ReadInt32(ret)) { + return WMError::WM_ERROR_IPC_FAILED; + } + return static_cast(ret); +} + +WMError WindowManagerProxy::SetWindowLayoutMode(WindowLayoutMode mode) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(static_cast(mode))) { + WLOGFE("Write mode failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_UPDATE_LAYOUT_MODE), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::UpdateProperty(sptr& windowProperty, PropertyChangeAction action, + bool isAsyncTask) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(static_cast(action))) { + WLOGFE("Write PropertyChangeAction failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!windowProperty->Write(data, action)) { + WLOGFE("Write windowProperty failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_UPDATE_PROPERTY), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteUint32(mainWinId)) { + WLOGFE("Write mainWinId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_TOP_WINDOW_ID), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + topWinId = reply.ReadUint32(); + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::GetAccessibilityWindowInfo(std::vector>& infos) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_ACCESSIBILITY_WINDOW_INFO_ID), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + if (!MarshallingHelper::UnmarshallingVectorParcelableObj(reply, infos)) { + WLOGFE("read accessibility window infos failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +WMError WindowManagerProxy::GetVisibilityWindowInfo(std::vector>& infos) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_VISIBILITY_WINDOW_INFO_ID), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + if (!MarshallingHelper::UnmarshallingVectorParcelableObj(reply, infos)) { + WLOGFE("read visibility window infos failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +WMError WindowManagerProxy::GetSystemConfig(SystemConfig& systemConfig) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_SYSTEM_CONFIG), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + sptr config = reply.ReadParcelable(); + systemConfig = *config; + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +WMError WindowManagerProxy::NotifyWindowTransition(sptr& from, sptr& to, + bool isFromClient) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("Failed to WriteInterfaceToken!"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteParcelable(from)) { + WLOGFE("Failed to write from ability window info!"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteParcelable(to)) { + WLOGFE("Failed to write to ability window info!"); + return WMError::WM_ERROR_IPC_FAILED; + } + + if (!data.WriteBool(isFromClient)) { + WLOGFE("Failed to write to isFromClient!"); + return WMError::WM_ERROR_IPC_FAILED; + } + auto error = Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_NOTIFY_WINDOW_TRANSITION), + data, reply, option); + if (error != ERR_NONE) { + WLOGFE("Send request error: %{public}d", static_cast(error)); + return WMError::WM_ERROR_IPC_FAILED; + } + auto ret = static_cast(reply.ReadInt32()); + return ret; +} + +WMError WindowManagerProxy::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint64(displayId)) { + WLOGFE("Write displayId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_FULLSCREEN_AND_SPLIT_HOT_ZONE), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + auto ret = static_cast(reply.ReadInt32()); + if (ret == WMError::WM_OK) { + hotZones.fullscreen_.posX_ = reply.ReadInt32(); + hotZones.fullscreen_.posY_ = reply.ReadInt32(); + hotZones.fullscreen_.width_ = reply.ReadUint32(); + hotZones.fullscreen_.height_ = reply.ReadUint32(); + + hotZones.primary_.posX_ = reply.ReadInt32(); + hotZones.primary_.posY_ = reply.ReadInt32(); + hotZones.primary_.width_ = reply.ReadUint32(); + hotZones.primary_.height_ = reply.ReadUint32(); + + hotZones.secondary_.posX_ = reply.ReadInt32(); + hotZones.secondary_.posY_ = reply.ReadInt32(); + hotZones.secondary_.width_ = reply.ReadUint32(); + hotZones.secondary_.height_ = reply.ReadUint32(); + } + return ret; +} + +void WindowManagerProxy::MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + + if (!data.WriteUInt32Vector(windowIds)) { + WLOGFE("Write windowIds failed"); + return; + } + + if (!data.WriteBool(isAnimated)) { + WLOGFE("Write isAnimated failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_ANIMATION_CALLBACK), + data, reply, option) != ERR_NONE) { + WLOGFE("Send request error"); + return; + } + ; + if (reply.ReadBool()) { + sptr finishCallbackObject = reply.ReadRemoteObject(); + finishCallback = iface_cast(finishCallbackObject); + } else { + finishCallback = nullptr; + } + return; +} + +WMError WindowManagerProxy::UpdateAvoidAreaListener(uint32_t windowId, bool haveListener) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteBool(haveListener)) { + WLOGFE("Write avoid area listener failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_UPDATE_AVOIDAREA_LISTENER), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +WMError WindowManagerProxy::UpdateRsTree(uint32_t windowId, bool isAdd) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteBool(isAdd)) { + WLOGFE("Write avoid area listener failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_UPDATE_RS_TREE), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + return static_cast(reply.ReadInt32()); +} + +WMError WindowManagerProxy::BindDialogTarget(uint32_t& windowId, sptr targetToken) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + if (targetToken != nullptr) { + if (!data.WriteRemoteObject(targetToken)) { + WLOGFE("Write targetToken failed"); + return WMError::WM_ERROR_IPC_FAILED; + } + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_BIND_DIALOG_TARGET), + data, reply, option) != ERR_NONE) { + return WMError::WM_ERROR_IPC_FAILED; + } + + int32_t ret = reply.ReadInt32(); + return static_cast(ret); +} + +void WindowManagerProxy::SetAnchorAndScale(int32_t x, int32_t y, float scale) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteInt32(x)) { + WLOGFE("Write anchor x failed"); + return; + } + if (!data.WriteInt32(y)) { + WLOGFE("Write anchor y failed"); + return; + } + if (!data.WriteFloat(scale)) { + WLOGFE("Write scale failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_SET_ANCHOR_AND_SCALE), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerProxy::SetAnchorOffset(int32_t deltaX, int32_t deltaY) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteInt32(deltaX)) { + WLOGFE("Write anchor delatX failed"); + return; + } + if (!data.WriteInt32(deltaY)) { + WLOGFE("Write anchor deltaY failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_SET_ANCHOR_OFFSET), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +void WindowManagerProxy::OffWindowZoom() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_OFF_WINDOW_ZOOM), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} + +std::shared_ptr WindowManagerProxy::GetSnapshot(int32_t windowId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + Media::InitializationOptions opts; + opts.size.width = 200; // 200:default width + opts.size.height = 300; // 300:default height + std::shared_ptr pixelMap(Media::PixelMap::Create(opts).release()); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return pixelMap; + } + if (!data.WriteUint32(windowId)) { + WLOGFE("Write windowId failed"); + return pixelMap; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_GET_SNAPSHOT), + data, reply, option) != ERR_NONE) { + return pixelMap; + } + + std::shared_ptr map(reply.ReadParcelable()); + if (map == nullptr) { + return pixelMap; + } + return map; +} + +void WindowManagerProxy::NotifyDumpInfoResult(const std::vector& info) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteStringVector(info)) { + WLOGFE("Write info failed"); + return; + } + if (Remote()->SendRequest(static_cast(WindowManagerMessage::TRANS_ID_NOTIFY_DUMP_INFO_RESULT), + data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + return; + } +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wmserver/src/zidl/window_manager_stub.cpp b/window_manager/wmserver/src/zidl/window_manager_stub.cpp new file mode 100644 index 0000000..b96689c --- /dev/null +++ b/window_manager/wmserver/src/zidl/window_manager_stub.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2021-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 "zidl/window_manager_stub.h" +#include +#include + +#include "marshalling_helper.h" +#include "memory_guard.h" +#include "window_manager_hilog.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManagerStub"}; +} + +int32_t WindowManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + MemoryGuard cacheGuard; + if (data.ReadInterfaceToken() != GetDescriptor()) { + WLOGFE("InterfaceToken check failed"); + return -1; + } + auto msgId = static_cast(code); + switch (msgId) { + case WindowManagerMessage::TRANS_ID_CREATE_WINDOW: { + sptr windowObject = data.ReadRemoteObject(); + sptr windowProxy = iface_cast(windowObject); + sptr windowProperty = data.ReadStrongParcelable(); + std::shared_ptr surfaceNode = RSSurfaceNode::Unmarshalling(data); + uint32_t windowId; + sptr token = nullptr; + if (windowProperty && windowProperty->GetTokenState()) { + token = data.ReadRemoteObject(); + } else { + WLOGFI("accept token is nullptr"); + } + WMError errCode = CreateWindow(windowProxy, windowProperty, surfaceNode, windowId, token); + reply.WriteUint32(windowId); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_ADD_WINDOW: { + sptr windowProperty = data.ReadStrongParcelable(); + WMError errCode = AddWindow(windowProperty); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_REMOVE_WINDOW: { + uint32_t windowId = data.ReadUint32(); + WMError errCode = RemoveWindow(windowId); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_DESTROY_WINDOW: { + uint32_t windowId = data.ReadUint32(); + WMError errCode = DestroyWindow(windowId); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_REQUEST_FOCUS: { + uint32_t windowId = data.ReadUint32(); + WMError errCode = RequestFocus(windowId); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_GET_AVOID_AREA: { + uint32_t windowId = data.ReadUint32(); + auto avoidAreaType = static_cast(data.ReadUint32()); + AvoidArea avoidArea = GetAvoidAreaByType(windowId, avoidAreaType); + reply.WriteParcelable(&avoidArea); + + break; + } + case WindowManagerMessage::TRANS_ID_REGISTER_WINDOW_MANAGER_AGENT: { + auto type = static_cast(data.ReadUint32()); + sptr windowManagerAgentObject = data.ReadRemoteObject(); + sptr windowManagerAgentProxy = + iface_cast(windowManagerAgentObject); + bool ret = RegisterWindowManagerAgent(type, windowManagerAgentProxy); + reply.WriteBool(ret); + break; + } + case WindowManagerMessage::TRANS_ID_UNREGISTER_WINDOW_MANAGER_AGENT: { + auto type = static_cast(data.ReadUint32()); + sptr windowManagerAgentObject = data.ReadRemoteObject(); + sptr windowManagerAgentProxy = + iface_cast(windowManagerAgentObject); + bool ret = UnregisterWindowManagerAgent(type, windowManagerAgentProxy); + reply.WriteBool(ret); + break; + } + case WindowManagerMessage::TRANS_ID_NOTIFY_READY_MOVE_OR_DRAG: { + uint32_t windowId = data.ReadUint32(); + sptr windowProperty = data.ReadStrongParcelable(); + sptr moveDragProperty = data.ReadStrongParcelable(); + NotifyServerReadyToMoveOrDrag(windowId, windowProperty, moveDragProperty); + break; + } + case WindowManagerMessage::TRANS_ID_PROCESS_POINT_DOWN: { + uint32_t windowId = data.ReadUint32(); + bool isPointDown = data.ReadBool(); + ProcessPointDown(windowId, isPointDown); + break; + } + case WindowManagerMessage::TRANS_ID_PROCESS_POINT_UP: { + uint32_t windowId = data.ReadUint32(); + ProcessPointUp(windowId); + break; + } + case WindowManagerMessage::TRANS_ID_GET_TOP_WINDOW_ID: { + uint32_t mainWinId = data.ReadUint32(); + uint32_t topWinId; + WMError errCode = GetTopWindowId(mainWinId, topWinId); + reply.WriteUint32(topWinId); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_MINIMIZE_ALL_APP_WINDOWS: { + MinimizeAllAppWindows(data.ReadUint64()); + break; + } + case WindowManagerMessage::TRANS_ID_TOGGLE_SHOWN_STATE_FOR_ALL_APP_WINDOWS: { + WMError errCode = ToggleShownStateForAllAppWindows(); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_UPDATE_LAYOUT_MODE: { + auto mode = static_cast(data.ReadUint32()); + WMError errCode = SetWindowLayoutMode(mode); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_UPDATE_PROPERTY: { + auto action = static_cast(data.ReadUint32()); + sptr windowProperty = new WindowProperty(); + windowProperty->Read(data, action); + WMError errCode = UpdateProperty(windowProperty, action); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_GET_ACCESSIBILITY_WINDOW_INFO_ID: { + std::vector> infos; + WMError errCode = GetAccessibilityWindowInfo(infos); + if (!MarshallingHelper::MarshallingVectorParcelableObj(reply, infos)) { + WLOGFE("Write accessibility window infos failed"); + return -1; + } + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_GET_VISIBILITY_WINDOW_INFO_ID: { + std::vector> infos; + WMError errCode = GetVisibilityWindowInfo(infos); + if (!MarshallingHelper::MarshallingVectorParcelableObj(reply, infos)) { + WLOGFE("Write visibility window infos failed"); + return -1; + } + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_ANIMATION_SET_CONTROLLER: { + sptr controllerObject = data.ReadRemoteObject(); + sptr controller = iface_cast(controllerObject); + WMError errCode = SetWindowAnimationController(controller); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_GET_SYSTEM_CONFIG: { + SystemConfig config; + WMError errCode = GetSystemConfig(config); + reply.WriteParcelable(&config); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_NOTIFY_WINDOW_TRANSITION: { + sptr from = data.ReadParcelable(); + sptr to = data.ReadParcelable(); + bool isFromClient = data.ReadBool(); + WMError errCode = NotifyWindowTransition(from, to, isFromClient); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_GET_FULLSCREEN_AND_SPLIT_HOT_ZONE: { + DisplayId displayId = data.ReadUint64(); + ModeChangeHotZones hotZones = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; + WMError errCode = GetModeChangeHotZones(displayId, hotZones); + reply.WriteInt32(static_cast(errCode)); + + reply.WriteInt32(hotZones.fullscreen_.posX_); + reply.WriteInt32(hotZones.fullscreen_.posY_); + reply.WriteUint32(hotZones.fullscreen_.width_); + reply.WriteUint32(hotZones.fullscreen_.height_); + + reply.WriteInt32(hotZones.primary_.posX_); + reply.WriteInt32(hotZones.primary_.posY_); + reply.WriteUint32(hotZones.primary_.width_); + reply.WriteUint32(hotZones.primary_.height_); + + reply.WriteInt32(hotZones.secondary_.posX_); + reply.WriteInt32(hotZones.secondary_.posY_); + reply.WriteUint32(hotZones.secondary_.width_); + reply.WriteUint32(hotZones.secondary_.height_); + break; + } + case WindowManagerMessage::TRANS_ID_GET_ANIMATION_CALLBACK: { + std::vector windowIds; + data.ReadUInt32Vector(&windowIds); + bool isAnimated = data.ReadBool(); + sptr finishedCallback = nullptr; + MinimizeWindowsByLauncher(windowIds, isAnimated, finishedCallback); + if (finishedCallback == nullptr) { + if (!reply.WriteBool(false)) { + WLOGFE("finishedCallback is nullptr and failed to write!"); + return 0; + } + } else { + if (!reply.WriteBool(true) || !reply.WriteRemoteObject(finishedCallback->AsObject())) { + WLOGFE("finishedCallback is not nullptr and failed to write!"); + return 0; + } + } + break; + } + case WindowManagerMessage::TRANS_ID_UPDATE_AVOIDAREA_LISTENER: { + uint32_t windowId = data.ReadUint32(); + bool haveAvoidAreaListener = data.ReadBool(); + WMError errCode = UpdateAvoidAreaListener(windowId, haveAvoidAreaListener); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_UPDATE_RS_TREE: { + uint32_t windowId = data.ReadUint32(); + bool isAdd = data.ReadBool(); + WMError errCode = UpdateRsTree(windowId, isAdd); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_BIND_DIALOG_TARGET: { + uint32_t windowId = data.ReadUint32(); + sptr targetToken = data.ReadRemoteObject(); + WMError errCode = BindDialogTarget(windowId, targetToken); + reply.WriteInt32(static_cast(errCode)); + break; + } + case WindowManagerMessage::TRANS_ID_SET_ANCHOR_AND_SCALE : { + int32_t x = data.ReadInt32(); + int32_t y = data.ReadInt32(); + float scale = data.ReadFloat(); + SetAnchorAndScale(x, y, scale); + break; + } + case WindowManagerMessage::TRANS_ID_SET_ANCHOR_OFFSET: { + int32_t deltaX = data.ReadInt32(); + int32_t deltaY = data.ReadInt32(); + SetAnchorOffset(deltaX, deltaY); + break; + } + case WindowManagerMessage::TRANS_ID_OFF_WINDOW_ZOOM: { + OffWindowZoom(); + break; + } + case WindowManagerMessage::TRANS_ID_GET_SNAPSHOT: { + uint32_t windowId = data.ReadUint32(); + std::shared_ptr pixelMap = GetSnapshot(windowId); + reply.WriteParcelable(pixelMap.get()); + break; + } + case WindowManagerMessage::TRANS_ID_NOTIFY_DUMP_INFO_RESULT: { + std::vector info; + data.ReadStringVector(&info); + NotifyDumpInfoResult(info); + break; + } + default: + WLOGFW("unknown transaction code %{public}d", code); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + return 0; +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/test/BUILD.gn b/window_manager/wmserver/test/BUILD.gn new file mode 100644 index 0000000..a29ddb1 --- /dev/null +++ b/window_manager/wmserver/test/BUILD.gn @@ -0,0 +1,17 @@ +# 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. + +group("test") { + testonly = true + deps = [ "unittest:unittest" ] +} diff --git a/window_manager/wmserver/test/unittest/BUILD.gn b/window_manager/wmserver/test/unittest/BUILD.gn new file mode 100644 index 0000000..5402c79 --- /dev/null +++ b/window_manager/wmserver/test/unittest/BUILD.gn @@ -0,0 +1,372 @@ +# 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. + +import("//build/test.gni") +import("//foundation/window/window_manager/windowmanager_aafwk.gni") +module_out_path = "window_manager/wmserver" + +group("unittest") { + testonly = true + deps = [ + ":wmserver_accessibility_connection_test", + ":wmserver_avoid_area_controller_test", + ":wmserver_display_group_controller_test", + ":wmserver_display_group_info_test", + ":wmserver_drag_controller_test", + ":wmserver_input_window_monitor_test", + ":wmserver_minimize_app_test", + ":wmserver_remote_animation_test", + ":wmserver_starting_window_test", + ":wmserver_window_controller_test", + ":wmserver_window_dumper_test", + ":wmserver_window_display_zoom_controller_test", + ":wmserver_window_freeze_controller_test", + ":wmserver_window_inner_manager_test", + ":wmserver_window_inner_window_test", + ":wmserver_window_layout_policy_test", + ":wmserver_window_manager_config_test", + ":wmserver_window_manager_proxy_test", + ":wmserver_window_manager_service_test", + ":wmserver_window_manager_stub_test", + ":wmserver_window_node_container_test", + ":wmserver_window_node_test", + ":wmserver_window_pair_test", + ":wmserver_window_root_test", + ":wmserver_window_snapshot_test", + ":wmserver_window_zorder_policy_test", + ] +} + +test_external_deps = [ + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ace_engine:ace_uicontent", + "bundle_framework:appexecfwk_base", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", + "display_manager:displaymgr", + "eventhandler:libeventhandler", + "graphic_standard:window_animation", + "hicollie_native:libhicollie", + "hilog_native:libhilog", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "input:libmmi-client", + "ipc:ipc_core", + "napi:ace_napi", + "power_manager:powermgr_client", + "safwk:system_ability_fwk", +] + +test_public_deps = [ + "//third_party/googletest:gmock", + "//third_party/googletest:gtest_main", +] + +test_inner_deps = [ + "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client", + "//foundation/window/window_manager/dm:libdm", + "//foundation/window/window_manager/dmserver:libdms", + "//foundation/window/window_manager/test/common/utils:libtestutil", + "//foundation/window/window_manager/utils:libwmutil", + "//foundation/window/window_manager/wm:libwm", + "//foundation/window/window_manager/wmserver:libwms", +] + +config("wmserver_unittest_common_public_config") { + include_dirs = [ + "//foundation/window/window_manager/test/common/mock", + "//foundation/window/window_manager/test/common/utils/include", + "//foundation/window/window_manager/wm/include", + "//foundation/window/window_manager/wmserver/include", + "//foundation/window/window_manager/wmserver/include/zidl", + "//foundation/window/window_manager/wmserver/include/window_snapshot", + "//foundation/window/window_manager/interfaces/innerkits/wm", + "//foundation/window/window_manager/utils/include", + "//third_party/googletest/googlemock/include", + "foundation/graphic/graphic_2d/rosen/modules/2d_graphics/include/", + ] +} + +test_public_config = [ + ":wmserver_unittest_common_public_config", + "//foundation/window/window_manager/resources/config/build:coverage_flags", + "//foundation/window/window_manager/resources/config/build:testcase_flags", +] + +ohos_unittest("wmserver_input_window_monitor_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "input_window_monitor_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_avoid_area_controller_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "avoid_area_controller_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_controller_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_controller_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_minimize_app_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "minimize_app_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_layout_policy_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_layout_policy_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_manager_config_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_manager_config_test.cpp" ] + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps + + deps += [ "//third_party/libxml2:libxml2" ] +} + +ohos_unittest("wmserver_window_snapshot_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_snapshot_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps + + external_deps += [ "multimedia_image_framework:image_native" ] +} + +ohos_unittest("wmserver_window_zorder_policy_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_zorder_policy_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_node_container_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_node_container_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_node_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_node_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_pair_test") { + module_out_path = module_out_path + configs = test_public_config + + sources = [ "window_pair_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_manager_stub_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_manager_stub_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_starting_window_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "starting_window_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_manager_service_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_manager_service_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_manager_proxy_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_manager_proxy_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_display_group_info_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "display_group_info_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_accessibility_connection_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "accessibility_connection_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_dumper_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_dumper_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_display_group_controller_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "display_group_controller_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_display_zoom_controller_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_display_zoom_controller_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_remote_animation_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "remote_animation_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_freeze_controller_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_freeze_controller_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_inner_window_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_inner_window_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_drag_controller_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "drag_controller_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_inner_manager_test") { + module_out_path = module_out_path + configs = test_public_config + sources = [ "window_inner_manager_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} + +ohos_unittest("wmserver_window_root_test") { + module_out_path = module_out_path + configs = test_public_config + + sources = [ "window_root_test.cpp" ] + + deps = test_inner_deps + public_deps = test_public_deps + external_deps = test_external_deps +} diff --git a/window_manager/wmserver/test/unittest/accessibility_connection_test.cpp b/window_manager/wmserver/test/unittest/accessibility_connection_test.cpp new file mode 100644 index 0000000..df3571c --- /dev/null +++ b/window_manager/wmserver/test/unittest/accessibility_connection_test.cpp @@ -0,0 +1,147 @@ +/* + * 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 "accessibility_connection.h" +#include "wm_common.h" +#include "dm_common.h" +#include "common_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class AccessibilityConnectionTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr accessibilityConnection_; +}; + +void AccessibilityConnectionTest::SetUpTestCase() +{ +} + +void AccessibilityConnectionTest::TearDownTestCase() +{ +} + +void AccessibilityConnectionTest::SetUp() +{ + sptr windowRoot_ = new WindowRoot([](Event event, const sptr& remoteObject) {}); + accessibilityConnection_ = new AccessibilityConnection(windowRoot_); +} + +void AccessibilityConnectionTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: FillAccessibilityWindowInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(AccessibilityConnectionTest, FillAccessibilityWindowInfo01, Function | SmallTest | Level2) +{ + uint32_t focusedWindow = 1; + sptr windowProperty1 = new WindowProperty(); + windowProperty1->SetWindowId(focusedWindow); + windowProperty1->SetDecorEnable(true); + sptr windowNode1 = new WindowNode(windowProperty1); + sptr windowNode2 = new WindowNode(); + sptr windowNode3 = nullptr; + std::vector> nodes; + nodes.emplace_back(windowNode1); + nodes.emplace_back(windowNode2); + nodes.emplace_back(windowNode3); + std::vector> infos; + accessibilityConnection_->FillAccessibilityWindowInfo(nodes, focusedWindow, infos); + ASSERT_EQ(2, infos.size()); + ASSERT_TRUE(infos[0]->isDecorEnable_); + ASSERT_TRUE(infos[0]->focused_); + ASSERT_FALSE(infos[1]->isDecorEnable_); + ASSERT_FALSE(infos[1]->focused_); +} + +/** + * @tc.name: GetAccessibilityWindowInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(AccessibilityConnectionTest, GetAccessibilityWindowInfo01, Function | SmallTest | Level2) +{ + std::vector> infos; + accessibilityConnection_->GetAccessibilityWindowInfo(infos); + ASSERT_EQ(0, infos.size()); +} + +/** + * @tc.name: UpdateFocusChangeEvent01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(AccessibilityConnectionTest, UpdateFocusChangeEvent01, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + ScreenId displayGroupId = 0; + sptr container = new WindowNodeContainer(displayInfo, displayGroupId); + accessibilityConnection_->UpdateFocusChangeEvent(container); + ASSERT_EQ(1, accessibilityConnection_->focusedWindowMap_.size()); +} + +/** + * @tc.name: UpdateFocusChangeEvent02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(AccessibilityConnectionTest, UpdateFocusChangeEvent02, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + ScreenId displayGroupId = 0; + sptr container = new WindowNodeContainer(displayInfo, displayGroupId); + uint32_t newFocusWindow = 1; + container->SetFocusWindow(newFocusWindow); + uint32_t oldFocusWindow = 1; + accessibilityConnection_->focusedWindowMap_.insert(std::make_pair(container, oldFocusWindow)); + accessibilityConnection_->UpdateFocusChangeEvent(container); + ASSERT_EQ(1, accessibilityConnection_->focusedWindowMap_.size()); + ASSERT_EQ(1, accessibilityConnection_->focusedWindowMap_[container]); +} + +/** + * @tc.name: UpdateFocusChangeEvent03 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(AccessibilityConnectionTest, UpdateFocusChangeEvent03, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + ScreenId displayGroupId = 0; + sptr container = new WindowNodeContainer(displayInfo, displayGroupId); + uint32_t newFocusWindow = 2; + container->SetFocusWindow(newFocusWindow); + uint32_t oldFocusWindow = 1; + accessibilityConnection_->focusedWindowMap_.insert(std::make_pair(container, oldFocusWindow)); + accessibilityConnection_->UpdateFocusChangeEvent(container); + ASSERT_EQ(1, accessibilityConnection_->focusedWindowMap_.size()); + ASSERT_EQ(2, accessibilityConnection_->focusedWindowMap_[container]); +} +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/test/unittest/avoid_area_controller_test.cpp b/window_manager/wmserver/test/unittest/avoid_area_controller_test.cpp new file mode 100644 index 0000000..390cac3 --- /dev/null +++ b/window_manager/wmserver/test/unittest/avoid_area_controller_test.cpp @@ -0,0 +1,551 @@ +/* + * 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 "avoid_area_controller.h" +#include "display_manager.h" +#include "display_manager_config.h" +#include "future.h" +#include "window_node.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "AvoidAreaControllerTest"}; + + const Rect EMPTY_RECT = { 0, 0, 0, 0 }; + const float BARRATIO = 0.3; + const long TIME_OUT = 1000; + const AvoidArea EMPTY_AVOID_AREA = {}; +} + +class AvoidAreaControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + static sptr statusbarWindowNode; + static sptr navigationBarWindowNode; + static sptr keyboardWindowNode; + static Rect screenRect; + static Rect cut_out_rect; +}; + +sptr AvoidAreaControllerTest::statusbarWindowNode = nullptr; +sptr AvoidAreaControllerTest::navigationBarWindowNode = nullptr; +sptr AvoidAreaControllerTest::keyboardWindowNode = nullptr; +Rect AvoidAreaControllerTest::screenRect; + +class WindowListener : public IWindow { +public: + WMError UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) override + { + return WMError::WM_OK; + } + WMError UpdateWindowMode(WindowMode mode) override + { + return WMError::WM_OK; + } + WMError UpdateFocusStatus(bool focused) override + { + return WMError::WM_OK; + } + WMError UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) override + { + if (type == AvoidAreaType::TYPE_SYSTEM) { + statusBarAvoidAreaFuture_.SetValue(*avoidArea); + } + if (type == AvoidAreaType::TYPE_KEYBOARD) { + keyboardAvoidAreaFuture_.SetValue(*avoidArea); + } + return WMError::WM_OK; + } + WMError UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) override + { + return WMError::WM_OK; + } + WMError UpdateWindowState(WindowState state) override + { + return WMError::WM_OK; + } + WMError UpdateWindowDragInfo(const PointInfo& point, DragEvent event) override + { + return WMError::WM_OK; + } + WMError UpdateDisplayId(DisplayId from, DisplayId to) override + { + return WMError::WM_OK; + } + WMError UpdateOccupiedAreaChangeInfo(const sptr& info) override + { + return WMError::WM_OK; + } + WMError UpdateActiveStatus(bool isActive) override + { + return WMError::WM_OK; + } + sptr GetWindowProperty() override + { + return nullptr; + } + WMError NotifyTouchOutside() override + { + return WMError::WM_OK; + } + WMError NotifyScreenshot() override + { + return WMError::WM_OK; + } + WMError NotifyDestroy(void) override + { + return WMError::WM_OK; + } + WMError NotifyForeground(void) override + { + return WMError::WM_OK; + } + WMError NotifyBackground(void) override + { + return WMError::WM_OK; + } + WMError UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) override + { + return WMError::WM_OK; + } + WMError DumpInfo(const std::vector& params) override + { + return WMError::WM_OK; + } + WMError NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) override + { + return WMError::WM_OK; + } + WMError RestoreSplitWindowMode(uint32_t mode) override + { + return WMError::WM_OK; + } + RunnableFuture statusBarAvoidAreaFuture_; + RunnableFuture keyboardAvoidAreaFuture_; + + sptr AsObject() override + { + return nullptr; + } +}; + +void AvoidAreaControllerTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_TRUE((display != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate()); + screenRect = { 0, 0, static_cast(display->GetWidth()), static_cast(display->GetHeight()) }; + auto barHeight = static_cast(screenRect.height_ * BARRATIO); + Rect statusBarRect = { 0, 0, screenRect.width_, barHeight }; + Rect navigationRect = { 0, static_cast(screenRect.height_ - barHeight), screenRect.width_, barHeight }; + + sptr statusbarProperty = new WindowProperty(); + statusbarProperty->SetWindowId(100u); + statusbarProperty->SetWindowName("status bar"); + statusbarProperty->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR); + statusbarProperty->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + statusbarProperty->SetWindowRect(statusBarRect); + sptr windowListener = new WindowListener(); + statusbarWindowNode = new WindowNode(statusbarProperty, windowListener, nullptr); + + sptr navigationBarProperty = new WindowProperty(); + navigationBarProperty->SetWindowId(101u); + navigationBarProperty->SetWindowName("navigation bar"); + navigationBarProperty->SetWindowType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + navigationBarProperty->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + navigationBarProperty->SetWindowRect(navigationRect); + windowListener = new WindowListener(); + navigationBarWindowNode = new WindowNode(navigationBarProperty, windowListener, nullptr); + + sptr keyboardProperty = new WindowProperty(); + keyboardProperty->SetWindowId(101u); + keyboardProperty->SetWindowName("keyboard bar"); + keyboardProperty->SetWindowType(WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT); + keyboardProperty->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + Rect keyboardRect = { 0, static_cast(screenRect.height_ / 2), screenRect.width_, screenRect.height_ / 2 }; + keyboardProperty->SetWindowRect(keyboardRect); + windowListener = new WindowListener(); + keyboardWindowNode = new WindowNode(keyboardProperty, windowListener, nullptr); +} + +void AvoidAreaControllerTest::TearDownTestCase() +{ +} + +void AvoidAreaControllerTest::SetUp() +{ +} + +void AvoidAreaControllerTest::TearDown() +{ +} + +bool CheckSameArea(AvoidArea avoidArea, Rect t, Rect l, Rect r, Rect b) +{ + return avoidArea.topRect_ == t && avoidArea.bottomRect_ == b + && avoidArea.leftRect_ == l && avoidArea.rightRect_ == r; +} + +sptr createWindowProperty(uint32_t windowId, const std::string& windowName, + WindowType type, WindowMode mode, const Rect& screenRect) +{ + sptr property = new WindowProperty(); + property->SetWindowId(windowId); + property->SetWindowName(windowName); + property->SetWindowType(type); + property->SetWindowMode(mode); + property->SetWindowRect(screenRect); + return property; +} + +namespace { +/** + * @tc.name: AvoidArea01 + * @tc.desc: Read and write avoidArea test + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, AvoidArea01, Function | SmallTest | Level2) +{ + AvoidArea avoidarea; + Parcel parcel; + AvoidArea* readArea = AvoidArea::Unmarshalling(parcel); + ASSERT_EQ(true, readArea == nullptr); + ASSERT_EQ(true, avoidarea.Marshalling(parcel)); +} + +/** + * @tc.name: GetSystemBarAvoidArea01 + * @tc.desc: Get avoid areas with TYPE_SYSTEM + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, GetSystemBarAvoidArea01, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr listener = new WindowListener(); + sptr appWindow = new WindowNode(property, listener, nullptr); + uint32_t focusedWindow = appWindow->GetWindowId(); + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_ADD, nullptr); + auto avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_SYSTEM); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), + EMPTY_RECT, EMPTY_RECT, navigationBarWindowNode->GetWindowRect())); + + // set rect + Rect statusBarRect = statusbarWindowNode->GetWindowRect(); + Rect navigationBarRect = navigationBarWindowNode->GetWindowRect(); + Rect windowRect = { 0, static_cast(statusBarRect.height_), statusBarRect.width_, + static_cast(navigationBarRect.posY_ - statusBarRect.height_) }; + property->SetWindowRect(windowRect); + avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_SYSTEM); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + + // restore rect + property->SetWindowRect(screenRect); + avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_SYSTEM); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), + EMPTY_RECT, EMPTY_RECT, navigationBarWindowNode->GetWindowRect())); + + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_SYSTEM); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); +} + +/** + * @tc.name: SystemBarAvoidArea02 + * @tc.desc: Get avoid areas with listener, TYPE_SYSTEM. + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, SystemBarAvoidArea02, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr windowListener = new WindowListener(); + sptr appWindow = new WindowNode(property, windowListener, nullptr); + uint32_t focusedWindow = appWindow->GetWindowId(); + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->UpdateAvoidAreaListener(appWindow, true); + + // add status bar + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + auto avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), + EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + + // add navigation bar + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), EMPTY_RECT, + EMPTY_RECT, navigationBarWindowNode->GetWindowRect())); + + // update appWindow rect + Rect statusBarRect = statusbarWindowNode->GetWindowRect(); + Rect navigationBarRect = navigationBarWindowNode->GetWindowRect(); + Rect windowRect = { 0, static_cast(statusBarRect.height_), statusBarRect.width_, + static_cast(navigationBarRect.posY_ - statusBarRect.height_) }; + property->SetWindowRect(windowRect); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_UPDATE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + + // restore appWindow rect + property->SetWindowRect(screenRect); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_UPDATE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), + EMPTY_RECT, EMPTY_RECT, navigationBarWindowNode->GetWindowRect())); + + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_REMOVE, nullptr); +} + +/** + * @tc.name: SystemBarAvoidArea03 + * @tc.desc: Get avoid areas with listener, TYPE_SYSTEM. + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, SystemBarAvoidArea03, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr windowListener = new WindowListener(); + sptr appWindow = new WindowNode(property, windowListener, nullptr); + uint32_t focusedWindow = appWindow->GetWindowId(); + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->UpdateAvoidAreaListener(appWindow, true); + + // add status bar + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + auto avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), EMPTY_RECT, + EMPTY_RECT, EMPTY_RECT)); + + // add navigation bar + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), EMPTY_RECT, + EMPTY_RECT, navigationBarWindowNode->GetWindowRect())); + + // remove status bar + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, + navigationBarWindowNode->GetWindowRect())); + + // remove navigation bar + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_REMOVE, nullptr); +} + +/** + * @tc.name: SystemBarAvoidArea01 + * @tc.desc: Get avoid areas with listener, TYPE_SYSTEM. + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, SystemBarAvoidArea01, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr windowListener = new WindowListener(); + sptr appWindow = new WindowNode(property, windowListener, nullptr); + uint32_t focusedWindow = appWindow->GetWindowId(); + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->UpdateAvoidAreaListener(appWindow, true); + + // update status bar window Rect + Rect statusbarWindowNodeRect = statusbarWindowNode->GetWindowRect(); + statusbarWindowNode->SetWindowRect(EMPTY_RECT); + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_UPDATE, + [](sptr windowNode) { return true; }); + auto avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, + navigationBarWindowNode->GetWindowRect())); + + // update navigation bar window Rect + Rect navigationBarWindowNodeRect = navigationBarWindowNode->GetWindowRect(); + navigationBarWindowNode->SetWindowRect(EMPTY_RECT); + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_UPDATE, + [](sptr windowNode) { return true; }); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + + // restore status bar window Rect + statusbarWindowNode->SetWindowRect(statusbarWindowNodeRect); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_UPDATE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), EMPTY_RECT, + EMPTY_RECT, EMPTY_RECT)); + + // restore navigation bar window Rect + navigationBarWindowNode->SetWindowRect(navigationBarWindowNodeRect); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_UPDATE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, statusbarWindowNode->GetWindowRect(), EMPTY_RECT, + EMPTY_RECT, navigationBarWindowNode->GetWindowRect())); + + // remove status bar + avoidAreaController->ProcessWindowChange(statusbarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, + navigationBarWindowNode->GetWindowRect())); + + // remove navigation bar + avoidAreaController->ProcessWindowChange(navigationBarWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = windowListener->statusBarAvoidAreaFuture_.GetResult(TIME_OUT); + windowListener->statusBarAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); +} + +/** + * @tc.name: KeyboardAvoidArea01 + * @tc.desc: Get avoid areas with TYPE_KEYBOARD. + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, KeyboardAvoidArea01, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr listener = new WindowListener(); + sptr appWindow = new WindowNode(property, listener, nullptr); + uint32_t focusedWindow = 0u; + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_ADD, nullptr); + + uint32_t start = static_cast(WindowMode::WINDOW_MODE_FULLSCREEN); + uint32_t end = static_cast(WindowMode::WINDOW_MODE_FLOATING); + for (uint32_t i = start; i <= end; i++) { + focusedWindow = 0u; + appWindow->SetWindowMode(static_cast(i)); + avoidAreaController->ProcessWindowChange(keyboardWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + auto avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_KEYBOARD); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + + keyboardWindowNode->SetCallingWindow(appWindow->GetWindowId()); + avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_KEYBOARD); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, + keyboardWindowNode->GetWindowRect())); + + keyboardWindowNode->SetCallingWindow(0); + focusedWindow = appWindow->GetWindowId(); + avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_KEYBOARD); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, + keyboardWindowNode->GetWindowRect())); + + avoidAreaController->ProcessWindowChange(keyboardWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_KEYBOARD); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + } +} + +/** + * @tc.name: KeyboardAvoidArea02 + * @tc.desc: Get avoid areas with listener, TYPE_KEYBOARD. + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, KeyboardAvoidArea02, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr listener = new WindowListener(); + sptr appWindow = new WindowNode(property, listener, nullptr); + uint32_t focusedWindow = appWindow->GetWindowId(); + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_ADD, nullptr); + avoidAreaController->UpdateAvoidAreaListener(appWindow, true); + uint32_t start = static_cast(WindowMode::WINDOW_MODE_FULLSCREEN); + uint32_t end = static_cast(WindowMode::WINDOW_MODE_FLOATING); + for (uint32_t i = start; i <= end; i++) { + avoidAreaController->ProcessWindowChange(keyboardWindowNode, AvoidControlType::AVOID_NODE_ADD, nullptr); + auto avoidArea = listener->keyboardAvoidAreaFuture_.GetResult(TIME_OUT); + listener->keyboardAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, + keyboardWindowNode->GetWindowRect())); + avoidAreaController->ProcessWindowChange(keyboardWindowNode, AvoidControlType::AVOID_NODE_REMOVE, nullptr); + avoidArea = listener->keyboardAvoidAreaFuture_.GetResult(TIME_OUT); + listener->keyboardAvoidAreaFuture_.Reset(EMPTY_AVOID_AREA); + ASSERT_EQ(true, CheckSameArea(avoidArea, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT, EMPTY_RECT)); + } + avoidAreaController->ProcessWindowChange(appWindow, AvoidControlType::AVOID_NODE_REMOVE, nullptr); +} +/** + * @tc.name: KeyboardAvoidArea02 + * @tc.desc: Get avoid areas with listener, TYPE_KEYBOARD. + * @tc.type: FUNC + */ +HWTEST_F(AvoidAreaControllerTest, UpdateAvoidAreaListener01, Function | SmallTest | Level2) +{ + sptr property = createWindowProperty(110u, "test", + WindowType::APP_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, screenRect); + sptr listener = new WindowListener(); + sptr appWindow = new WindowNode(property, listener, nullptr); + uint32_t focusedWindow = appWindow->GetWindowId(); + sptr avoidAreaController = new AvoidAreaController(focusedWindow); + + avoidAreaController->avoidAreaListenerNodes_.clear(); + avoidAreaController->lastUpdatedAvoidArea_.clear(); + avoidAreaController->avoidAreaListenerNodes_.insert(appWindow); + auto avoidArea = avoidAreaController->GetAvoidAreaByType(appWindow, AvoidAreaType::TYPE_KEYBOARD); + std::map type_area_map; + auto pair = std::make_pair(AvoidAreaType::TYPE_KEYBOARD, avoidArea); + type_area_map.insert(pair); + avoidAreaController->lastUpdatedAvoidArea_.insert(std::make_pair(focusedWindow, type_area_map)); + avoidAreaController->UpdateAvoidAreaListener(appWindow, false); + ASSERT_EQ(0, avoidAreaController->avoidAreaListenerNodes_.size()); + ASSERT_EQ(0, avoidAreaController->lastUpdatedAvoidArea_.size()); + + sptr node = nullptr; + avoidAreaController->UpdateAvoidAreaListener(node, true); + ASSERT_EQ(0, avoidAreaController->avoidAreaListenerNodes_.size()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/test/unittest/display_group_controller_test.cpp b/window_manager/wmserver/test/unittest/display_group_controller_test.cpp new file mode 100644 index 0000000..dd50e09 --- /dev/null +++ b/window_manager/wmserver/test/unittest/display_group_controller_test.cpp @@ -0,0 +1,858 @@ +/* + * 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 "iremote_object_mocker.h" +#include "display_group_controller.h" +#include "display_manager.h" +#include "window_helper.h" +#include "window_node_container.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + const Rect DEFAULT_RECT = {0, 0, 200, 200}; +} +class DisplayGroupControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr CreateWindowProperty(uint32_t windowId, + WindowType type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + static void SetDisplayGroupInfo(DisplayId displayId, Rect displayRect); +private: + static sptr container_; + static sptr displayGroupInfo_; + static sptr displayGroupController_; +}; + +sptr DisplayGroupControllerTest::container_ = nullptr; +sptr DisplayGroupControllerTest::displayGroupInfo_ = nullptr; +sptr DisplayGroupControllerTest::displayGroupController_ = nullptr; + +void DisplayGroupControllerTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_TRUE((display != nullptr)); + container_ = new WindowNodeContainer(display->GetDisplayInfo(), display->GetScreenId()); + displayGroupController_ = container_->displayGroupController_; + displayGroupInfo_ = displayGroupController_->displayGroupInfo_; +} + +void DisplayGroupControllerTest::TearDownTestCase() +{ + container_ = nullptr; + displayGroupInfo_ = nullptr; + displayGroupController_ = nullptr; +} + +void DisplayGroupControllerTest::SetUp() +{ + DisplayId defaultId = 0; + displayGroupController_->displayGroupWindowTree_.clear(); + displayGroupController_->InitNewDisplay(defaultId); + SetDisplayGroupInfo(0, DEFAULT_RECT); +} + +void DisplayGroupControllerTest::TearDown() +{ + displayGroupController_->defaultDisplayId_ = 0; + container_->GetLayoutPolicy()->isMultiDisplay_ = false; + displayGroupController_->ClearMapOfDestroyedDisplay(0); + displayGroupController_->ClearMapOfDestroyedDisplay(1); +} + +sptr DisplayGroupControllerTest::CreateWindowProperty(uint32_t windowId, WindowType type) +{ + sptr property = new WindowProperty(); + property->SetWindowId(windowId); + property->SetWindowType(type); + return property; +} + +void DisplayGroupControllerTest::SetDisplayGroupInfo(DisplayId displayId, Rect displayRect) +{ + sptr displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(displayId); + displayInfo->SetOffsetX(displayRect.posX_); + displayInfo->SetOffsetY(displayRect.posY_); + displayInfo->SetWidth(displayRect.width_); + displayInfo->SetHeight(displayRect.height_); + displayGroupInfo_->displayInfosMap_[displayId] = displayInfo; + displayGroupInfo_->leftDisplayId_ = 0; + displayGroupInfo_->rightDisplayId_ = 1; +} + +namespace { +/** + * @tc.name: GetWindowNodesByDisplayIdAndRootType01 + * @tc.desc: Use displayId which not exists + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, GetWindowNodesByDisplayIdAndRootType01, Function | SmallTest | Level2) +{ + DisplayId testId = 100; // 100 test display id + std::vector>* rootNodeVectorPtr = + displayGroupController_->GetWindowNodesByDisplayIdAndRootType(testId, WindowRootNodeType::APP_WINDOW_NODE); + ASSERT_EQ(nullptr, rootNodeVectorPtr); +} + +/** + * @tc.name: GetWindowNodesByDisplayIdAndRootType02 + * @tc.desc: Use WindowRootNodeType which not exists + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, GetWindowNodesByDisplayIdAndRootType02, Function | SmallTest | Level2) +{ + WindowRootNodeType rootType = static_cast(100); + std::vector>* rootNodeVectorPtr = + displayGroupController_->GetWindowNodesByDisplayIdAndRootType(0, rootType); + ASSERT_EQ(nullptr, rootNodeVectorPtr); +} + +/** + * @tc.name: AddWindowNodeOnWindowTree01 + * @tc.desc: Use WindowRootNodeType which not exists + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, AddWindowNodeOnWindowTree01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + WindowRootNodeType rootType = static_cast(100); + displayGroupController_->AddWindowNodeOnWindowTree(node1, rootType); +} + +/** + * @tc.name: UpdateDisplayGroupWindowTree01 + * @tc.desc: Use appWindowNode with nullptr + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateDisplayGroupWindowTree01, Function | SmallTest | Level2) +{ + auto originRootNode = container_->GetRootNode(WindowRootNodeType::APP_WINDOW_NODE); + ASSERT_NE(nullptr, originRootNode); + container_->appWindowNode_ = nullptr; + ASSERT_EQ(nullptr, container_->GetRootNode(WindowRootNodeType::APP_WINDOW_NODE)); + displayGroupController_->UpdateDisplayGroupWindowTree(); + container_->appWindowNode_ = originRootNode; + displayGroupController_->UpdateDisplayGroupWindowTree(); +} + +/** + * @tc.name: ProcessCrossNodes01 + * @tc.desc: IsShowingOnMultiDisplays_ is true + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessCrossNodes01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->isShowingOnMultiDisplays_ = true; + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + displayGroupController_->ProcessCrossNodes(1, DisplayStateChangeType::CREATE); +} + +/** + * @tc.name: ProcessCrossNodes02 + * @tc.desc: IsShowingOnMultiDisplays_ is true with different DisplayStateChangeType + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessCrossNodes02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->isShowingOnMultiDisplays_ = true; + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + displayGroupController_->ProcessCrossNodes(1, DisplayStateChangeType::SIZE_CHANGE); +} + +/** + * @tc.name: ProcessCrossNodes03 + * @tc.desc: IsShowingOnMultiDisplays_ is true with different DisplayStateChangeType + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessCrossNodes03, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->isShowingOnMultiDisplays_ = true; + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + displayGroupController_->ProcessCrossNodes(1, DisplayStateChangeType::UPDATE_ROTATION); +} + +/** + * @tc.name: ProcessCrossNodes04 + * @tc.desc: IsShowingOnMultiDisplays_ is true with multi showing display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessCrossNodes04, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->isShowingOnMultiDisplays_ = true; + node1->SetShowingDisplays({0, 1}); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + displayGroupController_->ProcessCrossNodes(1, DisplayStateChangeType::DISPLAY_COMPRESS); +} + +/** + * @tc.name: UpdateWindowShowingDisplays01 + * @tc.desc: Show only on left display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowShowingDisplays01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->SetWindowRect({0, 0, 50, 50}); + displayGroupController_->UpdateWindowShowingDisplays(node1); + ASSERT_EQ(1, node1->GetShowingDisplays().size()); +} + +/** + * @tc.name: UpdateWindowShowingDisplays02 + * @tc.desc: Not show on any display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowShowingDisplays02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->SetWindowRect({0, 0, 0, 0}); + SetDisplayGroupInfo(0, {0, 0, 0, 0}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {0, 0, 0, 0}); + displayGroupController_->UpdateWindowShowingDisplays(node1); +} + +/** + * @tc.name: UpdateWindowShowingDisplays03 + * @tc.desc: Show only on right display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowShowingDisplays03, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->SetWindowRect({100, 100, 50, 50}); + SetDisplayGroupInfo(0, {0, 0, 50, 50}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {50, 50, 100, 100}); + displayGroupController_->UpdateWindowShowingDisplays(node1); + ASSERT_EQ(1, node1->GetShowingDisplays().size()); +} + +/** + * @tc.name: UpdateWindowShowingDisplays04 + * @tc.desc: Show on multi display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowShowingDisplays04, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->SetWindowRect({50, 50, 60, 60}); // 110 > 0 && 50 < 100 + displayGroupController_->InitNewDisplay(0); + SetDisplayGroupInfo(0, {0, 0, 100, 100}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {100, 100, 200, 200}); + displayGroupController_->UpdateWindowShowingDisplays(node1); + ASSERT_EQ(2, node1->GetShowingDisplays().size()); +} + +/** + * @tc.name: UpdateWindowDisplayIdIfNeeded01 + * @tc.desc: Not show on any display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayIdIfNeeded01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetWindowRect({50, 50, 60, 60}); + displayGroupController_->InitNewDisplay(0); + SetDisplayGroupInfo(0, {0, 0, 100, 100}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {100, 100, 200, 200}); + displayGroupController_->UpdateWindowDisplayIdIfNeeded(node1); + ASSERT_EQ(0, node1->GetShowingDisplays().size()); +} + +/** + * @tc.name: UpdateWindowDisplayIdIfNeeded02 + * @tc.desc: Show on left display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayIdIfNeeded02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetShowingDisplays({0}); + node1->SetWindowRect({50, 50, 60, 60}); + displayGroupController_->InitNewDisplay(0); + SetDisplayGroupInfo(0, {0, 0, 100, 100}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {100, 100, 200, 200}); + displayGroupController_->UpdateWindowDisplayIdIfNeeded(node1); + ASSERT_EQ(0, node1->GetDisplayId()); +} + +/** + * @tc.name: UpdateWindowDisplayIdIfNeeded03 + * @tc.desc: Window covers whole display region + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayIdIfNeeded03, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetShowingDisplays({0, 1}); + node1->SetWindowRect({-50, -50, 200, 200}); + displayGroupController_->InitNewDisplay(0); + SetDisplayGroupInfo(0, {0, 0, 100, 100}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + displayGroupController_->UpdateWindowDisplayIdIfNeeded(node1); + ASSERT_EQ(0, node1->GetDisplayId()); +} + +/** + * @tc.name: UpdateWindowDisplayIdIfNeeded04 + * @tc.desc: Current display is default display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayIdIfNeeded04, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetShowingDisplays({0, 1}); + node1->SetWindowRect({50, 50, 100, 100}); + displayGroupController_->InitNewDisplay(0); + SetDisplayGroupInfo(0, {0, 0, 100, 100}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + displayGroupController_->UpdateWindowDisplayIdIfNeeded(node1); + ASSERT_EQ(0, node1->GetDisplayId()); +} + +/** + * @tc.name: UpdateWindowDisplayIdIfNeeded05 + * @tc.desc: Current display is expand display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayIdIfNeeded05, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetShowingDisplays({0, 1}); + node1->SetWindowRect({60, 60, 100, 100}); + SetDisplayGroupInfo(0, {0, 0, 100, 100}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + displayGroupController_->UpdateWindowDisplayIdIfNeeded(node1); + ASSERT_EQ(0, node1->GetDisplayId()); +} + +/** + * @tc.name: UpdateWindowDisplayIdIfNeeded06 + * @tc.desc: Current display is expand display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayIdIfNeeded06, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetShowingDisplays({0, 1}); + node1->SetWindowRect({60, 60, 120, 120}); + SetDisplayGroupInfo(0, {0, 0, 70, 70}); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {70, 70, 200, 200}); + displayGroupController_->UpdateWindowDisplayIdIfNeeded(node1); + ASSERT_EQ(1, node1->GetDisplayId()); +} + +/** + * @tc.name: ChangeToRectInDisplayGroup01 + * @tc.desc: Change to rect in Display Group + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ChangeToRectInDisplayGroup01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + displayGroupController_->ChangeToRectInDisplayGroup(node1, 0); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {DEFAULT_RECT.posX_, DEFAULT_RECT.posY_, 0, 0}; + ASSERT_EQ(expectRect, actualRect); +} + +/** + * @tc.name: PreProcessWindowNode01 + * @tc.desc: PreProcessWindowNode with child + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, PreProcessWindowNode01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + displayGroupController_->PreProcessWindowNode(node1, WindowUpdateType::WINDOW_UPDATE_ADDED); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {DEFAULT_RECT.posX_, DEFAULT_RECT.posY_, 0, 0}; + ASSERT_EQ(expectRect, actualRect); +} + +/** + * @tc.name: PreProcessWindowNode02 + * @tc.desc: PreProcessWindowNode with WINDOW_UPDATE_ACTIVE, and size change reason undefined + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, PreProcessWindowNode02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + container_->GetLayoutPolicy()->isMultiDisplay_ = true; + displayGroupController_->PreProcessWindowNode(node1, WindowUpdateType::WINDOW_UPDATE_ACTIVE); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {0, 0, 0, 0}; + ASSERT_EQ(expectRect, actualRect); +} + +/** + * @tc.name: PreProcessWindowNode03 + * @tc.desc: PreProcessWindowNode with WINDOW_UPDATE_ADDED, and isShowingOnMultiDisplays_ is true + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, PreProcessWindowNode03, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->isShowingOnMultiDisplays_ = true; + displayGroupController_->PreProcessWindowNode(node1, WindowUpdateType::WINDOW_UPDATE_ADDED); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {0, 0, 0, 0}; + ASSERT_EQ(expectRect, actualRect); +} + +/** + * @tc.name: PreProcessWindowNode04 + * @tc.desc: PreProcessWindowNode with WINDOW_UPDATE_ACTIVE, and size change reason MOVE + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, PreProcessWindowNode04, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + node1->SetWindowSizeChangeReason(WindowSizeChangeReason::MOVE); + displayGroupController_->PreProcessWindowNode(node1, WindowUpdateType::WINDOW_UPDATE_ACTIVE); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {DEFAULT_RECT.posX_, DEFAULT_RECT.posY_, 0, 0}; + ASSERT_EQ(expectRect, actualRect); +} + +/** + * @tc.name: PostProcessWindowNode01 + * @tc.desc: PostProcessWindowNode with multi display is true + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, PostProcessWindowNode01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + container_->GetLayoutPolicy()->isMultiDisplay_ = true; + ASSERT_EQ(true, container_->GetLayoutPolicy()->IsMultiDisplay()); +} + +/** + * @tc.name: UpdateWindowDisplayId01 + * @tc.desc: UpdateWindowDisplayId with windowToken + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateWindowDisplayId01, Function | SmallTest | Level2) +{ + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + sptr iWindow = iface_cast(iRemoteObjectMocker); + ASSERT_NE(nullptr, iWindow); + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + node1->SetWindowToken(iWindow); + ASSERT_NE(nullptr, node1->GetWindowToken()); + displayGroupController_->UpdateWindowDisplayId(node1, 1); + ASSERT_EQ(1, node1->GetDisplayId()); +} + +/** + * @tc.name: MoveCrossNodeToTargetDisplay01 + * @tc.desc: TargetDisplayId equals to default displayId + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, MoveCrossNodeToTargetDisplay01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + displayGroupController_->MoveCrossNodeToTargetDisplay(node1, 0); + auto showingDisplays = child->GetShowingDisplays(); + ASSERT_NE(0, showingDisplays.size()); + ASSERT_EQ(0, showingDisplays[0]); +} + +/** + * @tc.name: MoveCrossNodeToTargetDisplay02 + * @tc.desc: No child and targetDisplayId not equals to default displayId + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, MoveCrossNodeToTargetDisplay02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + displayGroupController_->MoveCrossNodeToTargetDisplay(node1, 1); + ASSERT_EQ(1, node1->GetDisplayId()); +} + +/** + * @tc.name: MoveCrossNodeToTargetDisplay03 + * @tc.desc: TargetDisplayId not equals to default displayId + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, MoveCrossNodeToTargetDisplay03, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + displayGroupController_->MoveCrossNodeToTargetDisplay(node1, 1); + ASSERT_EQ(1, node1->GetDisplayId()); + ASSERT_EQ(1, child->GetDisplayId()); +} + +/** + * @tc.name: MoveNotCrossNodeToDefaultDisplay01 + * @tc.desc: MoveNotCrossNodeToDefaultDisplay with window type pointer without child + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, MoveNotCrossNodeToDefaultDisplay01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100, WindowType::WINDOW_TYPE_POINTER)); + ASSERT_NE(nullptr, node1); + displayGroupController_->MoveNotCrossNodeToDefaultDisplay(node1, 1); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {100, 100, 0, 0}; + ASSERT_EQ(expectRect, actualRect); +} + +/** + * @tc.name: MoveNotCrossNodeToDefaultDisplay02 + * @tc.desc: MoveNotCrossNodeToDefaultDisplay with window type app with child + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, MoveNotCrossNodeToDefaultDisplay02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + sptr child = new WindowNode(CreateWindowProperty(101)); + ASSERT_NE(nullptr, child); + node1->children_.push_back(child); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + displayGroupController_->MoveNotCrossNodeToDefaultDisplay(node1, 1); + Rect actualRect = node1->GetRequestRect(); + Rect expectRect = {-200, -200, 0, 0}; + ASSERT_EQ(expectRect, actualRect); + ASSERT_EQ(expectRect, child->GetRequestRect()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay01 + * @tc.desc: DisplayId equals to defaultDisplayId + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay01, Function | SmallTest | Level2) +{ + std::vector windowIds; + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(0, windowIds); + ASSERT_EQ(0, windowIds.size()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay02 + * @tc.desc: DisplayId not equals to defaultDisplayId or node displayId + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay02, Function | SmallTest | Level2) +{ + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 1, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + std::vector windowIds; + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(1, windowIds); + ASSERT_EQ(0, node1->GetDisplayId()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay03 + * @tc.desc: DisplayId not equals to defaultDisplayId but equals to node displayId, isShowingOnMultiDisplays_ is true + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay03, Function | SmallTest | Level2) +{ + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 1, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + node1->SetDisplayId(1); + node1->isShowingOnMultiDisplays_ = true; + std::vector windowIds; + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(1, windowIds); + ASSERT_EQ(1, node1->GetDisplayId()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay04 + * @tc.desc: Node with WINDOW_TYPE_STATUS_BAR + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay04, Function | SmallTest | Level2) +{ + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + sptr node1 = new WindowNode(CreateWindowProperty(100, WindowType::WINDOW_TYPE_STATUS_BAR)); + ASSERT_NE(nullptr, node1); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 1, WindowRootNodeType::ABOVE_WINDOW_NODE); + rootApp->push_back(node1); + node1->SetDisplayId(1); + std::vector windowIds; + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(1, windowIds); + ASSERT_EQ(1, windowIds.size()); + ASSERT_EQ(1, node1->GetDisplayId()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay05 + * @tc.desc: Node with WINDOW_TYPE_NAVIGATION_BAR + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay05, Function | SmallTest | Level2) +{ + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + sptr node1 = new WindowNode(CreateWindowProperty(100, WindowType::WINDOW_TYPE_NAVIGATION_BAR)); + ASSERT_NE(nullptr, node1); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 1, WindowRootNodeType::ABOVE_WINDOW_NODE); + rootApp->push_back(node1); + node1->SetDisplayId(1); + std::vector windowIds; + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(1, windowIds); + ASSERT_EQ(1, windowIds.size()); + ASSERT_EQ(1, node1->GetDisplayId()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay06 + * @tc.desc: Execute to move to default display + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay06, Function | SmallTest | Level2) +{ + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 1, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + node1->SetDisplayId(1); + std::vector windowIds; + windowIds.push_back(node1->GetWindowId()); + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(1, windowIds); + ASSERT_EQ(0, node1->GetDisplayId()); +} + +/** + * @tc.name: ProcessNotCrossNodesOnDestroyedDisplay07 + * @tc.desc: DisplayId not equals to defaultDisplayId, and no node on groupWindowTree + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessNotCrossNodesOnDestroyedDisplay07, Function | SmallTest | Level2) +{ + displayGroupController_->InitNewDisplay(1); + SetDisplayGroupInfo(1, {200, 200, 200, 200}); + std::vector windowIds; + displayGroupController_->ProcessNotCrossNodesOnDestroyedDisplay(1, windowIds); + ASSERT_EQ(0, windowIds.size()); +} + +/** + * @tc.name: UpdateNodeSizeChangeReasonWithRotation01 + * @tc.desc: UpdateNodeSizeChangeReasonWithRotation Success + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateNodeSizeChangeReasonWithRotation01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100)); + ASSERT_NE(nullptr, node1); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::APP_WINDOW_NODE); + rootApp->push_back(node1); + displayGroupController_->UpdateNodeSizeChangeReasonWithRotation(0); + ASSERT_EQ(WindowSizeChangeReason::ROTATION, node1->GetWindowSizeChangeReason()); +} + +/** + * @tc.name: UpdateNodeSizeChangeReasonWithRotation02 + * @tc.desc: UpdateNodeSizeChangeReasonWithRotation failed + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateNodeSizeChangeReasonWithRotation02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(100, WindowType::WINDOW_TYPE_DOCK_SLICE)); + ASSERT_NE(nullptr, node1); + std::vector>* rootApp = displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::ABOVE_WINDOW_NODE); + rootApp->push_back(node1); + displayGroupController_->UpdateNodeSizeChangeReasonWithRotation(0); + ASSERT_NE(WindowSizeChangeReason::ROTATION, node1->GetWindowSizeChangeReason()); +} + +/** + * @tc.name: UpdateNodeSizeChangeReasonWithRotation03 + * @tc.desc: UpdateNodeSizeChangeReasonWithRotation with rootNodeVectorPtr null + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, UpdateNodeSizeChangeReasonWithRotation03, Function | SmallTest | Level2) +{ + displayGroupController_->displayGroupWindowTree_[0].erase(WindowRootNodeType::ABOVE_WINDOW_NODE); + ASSERT_EQ(nullptr, displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::ABOVE_WINDOW_NODE)); + displayGroupController_->UpdateNodeSizeChangeReasonWithRotation(0); + ASSERT_EQ(nullptr, displayGroupController_->GetWindowNodesByDisplayIdAndRootType( + 0, WindowRootNodeType::ABOVE_WINDOW_NODE)); +} + +/** + * @tc.name: ProcessDisplayChange01 + * @tc.desc: ProcessDisplayChange with different DisplayStateChangeType + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessDisplayChange01, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + ASSERT_NE(nullptr, displayInfo); + displayInfo->SetDisplayId(0); + displayGroupController_->ProcessDisplayChange(0, displayInfo, displayGroupInfo_->GetAllDisplayRects(), + DisplayStateChangeType::UPDATE_ROTATION); + displayGroupController_->ProcessDisplayChange(0, displayInfo, displayGroupInfo_->GetAllDisplayRects(), + DisplayStateChangeType::DISPLAY_COMPRESS); + displayGroupController_->ProcessDisplayChange(0, displayInfo, displayGroupInfo_->GetAllDisplayRects(), + DisplayStateChangeType::SIZE_CHANGE); + displayGroupController_->ProcessDisplayChange(0, displayInfo, displayGroupInfo_->GetAllDisplayRects(), + DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE); + displayGroupController_->ProcessDisplayChange(0, displayInfo, displayGroupInfo_->GetAllDisplayRects(), + DisplayStateChangeType::DESTROY); +} + +/** + * @tc.name: ProcessDisplaySizeChangeOrRotation01 + * @tc.desc: ProcessDisplaySizeChangeOrRotation with layout policy null + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, ProcessDisplaySizeChangeOrRotation01, Function | SmallTest | Level2) +{ + auto oriLayoutPolicy = container_->GetLayoutPolicy(); + container_->layoutPolicy_ = nullptr; + displayGroupController_->ProcessDisplaySizeChangeOrRotation(0, 0, displayGroupInfo_->GetAllDisplayRects(), + DisplayStateChangeType::UPDATE_ROTATION); + ASSERT_EQ(nullptr, container_->GetLayoutPolicy()); + container_->layoutPolicy_ = oriLayoutPolicy; +} + +/** + * @tc.name: GetWindowPairByDisplayId + * @tc.desc: GetWindowPairByDisplayId with displayId 1, which not exists + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupControllerTest, GetWindowPairByDisplayId01, Function | SmallTest | Level2) +{ + ASSERT_EQ(nullptr, displayGroupController_->GetWindowPairByDisplayId(1)); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/display_group_info_test.cpp b/window_manager/wmserver/test/unittest/display_group_info_test.cpp new file mode 100644 index 0000000..726e59e --- /dev/null +++ b/window_manager/wmserver/test/unittest/display_group_info_test.cpp @@ -0,0 +1,274 @@ +/* + * 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 "display_group_info.h" +#include "wm_common.h" +#include "dm_common.h" +#include "common_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { + +class DisplayGroupInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void AddTestDisplayInfo(std::map>& displayInfosMap_); + sptr displayGroupInfo_; +}; + +void DisplayGroupInfoTest::SetUpTestCase() +{ +} + +void DisplayGroupInfoTest::TearDownTestCase() +{ +} + +void DisplayGroupInfoTest::SetUp() +{ + ScreenId displayGroupId = 0; + sptr displayInfo = new DisplayInfo(); + DisplayId displayId = 0; + displayInfo->SetDisplayId(displayId); + displayInfo->SetOffsetX(1); + displayInfo->SetOffsetY(1); + displayInfo->SetWidth(1); + displayInfo->SetHeight(1); + displayGroupInfo_ = new DisplayGroupInfo(displayGroupId, displayInfo); + AddTestDisplayInfo(displayGroupInfo_->displayInfosMap_); +} + +void DisplayGroupInfoTest::TearDown() +{ +} + +void DisplayGroupInfoTest::AddTestDisplayInfo(std::map>& displayInfosMap_) +{ + sptr displayInfo1 = new DisplayInfo(); + DisplayId displayId1 = 1; + int32_t offsetX1 = 0; + int32_t offsetY1 = 0; + int32_t height1 = 0; + int32_t width1 = 0; + displayInfo1->SetDisplayId(displayId1); + displayInfo1->SetOffsetX(offsetX1); + displayInfo1->SetOffsetY(offsetY1); + displayInfo1->SetHeight(height1); + displayInfo1->SetWidth(width1); + displayInfosMap_.insert(std::make_pair(displayId1, displayInfo1)); + sptr displayInfo2 = new DisplayInfo(); + DisplayId displayId2 = 2; + int32_t offsetX2 = 2; + int32_t offsetY2 = 2; + int32_t height2 = 2; + int32_t width2 = 2; + displayInfo2->SetDisplayId(displayId2); + displayInfo2->SetOffsetX(offsetX2); + displayInfo2->SetOffsetY(offsetY2); + displayInfo2->SetHeight(height2); + displayInfo2->SetWidth(width2); + displayInfosMap_.insert(std::make_pair(displayId2, displayInfo2)); +} + +namespace { +/** + * @tc.name: AddDisplayInfo0 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, AddDisplayInfo01, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(0); + displayGroupInfo_->AddDisplayInfo(displayInfo); + ASSERT_EQ(3u, displayGroupInfo_->displayInfosMap_.size()); +} + +/** + * @tc.name: AddDisplayInfo1 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, AddDisplayInfo02, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(3); + displayGroupInfo_->AddDisplayInfo(displayInfo); + ASSERT_EQ(4u, displayGroupInfo_->displayInfosMap_.size()); +} + +/** + * @tc.name: RemoveDisplayInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, RemoveDisplayInfo01, Function | SmallTest | Level2) +{ + DisplayId displayId = 0; + displayGroupInfo_->RemoveDisplayInfo(displayId); + ASSERT_EQ(2u, displayGroupInfo_->displayInfosMap_.size()); +} + +/** + * @tc.name: RemoveDisplayInfo02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, RemoveDisplayInfo02, Function | SmallTest | Level2) +{ + DisplayId displayId = 3; + displayGroupInfo_->RemoveDisplayInfo(displayId); + ASSERT_EQ(3u, displayGroupInfo_->displayInfosMap_.size()); +} + +/** + * @tc.name: GetAllDisplayRects01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, GetAllDisplayRects01, Function | SmallTest | Level2) +{ + ASSERT_EQ(3u, displayGroupInfo_->GetAllDisplayRects().size()); +} + +/** + * @tc.name: UpdateLeftAndRightDisplayId01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, UpdateLeftAndRightDisplayId01, Function | SmallTest | Level2) +{ + displayGroupInfo_->UpdateLeftAndRightDisplayId(); + ASSERT_EQ(1u, displayGroupInfo_->GetLeftDisplayId()); + ASSERT_EQ(2u, displayGroupInfo_->GetRightDisplayId()); +} + +/** + * @tc.name: SetDisplayRotation01 and GetDisplayRotation01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, SetDisplayRotation01, Function | SmallTest | Level2) +{ + DisplayId displayId = 0; + displayGroupInfo_->SetDisplayRotation(displayId, Rotation::ROTATION_90); + ASSERT_EQ(Rotation::ROTATION_90, displayGroupInfo_->GetDisplayRotation(displayId)); +} + +/** + * @tc.name: SetDisplayRotation02 and GetDisplayRotation02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, SetDisplayRotation02, Function | SmallTest | Level2) +{ + DisplayId displayId = 3; + displayGroupInfo_->SetDisplayRotation(displayId, Rotation::ROTATION_90); + ASSERT_EQ(Rotation::ROTATION_0, displayGroupInfo_->GetDisplayRotation(displayId)); +} + +/** + * @tc.name: SetDisplayVirtualPixelRatio01 and GetDisplayVirtualPixelRatio01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, SetDisplayVirtualPixelRatio01, Function | SmallTest | Level2) +{ + DisplayId displayId = 0; + displayGroupInfo_->SetDisplayVirtualPixelRatio(displayId, 0.1f); + ASSERT_FLOAT_EQ(0.1f, displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId)); +} + +/** + * @tc.name: SetDisplayVirtualPixelRatio02 and GetDisplayVirtualPixelRatio02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, SetDisplayVirtualPixelRatio02, Function | SmallTest | Level2) +{ + DisplayId displayId = 3; + displayGroupInfo_->SetDisplayVirtualPixelRatio(displayId, 0.1f); + ASSERT_EQ(1.0f, displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId)); +} + +/** + * @tc.name: SetDisplayRect01 and GetDisplayRect01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, SetDisplayRect01, Function | SmallTest | Level2) +{ + DisplayId displayId = 0; + Rect rect = {3, 3, 3, 3}; + displayGroupInfo_->SetDisplayRect(displayId, rect); + ASSERT_EQ(rect, displayGroupInfo_->GetDisplayRect(displayId)); +} + +/** + * @tc.name: SetDisplayRect02 and GetDisplayRect02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, SetDisplayRect02, Function | SmallTest | Level2) +{ + DisplayId displayId = 3; + Rect rect1 = {3, 3, 3, 3}; + displayGroupInfo_->SetDisplayRect(displayId, rect1); + Rect rect2 = {0, 0, 0, 0}; + ASSERT_EQ(rect2, displayGroupInfo_->GetDisplayRect(displayId)); +} + +/** + * @tc.name: UpdateDisplayInfo01 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, UpdateDisplayInfo01, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + DisplayId displayId = 0; + displayInfo->SetDisplayId(displayId); + ScreenId screenId = 1; + displayInfo->SetScreenId(screenId); + displayGroupInfo_->UpdateDisplayInfo(displayInfo); + ASSERT_EQ(1u, displayGroupInfo_->GetDisplayInfo(displayId)->GetScreenId()); +} + +/** + * @tc.name: UpdateDisplayInfo02 + * @tc.desc: normal function + * @tc.type: FUNC + */ +HWTEST_F(DisplayGroupInfoTest, UpdateDisplayInfo02, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + DisplayId displayId = 3; + displayInfo->SetDisplayId(displayId); + ScreenId screenId = 1; + displayInfo->SetScreenId(screenId); + displayGroupInfo_->UpdateDisplayInfo(displayInfo); + ASSERT_EQ(nullptr, displayGroupInfo_->GetDisplayInfo(displayId)); +} +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/test/unittest/drag_controller_test.cpp b/window_manager/wmserver/test/unittest/drag_controller_test.cpp new file mode 100644 index 0000000..f01528a --- /dev/null +++ b/window_manager/wmserver/test/unittest/drag_controller_test.cpp @@ -0,0 +1,442 @@ +/* + * 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 "drag_controller.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_service.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class DragControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +private: + static sptr moveDragController_; + static std::shared_ptr inputListener_; +}; + +sptr DragControllerTest::moveDragController_ = nullptr; +std::shared_ptr DragControllerTest::inputListener_ = nullptr; + +void DragControllerTest::SetUpTestCase() +{ + WindowInnerManager::GetInstance().Init(); + moveDragController_ = WindowInnerManager::GetInstance().moveDragController_; + ASSERT_TRUE(moveDragController_); + inputListener_ = moveDragController_->inputListener_; + ASSERT_TRUE(inputListener_); +} + +void DragControllerTest::TearDownTestCase() +{ + moveDragController_ = nullptr; + inputListener_ = nullptr; + WindowInnerManager::GetInstance().Stop(); +} + +void DragControllerTest::SetUp() +{ +} + +void DragControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnInputEvent01 + * @tc.desc: OnInputEven01, keyEvent + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, OnInputEvent01, Function | SmallTest | Level2) +{ + ASSERT_TRUE(inputListener_); + std::shared_ptr keyEvent; + inputListener_->OnInputEvent(keyEvent); + keyEvent = MMI::KeyEvent::Create(); + inputListener_->OnInputEvent(keyEvent); +} + +/** + * @tc.name: OnInputEvent02 + * @tc.desc: OnInputEvent02, axisEvent + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, OnInputEvent02, Function | SmallTest | Level2) +{ + ASSERT_TRUE(inputListener_); + std::shared_ptr axisEvent; + inputListener_->OnInputEvent(axisEvent); + axisEvent = MMI::AxisEvent::Create(); + inputListener_->OnInputEvent(axisEvent); +} + +/** + * @tc.name: OnInputEvent03 + * @tc.desc: OnInputEvent03, pointerEvent + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, OnInputEvent03, Function | SmallTest | Level2) +{ + ASSERT_TRUE(inputListener_); + std::shared_ptr pointerEvent; + inputListener_->OnInputEvent(pointerEvent); + pointerEvent = MMI::PointerEvent::Create(); + ASSERT_TRUE(pointerEvent); + pointerEvent->SetAgentWindowId(INVALID_WINDOW_ID); + ASSERT_TRUE(moveDragController_); + moveDragController_->SetActiveWindowId(1); + inputListener_->OnInputEvent(pointerEvent); +} + +/** + * @tc.name: Stop01 + * @tc.desc: Stop01 + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, Stop01, Function | SmallTest | Level2) +{ + moveDragController_->Stop(); +} + +/** + * @tc.name: Stop02 + * @tc.desc: Stop02 + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, Stop02, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + moveDragController_->Init(); + moveDragController_->Stop(); + moveDragController_->Init(); +} + +/** + * @tc.name: HandleEndUpMovingOrDragging + * @tc.desc: HandleEndUpMovingOrDragging + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, HandleEndUpMovingOrDragging, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + uint32_t windowId = 1; // windowId: 1 + moveDragController_->HandleEndUpMovingOrDragging(windowId); + moveDragController_->activeWindowId_ = windowId; + moveDragController_->HandleEndUpMovingOrDragging(windowId); +} + +/** + * @tc.name: HandleWindowRemovedOrDestroyed + * @tc.desc: HandleWindowRemovedOrDestroyed + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, HandleWindowRemovedOrDestroyed, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + uint32_t windowId = 5; // windowId: 5 + moveDragController_->HandleWindowRemovedOrDestroyed(windowId); + moveDragController_->moveDragProperty_ = new MoveDragProperty(); + moveDragController_->HandleWindowRemovedOrDestroyed(windowId); + moveDragController_->moveDragProperty_->startMoveFlag_ = true; + moveDragController_->HandleWindowRemovedOrDestroyed(windowId); + moveDragController_->moveDragProperty_->startMoveFlag_ = false; + moveDragController_->moveDragProperty_->startDragFlag_ = true; + moveDragController_->HandleWindowRemovedOrDestroyed(windowId); + moveDragController_->moveDragProperty_->startMoveFlag_ = true; + moveDragController_->HandleWindowRemovedOrDestroyed(windowId); + moveDragController_->moveDragProperty_ = nullptr; +} + +/** + * @tc.name: ConvertPointerPosToDisplayGroupPos + * @tc.desc: ConvertPointerPosToDisplayGroupPos + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, ConvertPointerPosToDisplayGroupPos, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + int32_t posX = 0; + int32_t posY = 0; + moveDragController_->ConvertPointerPosToDisplayGroupPos(0, posX, posY); + Rect displayRect = { 0, 0, 720, 1280 }; // displayRect: 0, 0, 720, 1280 + + moveDragController_->displayRectMap_.insert(std::make_pair(0, displayRect)); + moveDragController_->ConvertPointerPosToDisplayGroupPos(1, posX, posY); + moveDragController_->ConvertPointerPosToDisplayGroupPos(0, posX, posY); + moveDragController_->displayRectMap_.clear(); +} + +/** + * @tc.name: ConsumePointerEvent + * @tc.desc: ConsumePointerEvent + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, ConsumePointerEvent, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + std::shared_ptr pointerEvent; + moveDragController_->ConsumePointerEvent(pointerEvent); + pointerEvent = MMI::PointerEvent::Create(); + ASSERT_TRUE(pointerEvent); + pointerEvent->SetAgentWindowId(1); + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_CANCEL); + moveDragController_->ConsumePointerEvent(pointerEvent); +} + +/** + * @tc.name: OnReceiveVsync + * @tc.desc: OnReceiveVsync + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, OnReceiveVsync, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + ASSERT_TRUE(pointerEvent); + moveDragController_->OnReceiveVsync(0); + moveDragController_->moveEvent_ = pointerEvent; + moveDragController_->OnReceiveVsync(0); +} + +/** + * @tc.name: GetHotZoneRect + * @tc.desc: GetHotZoneRect + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, GetHotZoneRect, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + Rect displayRect = { 0, 0, 720, 1280 }; // displayRect: 0, 0, 720, 1280 + moveDragController_->displayRectMap_.insert(std::make_pair(0, displayRect)); + moveDragController_->moveDragProperty_ = new MoveDragProperty(); + moveDragController_->moveDragProperty_->targetDisplayId_ = 0; + moveDragController_->moveDragProperty_->startRectExceptCorner_ = { 0, 0, 40, 40 }; + + moveDragController_->moveDragProperty_->startPointPosX_ = 20; // startPointPosX: 20 + moveDragController_->moveDragProperty_->startPointPosY_ = 20; // startPointPosY: 20 + moveDragController_->GetHotZoneRect(); + + moveDragController_->moveDragProperty_->startPointPosX_ = -1; // startPointPosX: -1 + moveDragController_->moveDragProperty_->startPointPosY_ = -1; // startPointPosY: -1 + moveDragController_->GetHotZoneRect(); + + moveDragController_->moveDragProperty_->startPointPosX_ = -1; // startPointPosX: -1 + moveDragController_->moveDragProperty_->startPointPosY_ = 20; // startPointPosY: 20 + moveDragController_->GetHotZoneRect(); + + moveDragController_->moveDragProperty_->startPointPosX_ = 41; // startPointPosX: 41 + moveDragController_->moveDragProperty_->startPointPosY_ = 20; // startPointPosY: 20 + moveDragController_->GetHotZoneRect(); + + moveDragController_->moveDragProperty_->startPointPosX_ = 20; // startPointPosX: 20 + moveDragController_->moveDragProperty_->startPointPosY_ = -1; // startPointPosY: -1 + moveDragController_->GetHotZoneRect(); + + moveDragController_->moveDragProperty_->startPointPosX_ = 20; // startPointPosX: 20 + moveDragController_->moveDragProperty_->startPointPosY_ = 41; // startPointPosY: 41 + moveDragController_->GetHotZoneRect(); + + moveDragController_->moveDragProperty_->startPointPosX_ = 41; // startPointPosX: 41 + moveDragController_->moveDragProperty_->startPointPosY_ = 41; // startPointPosY: 41 + moveDragController_->GetHotZoneRect(); + moveDragController_->moveDragProperty_ = nullptr; +} + +/** + * @tc.name: HandleDragEvent01 + * @tc.desc: HandleDragEvent01 + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, HandleDragEvent01, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + int32_t posX = 0; + int32_t posY = 0; + int32_t pointId = 0; + int32_t sourceType = 0; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_ = new MoveDragProperty(); + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_->startDragFlag_ = true; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + pointId = 1; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + pointId = 0; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + sourceType = 1; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + sourceType = 0; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_ = nullptr; +} + +/** + * @tc.name: HandleDragEvent02 + * @tc.desc: HandleDragEvent02 + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, HandleDragEvent02, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + int32_t posX = 0; + int32_t posY = 0; + int32_t pointId = 0; + int32_t sourceType = 0; + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_ = new MoveDragProperty(); + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_->startDragFlag_ = true; + moveDragController_->moveDragProperty_->targetDisplayId_ = 0; + moveDragController_->moveDragProperty_->startRectExceptCorner_ = { 0, 0, 40, 40 }; // hotZone: 0, 0, 40, 40 + + moveDragController_->moveDragProperty_->startPointPosX_ = -1; // startPointPosX: -1 + moveDragController_->moveDragProperty_->startPointPosY_ = -1; // startPointPosY: -1 + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_->startPointPosX_ = 45; // startPointPosX: 45 + moveDragController_->moveDragProperty_->startPointPosY_ = -1; // startPointPosY: -1 + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_->startPointPosX_ = -1; // startPointPosX: -1 + moveDragController_->moveDragProperty_->startPointPosY_ = 45; // startPointPosY: 45 + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_->startPointPosX_ = 45; // startPointPosX: 45 + moveDragController_->moveDragProperty_->startPointPosY_ = 45; // startPointPosY: 45 + moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_ = nullptr; +} + +/** + * @tc.name: HandleMoveEvent + * @tc.desc: HandleMoveEvent + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, HandleMoveEvent, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + int32_t posX = 0; + int32_t posY = 0; + int32_t pointId = 0; + int32_t sourceType = 0; + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_ = new MoveDragProperty(); + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_->startMoveFlag_ = true; + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + pointId = 1; + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + pointId = 0; + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + sourceType = 1; + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + sourceType = 0; + moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + + moveDragController_->moveDragProperty_ = nullptr; +} + +/** + * @tc.name: HandlePointerEvent + * @tc.desc: HandlePointerEvent + * @tc.type: FUNC + */ +HWTEST_F(DragControllerTest, HandlePointerEvent, Function | SmallTest | Level2) +{ + ASSERT_TRUE(moveDragController_); + std::shared_ptr pointerEvent = MMI::PointerEvent::Create(); + ASSERT_TRUE(pointerEvent); + pointerEvent->SetAgentWindowId(1); + MMI::PointerEvent::PointerItem pointerItem; + pointerItem.SetPointerId(0); + pointerItem.SetDisplayX(0); + pointerItem.SetDisplayY(0); + pointerEvent->AddPointerItem(pointerItem); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetPointerId(0); + pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_MOUSE); + pointerEvent->SetButtonId(MMI::PointerEvent::MOUSE_BUTTON_LEFT); + moveDragController_->HandlePointerEvent(pointerEvent); + + moveDragController_->windowProperty_ = new WindowProperty(); + moveDragController_->moveDragProperty_ = new MoveDragProperty(); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_MOUSE); + pointerEvent->SetButtonId(MMI::PointerEvent::MOUSE_BUTTON_RIGHT); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetButtonId(MMI::PointerEvent::MOUSE_BUTTON_LEFT); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_DOWN); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN); + moveDragController_->HandlePointerEvent(pointerEvent); + + moveDragController_->moveDragProperty_->startPointerId_ = 1; + moveDragController_->moveDragProperty_->sourceType_ = 2; // sourceType: 2 + moveDragController_->HandlePointerEvent(pointerEvent); + + moveDragController_->moveDragProperty_->startPointerId_ = 0; + moveDragController_->moveDragProperty_->sourceType_ = 2; // sourceType: 2 + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_MOVE); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_UP); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_UP); + moveDragController_->HandlePointerEvent(pointerEvent); + + pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_CANCEL); + moveDragController_->HandlePointerEvent(pointerEvent); + + moveDragController_->windowProperty_ = nullptr; + moveDragController_->moveDragProperty_ = nullptr; +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/test/unittest/input_window_monitor_test.cpp b/window_manager/wmserver/test/unittest/input_window_monitor_test.cpp new file mode 100644 index 0000000..86d7a3a --- /dev/null +++ b/window_manager/wmserver/test/unittest/input_window_monitor_test.cpp @@ -0,0 +1,100 @@ +/* + * 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 "input_window_monitor.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class InputWindowMonitorTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + sptr root_; + sptr input_monitor_; +}; + +void InputWindowMonitorTest::SetUpTestCase() +{ +} + +void InputWindowMonitorTest::TearDownTestCase() +{ +} + +void InputWindowMonitorTest::SetUp() +{ + root_ = new WindowRoot([](Event event, const sptr& remoteObject) {}); + input_monitor_ = new InputWindowMonitor(root_); +} + +void InputWindowMonitorTest::TearDown() +{ + root_ = nullptr; + input_monitor_->InputWindowMonitor::~InputWindowMonitor(); +} + +namespace { +/** + * @tc.name: UpdateInputWindow + * @tc.desc: Update Input Window + * @tc.type: FUNC + */ +HWTEST_F(InputWindowMonitorTest, UpdateInputWindow01, Function | SmallTest | Level2) +{ + input_monitor_->windowRoot_ = nullptr; + input_monitor_->UpdateInputWindow(0); + ASSERT_EQ(nullptr, input_monitor_->windowRoot_); + + input_monitor_->windowRoot_ = new WindowRoot([](Event event, const sptr& remoteObject) {}); + input_monitor_->windowRoot_->windowNodeMap_.insert(std::make_pair(0, nullptr)); + input_monitor_->UpdateInputWindow(0); + ASSERT_EQ(nullptr, input_monitor_->windowRoot_->windowNodeMap_[0]); +} +/** + * @tc.name: GetDisplayDirectionForMmi + * @tc.desc: get display direction + * @tc.type: FUNC + */ +HWTEST_F(InputWindowMonitorTest, GetDisplayDirectionForMmi01, Function | SmallTest | Level2) +{ + Rotation rotate = Rotation::ROTATION_0; + ASSERT_EQ(MMI::Direction0, input_monitor_->GetDisplayDirectionForMmi(rotate)); +} +/** + * @tc.name: UpdateDisplayInfo + * @tc.desc: update displayinfo + * @tc.type: FUNC + */ +HWTEST_F(InputWindowMonitorTest, UpdateDisplayInfo01, Function | SmallTest | Level2) +{ + std::vector> displayInfos; + std::vector displayInfoVector; + displayInfos.clear(); + displayInfoVector.clear(); + sptr displayinfo = nullptr; + displayInfos.emplace_back(displayinfo); + input_monitor_->UpdateDisplayInfo(displayInfos, displayInfoVector); + ASSERT_EQ(0, displayInfoVector.size()); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/minimize_app_test.cpp b/window_manager/wmserver/test/unittest/minimize_app_test.cpp new file mode 100644 index 0000000..3b2659b --- /dev/null +++ b/window_manager/wmserver/test/unittest/minimize_app_test.cpp @@ -0,0 +1,250 @@ +/* + * 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 "minimize_app.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class MinimizeAppTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + + sptr CreateWindowProperty(uint32_t windowId); +}; + +void MinimizeAppTest::SetUpTestCase() +{ +} + +void MinimizeAppTest::TearDownTestCase() +{ +} + +void MinimizeAppTest::SetUp() +{ +} + +void MinimizeAppTest::TearDown() +{ +} + +sptr MinimizeAppTest::CreateWindowProperty(uint32_t windowId) +{ + sptr property = new WindowProperty(); + property->SetWindowId(windowId); + return property; +} +namespace { +/** + * @tc.name: MinimizeAppTest01 + * @tc.desc: add and excute + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, MinimizeAppTest01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(CreateWindowProperty(1)); + sptr node2 = new WindowNode(CreateWindowProperty(2)); + sptr node3 = new WindowNode(CreateWindowProperty(3)); + sptr node4 = new WindowNode(CreateWindowProperty(4)); + sptr node5 = new WindowNode(CreateWindowProperty(5)); + sptr node6 = new WindowNode(CreateWindowProperty(6)); + sptr node7 = new WindowNode(CreateWindowProperty(7)); + sptr node8 = new WindowNode(CreateWindowProperty(8)); + sptr node9 = new WindowNode(CreateWindowProperty(9)); + + sptr node10 = new WindowNode(); + sptr node11 = nullptr; + sptr conflictNode = new WindowNode(CreateWindowProperty(2)); + + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_BUTTON); + MinimizeApp::AddNeedMinimizeApp(node2, MinimizeReason::MINIMIZE_ALL); + MinimizeApp::AddNeedMinimizeApp(node3, MinimizeReason::LAYOUT_TILE); + MinimizeApp::AddNeedMinimizeApp(node4, MinimizeReason::LAYOUT_CASCADE); + MinimizeApp::AddNeedMinimizeApp(node5, MinimizeReason::MAX_APP_COUNT); + MinimizeApp::AddNeedMinimizeApp(node6, MinimizeReason::SPLIT_REPLACE); + MinimizeApp::AddNeedMinimizeApp(node7, MinimizeReason::SPLIT_QUIT); + MinimizeApp::AddNeedMinimizeApp(node8, MinimizeReason::GESTURE_ANIMATION); + MinimizeApp::AddNeedMinimizeApp(node9, MinimizeReason::OTHER_WINDOW); + MinimizeApp::AddNeedMinimizeApp(conflictNode, MinimizeReason::MINIMIZE_ALL); + + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node1)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node2)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node3)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node4)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node5)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node6)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node7)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node8)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimize(node9)); + + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimize(node10)); + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimize(node11)); + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimize(conflictNode)); + + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_REPLACE); + MinimizeApp::ExecuteMinimizeAll(); +} +/** + * @tc.name: MinimizeAppTest02 + * @tc.desc: add, find and clear + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, MinimizeAppTest02, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(); + + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_ALL); + + auto getNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL); + ASSERT_EQ(node1, getNodes[0]); + + MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_ALL); +} +/** + * @tc.name: MinimizeAppTest03 + * @tc.desc: add and find + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, MinimizeAppTest03, Function | SmallTest | Level2) +{ + MinimizeApp::SetMinimizedByOtherConfig(false); + sptr node1 = new WindowNode(); + + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::OTHER_WINDOW); + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimize(node1)); + MinimizeApp::SetMinimizedByOtherConfig(true); + + MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); +} +/** + * @tc.name: MinimizeAppTest04 + * @tc.desc: add and recover + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, MinimizeAppTest04, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(); + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::LAYOUT_TILE); + + ASSERT_EQ(node1, MinimizeApp::GetRecoverdNodeFromMinimizeList()); + ASSERT_EQ(nullptr, MinimizeApp::GetRecoverdNodeFromMinimizeList()); + + MinimizeApp::ClearNodesWithReason(MinimizeReason::LAYOUT_TILE); +} +/** + * @tc.name: MinimizeAppTest05 + * @tc.desc: insert nullptr to needMinimizeAppNodes_ + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, MinimizeAppTest05, Function | SmallTest | Level2) +{ + MinimizeApp::needMinimizeAppNodes_[MinimizeReason::MINIMIZE_ALL].emplace_back(nullptr); + auto getNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL); + ASSERT_EQ(nullptr, getNodes[0].promote()); + + sptr node1 = new WindowNode(); + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_ALL); + auto getNodes2 = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL); + ASSERT_EQ(node1, getNodes2[1]); + + MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_ALL); +} +/** + * @tc.name: IsNodeNeedMinimizeWithReason + * @tc.desc: check node need minimize or not + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, IsNodeNeedMinimizeWithReason01, Function | SmallTest | Level2) +{ + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimizeWithReason(nullptr, MinimizeReason::MINIMIZE_ALL)); + + sptr node1 = new WindowNode(); + sptr node2 = new WindowNode(); + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_BUTTON); + MinimizeApp::AddNeedMinimizeApp(node2, MinimizeReason::MINIMIZE_ALL); + + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimizeWithReason(node1, MinimizeReason::GESTURE_ANIMATION)); + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimizeWithReason(node1, MinimizeReason::MINIMIZE_ALL)); + ASSERT_EQ(true, MinimizeApp::IsNodeNeedMinimizeWithReason(node1, MinimizeReason::MINIMIZE_BUTTON)); + + MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_ALL); + MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_BUTTON); +} +/** + * @tc.name: ClearNodesWithReason + * @tc.desc: clear node with reason + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, ClearNodesWithReason01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(); + sptr node2 = new WindowNode(); + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_BUTTON); + MinimizeApp::AddNeedMinimizeApp(node2, MinimizeReason::MINIMIZE_ALL); + + MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_ALL); + ASSERT_EQ(0, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL).size()); + MinimizeApp::ClearNodesWithReason(MinimizeReason::GESTURE_ANIMATION); + ASSERT_EQ(1, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_BUTTON).size()); +} +/** + * @tc.name: GetRecoverdNodeFromMinimizeList + * @tc.desc: Get recoverd node from list + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, GetRecoverdNodeFromMinimizeList01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(); + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_BUTTON); + + ASSERT_EQ(nullptr, MinimizeApp::GetRecoverdNodeFromMinimizeList()); + MinimizeApp::ClearNodesWithReason(MinimizeReason::MINIMIZE_BUTTON); +} +/** + * @tc.name: IsNodeNeedMinimize + * @tc.desc: check node need minize or not + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, IsNodeNeedMinimize01, Function | SmallTest | Level2) +{ + ASSERT_EQ(false, MinimizeApp::IsNodeNeedMinimize(nullptr)); +} +/** + * @tc.name: ExecuteMinimizeTargetReasons + * @tc.desc: Execute Minimize With TargetReason + * @tc.type: FUNC + */ +HWTEST_F(MinimizeAppTest, ExecuteMinimizeTargetReasons01, Function | SmallTest | Level2) +{ + sptr node1 = new WindowNode(); + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_BUTTON); + + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::MINIMIZE_BUTTON); + ASSERT_EQ(0, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_BUTTON).size()); + + MinimizeApp::AddNeedMinimizeApp(node1, MinimizeReason::MINIMIZE_BUTTON); + MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::GESTURE_ANIMATION); + ASSERT_EQ(1, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_BUTTON).size()); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/remote_animation_test.cpp b/window_manager/wmserver/test/unittest/remote_animation_test.cpp new file mode 100644 index 0000000..27af985 --- /dev/null +++ b/window_manager/wmserver/test/unittest/remote_animation_test.cpp @@ -0,0 +1,1039 @@ +/* + * 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 "display_manager.h" +#include "input_window_monitor.h" +#include "iremote_object_mocker.h" +#include "minimize_app.h" +#include "mock_RSIWindowAnimationController.h" +#include "remote_animation.h" +#include "starting_window.h" +#include "window_helper.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr uint32_t SLEEP_TIME_IN_US = 10000; +} + +class RemoteAnimationTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + void InitRemoteAnimation(); + void CreateWindowNodeContainer(); +private: + RSSurfaceNode::SharedPtr CreateRSSurfaceNode(uint32_t windowId); + sptr CreateWindowProperty(uint32_t windowId); + Rect GetSurfaceBoundsRect(sptr node); + sptr animationController_; + sptr windowRoot_; + sptr windowController_; + std::shared_ptr wmsTaskHandler_; + sptr transitionInfo_ = nullptr; + sptr node_ = nullptr; +}; + +void RemoteAnimationTest::SetUpTestCase() +{ +} + +void RemoteAnimationTest::TearDownTestCase() +{ +} + +void RemoteAnimationTest::SetUp() +{ + InitRemoteAnimation(); + CreateWindowNodeContainer(); + transitionInfo_ = new WindowTransitionInfo(); + sptr token = new IRemoteObjectMocker(); + transitionInfo_->SetAbilityToken(token); + transitionInfo_->supportWindowModes_ = { + AppExecFwk::SupportWindowMode::FULLSCREEN, + AppExecFwk::SupportWindowMode::SPLIT, + AppExecFwk::SupportWindowMode::FLOATING + }; + windowController_->StartingWindow(transitionInfo_, nullptr, 0xFFFFFFFF, true); + node_ = windowRoot_->FindWindowNodeWithToken(transitionInfo_->GetAbilityToken()); + EXPECT_NE(nullptr, node_); +} + +void RemoteAnimationTest::TearDown() +{ + windowController_->DestroyWindow(node_->GetWindowId(), false); + node_ = nullptr; + animationController_ = nullptr; + wmsTaskHandler_ = nullptr; + windowRoot_ = nullptr; + windowController_ = nullptr; + transitionInfo_ = nullptr; +} + +void RemoteAnimationTest::InitRemoteAnimation() +{ + animationController_ = new RSIWindowAnimationControllerMocker(); + EXPECT_EQ(WMError::WM_OK, RemoteAnimation::SetWindowAnimationController(animationController_)); + RemoteAnimation::isRemoteAnimationEnable_ = true; + RemoteAnimation::animationFirst_ = true; + windowRoot_ = new WindowRoot([](Event event, const sptr& remoteObject) {}); + sptr inputMonitor = new InputWindowMonitor(windowRoot_); + windowController_ = new WindowController(windowRoot_, inputMonitor); + RemoteAnimation::SetWindowControllerAndRoot(windowController_, windowRoot_); + auto runner = AppExecFwk::EventRunner::Create("RemoteAnimationTest"); + wmsTaskHandler_ = std::make_shared(runner); + RemoteAnimation::SetMainTaskHandler(wmsTaskHandler_); +} + +void RemoteAnimationTest::CreateWindowNodeContainer() +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_TRUE((display != nullptr)); + sptr displayInfo = display->GetDisplayInfo(); + ASSERT_TRUE((displayInfo != nullptr)); + windowRoot_->CreateWindowNodeContainer(displayInfo); +} + +sptr RemoteAnimationTest::CreateWindowProperty(uint32_t windowId) +{ + sptr property = new WindowProperty(); + property->SetWindowId(windowId); + return property; +} + +Rect RemoteAnimationTest::GetSurfaceBoundsRect(sptr node) +{ + if (!node->leashWinSurfaceNode_) { + return {0, 0, 0, 0}; + } + auto& stagingProperties = node->leashWinSurfaceNode_->GetStagingProperties(); + auto bounds = stagingProperties.GetBounds(); + Rect rect = {bounds[0], bounds[1], bounds[2], bounds[3]}; // 1, 2, 3 is index + return rect; +} + +RSSurfaceNode::SharedPtr RemoteAnimationTest::CreateRSSurfaceNode(uint32_t windowId) +{ + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = "AppSurfaceNode" + std::to_string(windowId); + auto surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig); + return surfaceNode; +} + +namespace { +/** + * @tc.name: IsRemoteAnimationEnabledAndFirst01 + * @tc.desc: IsRemoteAnimationEnabledAndFirst return false since animationFirst false + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, IsRemoteAnimationEnabledAndFirst01, Function | SmallTest | Level2) +{ + RemoteAnimation::SetAnimationFirst(false); + EXPECT_EQ(false, RemoteAnimation::animationFirst_); + EXPECT_EQ(false, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); +} + +/** + * @tc.name: IsRemoteAnimationEnabledAndFirst02 + * @tc.desc: IsRemoteAnimationEnabledAndFirst return true since animationFirst true + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, IsRemoteAnimationEnabledAndFirst02, Function | SmallTest | Level2) +{ + EXPECT_EQ(true, RemoteAnimation::animationFirst_); + EXPECT_EQ(true, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); +} + +/** + * @tc.name: IsRemoteAnimationEnabledAndFirst03 + * @tc.desc: IsRemoteAnimationEnabledAndFirst return false since CheckRemoteAnimationEnabled false + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, IsRemoteAnimationEnabledAndFirst03, Function | SmallTest | Level2) +{ + RemoteAnimation::windowRoot_ = nullptr; + EXPECT_EQ(false, RemoteAnimation::CheckRemoteAnimationEnabled(0)); + EXPECT_EQ(false, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); + RemoteAnimation::windowRoot_ = windowRoot_; + auto container = RemoteAnimation::windowRoot_->GetOrCreateWindowNodeContainer(0); + EXPECT_NE(nullptr, container); + container->isScreenLocked_ = true; + EXPECT_EQ(false, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); +} + +/** + * @tc.name: IsRemoteAnimationEnabledAndFirst04 + * @tc.desc: return false since CheckRemoteAnimationEnabled false, set animationController nullptr + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, IsRemoteAnimationEnabledAndFirst04, Function | SmallTest | Level2) +{ + sptr controller = nullptr; + EXPECT_EQ(WMError::WM_ERROR_NULLPTR, RemoteAnimation::SetWindowAnimationController(controller)); + RemoteAnimation::windowAnimationController_ = nullptr; + EXPECT_EQ(false, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); + controller = new RSIWindowAnimationControllerMocker(); + RemoteAnimation::isRemoteAnimationEnable_ = false; + EXPECT_EQ(WMError::WM_ERROR_NO_REMOTE_ANIMATION, RemoteAnimation::SetWindowAnimationController(controller)); + EXPECT_EQ(false, RemoteAnimation::CheckRemoteAnimationEnabled(0)); + EXPECT_EQ(false, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); + RemoteAnimation::isRemoteAnimationEnable_ = true; + EXPECT_EQ(WMError::WM_OK, RemoteAnimation::SetWindowAnimationController(controller)); + EXPECT_EQ(true, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); + RemoteAnimation::SetAnimationFirst(false); + EXPECT_EQ(false, RemoteAnimation::animationFirst_); + EXPECT_EQ(false, RemoteAnimation::IsRemoteAnimationEnabledAndFirst(0)); +} + +/** + * @tc.name: CheckTransition01 + * @tc.desc: CheckTransition return false + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CheckTransition01, Function | SmallTest | Level2) +{ + const sptr node = nullptr; + EXPECT_EQ(false, RemoteAnimation::CheckTransition(transitionInfo_, node, transitionInfo_, node)); + sptr srcNode = StartingWindow::CreateWindowNode(transitionInfo_, 0); + ASSERT_NE(nullptr, srcNode); + srcNode->leashWinSurfaceNode_ = nullptr; // leash and app surface node is nullptr + EXPECT_EQ(false, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, srcNode)); + srcNode->surfaceNode_ = CreateRSSurfaceNode(0); // leash is null, but surfaceNode is not + EXPECT_EQ(true, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, srcNode)); + srcNode = StartingWindow::CreateWindowNode(transitionInfo_, 0);// leash and app surfaceNode both not nullptr + ASSERT_NE(nullptr, srcNode); + sptr dstNode = StartingWindow::CreateWindowNode(transitionInfo_, 1); + ASSERT_NE(nullptr, dstNode); + EXPECT_EQ(true, RemoteAnimation::CheckTransition(transitionInfo_, node, transitionInfo_, dstNode)); + EXPECT_EQ(true, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, node)); + dstNode->leashWinSurfaceNode_ = nullptr; + EXPECT_EQ(false, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, dstNode)); + dstNode->surfaceNode_ = CreateRSSurfaceNode(1); // leash is null, but surfaceNode is not + EXPECT_EQ(true, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, dstNode)); +} + +/** + * @tc.name: CheckTransition02 + * @tc.desc: CheckTransition return false since windowMode not support + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CheckTransition02, Function | SmallTest | Level2) +{ + sptr srcNode = StartingWindow::CreateWindowNode(transitionInfo_, 0); + ASSERT_NE(nullptr, srcNode); + sptr dstNode = StartingWindow::CreateWindowNode(transitionInfo_, 1); + ASSERT_NE(nullptr, dstNode); + dstNode->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + dstNode->SetModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING); + ASSERT_EQ(false, WindowHelper::CheckSupportWindowMode(dstNode->GetWindowMode(), + dstNode->GetModeSupportInfo(), transitionInfo_)); + EXPECT_EQ(false, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, dstNode)); +} + +/** + * @tc.name: CheckTransition03 + * @tc.desc: CheckTransition return true + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CheckTransition03, Function | SmallTest | Level2) +{ + sptr srcNode = StartingWindow::CreateWindowNode(transitionInfo_, 0); + ASSERT_NE(nullptr, srcNode); + sptr dstNode = StartingWindow::CreateWindowNode(transitionInfo_, 1); + ASSERT_NE(nullptr, dstNode); + EXPECT_EQ(true, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, nullptr, dstNode)); + EXPECT_EQ(true, RemoteAnimation::CheckTransition(transitionInfo_, srcNode, transitionInfo_, dstNode)); +} + +/** + * @tc.name: OnRemoteDieAndCallbackTimeOutProcess01 + * @tc.desc: OnRemoteDie and setAnimationController nullptr + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, OnRemoteDieAndCallbackTimeOutProcess01, Function | SmallTest | Level2) +{ + auto testController = RemoteAnimation::windowAnimationController_; + ASSERT_EQ(true, RemoteAnimation::windowAnimationController_->AsObject() == animationController_->AsObject()); + RemoteAnimation::OnRemoteDie(animationController_->AsObject()); // controller is not nullptr + EXPECT_EQ(false, RemoteAnimation::CheckAnimationController()); + RemoteAnimation::OnRemoteDie(testController->AsObject()); // controller is nullptr + RemoteAnimation::SetAnimationFirst(false); + RemoteAnimation::OnRemoteDie(testController->AsObject()); // controller is nullptr +} + +/** + * @tc.name: OnRemoteDieAndCallbackTimeOutProcess02 + * @tc.desc: OnRemoteDie and not set animation controller + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, OnRemoteDieAndCallbackTimeOutProcess02, Function | SmallTest | Level2) +{ + sptr remoteObject = nullptr; + RemoteAnimation::windowRoot_ = nullptr; + RemoteAnimation::OnRemoteDie(remoteObject); // controller is not nullptr + EXPECT_EQ(true, RemoteAnimation::CheckAnimationController()); +} + +/** + * @tc.name: OnRemoteDieAndCallbackTimeOutProcess03 + * @tc.desc: OnRemoteDie and timeout process success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, OnRemoteDieAndCallbackTimeOutProcess03, Function | SmallTest | Level2) +{ + auto root = RemoteAnimation::windowRoot_; + node_->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + auto testController = RemoteAnimation::windowAnimationController_; + RemoteAnimation::OnRemoteDie(testController->AsObject()); // controller is not nullptr + EXPECT_EQ(false, RemoteAnimation::CheckAnimationController()); + EXPECT_EQ(true, node_->stateMachine_.currState_ == WindowNodeState::SHOW_ANIMATION_DONE); +} + +/** + * @tc.name: CreateWindowAnimationTarget01 + * @tc.desc: CreateWindowAnimationTarget with null node/different windowType + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CreateWindowAnimationTarget01, Function | SmallTest | Level2) +{ + sptr node = nullptr; + EXPECT_EQ(nullptr, RemoteAnimation::CreateWindowAnimationTarget(transitionInfo_, node)); + sptr srcNode = new WindowNode(CreateWindowProperty(1)); // 1 is windowId + EXPECT_EQ(nullptr, RemoteAnimation::CreateWindowAnimationTarget(transitionInfo_, srcNode)); // no surfaceNode + srcNode->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_DESKTOP); + EXPECT_EQ(nullptr, RemoteAnimation::CreateWindowAnimationTarget(transitionInfo_, srcNode)); // no surfaceNode + EXPECT_NE(nullptr, RemoteAnimation::CreateWindowAnimationTarget(transitionInfo_, node_)); +} + +/** + * @tc.name: CreateShowAnimationFinishedCallback01 + * @tc.desc: CreateShowAnimationFinishedCallback with animationFirst false + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CreateShowAnimationFinishedCallback01, Function | SmallTest | Level2) +{ + RemoteAnimation::SetAnimationFirst(false); + auto finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(node_, node_, true); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // not animation playing + usleep(SLEEP_TIME_IN_US); + + node_->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(node_, node_, true); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // leashSurfaceNode is not nullptr + usleep(SLEEP_TIME_IN_US); + + sptr dstNode = nullptr; + finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(node_, dstNode, true); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // dstNode is nullptr + usleep(SLEEP_TIME_IN_US); + + dstNode = new WindowNode(CreateWindowProperty(1)); // leashSurfaceNode is nullptr + dstNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(node_, dstNode, true); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); +} + +/** + * @tc.name: CreateShowAnimationFinishedCallback02 + * @tc.desc: CreateShowAnimationFinishedCallback with animationFirst true + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CreateShowAnimationFinishedCallback02, Function | SmallTest | Level2) +{ + sptr dstNode = nullptr; + auto finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(node_, dstNode, true); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // dstNode is nullptr + usleep(SLEEP_TIME_IN_US); + + sptr srcNode = nullptr; + finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(srcNode, node_, true); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // process srcNode state task with nullptr, node task count < 0 + usleep(SLEEP_TIME_IN_US); + + srcNode = nullptr; + node_->stateMachine_.ResetAnimationTaskCount(2); // 2 is animationCount + finishCallback = RemoteAnimation::CreateShowAnimationFinishedCallback(srcNode, node_, false); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // process srcNode state task with nullptr, node task count > 0 + usleep(SLEEP_TIME_IN_US); +} + +/** + * @tc.name: CreateHideAnimationFinishedCallback01 + * @tc.desc: CreateHideAnimationFinishedCallback with animationFirst false + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CreateHideAnimationFinishedCallback01, Function | SmallTest | Level2) +{ + RemoteAnimation::SetAnimationFirst(false); + sptr srcNode = nullptr; + auto finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(srcNode, TransitionEvent::MINIMIZE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // srcNode is nullptr + usleep(SLEEP_TIME_IN_US); + + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::MINIMIZE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // not hide animation playing + usleep(SLEEP_TIME_IN_US); + EXPECT_NE(WindowNodeState::HIDE_ANIMATION_DONE, node_->stateMachine_.currState_); + + node_->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::CLOSE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // hide animation playing and with close + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::HIDE_ANIMATION_DONE, node_->stateMachine_.currState_); + + node_->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::MINIMIZE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // hide animation playing and with MINIMIZE + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::HIDE_ANIMATION_DONE, node_->stateMachine_.currState_); + + node_->stateMachine_.TransitionTo(WindowNodeState::STARTING_CREATED); + node_->abilityToken_ = nullptr; + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::MINIMIZE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // abilityToken is nullptr + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::STARTING_CREATED, node_->stateMachine_.currState_); +} + +/** + * @tc.name: CreateHideAnimationFinishedCallback02 + * @tc.desc: CreateHideAnimationFinishedCallback with animationFirst true + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CreateHideAnimationFinishedCallback02, Function | SmallTest | Level2) +{ + sptr srcNode = nullptr; + auto finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(srcNode, TransitionEvent::CLOSE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // srcNode is nullptr + usleep(SLEEP_TIME_IN_US); + + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::MINIMIZE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // with minimize + usleep(SLEEP_TIME_IN_US); + + node_->firstFrameAvaliable_ = true; + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::CLOSE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // create hide callback with firstFrameAvaliable_ true + usleep(SLEEP_TIME_IN_US); + + node_->firstFrameAvaliable_ = false; + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::CLOSE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // create hide callback with surfaceNode null + usleep(SLEEP_TIME_IN_US); + + node_->firstFrameAvaliable_ = false; + node_->surfaceNode_ = CreateRSSurfaceNode(1); + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::CLOSE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // create hide callback with surfaceNode not null + usleep(SLEEP_TIME_IN_US); + + node_->leashWinSurfaceNode_ = CreateRSSurfaceNode(1); + finishCallback = RemoteAnimation::CreateHideAnimationFinishedCallback(node_, TransitionEvent::CLOSE); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); // create hide callback with leashWinSurfaceNode_ null + usleep(SLEEP_TIME_IN_US); +} + +/** + * @tc.name: ProcessNodeStateTask01 + * @tc.desc: ProcessNodeStateTask with different node state + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, ProcessNodeStateTask01, Function | SmallTest | Level2) +{ + // ExecuteFinalStateTask with task is nullptr + node_->stateMachine_.ResetAnimationTaskCount(1); + RemoteAnimation::ProcessNodeStateTask(node_); + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::STARTING_CREATED, node_->stateMachine_.currState_); + + node_->stateMachine_.ResetAnimationTaskCount(1); + node_->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + RemoteAnimation::ProcessNodeStateTask(node_); // hide animation playing + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::HIDE_ANIMATION_DONE, node_->stateMachine_.currState_); + + RemoteAnimation::windowRoot_ = nullptr; + node_->stateMachine_.ResetAnimationTaskCount(1); + RemoteAnimation::ProcessNodeStateTask(node_); // hide animation playing and windowRoot is nullptr + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::HIDE_ANIMATION_DONE, node_->stateMachine_.currState_); + + RemoteAnimation::windowRoot_ = windowRoot_; + node_->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + node_->stateMachine_.ResetAnimationTaskCount(1); + RemoteAnimation::ProcessNodeStateTask(node_); // show animation playing + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::SHOW_ANIMATION_DONE, node_->stateMachine_.currState_); + + bool taskExecute = false; + node_->stateMachine_.SetDestroyTask([&taskExecute] {taskExecute = true;}); + node_->stateMachine_.ResetAnimationTaskCount(1); + RemoteAnimation::ProcessNodeStateTask(node_); // execute destroy task + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(true, taskExecute); + + RemoteAnimation::windowRoot_ = nullptr; + node_->stateMachine_.ResetAnimationTaskCount(1); + RemoteAnimation::ProcessNodeStateTask(node_); // show animation playing and windowRoot is nullptr + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::SHOW_ANIMATION_DONE, node_->stateMachine_.currState_); + + wmsTaskHandler_ = nullptr; + RemoteAnimation::wmsTaskHandler_ = wmsTaskHandler_; + node_->stateMachine_.ResetAnimationTaskCount(1); + node_->stateMachine_.SetDestroyTask([&taskExecute] {taskExecute = false;}); + RemoteAnimation::ExecuteFinalStateTask(node_); // handler is nullptr + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(true, taskExecute); +} + +/** + * @tc.name: PostProcessShowCallback01 + * @tc.desc: PostProcessShowCallback with different leashWinSurfaceNode + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, PostProcessShowCallback01, Function | SmallTest | Level2) +{ + sptr dstNode = nullptr; + RemoteAnimation::PostProcessShowCallback(dstNode); + usleep(SLEEP_TIME_IN_US); + + Rect expectRect = {0, 0, 100, 100}; // 100 is test data + node_->SetWindowRect(expectRect); + RemoteAnimation::PostProcessShowCallback(node_); + usleep(SLEEP_TIME_IN_US); + Rect actualRect = GetSurfaceBoundsRect(node_); + EXPECT_EQ(expectRect, actualRect); + node_->leashWinSurfaceNode_ = nullptr; + RemoteAnimation::PostProcessShowCallback(node_); +} + +/** + * @tc.name: GetTransitionEvent01 + * @tc.desc: GetTransitionEvent with reason not ability_transition + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, GetTransitionEvent01, Function | SmallTest | Level2) +{ + transitionInfo_->SetTransitionReason(TransitionReason::MINIMIZE); + auto event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::MINIMIZE, event); + + transitionInfo_->SetTransitionReason(TransitionReason::BACK_TRANSITION); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::BACK_TRANSITION, event); + + transitionInfo_->SetTransitionReason(TransitionReason::CLOSE); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::CLOSE, event); + + node_->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + transitionInfo_->SetTransitionReason(TransitionReason::CLOSE); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::UNKNOWN, event); +} + +/** + * @tc.name: GetTransitionEvent02 + * @tc.desc: GetTransitionEvent with reason ability_transition + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, GetTransitionEvent02, Function | SmallTest | Level2) +{ + sptr srcNode = nullptr; + transitionInfo_->SetTransitionReason(TransitionReason::ABILITY_TRANSITION); + auto event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(TransitionEvent::APP_TRANSITION, event); + + sptr dstNode = nullptr; + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, dstNode); + EXPECT_EQ(TransitionEvent::UNKNOWN, event); + + node_->stateMachine_.TransitionTo(WindowNodeState::SHOW_ANIMATION_PLAYING); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::UNKNOWN, event); + + transitionInfo_->SetWindowType(WindowType::WINDOW_TYPE_DESKTOP); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::HOME, event); + + transitionInfo_->SetWindowType(WindowType::WINDOW_TYPE_FLOAT); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(TransitionEvent::UNKNOWN, event); + + transitionInfo_->SetAbilityToken(nullptr); + event = RemoteAnimation::GetTransitionEvent(transitionInfo_, transitionInfo_, node_, dstNode); + EXPECT_EQ(TransitionEvent::UNKNOWN, event); +} + +/** + * @tc.name: GetExpectRect01 + * @tc.desc: GetExpectRect + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, GetExpectRect01, Function | SmallTest | Level2) +{ + auto target = RemoteAnimation::CreateWindowAnimationTarget(transitionInfo_, node_); + RemoteAnimation::GetExpectRect(node_, target); + Rect actualRect = GetSurfaceBoundsRect(node_); + EXPECT_EQ(node_->GetWindowRect(), actualRect); // avoidRect is empty thus return + + sptr statusBar = new WindowNode(CreateWindowProperty(0)); + ASSERT_NE(nullptr, statusBar); + statusBar->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR); + statusBar->SetWindowRect({0, 0, 100, 100}); + windowRoot_->windowNodeMap_[0] = statusBar; + + Rect avoidRect = windowRoot_->GetDisplayRectWithoutSystemBarAreas(node_->GetDisplayId()); + EXPECT_FALSE(WindowHelper::IsEmptyRect(avoidRect)); + + RemoteAnimation::GetExpectRect(node_, target); + actualRect = GetSurfaceBoundsRect(node_); + EXPECT_EQ(avoidRect, actualRect); // get expect rect + + node_->leashWinSurfaceNode_ = nullptr; + RemoteAnimation::GetExpectRect(node_, target); + + node_->GetWindowProperty()->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + RemoteAnimation::GetExpectRect(node_, target); + EXPECT_FALSE(WindowHelper::IsMainFullScreenWindow(node_->GetWindowType(), node_->GetWindowMode())); + + RemoteAnimation::windowRoot_ = nullptr; + RemoteAnimation::GetExpectRect(node_, target); + + node_->GetWindowProperty()->SetWindowFlags(0); + RemoteAnimation::GetExpectRect(node_, target); + bool needAvoid = (node_->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + EXPECT_EQ(false, needAvoid); +} + +/** + * @tc.name: NotifyAnimationTransition01 + * @tc.desc: NotifyAnimationTransition failed + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationTransition01, Function | SmallTest | Level2) +{ + sptr dstNode = nullptr; + WMError ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, node_, dstNode); + EXPECT_EQ(WMError::WM_ERROR_NULLPTR, ret); // + dstNode = new WindowNode(CreateWindowProperty(1)); // leashSurfaceNode is nullptr + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, node_, dstNode); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); // no surfaceNode thus target is nullptr +} + +/** + * @tc.name: NotifyAnimationTransition02 + * @tc.desc: NotifyAnimationTransition with OnAppTransition + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationTransition02, Function | SmallTest | Level2) +{ + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + MinimizeApp::AddNeedMinimizeApp(srcNode, MinimizeReason::OTHER_WINDOW); + + WMError ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // + EXPECT_EQ(0, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::OTHER_WINDOW).size()); + + RemoteAnimation::SetAnimationFirst(false); + MinimizeApp::AddNeedMinimizeApp(srcNode, MinimizeReason::OTHER_WINDOW); + + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // + EXPECT_EQ(1, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::OTHER_WINDOW).size()); + + RemoteAnimation::windowController_ = nullptr; + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); +} + +/** + * @tc.name: NotifyAnimationTransition03 + * @tc.desc: NotifyAnimationTransition with NotifyAnimationStartApp + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationTransition03, Function | SmallTest | Level2) +{ + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + srcNode->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_DESKTOP); + node_->surfaceNode_ = CreateRSSurfaceNode(2); + WMError ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // srcNode is nullptr, from launcher + + srcNode->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + transitionInfo_->SetIsRecent(true); + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // srcNode is nullptr, from recent + + srcNode = nullptr; + transitionInfo_->SetIsRecent(false); + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // srcNode is null && need minimize false, from other + + MinimizeApp::AddNeedMinimizeApp(srcNode, MinimizeReason::OTHER_WINDOW); + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // srcNode is nullptr, but need minimize true, from other + + RemoteAnimation::SetAnimationFirst(false); + ret = RemoteAnimation::NotifyAnimationTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); // srcNode is nullptr, but need minimize true, from other +} + +/** + * @tc.name: NotifyAnimationMinimize01 + * @tc.desc: NotifyAnimationMinimize + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationMinimize01, Function | SmallTest | Level2) +{ + WMError ret = RemoteAnimation::NotifyAnimationMinimize(transitionInfo_, node_); + EXPECT_EQ(WMError::WM_OK, ret); + + RemoteAnimation::windowController_ = nullptr; + ret = RemoteAnimation::NotifyAnimationMinimize(transitionInfo_, node_); + EXPECT_EQ(WMError::WM_OK, ret); + + node_->leashWinSurfaceNode_ = nullptr; + ret = RemoteAnimation::NotifyAnimationMinimize(transitionInfo_, node_); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); // srcTarget is nullptr +} + +/** + * @tc.name: NotifyAnimationClose01 + * @tc.desc: NotifyAnimationClose + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationClose01, Function | SmallTest | Level2) +{ + WMError ret = RemoteAnimation::NotifyAnimationClose(transitionInfo_, node_, TransitionEvent::CLOSE); + EXPECT_EQ(WMError::WM_OK, ret); + + RemoteAnimation::windowController_ = nullptr; + ret = RemoteAnimation::NotifyAnimationClose(transitionInfo_, node_, TransitionEvent::CLOSE); + EXPECT_EQ(WMError::WM_OK, ret); + + node_->leashWinSurfaceNode_ = nullptr; + ret = RemoteAnimation::NotifyAnimationClose(transitionInfo_, node_, TransitionEvent::CLOSE); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); // srcTarget is nullptr +} + +/** + * @tc.name: NotifyAnimationBackTransition01 + * @tc.desc: NotifyAnimationBackTransition failed + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationBackTransition01, Function | SmallTest | Level2) +{ + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + srcNode->leashWinSurfaceNode_ = nullptr; + WMError ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); // only src Target is null + + sptr dstNode = new WindowNode(CreateWindowProperty(3)); // 3 is windowId + dstNode->leashWinSurfaceNode_ = nullptr; + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, node_, dstNode); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); // only dstTarget is null + + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, srcNode, dstNode); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); // both srcTarget and dstTarget art null + + srcNode = nullptr; + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_ERROR_NULLPTR, ret); // only srcNode is null + + dstNode = nullptr; + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, node_, dstNode); + EXPECT_EQ(WMError::WM_ERROR_NULLPTR, ret); // only dstNode is null + + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, srcNode, dstNode); + EXPECT_EQ(WMError::WM_ERROR_NULLPTR, ret); // both srcNode and dstNode are null + + RemoteAnimation::SetAnimationFirst(false); + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, node_, node_); + EXPECT_EQ(WMError::WM_ERROR_NO_REMOTE_ANIMATION, ret); +} + +/** + * @tc.name: NotifyAnimationBackTransition02 + * @tc.desc: NotifyAnimationBackTransition success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationBackTransition02, Function | SmallTest | Level2) +{ + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + srcNode->leashWinSurfaceNode_ = CreateRSSurfaceNode(2); // 2 is windowId + WMError ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->finishedCallback_); + testController->finishedCallback_->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); + + RemoteAnimation::windowController_ = nullptr; + ret = RemoteAnimation::NotifyAnimationBackTransition(transitionInfo_, transitionInfo_, srcNode, node_); + EXPECT_EQ(WMError::WM_OK, ret); + testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->finishedCallback_); + testController->finishedCallback_->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); +} + +/** + * @tc.name: NotifyAnimationByHome01 + * @tc.desc: NotifyAnimationByHome with animationFirst false and create animationTarget failed + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationByHome01, Function | SmallTest | Level2) +{ + RemoteAnimation::SetAnimationFirst(false); + WMError ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); // no node need home + + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + MinimizeApp::AddNeedMinimizeApp(srcNode, MinimizeReason::MINIMIZE_ALL); + ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); // create animationTarget failed with no surface, and no callback + + srcNode->leashWinSurfaceNode_ = CreateRSSurfaceNode(2); // 2 is windowId + srcNode->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_DESKTOP); + ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); // create animationTarget failed, and no callback + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->finishedCallback_); + testController->finishedCallback_->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); + EXPECT_NE(WindowNodeState::HIDE_ANIMATION_DONE, srcNode->stateMachine_.currState_); + + srcNode->stateMachine_.TransitionTo(WindowNodeState::HIDE_ANIMATION_PLAYING); + ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); // create animationTarget failed, and no callback + + srcNode->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); // create animationTarget failed, and no callback +} + +/* + * @tc.name: NotifyAnimationByHome02 + * @tc.desc: NotifyAnimationByHome with animationFirst false and create animationTarget success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationByHome02, Function | SmallTest | Level2) +{ + RemoteAnimation::SetAnimationFirst(false); + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + srcNode->leashWinSurfaceNode_ = CreateRSSurfaceNode(2); // 2 is windowId + MinimizeApp::AddNeedMinimizeApp(srcNode, MinimizeReason::MINIMIZE_ALL); + WMError ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); + + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->finishedCallback_); + testController->finishedCallback_->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::HIDE_ANIMATION_DONE, srcNode->stateMachine_.currState_); +} + +/* + * @tc.name: NotifyAnimationByHome03 + * @tc.desc: NotifyAnimationByHome with animationFirst true and create animationTarget success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationByHome03, Function | SmallTest | Level2) +{ + sptr srcNode = new WindowNode(CreateWindowProperty(2)); // 2 is windowId + srcNode->leashWinSurfaceNode_ = CreateRSSurfaceNode(2); // 2 is windowId + MinimizeApp::AddNeedMinimizeApp(srcNode, MinimizeReason::MINIMIZE_ALL); + EXPECT_EQ(1, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL).size()); + WMError ret = RemoteAnimation::NotifyAnimationByHome(); + EXPECT_EQ(WMError::WM_OK, ret); + EXPECT_EQ(0, MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::MINIMIZE_ALL).size()); + + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->finishedCallback_); + testController->finishedCallback_->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(WindowNodeState::HIDE_ANIMATION_DONE, srcNode->stateMachine_.currState_); +} + +/* + * @tc.name: NotifyAnimationTargetsUpdate01 + * @tc.desc: NotifyAnimationTargetsUpdate failed + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationTargetsUpdate01, Function | SmallTest | Level2) +{ + std::vector fullScreenWinIds; + std::vector floatWinIds; + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatWinIds); // fullScreenAnimationTarget is empty + usleep(SLEEP_TIME_IN_US); + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_EQ(nullptr, testController->animationTarget_); + EXPECT_EQ(0, testController->floatingWindowTargets_.size()); + + RemoteAnimation::windowRoot_ = nullptr; + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatWinIds); + usleep(SLEEP_TIME_IN_US); + testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_EQ(nullptr, testController->animationTarget_); + EXPECT_EQ(0, testController->floatingWindowTargets_.size()); + + RemoteAnimation::windowAnimationController_ = nullptr; + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatWinIds); + usleep(SLEEP_TIME_IN_US); + testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_EQ(nullptr, testController->animationTarget_); + EXPECT_EQ(0, testController->floatingWindowTargets_.size()); + + wmsTaskHandler_ = nullptr; + RemoteAnimation::wmsTaskHandler_ = wmsTaskHandler_; + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatWinIds); + usleep(SLEEP_TIME_IN_US); + testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_EQ(nullptr, testController->animationTarget_); + EXPECT_EQ(0, testController->floatingWindowTargets_.size()); +} + +/* + * @tc.name: NotifyAnimationTargetsUpdate02 + * @tc.desc: NotifyAnimationTargetsUpdate success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationTargetsUpdate02, Function | SmallTest | Level2) +{ + std::vector fullScreenWinIds; + std::vector floatWinIds; + fullScreenWinIds.push_back(2); // 2 is windowId + floatWinIds.push_back(2); // 2 is windowId + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatWinIds); // CreateWindowAnimationTarget nullptr + usleep(SLEEP_TIME_IN_US); + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_EQ(nullptr, testController->animationTarget_); + EXPECT_EQ(0, testController->floatingWindowTargets_.size()); + + fullScreenWinIds.push_back(node_->GetWindowId()); // 1, 2 in vector + floatWinIds.push_back(node_->GetWindowId()); // CreateWindowAnimationTarget success + RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatWinIds); + usleep(SLEEP_TIME_IN_US); + testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->animationTarget_); + EXPECT_EQ(1, testController->floatingWindowTargets_.size()); +} + +/* + * @tc.name: NotifyAnimationScreenUnlock01 + * @tc.desc: NotifyAnimationScreenUnlock success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationScreenUnlock01, Function | SmallTest | Level2) +{ + std::function callback = nullptr; + WMError ret = RemoteAnimation::NotifyAnimationScreenUnlock(callback); + EXPECT_EQ(WMError::WM_ERROR_NO_MEM, ret); + + callback = []() {}; + ret = RemoteAnimation::NotifyAnimationScreenUnlock(callback); + EXPECT_EQ(WMError::WM_OK, ret); + + RemoteAnimation::windowAnimationController_ = nullptr; + ret = RemoteAnimation::NotifyAnimationScreenUnlock(callback); + EXPECT_EQ(WMError::WM_ERROR_NO_REMOTE_ANIMATION, ret); +} + +/* + * @tc.name: NotifyAnimationUpdateWallpaper01 + * @tc.desc: NotifyAnimationUpdateWallpaper success + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, NotifyAnimationUpdateWallpaper01, Function | SmallTest | Level2) +{ + RemoteAnimation::NotifyAnimationUpdateWallpaper(node_); + RSIWindowAnimationControllerMocker* testController = reinterpret_cast( + animationController_.GetRefPtr()); + EXPECT_NE(nullptr, testController->animationTarget_); + + testController->animationTarget_ = nullptr; + RemoteAnimation::windowAnimationController_ = nullptr; + RemoteAnimation::NotifyAnimationUpdateWallpaper(node_); + EXPECT_EQ(nullptr, testController->animationTarget_); +} + +/* + * @tc.name: CreateAnimationFinishedCallback01 + * @tc.desc: CreateAnimationFinishedCallback + * @tc.type: FUNC + */ +HWTEST_F(RemoteAnimationTest, CreateAnimationFinishedCallback01, Function | SmallTest | Level2) +{ + std::function callback = nullptr; + EXPECT_EQ(nullptr, RemoteAnimation::CreateAnimationFinishedCallback(callback)); + + bool testFlag = false; + callback = [&testFlag]() { testFlag = true; }; + auto finishCallback = RemoteAnimation::CreateAnimationFinishedCallback(callback); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(true, testFlag); + + wmsTaskHandler_ = nullptr; + RemoteAnimation::wmsTaskHandler_ = wmsTaskHandler_; + callback = [&testFlag]() { testFlag = false; }; + finishCallback = RemoteAnimation::CreateAnimationFinishedCallback(callback); + EXPECT_NE(nullptr, finishCallback); + finishCallback->OnAnimationFinished(); + usleep(SLEEP_TIME_IN_US); + EXPECT_EQ(false, testFlag); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/starting_window_test.cpp b/window_manager/wmserver/test/unittest/starting_window_test.cpp new file mode 100644 index 0000000..a080931 --- /dev/null +++ b/window_manager/wmserver/test/unittest/starting_window_test.cpp @@ -0,0 +1,420 @@ +/* + * 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 "iremote_object_mocker.h" +#include "mock_RSIWindowAnimationController.h" +#include "remote_animation.h" +#include "starting_window.h" +#include "window_helper.h" +#include "window_transition_info.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class StartingWindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + sptr CreateWindowProperty(); +private: + static sptr transitionInfo_; + RSSurfaceNode::SharedPtr CreateRSSurfaceNode(); + static sptr animationController_; + static sptr node_; +}; + +sptr StartingWindowTest::transitionInfo_ = nullptr; +sptr StartingWindowTest::animationController_ = nullptr; +sptr StartingWindowTest::node_ = nullptr; + +void StartingWindowTest::SetUpTestCase() +{ +} + +void StartingWindowTest::TearDownTestCase() +{ +} + +void StartingWindowTest::SetUp() +{ + transitionInfo_ = new WindowTransitionInfo(); + animationController_ = new RSIWindowAnimationControllerMocker(); + ASSERT_EQ(WMError::WM_OK, RemoteAnimation::SetWindowAnimationController(animationController_)); + transitionInfo_->supportWindowModes_ = { + AppExecFwk::SupportWindowMode::FULLSCREEN, + AppExecFwk::SupportWindowMode::SPLIT, + AppExecFwk::SupportWindowMode::FLOATING + }; + node_ = StartingWindow::CreateWindowNode(transitionInfo_, 101); // 101 is windowId + node_->SetWindowRect({0, 0, 100, 100}); +} + +void StartingWindowTest::TearDown() +{ + transitionInfo_ = nullptr; + node_ = nullptr; +} + +RSSurfaceNode::SharedPtr StartingWindowTest::CreateRSSurfaceNode() +{ + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = "startingWindowTestSurfaceNode"; + auto surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig); + return surfaceNode; +} + +sptr StartingWindowTest::CreateWindowProperty() +{ + sptr property = new WindowProperty(); + return property; +} +namespace { +/** + * @tc.name: NeedToStopStartingWindow01 + * @tc.desc: stop starting window test without main App window + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, NeedToStopStartingWindow01, Function | SmallTest | Level2) +{ + transitionInfo_->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + sptr node = new WindowNode(CreateWindowProperty()); + ASSERT_EQ(true, WindowHelper::CheckSupportWindowMode(node->GetWindowMode(), + node->GetModeSupportInfo(), transitionInfo_)); +} + +/** + * @tc.name: NeedToStopStartingWindow02 + * @tc.desc: need to stop starting window test with unsupport mode + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, NeedToStopStartingWindow02, Function | SmallTest | Level2) +{ + sptr node = new WindowNode(CreateWindowProperty()); + node->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + node->SetModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING); + ASSERT_EQ(false, WindowHelper::CheckSupportWindowMode(node->GetWindowMode(), + node->GetModeSupportInfo(), transitionInfo_)); +} + +/** + * @tc.name: NeedToStopStartingWindow03 + * @tc.desc: need to stop starting window test with support mode + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, NeedToStopStartingWindow03, Function | SmallTest | Level2) +{ + sptr node = new WindowNode(CreateWindowProperty()); + ASSERT_EQ(true, WindowHelper::CheckSupportWindowMode(node->GetWindowMode(), + node->GetModeSupportInfo(), transitionInfo_)); +} + +/** + * @tc.name: NeedToStopStartingWindow04 + * @tc.desc: need to stop starting window test with support mode + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, NeedToStopStartingWindow04, Function | SmallTest | Level2) +{ + sptr node = new WindowNode(CreateWindowProperty()); + transitionInfo_->SetShowFlagWhenLocked(true); + node->SetModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY | + WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY); + ASSERT_EQ(false, WindowHelper::CheckSupportWindowMode(node->GetWindowMode(), + node->GetModeSupportInfo(), transitionInfo_)); +} + +/** + * @tc.name: CreateWindowNode01 + * @tc.desc: create starting window node test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, CreateWindowNode01, Function | SmallTest | Level2) +{ + sptr info = nullptr; + ASSERT_EQ(nullptr, StartingWindow::CreateWindowNode(info, 0)); +} + +/** + * @tc.name: CreateWindowNode02 + * @tc.desc: create starting window node test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, CreateWindowNode02, Function | SmallTest | Level2) +{ + transitionInfo_->SetWindowMode(WindowMode::WINDOW_MODE_UNDEFINED); + sptr node = StartingWindow::CreateWindowNode(transitionInfo_, 0); + ASSERT_NE(nullptr, node); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, node->GetWindowMode()); +} + +/** + * @tc.name: CreateWindowNode03 + * @tc.desc: create starting window node test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, CreateWindowNode03, Function | SmallTest | Level2) +{ + transitionInfo_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + sptr node = StartingWindow::CreateWindowNode(transitionInfo_, 0); + ASSERT_NE(nullptr, node); + ASSERT_EQ(WindowMode::WINDOW_MODE_FLOATING, node->GetWindowMode()); +} + +/** + * @tc.name: CreateWindowNode04 + * @tc.desc: create starting window node test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, CreateWindowNode04, Function | SmallTest | Level2) +{ + transitionInfo_->SetShowFlagWhenLocked(true); + sptr node = StartingWindow::CreateWindowNode(transitionInfo_, 0); + ASSERT_NE(nullptr, node); +} + +/** + * @tc.name: DrawStartingWindow01 + * @tc.desc: draw starting window node + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, DrawStartingWindow01, Function | SmallTest | Level2) +{ + std::shared_ptr pixelMap = std::make_shared(); + sptr node = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, StartingWindow::DrawStartingWindow(node, pixelMap, 0x00FFFFFF, true)); +} + +/** + * @tc.name: DrawStartingWindow02 + * @tc.desc: draw starting window node + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, DrawStartingWindow02, Function | SmallTest | Level2) +{ + node_->leashWinSurfaceNode_ = nullptr; + std::shared_ptr pixelMap = std::make_shared(); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, pixelMap, 0x00FFFFFF, true)); +} + +/** + * @tc.name: DrawStartingWindow03 + * @tc.desc: draw starting window node + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, DrawStartingWindow03, Function | SmallTest | Level2) +{ + std::shared_ptr pixelMap = std::make_shared(); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, pixelMap, 0x00FFFFFF, false)); +} + +/** + * @tc.name: DrawStartingWindow04 + * @tc.desc: draw starting window node + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, DrawStartingWindow04, Function | SmallTest | Level2) +{ + node_->startingWinSurfaceNode_ = nullptr; + std::shared_ptr pixelMap = std::make_shared(); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, StartingWindow::DrawStartingWindow(node_, pixelMap, 0x00FFFFFF, true)); +} + +/** + * @tc.name: DrawStartingWindow05 + * @tc.desc: draw starting window node + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, DrawStartingWindow05, Function | SmallTest | Level2) +{ + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x00FFFFFF, true)); +} + +/** + * @tc.name: DrawStartingWindow06 + * @tc.desc: draw starting window node + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, DrawStartingWindow06, Function | SmallTest | Level2) +{ + std::shared_ptr pixelMap = std::make_shared(); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, pixelMap, 0x00FFFFFF, true)); +} + +/** + * @tc.name: HandleClientWindowCreateAndRelease01 + * @tc.desc: handle client window create + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, HandleClientWindowCreateAndRelease01, Function | SmallTest | Level2) +{ + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + sptr iWindow = iface_cast(iRemoteObjectMocker); + ASSERT_NE(nullptr, iWindow); + uint32_t windowId = 0; + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + sptr windowProperty = new WindowProperty(); + StartingWindow::HandleClientWindowCreate(node_, iWindow, windowId, surfaceNode, windowProperty, 0, 0); + ASSERT_EQ(node_->GetWindowId(), windowId); + StartingWindow::ReleaseStartWinSurfaceNode(node_); +} + +/** + * @tc.name: HandleClientWindowCreate02 + * @tc.desc: handle client window create + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, HandleClientWindowCreate02, Function | SmallTest | Level2) +{ + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + sptr iWindow = iface_cast(iRemoteObjectMocker); + ASSERT_NE(nullptr, iWindow); + uint32_t windowId = 0; + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + sptr windowProperty = new WindowProperty(); + sptr node = nullptr; + StartingWindow::HandleClientWindowCreate(node, iWindow, windowId, surfaceNode, windowProperty, 0, 0); +} + +/** + * @tc.name: HandleClientWindowCreateAndRelease03 + * @tc.desc: handle client window create and Release with null leashNode + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, HandleClientWindowCreateAndRelease03, Function | SmallTest | Level2) +{ + node_->leashWinSurfaceNode_ = nullptr; + uint32_t windowId = 0; + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + sptr windowProperty = new WindowProperty(); + sptr iWindow = nullptr; + StartingWindow::HandleClientWindowCreate(node_, iWindow, windowId, surfaceNode, windowProperty, 0, 0); + StartingWindow::ReleaseStartWinSurfaceNode(node_); +} + +/** + * @tc.name: AddNodeOnRSTree01 + * @tc.desc: Add node on rs tree test with surfaceNode nullptr and hot start + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, AddNodeOnRSTree01, Function | SmallTest | Level2) +{ + sptr testController = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, RemoteAnimation::SetWindowAnimationController(testController)); + AnimationConfig config; + StartingWindow::AddNodeOnRSTree(node_, config, true); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x66FFFFFF, false)); + usleep(200000); +} + +/** + * @tc.name: AddNodeOnRSTree02 + * @tc.desc: Add node on rs tree test with hot start and surfaceNode + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, AddNodeOnRSTree02, Function | SmallTest | Level2) +{ + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + node_->surfaceNode_ = surfaceNode; + sptr testController = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, RemoteAnimation::SetWindowAnimationController(testController)); + AnimationConfig config; + StartingWindow::AddNodeOnRSTree(node_, config, true); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x66FFFFFF, false)); + usleep(200000); +} + +/** + * @tc.name: AddNodeOnRSTree03 + * @tc.desc: Add node on rs tree test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, AddNodeOnRSTree03, Function | SmallTest | Level2) +{ + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + node_->surfaceNode_ = surfaceNode; + node_->leashWinSurfaceNode_ = nullptr; + sptr testController = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, RemoteAnimation::SetWindowAnimationController(testController)); + AnimationConfig config; + StartingWindow::AddNodeOnRSTree(node_, config, true); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x66FFFFFF, false)); + usleep(200000); +} + +/** + * @tc.name: AddNodeOnRSTree04 + * @tc.desc: Add node on rs tree test with surfaceNode nullptr, with animation controller + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, AddNodeOnRSTree04, Function | SmallTest | Level2) +{ + sptr testController = new RSIWindowAnimationControllerMocker(); + ASSERT_EQ(WMError::WM_OK, RemoteAnimation::SetWindowAnimationController(testController)); + AnimationConfig config; + StartingWindow::AddNodeOnRSTree(node_, config, true); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x66FFFFFF, false)); + usleep(200000); +} + +/** + * @tc.name: AddNodeOnRSTree05 + * @tc.desc: Add node on rs tree test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, AddNodeOnRSTree05, Function | SmallTest | Level2) +{ + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + node_->surfaceNode_ = surfaceNode; + sptr testController = new RSIWindowAnimationControllerMocker(); + ASSERT_EQ(WMError::WM_OK, RemoteAnimation::SetWindowAnimationController(testController)); + AnimationConfig config; + StartingWindow::AddNodeOnRSTree(node_, config, true); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x66FFFFFF, false)); + usleep(200000); +} + +/** + * @tc.name: AddNodeOnRSTree06 + * @tc.desc: Add node on rs tree test + * @tc.type: FUNC + */ +HWTEST_F(StartingWindowTest, AddNodeOnRSTree06, Function | SmallTest | Level2) +{ + auto surfaceNode = CreateRSSurfaceNode(); + ASSERT_NE(nullptr, surfaceNode); + node_->surfaceNode_ = surfaceNode; + node_->leashWinSurfaceNode_ = nullptr; + sptr testController = new RSIWindowAnimationControllerMocker(); + ASSERT_EQ(WMError::WM_OK, RemoteAnimation::SetWindowAnimationController(testController)); + AnimationConfig config; + StartingWindow::AddNodeOnRSTree(node_, config, true); + ASSERT_EQ(WMError::WM_OK, StartingWindow::DrawStartingWindow(node_, nullptr, 0x66FFFFFF, false)); + usleep(200000); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_controller_test.cpp b/window_manager/wmserver/test/unittest/window_controller_test.cpp new file mode 100644 index 0000000..3cf437a --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_controller_test.cpp @@ -0,0 +1,507 @@ +/* + * 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 "iremote_object_mocker.h" +#include "mock_rs_iwindow_animation_controller.h" +#include "remote_animation.h" +#include "starting_window.h" +#include "window_controller.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static sptr windowController_; + static sptr windowRoot_; + static sptr inputWindowMonitor_; + static sptr node_; + static sptr transitionInfo_; +}; + +sptr WindowControllerTest::windowController_ = nullptr; +sptr WindowControllerTest::windowRoot_ = nullptr; +sptr WindowControllerTest::inputWindowMonitor_ = nullptr; +sptr WindowControllerTest::node_ = nullptr; +sptr WindowControllerTest::transitionInfo_ = nullptr; + +void RootCallback(Event event, const sptr& remoteObject) +{ + return; +} + +void WindowControllerTest::SetUpTestCase() +{ + windowRoot_ = new WindowRoot(RootCallback); + windowRoot_->displayIdMap_[0].push_back(0); + inputWindowMonitor_ = new InputWindowMonitor(windowRoot_); + windowController_ = new WindowController(windowRoot_, inputWindowMonitor_); + transitionInfo_ = new WindowTransitionInfo(); + transitionInfo_->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + node_ = StartingWindow::CreateWindowNode(transitionInfo_, 101); // 101 is windowId + node_->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); +} + +void WindowControllerTest::TearDownTestCase() +{ +} + +void WindowControllerTest::SetUp() +{ +} + +void WindowControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: StartingWindow + * @tc.desc: Window controller starting window + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, StartingWindow, Function | SmallTest | Level3) +{ + windowRoot_->windowNodeMap_.clear(); + windowController_->StartingWindow(nullptr, nullptr, 0, false); + ASSERT_EQ(0, windowRoot_->windowNodeMap_.size()); + + transitionInfo_->SetWindowMode(WindowMode::WINDOW_MODE_UNDEFINED); + windowController_->StartingWindow(transitionInfo_, nullptr, 0, false); + ASSERT_EQ(0, windowRoot_->windowNodeMap_.size()); + + sptr abilityTokenMocker = new IRemoteObjectMocker(); + transitionInfo_->SetAbilityToken(abilityTokenMocker); + windowController_->StartingWindow(transitionInfo_, nullptr, 0, false); + windowController_->StartingWindow(transitionInfo_, nullptr, 0, true); + ASSERT_EQ(1, windowRoot_->windowNodeMap_.size()); + + windowRoot_->windowNodeMap_.clear(); + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + RemoteAnimation::windowAnimationController_ = iface_cast(iRemoteObjectMocker); + windowController_->StartingWindow(transitionInfo_, nullptr, 0, true); + ASSERT_EQ(1, windowRoot_->windowNodeMap_.size()); + + windowRoot_->windowNodeMap_.clear(); + windowRoot_->windowNodeMap_.insert(std::make_pair(node_->GetWindowId(), node_)); + node_->abilityToken_ = abilityTokenMocker; + node_->stateMachine_.currState_ = WindowNodeState::SHOW_ANIMATION_PLAYING; + windowController_->StartingWindow(transitionInfo_, nullptr, 0, false); + ASSERT_EQ(1, windowRoot_->windowNodeMap_.size()); + + node_->stateMachine_.currState_ = WindowNodeState::STARTING_CREATED; + windowController_->StartingWindow(transitionInfo_, nullptr, 0, false); + transitionInfo_->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + windowController_->StartingWindow(transitionInfo_, nullptr, 0, false); + transitionInfo_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + node_->property_->modeSupportInfo_ = WindowModeSupport::WINDOW_MODE_SUPPORT_ALL; + windowController_->StartingWindow(transitionInfo_, nullptr, 0, false); + ASSERT_EQ(1, windowRoot_->windowNodeMap_.size()); + + // Cancel starting window + windowController_->CancelStartingWindow(nullptr); + windowController_->CancelStartingWindow(abilityTokenMocker); + + node_->startingWindowShown_ = true; + windowController_->CancelStartingWindow(abilityTokenMocker); + ASSERT_EQ(0, windowRoot_->windowNodeMap_.size()); + + windowRoot_->windowNodeMap_.clear(); + RemoteAnimation::windowAnimationController_ = nullptr; +} +/** + * @tc.name: NotifyWindowTransition + * @tc.desc: Window controller notify window transtition + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, NotifyWindowTransition, Function | SmallTest | Level3) +{ + sptr srcInfo = nullptr; + sptr dstInfo = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NO_REMOTE_ANIMATION, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + srcInfo = new WindowTransitionInfo(); + sptr srcAbilityTokenMocker = new IRemoteObjectMocker(); + srcInfo->SetAbilityToken(srcAbilityTokenMocker); + sptr srcNode = StartingWindow::CreateWindowNode(srcInfo, 102); // 102 is windowId + srcNode->property_->modeSupportInfo_ = WindowModeSupport::WINDOW_MODE_SUPPORT_ALL; + + dstInfo = new WindowTransitionInfo(); + sptr dstAbilityTokenMocker = new IRemoteObjectMocker(); + dstInfo->SetAbilityToken(dstAbilityTokenMocker); + sptr dstNode = StartingWindow::CreateWindowNode(dstInfo, 103); // 103 is windowId + dstNode->property_->modeSupportInfo_ = WindowModeSupport::WINDOW_MODE_SUPPORT_ALL; + + windowRoot_->windowNodeMap_.clear(); + windowRoot_->windowNodeMap_.insert(std::make_pair(srcNode->GetWindowId(), srcNode)); + windowRoot_->windowNodeMap_.insert(std::make_pair(dstNode->GetWindowId(), dstNode)); + + sptr displayInfo = new DisplayInfo(); + sptr container = new WindowNodeContainer(displayInfo, 0); + windowRoot_->windowNodeContainerMap_.insert(std::make_pair(0, container)); + + sptr mock = new MockRSIWindowAnimationController(); + RemoteAnimation::windowAnimationController_ = mock; + RemoteAnimation::windowRoot_ = windowRoot_; + RemoteAnimation::animationFirst_ = true; + + srcInfo->SetTransitionReason(TransitionReason::MINIMIZE); + srcNode->stateMachine_.currState_ = WindowNodeState::HIDDEN; + ASSERT_EQ(WMError::WM_ERROR_NO_REMOTE_ANIMATION, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + srcInfo->SetTransitionReason(TransitionReason::MINIMIZE); + srcNode->stateMachine_.currState_ = WindowNodeState::STARTING_CREATED; + EXPECT_CALL(*mock, OnMinimizeWindow(_, _)).Times(1); + ASSERT_EQ(WMError::WM_OK, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + srcInfo->SetTransitionReason(TransitionReason::CLOSE); + srcNode->stateMachine_.currState_ = WindowNodeState::STARTING_CREATED; + EXPECT_CALL(*mock, OnCloseWindow(_, _)).Times(1); + ASSERT_EQ(WMError::WM_OK, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + srcInfo->SetTransitionReason(TransitionReason::BACK_TRANSITION); + srcNode->stateMachine_.currState_ = WindowNodeState::STARTING_CREATED; + EXPECT_CALL(*mock, OnAppTransition(_, _, _)).Times(1); + ASSERT_EQ(WMError::WM_OK, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + srcInfo->SetTransitionReason(TransitionReason::ABILITY_TRANSITION); + dstNode->stateMachine_.currState_ = WindowNodeState::STARTING_CREATED; + dstNode->property_->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + dstNode->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + EXPECT_CALL(*mock, OnStartApp(_, _, _)).Times(1); + ASSERT_EQ(WMError::WM_OK, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + dstNode->stateMachine_.currState_ = WindowNodeState::STARTING_CREATED; + dstNode->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + EXPECT_CALL(*mock, OnStartApp(_, _, _)).Times(1); + ASSERT_EQ(WMError::WM_OK, windowController_->NotifyWindowTransition(srcInfo, dstInfo)); + + windowRoot_->windowNodeContainerMap_.clear(); + RemoteAnimation::windowAnimationController_ = nullptr; +} +/** + * @tc.name: FocusWindow + * @tc.desc: Window controller focus window + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, FocusWindow, Function | SmallTest | Level3) +{ + sptr abilityToken = nullptr; + windowController_->GetFocusWindowInfo(abilityToken); + + sptr displayInfo = new DisplayInfo(); + sptr container = new WindowNodeContainer(displayInfo, 0); + windowRoot_->windowNodeContainerMap_.insert(std::make_pair(0, container)); + + sptr windowNode; + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, windowController_->GetFocusWindowNode(0, windowNode)); + + windowRoot_->windowNodeMap_.clear(); + windowRoot_->windowNodeMap_.insert(std::make_pair(node_->GetWindowId(), node_)); + container->focusedWindow_ = node_->GetWindowId(); + node_->currentVisibility_ = false; + ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, windowController_->GetFocusWindowNode(0, windowNode)); + + node_->currentVisibility_ = true; + ASSERT_EQ(WMError::WM_OK, windowController_->GetFocusWindowNode(0, windowNode)); + windowRoot_->windowNodeContainerMap_.clear(); +} +/** + * @tc.name: CreateWindow + * @tc.desc: Window controller create window + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, CreateWindow, Function | SmallTest | Level3) +{ + sptr window; + sptr property = new WindowProperty(); + std::shared_ptr surfaceNode; + + uint32_t windowId; + property->SetParentId(INVALID_WINDOW_ID); + ASSERT_EQ(WMError::WM_OK, windowController_->CreateWindow(window, property, surfaceNode, windowId, nullptr, 0, 0)); + + property->SetParentId(1); + property->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + ASSERT_EQ(WMError::WM_ERROR_INVALID_TYPE, + windowController_->CreateWindow(window, property, surfaceNode, windowId, nullptr, 0, 0)); + + property->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + ASSERT_EQ(WMError::WM_OK, windowController_->CreateWindow(window, property, surfaceNode, windowId, nullptr, 0, 0)); + + property->SetWindowType(WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW); + ASSERT_EQ(WMError::WM_OK, windowController_->CreateWindow(window, property, surfaceNode, windowId, nullptr, 0, 0)); + windowRoot_->windowNodeMap_.clear(); + + sptr abilityTokenMocker = new IRemoteObjectMocker(); + node_->abilityToken_ = abilityTokenMocker; + + property->SetParentId(INVALID_WINDOW_ID); + property->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + ASSERT_EQ(WMError::WM_OK, + windowController_->CreateWindow(window, property, surfaceNode, windowId, abilityTokenMocker, 0, 0)); + + property->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + ASSERT_EQ(WMError::WM_OK, + windowController_->CreateWindow(window, property, surfaceNode, windowId, abilityTokenMocker, 0, 0)); + + property->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + node_->startingWindowShown_ = false; + ASSERT_EQ(WMError::WM_OK, + windowController_->CreateWindow(window, property, surfaceNode, windowId, abilityTokenMocker, 0, 0)); + windowRoot_->windowNodeMap_.clear(); +} +/** + * @tc.name: NotifyAfterAddWindow + * @tc.desc: Window controller notify after add window + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, NotifyAfterAddWindow, Function | SmallTest | Level3) +{ + ASSERT_NE(nullptr, windowController_); + sptr node0 = new WindowNode(); + windowController_->NotifyAfterAddWindow(node0); + ASSERT_EQ(0, node0->children_.size()); + + sptr node1 = new WindowNode(); + node1->currentVisibility_ = false; + sptr node2= new WindowNode(); + node2->currentVisibility_ = true; + + node0->children_.push_back(node1); + node0->children_.push_back(node2); + windowController_->NotifyAfterAddWindow(node0); + ASSERT_EQ(2, node0->children_.size()); + ASSERT_EQ(nullptr, node0->children_[0]->abilityToken_); +} +/** + * @tc.name: AddWindowNode + * @tc.desc: Window controller add window node + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, AddWindowNode, Function | SmallTest | Level3) +{ + sptr property = new WindowProperty(); + property->SetWindowId(0); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, windowController_->AddWindowNode(property)); + + windowRoot_->windowNodeMap_.clear(); + windowRoot_->windowNodeMap_.insert(std::make_pair(node_->GetWindowId(), node_)); + property->SetWindowId(node_->GetWindowId()); + node_->currentVisibility_ = true; + node_->startingWindowShown_ = false; + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, windowController_->AddWindowNode(property)); + windowRoot_->windowNodeMap_.clear(); +} +/** + * @tc.name: InputCallingWindow + * @tc.desc: Window controller input calling window + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, InputCallingWindow, Function | SmallTest | Level3) +{ + windowController_->callingWindowId_ = 0; + windowRoot_->windowNodeMap_.clear(); + sptr node = new WindowNode(); + node->property_->callingWindow_ = 0; + node->property_->displayId_ = DISPLAY_ID_INVALID; + windowController_->ResizeSoftInputCallingWindowIfNeed(node); + ASSERT_EQ(0, windowController_->callingWindowId_); + + sptr displayInfo = new DisplayInfo(); + sptr container = new WindowNodeContainer(displayInfo, 0); + windowRoot_->windowNodeContainerMap_.insert(std::make_pair(0, container)); + node->property_->displayId_ = 0; + windowController_->ResizeSoftInputCallingWindowIfNeed(node); + ASSERT_EQ(0, windowController_->callingWindowId_); + + windowRoot_->windowNodeMap_.insert(std::make_pair(node_->GetWindowId(), node_)); + container->focusedWindow_ = node_->GetWindowId(); + node_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + node_->currentVisibility_ = false; + windowController_->ResizeSoftInputCallingWindowIfNeed(node); + ASSERT_EQ(0, windowController_->callingWindowId_); + + node_->currentVisibility_ = true; + node_->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + windowController_->ResizeSoftInputCallingWindowIfNeed(node); + + node_->currentVisibility_ = true; + node_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + windowController_->ResizeSoftInputCallingWindowIfNeed(node); + ASSERT_EQ(0, windowController_->callingWindowId_); + + windowController_->callingWindowId_ = node_->GetWindowId(); + windowController_->callingWindowRestoringRect_ = {0, 0, 0, 0}; + windowController_->RestoreCallingWindowSizeIfNeed(); + ASSERT_EQ(0, windowController_->callingWindowId_); + + windowController_->callingWindowRestoringRect_ = {0, 0, 1, 1}; + windowController_->callingWindowId_ = 0; + windowController_->RestoreCallingWindowSizeIfNeed(); + + windowController_->callingWindowId_ = node_->GetWindowId(); + windowController_->RestoreCallingWindowSizeIfNeed(); + ASSERT_EQ(0, windowController_->callingWindowId_); + + windowController_->callingWindowId_ = node_->GetWindowId(); + node_->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + windowController_->RestoreCallingWindowSizeIfNeed(); + ASSERT_EQ(0, windowController_->callingWindowId_); + + windowRoot_->windowNodeMap_.clear(); + windowRoot_->windowNodeContainerMap_.clear(); +} +/** + * @tc.name: SetDefaultDisplayInfo + * @tc.desc: Window controller set default display info + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, SetDefaultDisplayInfo, Function | SmallTest | Level3) +{ + const int32_t displayWidth = 100; + const int32_t displayHeight = 200; + windowController_->defaultDisplayRect_ = { 0, 0, 0, 0 }; + + sptr displayInfo = nullptr; + windowController_->SetDefaultDisplayInfo(0, displayInfo); + ASSERT_EQ(0, windowController_->defaultDisplayRect_.width_); + ASSERT_EQ(0, windowController_->defaultDisplayRect_.height_); + + displayInfo = new DisplayInfo(); + displayInfo->id_ = 1; + displayInfo->width_ = displayWidth; + displayInfo->height_ = displayHeight; + + windowController_->SetDefaultDisplayInfo(0, displayInfo); + ASSERT_EQ(0, windowController_->defaultDisplayRect_.width_); + ASSERT_EQ(0, windowController_->defaultDisplayRect_.height_); + + displayInfo->id_ = 0; + windowController_->SetDefaultDisplayInfo(0, displayInfo); + ASSERT_EQ(displayWidth, windowController_->defaultDisplayRect_.width_); + ASSERT_EQ(displayHeight, windowController_->defaultDisplayRect_.height_); +} +/** + * @tc.name: ProcessDisplayCompression + * @tc.desc: Window controller process display compression + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, ProcessDisplayCompression, Function | SmallTest | Level3) +{ + ASSERT_NE(nullptr, windowController_); + DisplayId defaultDisplayId = 0; + sptr displayInfo = new DisplayInfo(); + displayInfo->id_ = 1; + windowController_->ProcessDisplayCompression(defaultDisplayId, displayInfo); + ASSERT_EQ(nullptr, windowController_->maskingSurfaceNode_); + + displayInfo->id_ = defaultDisplayId; + displayInfo->waterfallDisplayCompressionStatus_ = false; + windowController_->ProcessDisplayCompression(defaultDisplayId, displayInfo); + ASSERT_EQ(nullptr, windowController_->maskingSurfaceNode_); + + displayInfo->waterfallDisplayCompressionStatus_ = true; + windowController_->ProcessDisplayCompression(defaultDisplayId, displayInfo); + ASSERT_NE(nullptr, windowController_->maskingSurfaceNode_); +} +/** + * @tc.name: StopBootAnimationIfNeed + * @tc.desc: Window controller stop boot animation if need + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, StopBootAnimationIfNeed, Function | SmallTest | Level3) +{ + ASSERT_NE(nullptr, windowController_); + + sptr node = nullptr; + windowController_->isBootAnimationStopped_ = true; + windowController_->StopBootAnimationIfNeed(node); + ASSERT_EQ(true, windowController_->isBootAnimationStopped_); + + windowController_->isBootAnimationStopped_ = false; + windowController_->StopBootAnimationIfNeed(node); + ASSERT_EQ(false, windowController_->isBootAnimationStopped_); + + node = new WindowNode(); + node->SetDisplayId(DISPLAY_ID_INVALID + 1); + windowController_->StopBootAnimationIfNeed(node); + ASSERT_EQ(false, windowController_->isBootAnimationStopped_); + + node->SetDisplayId(DISPLAY_ID_INVALID); + windowController_->StopBootAnimationIfNeed(node); + ASSERT_EQ(false, windowController_->isBootAnimationStopped_); +} +/** + * @tc.name: GetEmbedNodeId + * @tc.desc: Window controller get embed node id + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, GetEmbedNodeId, Function | SmallTest | Level3) +{ + std::vector> windowNodes; + sptr node0 = nullptr; + sptr node1 = new WindowNode(); + node1->property_->windowId_ = 1; + sptr node2 = new WindowNode(); + node2->property_->windowId_ = 2; + sptr node3 = new WindowNode(); + node3->property_->windowId_ = 3; + + node1->property_->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + ASSERT_EQ(0, windowController_->GetEmbedNodeId(windowNodes, node1)); + + node1->property_->SetWindowType(WindowType::WINDOW_TYPE_APP_COMPONENT); + ASSERT_EQ(0, windowController_->GetEmbedNodeId(windowNodes, node1)); + + windowNodes.push_back(node0); + windowNodes.push_back(node2); + windowNodes.push_back(node1); + windowNodes.push_back(node2); + windowNodes.push_back(node3); + + node1->SetWindowRect({50, 50, 50, 50}); + node3->SetWindowRect({0, 0, 200, 200}); + ASSERT_EQ(node3->GetWindowId(), windowController_->GetEmbedNodeId(windowNodes, node1)); +} +/** + * @tc.name: BindDialogTarget + * @tc.desc: Window controller bind dialog target + * @tc.type: FUNC + */ +HWTEST_F(WindowControllerTest, BindDialogTarget, Function | SmallTest | Level3) +{ + windowRoot_->windowNodeMap_.clear(); + + uint32_t id = 0; + sptr abilityTokenMocker = new IRemoteObjectMocker(); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, windowController_->BindDialogTarget(id, abilityTokenMocker)); + + windowRoot_->windowNodeMap_.insert(std::make_pair(node_->GetWindowId(), node_)); + id = node_->GetWindowId(); + ASSERT_EQ(WMError::WM_OK, windowController_->BindDialogTarget(id, abilityTokenMocker)); + windowRoot_->windowNodeMap_.clear(); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_display_zoom_controller_test.cpp b/window_manager/wmserver/test/unittest/window_display_zoom_controller_test.cpp new file mode 100644 index 0000000..f930ade --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_display_zoom_controller_test.cpp @@ -0,0 +1,88 @@ +/* + * 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 "display_zoom_controller.h" +#include "display_manager.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowDisplayZoomControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr windowRoot_; + sptr displayController_; +}; + +void WindowDisplayZoomControllerTest::SetUpTestCase() +{ +} + +void WindowDisplayZoomControllerTest::TearDownTestCase() +{ +} + +void WindowDisplayZoomControllerTest::SetUp() +{ + windowRoot_ = new WindowRoot(nullptr); + displayController_ = new DisplayZoomController(windowRoot_); +} + +void WindowDisplayZoomControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: WindowDisplayZoomControllerTest01 + * @tc.desc: test WindowDisplayZoomController + * @tc.type: FUNC + */ +HWTEST_F(WindowDisplayZoomControllerTest, WindowDisplayZoomControllerTest01, Function | SmallTest | Level2) +{ + DisplayId displayId; + uint32_t windowId; + + // windowNodeContainer is null + displayController_->SetAnchorAndScale(1, 1, 10.0); + displayController_->SetAnchorOffset(1, 1); + displayController_->OffWindowZoom(); + displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + displayController_->UpdateAllWindowsZoomInfo(displayId); + windowId = INVALID_WINDOW_ID; + displayController_->UpdateWindowZoomInfo(windowId); + + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_NE(display, nullptr); + sptr displayInfo = display->GetDisplayInfo(); + ASSERT_NE(displayInfo, nullptr); + auto container = windowRoot_->CreateWindowNodeContainer(displayInfo); + ASSERT_NE(container, nullptr); + + // windowNodeContainer is not null + displayController_->SetAnchorAndScale(1, 1, 10.0); + displayController_->SetAnchorOffset(1, 1); + displayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); + + ASSERT_EQ(true, true); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_dumper_test.cpp b/window_manager/wmserver/test/unittest/window_dumper_test.cpp new file mode 100644 index 0000000..58dabfe --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_dumper_test.cpp @@ -0,0 +1,192 @@ +/* + * 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 "window_dumper.h" +#include "window_manager_service.h" +#include "window_impl.h" +#include "window_agent.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowDumperTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void WindowDumperTest::SetUpTestCase() +{ +} + +void WindowDumperTest::TearDownTestCase() +{ +} + +void WindowDumperTest::SetUp() +{ +} + +void WindowDumperTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Dump01 + * @tc.desc: Dump + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump01, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = 0; + std::vector args; + WMError ret = windowDumper->Dump(fd, args); + ASSERT_EQ(ret, WMError::WM_OK); +} + +/** + * @tc.name: Dump02 + * @tc.desc: Dump fd less 0 + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump02, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = -1; + std::vector args; + WMError ret = windowDumper->Dump(fd, args); + ASSERT_EQ(ret, WMError::WM_ERROR_INVALID_PARAM); +} + +/** + * @tc.name: Dump03 + * @tc.desc: Dump one param with '-h' + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump03, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = 1; + std::vector args; + const std::u16string DUMP_HELP = u"-h"; + args.emplace_back(DUMP_HELP); + WMError ret = windowDumper->Dump(fd, args); + ASSERT_EQ(ret, WMError::WM_OK); +} + +/** + * @tc.name: Dump04 + * @tc.desc: Dump one param with '-x' + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump04, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = 2; + std::vector args; + const std::u16string DUMP_HELP = u"-x"; + args.emplace_back(DUMP_HELP); + WMError ret = windowDumper->Dump(fd, args); + ASSERT_EQ(ret, WMError::WM_OK); +} + +/** + * @tc.name: Dump05 + * @tc.desc: Dump two param with '-a' + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump05, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = 3; + std::vector args; + const std::u16string DUMP_ALL = u"-a"; + args.emplace_back(DUMP_ALL); + WMError ret = windowDumper->Dump(fd, args); + ASSERT_TRUE(ret == WMError::WM_OK || ret == WMError::WM_ERROR_INVALID_OPERATION); +} + +/** + * @tc.name: Dump06 + * @tc.desc: Dump two param with '-w 1' + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump06, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = 4; + std::vector args; + const std::u16string DUMP_WINDOW = u"-w"; + const std::u16string DUMP_WINDOW_ID = u"3"; + args.emplace_back(DUMP_WINDOW); + args.emplace_back(DUMP_WINDOW_ID); + WMError ret = windowDumper->Dump(fd, args); + ASSERT_TRUE(ret == WMError::WM_OK || ret == WMError::WM_ERROR_INVALID_OPERATION); +} + +/** + * @tc.name: Dump07 + * @tc.desc: Dump two param with '-w n' + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, Dump07, Function | SmallTest | Level1) +{ + sptr windowDumper; + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + int fd = 5; + std::vector args; + const std::u16string DUMP_WINDOW = u"-w"; + const std::u16string DUMP_WINDOW_ID = u"n"; + args.emplace_back(DUMP_WINDOW); + args.emplace_back(DUMP_WINDOW_ID); + WMError ret = windowDumper->Dump(fd, args); + ASSERT_EQ(ret, WMError::WM_ERROR_INVALID_OPERATION); +} + +/** + * @tc.name: ShowAceDumpHelp02 + * @tc.desc: ShowAceDumpHelp + * @tc.type: FUNC + */ +HWTEST_F(WindowDumperTest, ShowAceDumpHelp02, Function | SmallTest | Level1) +{ + sptr windowDumper; + sptr node = new WindowNode(); + uint32_t id = 102; + node->property_->SetWindowId(id); + node->property_->SetWindowType(WindowType::WINDOW_TYPE_KEYGUARD); + WindowManagerService::GetInstance().windowRoot_->windowNodeMap_.insert(std::make_pair(id, node)); + windowDumper = new WindowDumper(WindowManagerService::GetInstance().windowRoot_); + std::string dumpInfo; + windowDumper->ShowAceDumpHelp(dumpInfo); + WindowManagerService::GetInstance().windowRoot_->windowNodeMap_.clear(); + ASSERT_TRUE(dumpInfo.empty()); +} +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/test/unittest/window_freeze_controller_test.cpp b/window_manager/wmserver/test/unittest/window_freeze_controller_test.cpp new file mode 100644 index 0000000..06afd88 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_freeze_controller_test.cpp @@ -0,0 +1,87 @@ +/* + * 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 "wm_common.h" +#include "common_test_utils.h" +#include "freeze_controller.h" +#include "display_manager.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowFreezeControllerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr controller_; + + void SetAceessTokenPermission(const std::string processName); +}; + +void WindowFreezeControllerTest::SetUpTestCase() +{ + const char** perms = new const char *[1]; + perms[0] = "ohos.permission.CAPTURE_SCREEN"; + std::string processName = "WindowFreezeControllerTest"; + CommonTestUtils::SetAceessTokenPermission(processName, perms, 1); +} + +void WindowFreezeControllerTest::TearDownTestCase() +{ +} + +void WindowFreezeControllerTest::SetUp() +{ + controller_ = new FreezeController(); +} + +void WindowFreezeControllerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: FreezeDisplay01 + * @tc.desc: test FreezeDisplay/UnFreezeDisplay + * @tc.type: FUNC + */ +HWTEST_F(WindowFreezeControllerTest, FreezeDisplay01, Function | SmallTest | Level2) +{ + DisplayId displayId = DISPLAY_ID_INVALID; + bool res = true; + + res = controller_->UnfreezeDisplay(displayId); + ASSERT_EQ(res, false); + res = controller_->FreezeDisplay(displayId); + ASSERT_EQ(res, false); + res = controller_->FreezeDisplay(displayId); + ASSERT_EQ(res, false); + res = controller_->UnfreezeDisplay(displayId); + ASSERT_EQ(res, true); + + displayId = DisplayManager::GetInstance().GetDefaultDisplayId(); + + res = controller_->FreezeDisplay(displayId); + ASSERT_EQ(res, false); + res = controller_->UnfreezeDisplay(displayId); + ASSERT_EQ(res, true); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_inner_manager_test.cpp b/window_manager/wmserver/test/unittest/window_inner_manager_test.cpp new file mode 100644 index 0000000..da4cdeb --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_inner_manager_test.cpp @@ -0,0 +1,175 @@ +/* + * 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 "event_runner.h" +#include "pointer_event.h" +#include "window_inner_manager.h" +#include "wm_common.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +using InnerTask = std::function; +using EventRunner = OHOS::AppExecFwk::EventRunner; +using EventHandler = OHOS::AppExecFwk::EventHandler; +using EventPriority = OHOS::AppExecFwk::EventQueue::Priority; + +namespace { + const std::string INNER_WM_THREAD_NAME = "TestInnerWindowManager"; +} + +class WindowInnerManagerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void WindowInnerManagerTest::SetUpTestCase() +{ +} + +void WindowInnerManagerTest::TearDownTestCase() +{ +} + +void WindowInnerManagerTest::SetUp() +{ +} + +void WindowInnerManagerTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: Stop + * @tc.desc: test WindowInnerManager Stop + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerManagerTest, Stop, Function | SmallTest | Level2) +{ + WindowInnerManager& windowInnerManager = WindowInnerManager::GetInstance(); + windowInnerManager.state_ = InnerWMRunningState::STATE_RUNNING; + windowInnerManager.eventLoop_ = nullptr; + windowInnerManager.eventHandler_ = nullptr; + windowInnerManager.moveDragController_ = nullptr; + windowInnerManager.Stop(); + ASSERT_EQ(InnerWMRunningState::STATE_NOT_START, windowInnerManager.state_); + + windowInnerManager.eventLoop_ = AppExecFwk::EventRunner::Create(INNER_WM_THREAD_NAME); + windowInnerManager.eventHandler_ = std::make_shared(windowInnerManager.eventLoop_); + windowInnerManager.moveDragController_ = new MoveDragController(); + windowInnerManager.Stop(); + ASSERT_EQ(0, windowInnerManager.eventLoop_.use_count()); + ASSERT_EQ(0, windowInnerManager.eventHandler_.use_count()); +} + +/** + * @tc.name: NotifyServerReadyToMoveOrDrag + * @tc.desc: test WindowInnerManager NotifyServerReadyToMoveOrDrag + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerManagerTest, NotifyServerReadyToMoveOrDrag, Function | SmallTest | Level2) +{ + WindowInnerManager& windowInnerManager = WindowInnerManager::GetInstance(); + windowInnerManager.eventHandler_ = nullptr; + windowInnerManager.moveDragController_ = new MoveDragController(); + windowInnerManager.moveDragController_->activeWindowId_ = 1; + uint32_t windowId = 1; + sptr property = new WindowProperty(); + ASSERT_NE(property, nullptr); + sptr moveDragProperty = new MoveDragProperty(); + ASSERT_NE(moveDragProperty, nullptr); + auto result = windowInnerManager.NotifyServerReadyToMoveOrDrag(windowId, property, moveDragProperty); + ASSERT_EQ(false, result); + + windowInnerManager.moveDragController_->activeWindowId_ = INVALID_WINDOW_ID; + result = windowInnerManager.NotifyServerReadyToMoveOrDrag(windowId, property, moveDragProperty); + ASSERT_EQ(true, result); +} + +/** + * @tc.name: NotifyWindowEndUpMovingOrDragging + * @tc.desc: test WindowInnerManager NotifyWindowEndUpMovingOrDragging + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerManagerTest, NotifyWindowEndUpMovingOrDragging, Function | SmallTest | Level2) +{ + WindowInnerManager& windowInnerManager = WindowInnerManager::GetInstance(); + windowInnerManager.eventHandler_ = nullptr; + windowInnerManager.moveDragController_ = new MoveDragController(); + windowInnerManager.moveDragController_->activeWindowId_ = INVALID_WINDOW_ID; + uint32_t windowId = 1; + + windowInnerManager.NotifyWindowEndUpMovingOrDragging(windowId); + + windowId = INVALID_WINDOW_ID; + windowInnerManager.NotifyWindowEndUpMovingOrDragging(windowId); +} +/** + * @tc.name: NotifyWindowRemovedOrDestroyed + * @tc.desc: test WindowInnerManager NotifyWindowRemovedOrDestroyed + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerManagerTest, NotifyWindowRemovedOrDestroyed, Function | SmallTest | Level2) +{ + WindowInnerManager& windowInnerManager = WindowInnerManager::GetInstance(); + windowInnerManager.eventHandler_ = nullptr; + windowInnerManager.moveDragController_ = new MoveDragController(); + windowInnerManager.moveDragController_->activeWindowId_ = INVALID_WINDOW_ID; + + uint32_t windowId = 1; + windowInnerManager.NotifyWindowRemovedOrDestroyed(windowId); + + windowId = INVALID_WINDOW_ID; + windowInnerManager.NotifyWindowRemovedOrDestroyed(windowId); +} +/** + * @tc.name: ConsumePointerEvent + * @tc.desc: test WindowInnerManager ConsumePointerEvent + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerManagerTest, ConsumePointerEvent, Function | SmallTest | Level2) +{ + WindowInnerManager& windowInnerManager = WindowInnerManager::GetInstance(); + windowInnerManager.eventHandler_ = nullptr; + windowInnerManager.moveDragController_ = new MoveDragController(); + + auto pointerEvent = MMI::PointerEvent::Create(); + pointerEvent->processedCallback_ = nullptr; + pointerEvent->sourceType_ = MMI::PointerEvent::SOURCE_TYPE_MOUSE; + pointerEvent->buttonId_ = MMI::PointerEvent::MOUSE_BUTTON_RIGHT; + pointerEvent->pointerAction_ = MMI::PointerEvent::POINTER_ACTION_UNKNOWN; + + pointerEvent->agentWindowId_ = 1; + windowInnerManager.moveDragController_->activeWindowId_ = INVALID_WINDOW_ID; + windowInnerManager.ConsumePointerEvent(pointerEvent); + + pointerEvent->agentWindowId_ = 1; + windowInnerManager.moveDragController_->activeWindowId_ = 1; + windowInnerManager.ConsumePointerEvent(pointerEvent); + + pointerEvent->agentWindowId_ = INVALID_WINDOW_ID; + windowInnerManager.moveDragController_->activeWindowId_ = INVALID_WINDOW_ID; + windowInnerManager.ConsumePointerEvent(pointerEvent); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_inner_window_test.cpp b/window_manager/wmserver/test/unittest/window_inner_window_test.cpp new file mode 100644 index 0000000..aaa266c --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_inner_window_test.cpp @@ -0,0 +1,116 @@ +/* + * 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 "inner_window.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowInnerWindowTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr holderWindow_; + sptr windowListener_; + std::shared_ptr inputEventConsumer_; +}; + +void WindowInnerWindowTest::SetUpTestCase() +{ +} + +void WindowInnerWindowTest::TearDownTestCase() +{ +} + +void WindowInnerWindowTest::SetUp() +{ + holderWindow_ = new PlaceHolderWindow(); + windowListener_ = new PlaceholderWindowListener(); + inputEventConsumer_ = std::make_shared (); +} + +void WindowInnerWindowTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: PlaceHolderWindow01 + * @tc.desc: test PlaceHolderWindow create/destroy + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerWindowTest, CreatePlaceHolderWindow01, Function | SmallTest | Level2) +{ + Rect rect = { 100, 100, 200, 200 }; + holderWindow_->Create("test01", 0, rect, WindowMode::WINDOW_MODE_FULLSCREEN); + holderWindow_->Destroy(); + + rect = { 100, 100, 200, 200 }; + holderWindow_->Create("test02", 0, rect, WindowMode::WINDOW_MODE_FULLSCREEN); + holderWindow_->Create("test02", 0, rect, WindowMode::WINDOW_MODE_FULLSCREEN); + holderWindow_->Destroy(); + + rect = { 100, 100, 200, 200 }; + holderWindow_->Create("", 0, rect, WindowMode::WINDOW_MODE_FULLSCREEN); + holderWindow_->Destroy(); + + rect = { 0, 0, 0, 0 }; + holderWindow_->Create("test03", 0, rect, WindowMode::WINDOW_MODE_FULLSCREEN); + holderWindow_->Destroy(); + + holderWindow_->Destroy(); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: PlaceholderWindowListener01 + * @tc.desc: test PlaceholderWindowListener OnTouchOutside/AfterUnfocused + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerWindowTest, PlaceholderWindowListener01, Function | SmallTest | Level2) +{ + windowListener_->OnTouchOutside(); + windowListener_->AfterUnfocused(); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: PlaceholderInputEventConsumer01 + * @tc.desc: test PlaceholderInputEventConsumer OnInputEvent + * @tc.type: FUNC + */ +HWTEST_F(WindowInnerWindowTest, PlaceholderInputEventConsumer01, Function | SmallTest | Level2) +{ + std::shared_ptr keyEvent = nullptr; + std::shared_ptr pointerEvent = nullptr; + std::shared_ptr axisEvent = nullptr; + + inputEventConsumer_->OnInputEvent(keyEvent); + inputEventConsumer_->OnInputEvent(pointerEvent); + inputEventConsumer_->OnInputEvent(axisEvent); + + ASSERT_EQ(true, true); +} + +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_layout_policy_test.cpp b/window_manager/wmserver/test/unittest/window_layout_policy_test.cpp new file mode 100644 index 0000000..4bb6e6f --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_layout_policy_test.cpp @@ -0,0 +1,1381 @@ +/* + * 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 "display_group_controller.h" +#include "display_group_info.h" +#include "display_manager.h" +#include "remote_animation.h" +#include "window_helper.h" +#include "window_layout_policy.h" +#include "window_layout_policy_cascade.h" +#include "window_node_container.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { + +struct WindowInfo { + Rect winRect_; + WindowType winType_; + WindowMode winMode_; + WindowSizeChangeReason reason_; + DragType dragType_; + bool decorEnable_; +}; + +class WindowLayoutPolicyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + sptr CreateWindowNode(const WindowInfo& windowInfo); + sptr CreateDisplayInfo(const Rect& displayRect); + + static WindowInfo windowInfo_; + static sptr container_; + static sptr displayGroupInfo_; + static sptr defaultDisplayInfo_; + static sptr displayGroupController_; + static sptr layoutPolicy_; +}; + +sptr WindowLayoutPolicyTest::container_ = nullptr; +sptr WindowLayoutPolicyTest::displayGroupInfo_ = nullptr; +sptr WindowLayoutPolicyTest::displayGroupController_ = nullptr; +sptr WindowLayoutPolicyTest::layoutPolicy_ = nullptr; +sptr WindowLayoutPolicyTest::defaultDisplayInfo_ = nullptr; +WindowInfo WindowLayoutPolicyTest::windowInfo_ = { + .winRect_ = { 0, 0, 0, 0 }, + .winType_ = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .winMode_ = WindowMode::WINDOW_MODE_FLOATING, + .reason_ = WindowSizeChangeReason::UNDEFINED, + .dragType_ = DragType::DRAG_UNDEFINED, + .decorEnable_ = false, +}; + +void WindowLayoutPolicyTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_TRUE((display != nullptr)); + + defaultDisplayInfo_ = display->GetDisplayInfo(); + ASSERT_TRUE((defaultDisplayInfo_ != nullptr)); + + windowInfo_ = { + .winRect_ = { 0, 0, 0, 0 }, + .winType_ = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .winMode_ = WindowMode::WINDOW_MODE_FLOATING, + .reason_ = WindowSizeChangeReason::UNDEFINED, + .dragType_ = DragType::DRAG_UNDEFINED, + .decorEnable_ = false, + }; + + container_ = new WindowNodeContainer(defaultDisplayInfo_, display->GetScreenId()); + displayGroupInfo_ = container_->displayGroupInfo_; + displayGroupController_ = container_->displayGroupController_; + layoutPolicy_ = container_->GetLayoutPolicy(); +} + +void WindowLayoutPolicyTest::TearDownTestCase() +{ + container_ = nullptr; + displayGroupInfo_ = nullptr; + defaultDisplayInfo_ = nullptr; + displayGroupController_ = nullptr; + layoutPolicy_ = nullptr; +} + +void WindowLayoutPolicyTest::SetUp() +{ + displayGroupInfo_->AddDisplayInfo(defaultDisplayInfo_); +} + +void WindowLayoutPolicyTest::TearDown() +{ + displayGroupInfo_->displayInfosMap_.clear(); +} + +sptr WindowLayoutPolicyTest::CreateWindowNode(const WindowInfo& windowInfo) +{ + sptr property = new WindowProperty(); + property->SetWindowType(windowInfo.winType_); + property->SetWindowMode(windowInfo.winMode_); + property->SetWindowRect(windowInfo.winRect_); + property->SetOriginRect(windowInfo.winRect_); + property->SetDecorEnable(windowInfo.decorEnable_); + sptr node = new WindowNode(property, nullptr, nullptr); + node->SetWindowSizeChangeReason(windowInfo.reason_); + node->SetDragType(windowInfo.dragType_); + return node; +} + +sptr WindowLayoutPolicyTest::CreateDisplayInfo(const Rect& displayRect) +{ + sptr displayInfo = new DisplayInfo(); + displayInfo->SetOffsetX(displayRect.posX_); + displayInfo->SetOffsetY(displayRect.posY_); + displayInfo->SetWidth(displayRect.width_); + displayInfo->SetHeight(displayRect.height_); + displayInfo->SetDisplayId((defaultDisplayInfo_->GetDisplayId() + 1)); + return displayInfo; +} +namespace { +/** + * @tc.name: CalcEntireWindowHotZone + * @tc.desc: calc entire window hot zone + * @tc.type: FUNC + * @tc.require issueI5LYDC + */ +HWTEST_F(WindowLayoutPolicyTest, CalcEntireWindowHotZone, Function | SmallTest | Level2) +{ + TransformHelper::Vector2 hotZoneScale = {1.f, 1.f}; // ratio 1.0 + sptr property = new WindowProperty(); + + property->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + property->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + sptr node0 = new WindowNode(property, nullptr, nullptr); + Rect winRect = { 50, 100, 400, 500 }; // rect: 50, 100, 400, 500 + auto actRect0 = layoutPolicy_->CalcEntireWindowHotZone(node0, winRect, 10, 2.f, hotZoneScale); // param: 10, 2.0 + Rect expRect0 = { 30, 80, 440, 540 }; // rect: 30, 80, 440, 540 + ASSERT_EQ(expRect0, actRect0); + + property->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + sptr node1 = new WindowNode(property, nullptr, nullptr); + auto actRect1 = layoutPolicy_->CalcEntireWindowHotZone(node1, winRect, 10, 2.f, hotZoneScale); // param: 10, 2.0 + Rect expRect1 = { 30, 100, 440, 500 }; // rect: 30, 100, 440, 500 + ASSERT_EQ(expRect1, actRect1); + + property->SetWindowType(WindowType::WINDOW_TYPE_LAUNCHER_RECENT); + sptr node2 = new WindowNode(property, nullptr, nullptr); + auto actRect2 = layoutPolicy_->CalcEntireWindowHotZone(node2, winRect, 10, 2.f, hotZoneScale); // param: 10, 2.0 + Rect expRect2 = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId());; + ASSERT_EQ(expRect2, actRect2); +} + +/** + * @tc.name: UpdateFloatingWindowSizeForStretchableWindow01 + * @tc.desc: UpdateFloatingWindowSizeForStretchableWindow test for drag width + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow01, Function | SmallTest | Level2) +{ + windowInfo_.winRect_ = { 50, 50, 100, 150 }; // rect: 50, 50, 100, 150 + windowInfo_.dragType_ = DragType::DRAG_LEFT_OR_RIGHT; + windowInfo_.reason_ = WindowSizeChangeReason::DRAG; + sptr node = CreateWindowNode(windowInfo_); + Rect newWinRect = { 50, 50, 200, 200 }; // rect: 50, 50, 200, 200 + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, { 0, 0, 0, 0 }, newWinRect); + Rect expRect = { 50, 50, 200, 300 }; // rect: 50, 50, 200, 300 + ASSERT_EQ(expRect, newWinRect); +} + +/** + * @tc.name: UpdateFloatingWindowSizeForStretchableWindow02 + * @tc.desc: UpdateFloatingWindowSizeForStretchableWindow test for drag coner + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow02, Function | SmallTest | Level2) +{ + windowInfo_.winRect_ = { 50, 50, 100, 150 }; // rect: 50, 50, 100, 150 + windowInfo_.dragType_ = DragType::DRAG_LEFT_TOP_CORNER; + windowInfo_.reason_ = WindowSizeChangeReason::DRAG; + sptr node = CreateWindowNode(windowInfo_); + Rect newWinRect = { 50, 50, 200, 200 }; // rect: 50, 50, 200, 200 + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, { 0, 0, 0, 0 }, newWinRect); + Rect expRect = { 50, 50, 200, 300 }; // rect: 50, 50, 200, 300 + ASSERT_EQ(expRect, newWinRect); +} + +/** + * @tc.name: UpdateFloatingWindowSizeForStretchableWindow03 + * @tc.desc: UpdateFloatingWindowSizeForStretchableWindow test for drag height + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow03, Function | SmallTest | Level2) +{ + windowInfo_.winRect_ = { 50, 50, 100, 150 }; // rect: 50, 50, 100, 150 + windowInfo_.dragType_ = DragType::DRAG_BOTTOM_OR_TOP; + windowInfo_.reason_ = WindowSizeChangeReason::DRAG; + sptr node = CreateWindowNode(windowInfo_); + Rect newWinRect = { 50, 50, 150, 300 }; // rect: 50, 50, 150, 300 + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, { 0, 0, 0, 0 }, newWinRect); + Rect expRect = { 50, 50, 200, 300 }; // rect: 50, 50, 200, 300 + ASSERT_EQ(expRect, newWinRect); +} + +/** + * @tc.name: LimitWindowToBottomRightCorner + * @tc.desc: test LimitWindowToBottomRightCorner01 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitWindowToBottomRightCorner01, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + windowInfo_.winRect_ = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_ * 0.5), // ratio: 0.5 + .posY_ = displayRect.posY_, + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->LimitWindowToBottomRightCorner(node); + + Rect winRect = { + .posX_ = displayRect.posX_, + .posY_ = displayRect.posY_, + .width_ = static_cast(displayRect.width_ * 0.5), // ratio: 0.5 + .height_ = static_cast(displayRect.height_ * 0.5) // ratio: 0.5 + }; + node ->SetRequestRect(winRect); + layoutPolicy_->LimitWindowToBottomRightCorner(node); +} + +/** + * @tc.name: LimitWindowToBottomRightCorner + * @tc.desc: test LimitWindowToBottomRightCorner02 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitWindowToBottomRightCorner02, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + windowInfo_.winRect_ = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_ * 0.5), // ratio: 0.5 + .posY_ = static_cast(displayRect.posY_ + displayRect.height_ * 0.5), // ratio: 0.5 + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->LimitWindowToBottomRightCorner(node); + + Rect winRect = { + .posX_ = displayRect.posX_, + .posY_ = static_cast(displayRect.posY_ + displayRect.height_ * 0.5), // ratio: 0.5 + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + node ->SetRequestRect(winRect); + layoutPolicy_->LimitWindowToBottomRightCorner(node); + ASSERT_TRUE(node != nullptr); +} + +/** + * @tc.name: LimitWindowToBottomRightCorner + * @tc.desc: test LimitWindowToBottomRightCorner03, test childNode + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitWindowToBottomRightCorner03, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + windowInfo_.winRect_ = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_ * 0.5), // ratio: 0.5 + .posY_ = static_cast(displayRect.posY_ + displayRect.height_ * 0.5), // ratio: 0.5 + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + sptr parentNode = CreateWindowNode(windowInfo_); + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(parentNode != nullptr); + ASSERT_TRUE(node != nullptr); + parentNode->children_.push_back(node); + layoutPolicy_->LimitWindowToBottomRightCorner(node); +} + +/** + * @tc.name: UpdateDisplayGroupRect + * @tc.desc: test UpdateDisplayGroupRect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateDisplayGroupRect, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + auto displayInfo = CreateDisplayInfo(newDisplayRect); + ASSERT_TRUE(displayInfo != nullptr); + displayGroupInfo_->AddDisplayInfo(displayInfo); + layoutPolicy_->UpdateDisplayGroupRect(); + + displayGroupInfo_->displayInfosMap_.clear(); + layoutPolicy_->UpdateDisplayGroupRect(); +} + +/** + * @tc.name: UpdateDisplayGroupLimitRect + * @tc.desc: test UpdateDisplayGroupLimitRect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateDisplayGroupLimitRect, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + auto displayInfo = CreateDisplayInfo(newDisplayRect); + ASSERT_TRUE(displayInfo != nullptr); + displayGroupInfo_->AddDisplayInfo(displayInfo); + auto allDisplayRect = displayGroupInfo_->GetAllDisplayRects(); + layoutPolicy_->limitRectMap_ = allDisplayRect; + layoutPolicy_->UpdateDisplayGroupLimitRect(); + + layoutPolicy_->limitRectMap_.clear(); + layoutPolicy_->UpdateDisplayGroupLimitRect(); +} + +/** + * @tc.name: UpdateRectInDisplayGroup + * @tc.desc: test UpdateRectInDisplayGroup, test childNode + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateRectInDisplayGroup, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + windowInfo_.winRect_ = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_ * 0.5), // ratio: 0.5 + .posY_ = static_cast(displayRect.posY_ + displayRect.height_ * 0.5), // ratio: 0.5 + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + sptr parentNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(parentNode != nullptr); + + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + layoutPolicy_->UpdateRectInDisplayGroup(parentNode, displayRect, newDisplayRect); + + // create child node + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + parentNode->children_.push_back(node); + layoutPolicy_->UpdateRectInDisplayGroup(parentNode, displayRect, newDisplayRect); +} + +/** + * @tc.name: UpdateMultiDisplayFlag + * @tc.desc: test UpdateMultiDisplayFlag + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateMultiDisplayFlag, Function | SmallTest | Level2) +{ + layoutPolicy_->UpdateMultiDisplayFlag(); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + auto displayInfo = CreateDisplayInfo(newDisplayRect); + ASSERT_TRUE(displayInfo != nullptr); + displayGroupInfo_->AddDisplayInfo(displayInfo); + layoutPolicy_->UpdateMultiDisplayFlag(); +} + +/** + * @tc.name: UpdateRectInDisplayGroupForAllNodes01 + * @tc.desc: test UpdateRectInDisplayGroupForAllNodes01 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateRectInDisplayGroupForAllNodes01, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + + layoutPolicy_->UpdateRectInDisplayGroupForAllNodes(0, displayRect, newDisplayRect); + + windowInfo_.winRect_ = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_ * 0.5), // ratio: 0.5 + .posY_ = static_cast(displayRect.posY_ + displayRect.height_ * 0.5), // ratio: 0.5 + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + + // Add node on display window tree + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::APP_WINDOW_NODE]->push_back(node); + layoutPolicy_->UpdateRectInDisplayGroupForAllNodes(0, displayRect, newDisplayRect); + + node->isShowingOnMultiDisplays_ = true; + layoutPolicy_->UpdateRectInDisplayGroupForAllNodes(0, displayRect, newDisplayRect); +} + +/** + * @tc.name: UpdateRectInDisplayGroupForAllNodes02 + * @tc.desc: test UpdateRectInDisplayGroupForAllNodes + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateRectInDisplayGroupForAllNodes02, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + + windowInfo_.winRect_ = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_ * 0.5), // ratio: 0.5 + .posY_ = static_cast(displayRect.posY_ + displayRect.height_ * 0.5), // ratio: 0.5 + .width_ = displayRect.width_, + .height_ = displayRect.height_ + }; + + // Add app node on display window tree + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + node->isShowingOnMultiDisplays_ = true; + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::APP_WINDOW_NODE]->push_back(node); + layoutPolicy_->UpdateRectInDisplayGroupForAllNodes(0, displayRect, newDisplayRect); + + // Add above node on display window tree + windowInfo_.winType_ = WindowType::WINDOW_TYPE_FLOAT_CAMERA; + sptr aboveNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(aboveNode != nullptr); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(aboveNode); + layoutPolicy_->UpdateRectInDisplayGroupForAllNodes(0, displayRect, newDisplayRect); +} + +/** + * @tc.name: UpdateDisplayRectAndDisplayGroupInfo + * @tc.desc: test UpdateDisplayRectAndDisplayGroupInfo + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateDisplayRectAndDisplayGroupInfo, Function | SmallTest | Level2) +{ + std::map displayRectMap = {}; + layoutPolicy_->UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); + displayRectMap = displayGroupInfo_->GetAllDisplayRects(); + layoutPolicy_->UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); +} + +/** + * @tc.name: ProcessDisplayCreate + * @tc.desc: test ProcessDisplayCreate + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, ProcessDisplayCreate, Function | SmallTest | Level2) +{ + std::map newDisplayRectMap = {}; + layoutPolicy_->ProcessDisplayCreate(0, newDisplayRectMap); + + layoutPolicy_->ProcessDisplayCreate(1, newDisplayRectMap); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + newDisplayRectMap.insert(std::make_pair(0, displayRect)); + Rect newDisplayRect = { + .posX_ = static_cast(displayRect.posX_ + displayRect.width_), + .posY_ = displayRect.posY_, + .width_ = 1920, // width: 1920 + .height_ = 1280 // height: 1080 + }; + newDisplayRectMap.insert(std::make_pair(1, newDisplayRect)); + layoutPolicy_->ProcessDisplayCreate(1, newDisplayRectMap); + + auto displayInfo = CreateDisplayInfo(newDisplayRect); + ASSERT_TRUE(displayInfo != nullptr); +} + +/** + * @tc.name: ProcessDisplayDestroy + * @tc.desc: test ProcessDisplayDestroy + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, ProcessDisplayDestroy, Function | SmallTest | Level2) +{ + std::map newDisplayRectMap = {}; + layoutPolicy_->ProcessDisplayDestroy(0, newDisplayRectMap); + + layoutPolicy_->ProcessDisplayDestroy(1, newDisplayRectMap); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); +} + +/** + * @tc.name: ProcessDisplaySizeChangeOrRotation + * @tc.desc: test ProcessDisplaySizeChangeOrRotation + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, ProcessDisplaySizeChangeOrRotation, Function | SmallTest | Level2) +{ + std::map newDisplayRectMap = {}; + layoutPolicy_->ProcessDisplayDestroy(0, newDisplayRectMap); + + layoutPolicy_->ProcessDisplayDestroy(1, newDisplayRectMap); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); +} + +/** + * @tc.name: NotifyAnimationSizeChangeIfNeeded + * @tc.desc: test NotifyAnimationSizeChangeIfNeeded + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, NotifyAnimationSizeChangeIfNeeded, Function | SmallTest | Level2) +{ + layoutPolicy_->NotifyAnimationSizeChangeIfNeeded(); +} + +/** + * @tc.name: LayoutWindowNode + * @tc.desc: test LayoutWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LayoutWindowNode, Function | SmallTest | Level2) +{ + sptr node = nullptr; + layoutPolicy_->LayoutWindowNode(node); + + node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->LayoutWindowNode(node); + + node->parent_ = container_->appWindowNode_; + layoutPolicy_->LayoutWindowNode(node); + + node->currentVisibility_ = true; + layoutPolicy_->LayoutWindowNode(node); + + node->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR); + layoutPolicy_->LayoutWindowNode(node); + + // create child node + sptr child = CreateWindowNode(windowInfo_); + ASSERT_TRUE(child != nullptr); + node->children_.push_back(child); + layoutPolicy_->LayoutWindowNode(node); +} + +/** + * @tc.name: UpdateClientRect + * @tc.desc: test UpdateClientRect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateClientRect, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->UpdateClientRect(node->GetWindowRect(), node, WindowSizeChangeReason::MOVE); +} + +/** + * @tc.name: UpdateClientRectAndResetReason + * @tc.desc: test UpdateClientRectAndResetReason + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateClientRectAndResetReason, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->UpdateClientRectAndResetReason(node, node->GetWindowRect()); +} + +/** + * @tc.name: RemoveWindowNode + * @tc.desc: test RemoveWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, RemoveWindowNode, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->RemoveWindowNode(node); + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_NAVIGATION_BAR; + sptr avoidNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(avoidNode != nullptr); + layoutPolicy_->RemoveWindowNode(avoidNode); + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_DOCK_SLICE; + sptr dividerNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(dividerNode != nullptr); + layoutPolicy_->RemoveWindowNode(dividerNode); +} + +/** + * @tc.name: UpdateWindowNode + * @tc.desc: test UpdateWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateWindowNode, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + windowInfo_.winRect_ = { 0, static_cast(displayRect.height_ * 0.9), // ratio: 0.9 + displayRect.width_, static_cast(displayRect.height_ * 0.1) }; // ratio: 0.1 + windowInfo_.winType_ = WindowType::WINDOW_TYPE_NAVIGATION_BAR; + sptr avoidNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(avoidNode != nullptr); + layoutPolicy_->UpdateWindowNode(avoidNode); +} + +/** + * @tc.name: ComputeDecoratedRequestRect + * @tc.desc: test ComputeDecoratedRequestRect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, ComputeDecoratedRequestRect, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->ComputeDecoratedRequestRect(node); + + sptr node1 = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node1 != nullptr); + windowInfo_.reason_ = WindowSizeChangeReason::MOVE; + layoutPolicy_->ComputeDecoratedRequestRect(node1); + + windowInfo_.decorEnable_ = true; + sptr node2 = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node2 != nullptr); + layoutPolicy_->ComputeDecoratedRequestRect(node2); +} + +/** + * @tc.name: CalcAndSetNodeHotZone + * @tc.desc: test CalcAndSetNodeHotZone + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, CalcAndSetNodeHotZone, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + layoutPolicy_->CalcAndSetNodeHotZone(node->GetWindowRect(), node); + + layoutPolicy_->UpdateLayoutRect(node); + layoutPolicy_->CalcAndSetNodeHotZone(node->GetWindowRect(), node); + + layoutPolicy_->CalcAndSetNodeHotZone(node->GetWindowRect(), node); +} + +/** + * @tc.name: FixWindowSizeByRatioIfDragBeyondLimitRegion01 + * @tc.desc: test FixWindowSizeByRatioIfDragBeyondLimitRegion01 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, FixWindowSizeByRatioIfDragBeyondLimitRegion01, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 400, 400, 400, 400, 2.0, 2.0 }; // sizeLimits: 400, 400, 400, 400, 2.0, 2.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + Rect finalRect; + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + sizeLimits.maxWidth_ = 800; // maxWidth: 800 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + sizeLimits.maxWidth_ = 400; // maxWidth: 400 + sizeLimits.maxHeight_ = 800; // maxHeight: 800 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + sizeLimits.maxWidth_ = 800; // maxWidth: 800 + sizeLimits.maxHeight_ = 800; // maxHeight: 800 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + sizeLimits.maxWidth_ = 800; // maxWidth: 800 + sizeLimits.maxHeight_ = 800; // maxHeight: 800 + node->SetWindowUpdatedSizeLimits(sizeLimits); + + auto newRect = node->GetWindowRect(); + newRect.height_ = 400; // maxHeight: 400 + node->SetWindowRect(newRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + newRect = { 200, 200, 500, 200 }; // rect: 200, 200, 500, 200 + node->SetWindowRect(newRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + newRect = { 200, 200, 100, 200 }; // rect: 200, 200, 100, 200 + node->SetWindowRect(newRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); +} + +/** + * @tc.name: FixWindowSizeByRatioIfDragBeyondLimitRegion02 + * @tc.desc: test FixWindowSizeByRatioIfDragBeyondLimitRegion02 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, FixWindowSizeByRatioIfDragBeyondLimitRegion02, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + + Rect newRect = { 200, 200, 300, 200 }; // rect: 200, 200, 300, 200 + Rect finalRect; + node->SetWindowRect(newRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + sizeLimits.minRatio_ = 1.0; // ratio: 1.0 + sizeLimits.maxRatio_ = 1.0; // ratio: 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + sizeLimits.minRatio_ = 2.0; // ratio: 2.0 + sizeLimits.maxRatio_ = 2.0; // ratio: 2.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + newRect = { 200, 200, 400, 200 }; // rect: 200, 200, 400, 200 + node->SetWindowRect(newRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + layoutPolicy_->limitRectMap_[0] = displayRect; +} + +/** + * @tc.name: FixWindowSizeByRatioIfDragBeyondLimitRegion03 + * @tc.desc: test FixWindowSizeByRatioIfDragBeyondLimitRegion03 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, FixWindowSizeByRatioIfDragBeyondLimitRegion03, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + + node->SetWindowUpdatedSizeLimits(sizeLimits); + + Rect newRect = { 200, 200, 300, 200 }; // rect: 200, 200, 300, 200 + node->SetWindowRect(newRect); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + layoutPolicy_->limitRectMap_[0] = displayRect; + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + sptr dockNode = CreateWindowNode(windowInfo_); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(dockNode); + + Rect dockWinRect = { 200, 200, 50, 20 }; // rect: 200, 200, 50, 20 + Rect finalRect; + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + dockWinRect = { 200, 200, 50, (displayRect.height_ - static_cast(200)) }; // param: 200, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + dockWinRect = { 200, 200, 20, 50 }; // param: 200, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + dockWinRect = { 0, 200, 20, 50 }; // param: 0, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + dockWinRect = { 200, 200, (displayRect.width_ - static_cast(200)), 50 }; // param: 200, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + dockWinRect = { 200, 200, (displayRect.width_ - static_cast(100)), 50 }; // param: 200, 100, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); +} + +/** + * @tc.name: FixWindowSizeByRatioIfDragBeyondLimitRegion04 + * @tc.desc: test FixWindowSizeByRatioIfDragBeyondLimitRegion04 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, FixWindowSizeByRatioIfDragBeyondLimitRegion04, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + + Rect newRect = { 200, 200, 300, 200 }; // rect: 200, 200, 300, 200 + node->SetWindowRect(newRect); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + layoutPolicy_->limitRectMap_[0] = displayRect; + windowInfo_.winType_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + sptr dockNode = CreateWindowNode(windowInfo_); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(dockNode); + + Rect dockWinRect = { 200, (displayRect.height_ * 0.9), // param: 200, 0.9, + 50, ((displayRect.height_ * 0.1)) }; // param: 50, 0.1 + dockNode->SetWindowRect(dockWinRect); + Rect finalRect; + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + float virtualPixelRatio = layoutPolicy_->GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + int32_t limitMaxPosX = displayRect.posX_ + static_cast(displayRect.width_ - windowTitleBarH); + + newRect = { limitMaxPosX, 200, 300, 200 }; // param: 200, 300 + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + newRect = { limitMaxPosX, 200, 200, 200 }; // param: 200 + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); +} + +/** + * @tc.name: FixWindowSizeByRatioIfDragBeyondLimitRegion05 + * @tc.desc: test FixWindowSizeByRatioIfDragBeyondLimitRegion05 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, FixWindowSizeByRatioIfDragBeyondLimitRegion05, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + + Rect newRect = { 200, 200, 300, 200 }; // rect: 200, 200, 300, 200 + node->SetWindowRect(newRect); + + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + layoutPolicy_->limitRectMap_[0] = displayRect; + windowInfo_.winType_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + sptr dockNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(dockNode != nullptr); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(dockNode); + + Rect dockWinRect = { + 0, + static_cast(displayRect.height_ * 0.9), // ratio: 0.9 + static_cast(displayRect.height_ * 0.1), // ratio: 0.1 + static_cast(displayRect.height_ * 0.1) // ratio: 0.1 + }; + dockNode->SetWindowRect(dockWinRect); + Rect finalRect; + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + float virtualPixelRatio = layoutPolicy_->GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + int32_t limitMinPosX = displayRect.posX_ + static_cast(windowTitleBarH); + + newRect = { limitMinPosX, 200, 300, 200 }; // rect: 200, 300, 200 + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); + + newRect = { limitMinPosX, 200, 200, 200 }; // rect: 200, 200, 200 + layoutPolicy_->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, finalRect); +} + +/** + * @tc.name: GetSystemSizeLimits + * @tc.desc: test GetSystemSizeLimits + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, GetSystemSizeLimits, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node1 = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node1 != nullptr); + static_cast(layoutPolicy_->GetSystemSizeLimits(node1, displayRect, 1.0)); // ratio: 1.0 + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_FLOAT_CAMERA; + sptr node2 = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node2 != nullptr); + static_cast(layoutPolicy_->GetSystemSizeLimits(node2, displayRect, 1.0)); // ratio: 1.0 +} + +/** + * @tc.name: UpdateWindowSizeLimits + * @tc.desc: test UpdateWindowSizeLimits + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateWindowSizeLimits, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node1 = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node1 != nullptr); + static_cast(layoutPolicy_->GetSystemSizeLimits(node1, displayRect, 1.0)); // ratio: 1.0 + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_FLOAT_CAMERA; + sptr node2 = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node2 != nullptr); + static_cast(layoutPolicy_->GetSystemSizeLimits(node2, displayRect, 1.0)); // ratio: 1.0 +} + +/** + * @tc.name: UpdateFloatingWindowSizeForStretchableWindow04 + * @tc.desc: test UpdateFloatingWindowSizeForStretchableWindow04 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow04, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 0, 0}; + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + winRect = { 0, 0, 40, 0 }; // width: 40 + node->SetOriginRect(winRect); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + winRect = { 0, 0, 0, 40 }; // height: 40 + node->SetOriginRect(winRect); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + winRect = { 0, 0, 40, 40 }; // width/height: 40 + node->SetOriginRect(winRect); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + node->SetDragType(DragType::DRAG_LEFT_OR_RIGHT); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + node->SetDragType(DragType::DRAG_BOTTOM_OR_TOP); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + node->SetDragType(DragType::DRAG_LEFT_TOP_CORNER); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + node->SetDragType(DragType::DRAG_RIGHT_TOP_CORNER); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); +} + +/** + * @tc.name: UpdateFloatingWindowSizeForStretchableWindow05 + * @tc.desc: test UpdateFloatingWindowSizeForStretchableWindow05 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow05, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + node->SetOriginRect(winRect); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + winRect = { 0, 0, 300, 300 }; // width/height: 300 + node->SetOriginRect(winRect); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + winRect = { 0, 0, 500, 500 }; // width/height: 500 + node->SetOriginRect(winRect); + layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); +} + +/** + * @tc.name: UpdateFloatingWindowSizeBySizeLimits + * @tc.desc: test UpdateFloatingWindowSizeBySizeLimits + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeBySizeLimits, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + WindowSizeLimits sizeLimits = { 800, 400, 800, 400, 2.0, 1.0 }; // sizeLimits: 800, 400, 800, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + winRect = { 0, 0, 400, 400 }; // width/height: 400 + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + sizeLimits = { 800, 500, 800, 400, 2.0, 1.0 }; // sizeLimits: 800, 500, 800, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + sizeLimits = { 800, 400, 600, 400, 2.0, 1.0 }; // sizeLimits: 800, 400, 600, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + sizeLimits = { 800, 400, 800, 400, 2.0, 1.0 }; // sizeLimits: 800, 400, 800, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + sizeLimits = { 800, 800, 400, 400, 2.0, 1.0 }; // sizeLimits: 800, 800, 400, 400, 2.0, 1.0 + node->SetWindowUpdatedSizeLimits(sizeLimits); + node->SetDragType(DragType::DRAG_BOTTOM_OR_TOP); + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + node->SetDragType(DragType::DRAG_LEFT_OR_RIGHT); + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + + node->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_DRAGGING_EFFECT); + layoutPolicy_->UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); +} + +/** + * @tc.name: LimitFloatingWindowSize + * @tc.desc: test LimitFloatingWindowSize + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitFloatingWindowSize, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG); + node->SetWindowRect(winRect); + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + + Rect newRect = { 10, 0, 400, 400 }; // window rect: 10, 0, 400, 400 + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, newRect); + + newRect = { 0, 10, 400, 400 }; // window rect: 0, 10, 400, 400 + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, newRect); + + newRect = { 10, 10, 400, 400 }; // window rect: 10, 10, 400, 400 + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, newRect); + + node->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + + node->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_APP_COMPONENT); + layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); +} + +/** + * @tc.name: LimitMainFloatingWindowPosition + * @tc.desc: test LimitMainFloatingWindowPosition + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitMainFloatingWindowPosition, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + node->SetWindowRect(winRect); + node->SetRequestRect(winRect); + winRect.posX_ = 20; // posX: 20 + layoutPolicy_->LimitMainFloatingWindowPosition(node, winRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG); + node->SetWindowRect(winRect); + layoutPolicy_->LimitMainFloatingWindowPosition(node, winRect); + + node->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + layoutPolicy_->LimitMainFloatingWindowPosition(node, winRect); +} + +/** + * @tc.name: LimitWindowPositionWhenDrag + * @tc.desc: test LimitWindowPositionWhenDrag + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitWindowPositionWhenDrag, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + node->SetWindowRect(winRect); + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + sptr dockNode = CreateWindowNode(windowInfo_); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(dockNode); + + Rect dockWinRect = { 200, 200, 50, 20 }; // 200, 200, 50, 20 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenDrag(node, winRect); + + dockWinRect = { 200, 200, 50, (displayRect.height_ - static_cast(200)) }; //param: 200 200 20 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenDrag(node, winRect); + + dockWinRect = { 200, 200, 20, 50 }; // 200, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenDrag(node, winRect); + + dockWinRect = { 0, 200, 20, 50 }; // 200, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenDrag(node, winRect); +} + +/** + * @tc.name: LimitWindowPositionWhenDrag01 + * @tc.desc: test LimitWindowPositionWhenDrag01 + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitWindowPositionWhenDrag01, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + node->SetWindowRect(winRect); + + layoutPolicy_->limitRectMap_[node->GetDisplayId()] = displayRect; + float virtualPixelRatio = layoutPolicy_->GetVirtualPixelRatio(node->GetDisplayId()); + uint32_t windowTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); + int32_t limitMinPosX = displayRect.posX_ + static_cast(windowTitleBarH); + int32_t limitMaxPosX = displayRect.posX_ + static_cast(displayRect.width_ - windowTitleBarH); + int32_t limitMinPosY = displayRect.posY_; + int32_t limitMaxPosY = displayRect.posY_ + static_cast(displayRect.height_ - windowTitleBarH); + + Rect newRect = winRect; + newRect.posX_ = limitMinPosX - newRect.width_ - 1; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + newRect.width_ -= 1; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + winRect.posX_ = limitMaxPosX + 1; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + newRect.width_ = winRect.width_; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + newRect.posY_ = limitMaxPosY + 1; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + newRect.height_ += 1; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + newRect.posY_ = limitMinPosY - 1; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); + + newRect.height_ = winRect.height_; + layoutPolicy_->LimitWindowPositionWhenDrag(node, newRect); +} + +/** + * @tc.name: LimitWindowPositionWhenInitRectOrMove + * @tc.desc: test LimitWindowPositionWhenInitRectOrMove + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, LimitWindowPositionWhenInitRectOrMove, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 + node->SetWindowRect(winRect); + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + sptr dockNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(dockNode != nullptr); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(dockNode); + + Rect dockWinRect = { 200, 200, 50, 20 }; // rect : 200, 200, 50, 20 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenInitRectOrMove(node, winRect); + + dockWinRect = { 200, 200, 50, (displayRect.height_ - static_cast(200)) }; // param: 200, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenInitRectOrMove(node, winRect); + + dockWinRect = { 200, 200, 20, 50 }; // rect : 200, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenInitRectOrMove(node, winRect); + + dockWinRect = { 0, 200, 20, 50 }; // rect : 0, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->LimitWindowPositionWhenInitRectOrMove(node, winRect); + + node->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + layoutPolicy_->LimitWindowPositionWhenInitRectOrMove(node, winRect); +} + +/** + * @tc.name: GetDockWindowShowState + * @tc.desc: test GetDockWindowShowState + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, GetDockWindowShowState, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + Rect dockWinRect = { 200, 200, 50, 20 }; // rect : 200, 200, 50, 20 + layoutPolicy_->GetDockWindowShowState(0, dockWinRect); + + windowInfo_.winType_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK; + sptr dockNode = CreateWindowNode(windowInfo_); + ASSERT_TRUE(dockNode != nullptr); + layoutPolicy_->displayGroupWindowTree_[0][WindowRootNodeType::ABOVE_WINDOW_NODE]->push_back(dockNode); + + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->GetDockWindowShowState(0, dockWinRect); + + dockWinRect = { 200, 200, 50, (displayRect.height_ - static_cast(200)) }; // param : 200, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->GetDockWindowShowState(0, dockWinRect); + + dockWinRect = { 200, 200, 20, 50 }; // rect : 200, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->GetDockWindowShowState(0, dockWinRect); + + dockWinRect = { 0, 200, 20, 50 }; // rect : 0, 200, 20, 50 + dockNode->SetWindowRect(dockWinRect); + layoutPolicy_->GetDockWindowShowState(0, dockWinRect); +} + +/** + * @tc.name: GetAvoidPosType + * @tc.desc: test GetAvoidPosType + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, GetAvoidPosType, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + Rect winRect = { 200, 200, 50, 20 }; // rect : 200, 200, 50, 20 + layoutPolicy_->GetAvoidPosType(winRect, 0); + + layoutPolicy_->GetAvoidPosType(winRect, 1); + + winRect.width_ = displayRect.width_; + layoutPolicy_->GetAvoidPosType(winRect, 0); + + winRect.posY_ = displayRect.posY_; + layoutPolicy_->GetAvoidPosType(winRect, 0); + + winRect.height_ = displayRect.height_; + layoutPolicy_->GetAvoidPosType(winRect, 0); + + winRect.posY_ = displayRect.posY_; + layoutPolicy_->GetAvoidPosType(winRect, 0); +} + +/** + * @tc.name: UpdateLimitRect + * @tc.desc: test UpdateLimitRect + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateLimitRect, Function | SmallTest | Level2) +{ + auto displayRect = displayGroupInfo_->GetDisplayRect(defaultDisplayInfo_->GetDisplayId()); + ASSERT_FALSE(WindowHelper::IsEmptyRect(displayRect)); + + Rect limitRect = displayRect; + + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect avoidRect = { 200, 200, 50, 20 }; // rect : 200, 200, 50, 20 + node->SetWindowRect(avoidRect); + layoutPolicy_->UpdateLimitRect(node, limitRect); + + node->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + layoutPolicy_->UpdateLimitRect(node, limitRect); + + avoidRect.width_ = displayRect.width_; + node->SetWindowRect(avoidRect); + layoutPolicy_->UpdateLimitRect(node, limitRect); + + avoidRect.posY_ = displayRect.posY_; + node->SetWindowRect(avoidRect); + layoutPolicy_->UpdateLimitRect(node, limitRect); + + avoidRect.height_ = displayRect.height_; + node->SetWindowRect(avoidRect); + layoutPolicy_->UpdateLimitRect(node, limitRect); + + avoidRect.posY_ = displayRect.posY_; + node->SetWindowRect(avoidRect); + layoutPolicy_->UpdateLimitRect(node, limitRect); +} + +/** + * @tc.name: UpdateSurfaceBounds + * @tc.desc: test UpdateSurfaceBounds + * @tc.type: FUNC + */ +HWTEST_F(WindowLayoutPolicyTest, UpdateSurfaceBounds, Function | SmallTest | Level2) +{ + sptr node = CreateWindowNode(windowInfo_); + ASSERT_TRUE(node != nullptr); + Rect winRect = { 0, 0, 20, 50 }; // rect : 0, 0, 20, 50 + Rect preRect = { 0, 0, 20, 60 }; // rect : 0, 0, 20, 60 + layoutPolicy_->UpdateSurfaceBounds(node, winRect, preRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::MAXIMIZE); + layoutPolicy_->UpdateSurfaceBounds(node, winRect, preRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::RECOVER); + layoutPolicy_->UpdateSurfaceBounds(node, winRect, preRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::ROTATION); + layoutPolicy_->UpdateSurfaceBounds(node, winRect, preRect); + + node->SetWindowSizeChangeReason(WindowSizeChangeReason::UNDEFINED); + layoutPolicy_->UpdateSurfaceBounds(node, winRect, preRect); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_manager_config_test.cpp b/window_manager/wmserver/test/unittest/window_manager_config_test.cpp new file mode 100644 index 0000000..f90b561 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_manager_config_test.cpp @@ -0,0 +1,254 @@ +/* + * 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 "window_manager_service.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using ConfigItem = WindowManagerConfig::ConfigItem; +const std::string XML_STR = R"( + + + + + 100 + + 99 + + + + 50 50 50 + + + + 0.1 0.9 + + 0.5 0.33 0.67 + + 1 + + + + + 350 + + + + + 0.7 0.7 + + 0 0 1 0 + + 0 0 + + 0 + + + + + + 500 + + 300 + + 0.2 0.0 0.2 1.0 + + + + + + + + + + + off + off + off + + + + 0 + #000000 + 0 + 0 + 0 + + + 0 + #000000 + 0 + 0 + 0 + + + + + +)"; + +class WindowManagerConfigTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + ConfigItem ReadConfig(const std::string& xmlStr); +}; + +void WindowManagerConfigTest::SetUpTestCase() +{ +} + +void WindowManagerConfigTest::TearDownTestCase() +{ +} + +void WindowManagerConfigTest::SetUp() +{ +} + +void WindowManagerConfigTest::TearDown() +{ +} + +ConfigItem WindowManagerConfigTest::ReadConfig(const std::string& xmlStr) +{ + ConfigItem config; + xmlDocPtr docPtr = xmlParseMemory(xmlStr.c_str(), xmlStr.length() + 1); + if (docPtr == nullptr) { + return config; + } + + xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr); + if (rootPtr == nullptr || rootPtr->name == nullptr || + xmlStrcmp(rootPtr->name, reinterpret_cast("Configs"))) { + xmlFreeDoc(docPtr); + return config; + } + + std::map configMap; + config.SetValue(configMap); + WindowManagerConfig::ReadConfig(rootPtr, *config.mapValue_); + xmlFreeDoc(docPtr); + return config; +} +namespace { +/** + * @tc.name: AnimationConfig + * @tc.desc: animation config test + * @tc.type: FUNC + * @tc.require issueI5N26H + */ +HWTEST_F(WindowManagerConfigTest, AnimationConfig, Function | SmallTest | Level2) +{ + WindowManagerConfig::config_ = ReadConfig(XML_STR); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ConfigItem item = WindowManagerConfig::config_["windowAnimation"]; + ASSERT_EQ(true, item.IsMap()); + item = WindowManagerConfig::config_["windowAnimation"]["timing"]["duration"]; + ASSERT_EQ(true, item.IsInts()); + auto value = *item.intsValue_; + ASSERT_EQ(true, value.size() == 1); + ASSERT_EQ(350, value[0]); + item = WindowManagerConfig::config_["windowAnimation"]["timing"]["curve"].GetProp("name"); + ASSERT_EQ(true, item.IsString()); + ASSERT_EQ("easeOut", item.stringValue_); + item = WindowManagerConfig::config_["windowAnimation"]["scale"]; + ASSERT_EQ(true, item.IsFloats()); + ASSERT_EQ(true, item.floatsValue_->size() == 2); + item = WindowManagerConfig::config_["windowAnimation"]["rotation"]; + ASSERT_EQ(true, item.IsFloats()); + ASSERT_EQ(true, item.floatsValue_->size() == 4); + item = WindowManagerConfig::config_["windowAnimation"]["translate"]; + ASSERT_EQ(true, item.IsFloats()); + ASSERT_EQ(true, item.floatsValue_->size() == 2); + item = WindowManagerConfig::config_["windowAnimation"]["opacity"]; + ASSERT_EQ(true, item.IsFloats()); + ASSERT_EQ(true, item.floatsValue_->size() == 1); +} + +/** + * @tc.name: maxAppWindowNumber + * @tc.desc: maxAppWindowNumber test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerConfigTest, MaxAppWindowNumber, Function | SmallTest | Level2) +{ + std::string xmlStr = "" + "" + "0" + ""; + WindowManagerConfig::config_ = ReadConfig(xmlStr); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ASSERT_EQ(true, WindowManagerService::GetInstance().windowRoot_->maxAppWindowNumber_ == 100); + + xmlStr = "" + "" + "-2" + ""; + WindowManagerConfig::config_ = ReadConfig(xmlStr); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ASSERT_EQ(true, WindowManagerService::GetInstance().windowRoot_->maxAppWindowNumber_ == 100); + + xmlStr = "" + "" + "4" + ""; + WindowManagerConfig::config_ = ReadConfig(xmlStr); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ASSERT_EQ(true, WindowManagerService::GetInstance().windowRoot_->maxAppWindowNumber_ == 4); + + xmlStr = "" + "" + "1000" + ""; + WindowManagerConfig::config_ = ReadConfig(xmlStr); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ASSERT_EQ(true, WindowManagerService::GetInstance().windowRoot_->maxAppWindowNumber_ == 1000); +} + +/** + * @tc.name: decor + * @tc.desc: set decor true and false. + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerConfigTest, Decor, Function | SmallTest | Level2) +{ + std::string xmlStr = "" + "" + "" + ""; + WindowManagerConfig::config_ = ReadConfig(xmlStr); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ASSERT_EQ(true, WindowManagerService::GetInstance().systemConfig_.isSystemDecorEnable_); + + xmlStr = "" + "" + "" + ""; + WindowManagerConfig::config_ = ReadConfig(xmlStr); + WindowManagerService::GetInstance().ConfigureWindowManagerService(); + ASSERT_EQ(false, WindowManagerService::GetInstance().systemConfig_.isSystemDecorEnable_); +} +} // namespace +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/window_manager/wmserver/test/unittest/window_manager_proxy_test.cpp b/window_manager/wmserver/test/unittest/window_manager_proxy_test.cpp new file mode 100644 index 0000000..d6eb381 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_manager_proxy_test.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2022-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 "window_manager_proxy.h" +#include "window_manager_stub_impl.h" +#include "iremote_object_mocker.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowManagerProxyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr mockWindowManagerStub_; + sptr windowManagerProxy_; +}; + +void WindowManagerProxyTest::SetUpTestCase() +{ +} + +void WindowManagerProxyTest::TearDownTestCase() +{ +} + +void WindowManagerProxyTest::SetUp() +{ + mockWindowManagerStub_ = new WindowManagerStubImpl(); + windowManagerProxy_ = new WindowManagerProxy(mockWindowManagerStub_); +} + +void WindowManagerProxyTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: RequestFocus + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, RequestFocus, Function | SmallTest | Level2) +{ + uint32_t windowId = 0; + WMError err = windowManagerProxy_->RequestFocus(windowId); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: SetWindowAnimationController + * @tc.desc: test failed + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, SetWindowAnimationController, Function | SmallTest | Level2) +{ + sptr controller = nullptr; + WMError err = windowManagerProxy_->SetWindowAnimationController(controller); + ASSERT_EQ(err, WMError::WM_ERROR_IPC_FAILED); +} + +/** + * @tc.name: SetWindowAnimationController01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, SetWindowAnimationController01, Function | SmallTest | Level2) +{ + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + sptr controller = iface_cast(iRemoteObjectMocker); + WMError err = windowManagerProxy_->SetWindowAnimationController(controller); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: ToggleShownStateForAllAppWindows + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, ToggleShownStateForAllAppWindows, Function | SmallTest | Level2) +{ + WMError err = windowManagerProxy_->ToggleShownStateForAllAppWindows(); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: GetTopWindowId + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, GetTopWindowId, Function | SmallTest | Level2) +{ + uint32_t mainWinId = 0; + uint32_t topWinId; + WMError err = windowManagerProxy_->GetTopWindowId(mainWinId, topWinId); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: NotifyWindowTransition + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, NotifyWindowTransition, Function | SmallTest | Level2) +{ + sptr from = new WindowTransitionInfo(); + sptr to = new WindowTransitionInfo(); + bool isFromClient = false; + WMError err = windowManagerProxy_->NotifyWindowTransition(from, to, isFromClient); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: GetModeChangeHotZones + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, GetModeChangeHotZones, Function | SmallTest | Level2) +{ + DisplayId displayId = 10; + ModeChangeHotZones hotZones; + WMError err = windowManagerProxy_->GetModeChangeHotZones(displayId, hotZones); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: MinimizeWindowsByLauncher + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, MinimizeWindowsByLauncher, Function | SmallTest | Level2) +{ + std::vector windowIds; + bool isAnimated = false; + sptr finishCallback; + windowManagerProxy_->MinimizeWindowsByLauncher(windowIds, isAnimated, finishCallback); + ASSERT_EQ(finishCallback, nullptr); +} + +/** + * @tc.name: MinimizeWindowsByLauncher01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, MinimizeWindowsByLauncher01, Function | SmallTest | Level2) +{ + std::vector windowIds; + windowIds.push_back(0); + windowIds.push_back(1); + bool isAnimated = false; + sptr finishCallback; + windowManagerProxy_->MinimizeWindowsByLauncher(windowIds, isAnimated, finishCallback); + ASSERT_EQ(finishCallback, nullptr); +} + +/** + * @tc.name: UpdateRsTree + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, UpdateRsTree, Function | SmallTest | Level2) +{ + uint32_t windowId = 0; + bool isAdd = false; + WMError err = windowManagerProxy_->UpdateRsTree(windowId, isAdd); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: BindDialogTarget + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, BindDialogTarget, Function | SmallTest | Level2) +{ + uint32_t windowId = 0; + sptr targetToken = nullptr; + WMError err = windowManagerProxy_->BindDialogTarget(windowId, targetToken); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: BindDialogTarget01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, BindDialogTarget01, Function | SmallTest | Level2) +{ + uint32_t windowId = 0; + sptr targetToken = nullptr; + WMError err = windowManagerProxy_->BindDialogTarget(windowId, targetToken); + ASSERT_EQ(err, WMError::WM_OK); +} + +/** + * @tc.name: GetVisibilityWindowInfo01 + * @tc.desc: test success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerProxyTest, GetVisibilityWindowInfo01, Function | SmallTest | Level2) +{ + std::vector> infos; + WMError err = windowManagerProxy_->GetVisibilityWindowInfo(infos); + ASSERT_EQ(err, WMError::WM_OK); +} + +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_manager_service_test.cpp b/window_manager/wmserver/test/unittest/window_manager_service_test.cpp new file mode 100644 index 0000000..bc95191 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_manager_service_test.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2022-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 "common_test_utils.h" +#include "iremote_object_mocker.h" +#include "mock_RSIWindowAnimationController.h" +#include "window_manager_service.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xcollie/watchdog.h" + +#include "color_parser.h" +#include "display_manager_service_inner.h" +#include "dm_common.h" +#include "drag_controller.h" +#include "minimize_app.h" +#include "permission.h" +#include "remote_animation.h" +#include "singleton_container.h" +#include "ui/rs_ui_director.h" +#include "window_helper.h" +#include "window_inner_manager.h" +#include "window_manager_agent_controller.h" +#include "window_manager_hilog.h" +#include "wm_common.h" +#include "wm_math.h" + + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowManagerServiceTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void SetAceessTokenPermission(const std::string processName); + sptr wms = new WindowManagerService(); +}; + +void WindowManagerServiceTest::SetUpTestCase() +{ +} + +void WindowManagerServiceTest::TearDownTestCase() +{ +} + +void WindowManagerServiceTest::SetUp() +{ + CommonTestUtils::SetAceessTokenPermission("WindowManagerServiceTest"); +} + +void WindowManagerServiceTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnAddSystemAbility + * @tc.desc: OnAddSystemAbility test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, OnAddSystemAbility01, Function | SmallTest | Level2) +{ + std::string str = "OnAddSystemAbility"; + wms->OnAddSystemAbility(0, str); + ASSERT_EQ(nullptr, wms->windowCommonEvent_->subscriber_); +} +/** + * @tc.name: WindowVisibilityChangeCallback + * @tc.desc: WindowVisibilityChangeCallback test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, WindowVisibilityChangeCallback01, Function | SmallTest | Level2) +{ + std::shared_ptr occlusionData = nullptr; + wms->WindowVisibilityChangeCallback(occlusionData); + ASSERT_EQ(nullptr, occlusionData); +} +/** + * @tc.name: InitWithAbilityManagerServiceAdded + * @tc.desc: Init with ability manager service added. + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, InitWithAbilityManagerServiceAdded01, Function | SmallTest | Level2) +{ + wms->wmsHandler_ = new WindowManagerServiceHandler; + wms->InitWithAbilityManagerServiceAdded(); + ASSERT_NE(nullptr, wms->wmsHandler_); +} +/** + * @tc.name: Dump + * @tc.desc: Dump info + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, Dump01, Function | SmallTest | Level2) +{ + wms->windowDumper_ = nullptr; + std::vector args; + ASSERT_EQ(static_cast(WMError::WM_ERROR_INVALID_PARAM), wms->Dump(-1, args)); + ASSERT_EQ(static_cast(WMError::WM_OK), wms->Dump(0, args)); +} +/** + * @tc.name: NotifyWindowTransition + * @tc.desc: NotifyWindowTransition test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, NotifyWindowTransition01, Function | SmallTest | Level2) +{ + sptr fromInfo = nullptr; + sptr toInfo = nullptr; + ASSERT_EQ(WMError::WM_OK, wms->NotifyWindowTransition(fromInfo, toInfo, false)); + ASSERT_EQ(WMError::WM_ERROR_NO_REMOTE_ANIMATION, wms->NotifyWindowTransition(fromInfo, toInfo, true)); +} +/** + * @tc.name: StartingWindow + * @tc.desc: StartingWindow test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, StartingWindow01, Function | SmallTest | Level2) +{ + wms->startingOpen_ = false; + wms->StartingWindow(nullptr, nullptr, false, 0); + ASSERT_EQ(false, wms->startingOpen_); + wms->CancelStartingWindow(nullptr); + wms->startingOpen_ = true; + wms->StartingWindow(nullptr, nullptr, false, 0); + ASSERT_EQ(true, wms->startingOpen_); + wms->CancelStartingWindow(nullptr); +} +/** + * @tc.name: CreateWindow + * @tc.desc: CreateWindow test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, CreateWindow01, Function | SmallTest | Level2) +{ + sptr window = nullptr; + uint32_t id = 2; + std::shared_ptr RS_node = nullptr; + sptr property = new WindowProperty(); + property->SetWindowType(WindowType::WINDOW_TYPE_WALLPAPER); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, wms->CreateWindow(window, property, RS_node, id, nullptr)); + wms->DestroyWindow(id, true); +} +/** + * @tc.name: AddWindow + * @tc.desc: AddWindow test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, AddWindow01, Function | SmallTest | Level2) +{ + sptr property = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, wms->AddWindow(property)); +} +/** + * @tc.name: RegisterWindowManagerAgent + * @tc.desc: RegisterWindowManagerAgent test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, RegisterWindowManagerAgent01, Function | SmallTest | Level2) +{ + sptr windowManagerAgent = nullptr; + WindowManagerAgentType type = WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT; + ASSERT_EQ(false, wms->RegisterWindowManagerAgent(type, windowManagerAgent)); + ASSERT_EQ(false, wms->UnregisterWindowManagerAgent(type, windowManagerAgent)); +} +/** + * @tc.name: SetWindowAnimationController + * @tc.desc: SetWindowAnimationController test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, SetWindowAnimationController01, Function | SmallTest | Level2) +{ + sptr controller = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, wms->SetWindowAnimationController(controller)); + controller = new RSIWindowAnimationControllerMocker; + ASSERT_EQ(WMError::WM_OK, wms->SetWindowAnimationController(controller)); +} +/** + * @tc.name: OnWindowEvent + * @tc.desc: OnWindowEvent test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, OnWindowEvent01, Function | SmallTest | Level2) +{ + sptr remoteObject = new IRemoteObjectMocker; + wms->OnWindowEvent(static_cast(1), remoteObject); + wms->OnWindowEvent(Event::REMOTE_DIED, remoteObject); + ASSERT_EQ(INVALID_WINDOW_ID, wms->windowRoot_->GetWindowIdByObject(remoteObject)); +} +/** + * @tc.name: UpdateProperty + * @tc.desc: UpdateProperty test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, UpdateProperty01, Function | SmallTest | Level2) +{ + sptr windowProperty = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, wms->UpdateProperty(windowProperty, + PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG, true)); +} +/** + * @tc.name: GetModeChangeHotZones + * @tc.desc: GetModeChangeHotZones test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, GetModeChangeHotZones01, Function | SmallTest | Level2) +{ + ModeChangeHotZonesConfig config = {false, 0, 0, 0}; + DisplayId displayId = 0; + ModeChangeHotZones hotZone; + wms->hotZonesConfig_ = config; + ASSERT_EQ(WMError::WM_DO_NOTHING, wms->GetModeChangeHotZones(displayId, hotZone)); + config.isModeChangeHotZoneConfigured_ = true; + wms->hotZonesConfig_ = config; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, wms->GetModeChangeHotZones(displayId, hotZone)); +} +/** + * @tc.name: UpdateAvoidAreaListener + * @tc.desc: UpdateAvoidAreaListener test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, UpdateAvoidAreaListener01, Function | SmallTest | Level2) +{ + sptr property = new WindowProperty(); + sptr node = new WindowNode(property); + wms->windowRoot_->windowNodeMap_.insert(std::make_pair(0, node)); + ASSERT_EQ(WMError::WM_DO_NOTHING, wms->UpdateAvoidAreaListener(0, true)); +} +/** + * @tc.name: BindDialogTarget + * @tc.desc: BindDialogTarget test + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerServiceTest, BindDialogTarget01, Function | SmallTest | Level2) +{ + sptr targetToken = new IRemoteObjectMocker(); + uint32_t id = 0; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, wms->BindDialogTarget(id, targetToken)); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_manager_stub_impl.h b/window_manager/wmserver/test/unittest/window_manager_stub_impl.h new file mode 100644 index 0000000..8db8b9d --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_manager_stub_impl.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2022-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 "window_manager_stub.h" +#include "window_manager_agent.h" +#include +#include "window_impl.h" +#include "window_agent.h" + +namespace OHOS { +namespace Rosen { +class WindowManagerStubImpl : public WindowManagerStub { +WMError CreateWindow(sptr& window, sptr& property, + const std::shared_ptr& surfaceNode, + uint32_t& windowId, sptr token) +{ + return WMError::WM_OK; +}; +WMError AddWindow(sptr& property) +{ + return WMError::WM_OK; +}; +WMError RemoveWindow(uint32_t windowId) +{ + return WMError::WM_OK; +}; +WMError DestroyWindow(uint32_t windowId, bool onlySelf = false) +{ + return WMError::WM_OK; +}; +WMError RequestFocus(uint32_t windowId) +{ + return WMError::WM_OK; +}; +AvoidArea GetAvoidAreaByType(uint32_t windowId, AvoidAreaType type) +{ + AvoidArea area; + return area; +}; +WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId) +{ + return WMError::WM_OK; +}; +void NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, + sptr& moveDragProperty){}; +void ProcessPointDown(uint32_t windowId, bool isPointDown){}; +void ProcessPointUp(uint32_t windowId){}; +void MinimizeAllAppWindows(DisplayId displayId){}; +WMError ToggleShownStateForAllAppWindows() +{ + return WMError::WM_OK; +}; +WMError SetWindowLayoutMode(WindowLayoutMode mode) +{ + return WMError::WM_OK; +}; +WMError UpdateProperty(sptr& windowProperty, PropertyChangeAction action, + bool isAsyncTask = false) +{ + return WMError::WM_OK; +}; +bool RegisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + return true; +}; +bool UnregisterWindowManagerAgent(WindowManagerAgentType type, + const sptr& windowManagerAgent) +{ + return true; +}; +WMError GetAccessibilityWindowInfo(std::vector>& infos) +{ + return WMError::WM_OK; +}; +WMError GetVisibilityWindowInfo(std::vector>& infos) +{ + return WMError::WM_OK; +}; +WMError SetWindowAnimationController(const sptr& controller) +{ + return WMError::WM_OK; +}; +WMError GetSystemConfig(SystemConfig& systemConfig) +{ + return WMError::WM_OK; +}; +WMError NotifyWindowTransition(sptr& from, sptr& to, + bool isFromClient = false) +{ + return WMError::WM_OK; +}; +WMError GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones) +{ + return WMError::WM_OK; +}; +void MinimizeWindowsByLauncher(std::vector windowIds, bool isAnimated, + sptr& finishCallback){}; +WMError UpdateAvoidAreaListener(uint32_t windowId, bool haveListener) +{ + return WMError::WM_OK; +}; +WMError UpdateRsTree(uint32_t windowId, bool isAdd) +{ + return WMError::WM_OK; +}; +WMError BindDialogTarget(uint32_t& windowId, sptr targetToken) +{ + return WMError::WM_OK; +}; +void SetAnchorAndScale(int32_t x, int32_t y, float scale){}; +void SetAnchorOffset(int32_t deltaX, int32_t deltaY){}; +void OffWindowZoom(){}; +std::shared_ptr GetSnapshot(int32_t windowId) override +{ + return nullptr; +} +}; +} +} \ No newline at end of file diff --git a/window_manager/wmserver/test/unittest/window_manager_stub_test.cpp b/window_manager/wmserver/test/unittest/window_manager_stub_test.cpp new file mode 100644 index 0000000..a59593d --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_manager_stub_test.cpp @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2022-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 "window_manager_stub_impl.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { +class WindowManagerStubTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + sptr stub_; +}; + +void WindowManagerStubTest::SetUpTestCase() +{ +} + +void WindowManagerStubTest::TearDownTestCase() +{ +} + +void WindowManagerStubTest::SetUp() +{ + stub_ = new WindowManagerStubImpl(); +} + +void WindowManagerStubTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: OnRemoteRequest01 + * @tc.desc: test InterfaceToken check failed + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest01, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(u"error.GetDescriptor"); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_CREATE_WINDOW); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, -1); +} + +/** + * @tc.name: OnRemoteRequest02 + * @tc.desc: test TRANS_ID_REMOVE_WINDOW + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest02, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + + data.WriteUint32(1); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_REMOVE_WINDOW); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest03 + * @tc.desc: test TRANS_ID_REQUEST_FOCUS success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest03, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(1); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_REQUEST_FOCUS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest04 + * @tc.desc: test TRANS_ID_GET_AVOID_AREA success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest04, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(1); + data.WriteUint32(static_cast(AvoidAreaType::TYPE_CUTOUT)); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_AVOID_AREA); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest05 + * @tc.desc: test TRANS_ID_UNREGISTER_WINDOW_MANAGER_AGENT success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest05, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(static_cast(WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_CAMERA_FLOAT)); + sptr focusChangedListenerAgent = new WindowManagerAgent(); + data.WriteRemoteObject(focusChangedListenerAgent->AsObject()); + + uint32_t code = + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UNREGISTER_WINDOW_MANAGER_AGENT); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest06 + * @tc.desc: test TRANS_ID_NOTIFY_READY_MOVE_OR_DRAG success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest06, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(1); + sptr windowProperty = new WindowProperty(); + data.WriteParcelable(windowProperty.GetRefPtr()); + sptr moveDragProperty = new MoveDragProperty(); + data.WriteParcelable(moveDragProperty.GetRefPtr()); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_NOTIFY_READY_MOVE_OR_DRAG); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest07 + * @tc.desc: test TRANS_ID_PROCESS_POINT_DOWN success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest07, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(1); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_PROCESS_POINT_DOWN); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest08 + * @tc.desc: test TRANS_ID_PROCESS_POINT_UP success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest08, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(1); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_PROCESS_POINT_UP); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest09 + * @tc.desc: test TRANS_ID_GET_TOP_WINDOW_ID success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest09, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(1); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_TOP_WINDOW_ID); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest10 + * @tc.desc: test TRANS_ID_MINIMIZE_ALL_APP_WINDOWS success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest10, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(0); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_MINIMIZE_ALL_APP_WINDOWS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest11 + * @tc.desc: test TRANS_ID_TOGGLE_SHOWN_STATE_FOR_ALL_APP_WINDOWS success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest11, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + + uint32_t code = + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_TOGGLE_SHOWN_STATE_FOR_ALL_APP_WINDOWS); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest12 + * @tc.desc: test TRANS_ID_UPDATE_LAYOUT_MODE success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest12, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(static_cast(WindowLayoutMode::CASCADE)); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UPDATE_LAYOUT_MODE); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest13 + * @tc.desc: test TRANS_ID_UPDATE_PROPERTY success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest13, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + data.WriteUint32(static_cast(PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG)); + sptr windowProperty = new WindowProperty(); + windowProperty->Write(data, PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UPDATE_PROPERTY); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest14 + * @tc.desc: test TRANS_ID_ANIMATION_SET_CONTROLLER success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest14, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_ANIMATION_SET_CONTROLLER); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest15 + * @tc.desc: test TRANS_ID_NOTIFY_WINDOW_TRANSITION success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest15, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + sptr from = new WindowTransitionInfo(); + sptr to = new WindowTransitionInfo(); + data.WriteParcelable(from); + data.WriteParcelable(to); + data.WriteBool(false); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_NOTIFY_WINDOW_TRANSITION); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest16 + * @tc.desc: test TRANS_ID_GET_FULLSCREEN_AND_SPLIT_HOT_ZONE success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest16, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + DisplayId displayId = 0; + data.WriteUint64(displayId); + + uint32_t code = + static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_FULLSCREEN_AND_SPLIT_HOT_ZONE); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest17 + * @tc.desc: test TRANS_ID_GET_ANIMATION_CALLBACK success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest17, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + std::vector windowIds; + windowIds.emplace_back(1); + windowIds.emplace_back(10); + bool isAnimated = false; + data.WriteUInt32Vector(windowIds); + data.WriteBool(isAnimated); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_GET_ANIMATION_CALLBACK); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest18 + * @tc.desc: test TRANS_ID_UPDATE_RS_TREE success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest18, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + uint32_t windowId = 1; + bool isAdd = false; + data.WriteUint32(windowId); + data.WriteBool(isAdd); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_UPDATE_RS_TREE); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest19 + * @tc.desc: test TRANS_ID_CREATE_WINDOW success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest19, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + sptr windowOption = new WindowOption(); + sptr windowImpl = new WindowImpl(windowOption); + sptr window = new WindowAgent(windowImpl); + sptr property = nullptr; + struct RSSurfaceNodeConfig surfaceNodeConfig; + surfaceNodeConfig.SurfaceNodeName = "SurfaceNode"; + std::shared_ptr surNode = RSSurfaceNode::Create(surfaceNodeConfig, RSSurfaceNodeType::DEFAULT); + sptr token; + + data.WriteRemoteObject(window->AsObject()); + data.WriteParcelable(property.GetRefPtr()); + surNode->Marshalling(data); + data.WriteRemoteObject(token); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_CREATE_WINDOW); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: OnRemoteRequest20 + * @tc.desc: test TRANS_ID_CREATE_WINDOW success + * @tc.type: FUNC + */ +HWTEST_F(WindowManagerStubTest, OnRemoteRequest20, Function | SmallTest | Level2) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(WindowManagerStub::GetDescriptor()); + sptr windowOption = new WindowOption(); + sptr windowImpl = new WindowImpl(windowOption); + sptr window = new WindowAgent(windowImpl); + sptr property = new WindowProperty(); + property->SetTokenState(false); + struct RSSurfaceNodeConfig surfaceNodeConfig; + surfaceNodeConfig.SurfaceNodeName = "SurfaceNode"; + std::shared_ptr surNode = RSSurfaceNode::Create(surfaceNodeConfig, RSSurfaceNodeType::DEFAULT); + sptr token; + + data.WriteRemoteObject(window->AsObject()); + data.WriteParcelable(property.GetRefPtr()); + surNode->Marshalling(data); + data.WriteRemoteObject(token); + + uint32_t code = static_cast(IWindowManager::WindowManagerMessage::TRANS_ID_CREATE_WINDOW); + + int res = stub_->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(res, 0); +} + +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_node_container_test.cpp b/window_manager/wmserver/test/unittest/window_node_container_test.cpp new file mode 100644 index 0000000..fdbbb3d --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_node_container_test.cpp @@ -0,0 +1,802 @@ +/* + * 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 "display_manager.h" +#include "display_manager_config.h" +#include "window_node_container.h" +#include "future.h" +#include "window_node.h" +#include "wm_common.h" +#include "window_transition_info.h" +#include "starting_window.h" +#include "minimize_app.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowNodeContainerTest"}; +} + +class WindowNodeContainerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + static sptr defaultDisplay_; + static sptr container_; + static Rect windowRect_; +}; + +sptr WindowNodeContainerTest::defaultDisplay_ = nullptr; +sptr WindowNodeContainerTest::container_ = nullptr; +Rect WindowNodeContainerTest::windowRect_; + +void WindowNodeContainerTest::SetUpTestCase() +{ + defaultDisplay_ = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_TRUE((defaultDisplay_ != nullptr)); + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + defaultDisplay_->GetId(), defaultDisplay_->GetWidth(), defaultDisplay_->GetHeight(), + defaultDisplay_->GetRefreshRate()); + + container_ = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), defaultDisplay_->GetScreenId()); + windowRect_ = {0, 0, 100, 200}; +} + +void WindowNodeContainerTest::TearDownTestCase() +{ + container_ = nullptr; +} + +void WindowNodeContainerTest::SetUp() +{ +} + +void WindowNodeContainerTest::TearDown() +{ +} + +sptr CreateWindowProperty(uint32_t windowId, const std::string& windowName, + WindowType type, WindowMode mode, const Rect& screenRect) +{ + sptr property = new WindowProperty(); + property->SetWindowId(windowId); + property->SetWindowName(windowName); + property->SetWindowType(type); + property->SetWindowMode(mode); + property->SetWindowRect(screenRect); + return property; +} + +namespace { +/** + * @tc.name: AddWindowNodeOnWindowTree01 + * @tc.desc: add system sub window to system window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, AddWindowNodeOnWindowTree01, Function | SmallTest | Level2) +{ + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_LAUNCHING, WindowMode::WINDOW_MODE_FLOATING, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr subProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW, WindowMode::WINDOW_MODE_FLOATING, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + + ASSERT_EQ(WMError::WM_OK, container_->AddWindowNodeOnWindowTree(subNode, parentNode)); +} + +/** + * @tc.name: AddWindowNodeOnWindowTree02 + * @tc.desc: add system sub window to system sub window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, AddWindowNodeOnWindowTree02, Function | SmallTest | Level2) +{ + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW, WindowMode::WINDOW_MODE_FLOATING, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr subProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW, WindowMode::WINDOW_MODE_FLOATING, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, container_->AddWindowNodeOnWindowTree(subNode, parentNode)); +} + +/** + * @tc.name: AddWindowNodeOnWindowTree03 + * @tc.desc: add system sub window without parent + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, AddWindowNodeOnWindowTree03, Function | SmallTest | Level2) +{ + sptr subProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW, WindowMode::WINDOW_MODE_FLOATING, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container_->AddWindowNodeOnWindowTree(subNode, nullptr)); +} +/** + * @tc.name: MinimizeAppNodeExceptOptions + * @tc.desc: minimize app node + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, MinimizeAppNodeExceptOptions, Function | SmallTest | Level2) +{ + std::vector exceptionalIds; + std::vector exceptionalModes; + ASSERT_EQ(WMError::WM_OK, container_->MinimizeAppNodeExceptOptions(MinimizeReason::OTHER_WINDOW, + exceptionalIds, exceptionalModes)); + + sptr property1 = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node1 = new WindowNode(property1, nullptr, nullptr); + + sptr property2 = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FLOATING, windowRect_); + sptr node2 = new WindowNode(property2, nullptr, nullptr); + + ASSERT_EQ(WMError::WM_OK, container_->AddWindowNodeOnWindowTree(node1, nullptr)); + ASSERT_EQ(WMError::WM_OK, container_->AddWindowNodeOnWindowTree(node2, nullptr)); + ASSERT_EQ(WMError::WM_OK, container_->MinimizeAppNodeExceptOptions(MinimizeReason::OTHER_WINDOW, + exceptionalIds, exceptionalModes)); +} +/** + * @tc.name: DropShowWhenLockedWindowIfNeeded + * @tc.desc: drop show when locken window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, DropShowWhenLockedWindowIfNeeded, Function | SmallTest | Level2) +{ + sptr property = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_KEYGUARD, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + ASSERT_NE(nullptr, node); + container_->DropShowWhenLockedWindowIfNeeded(node); +} +/** + * @tc.name: GetModeChangeHotZones + * @tc.desc: get mode change hot zones + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, GetModeChangeHotZones, Function | SmallTest | Level2) +{ + ModeChangeHotZonesConfig hotZonesConfig { true, 10, 20, 30 }; + ModeChangeHotZones hotZones; + container_->GetModeChangeHotZones(0, hotZones, hotZonesConfig); + ASSERT_EQ(hotZones.fullscreen_.height_, 10); + ASSERT_EQ(hotZones.primary_.width_, 20); + ASSERT_EQ(hotZones.secondary_.width_, 30); +} +/** + * @tc.name: UpdateCameraFloatWindowStatus + * @tc.desc: update camera float window status + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, UpdateCameraFloatWindowStatus, Function | SmallTest | Level2) +{ + sptr property = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_FLOAT_CAMERA, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + ASSERT_NE(nullptr, node); + container_->UpdateCameraFloatWindowStatus(node, true); +} +/** + * @tc.name: UpdateWindowNode + * @tc.desc: preprocess node and update RSTree + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, UpdateWindowNode, Function | SmallTest | Level2) +{ + sptr property = CreateWindowProperty(110u, "test1", + WindowType::SYSTEM_WINDOW_BASE, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + ASSERT_EQ(WMError::WM_OK, container_->UpdateWindowNode(node, WindowUpdateReason::UPDATE_ALL)); + ASSERT_EQ(WMError::WM_OK, container_->UpdateWindowNode(node, WindowUpdateReason::UPDATE_MODE)); +} + +/** + * @tc.name: ShowStartingWindow + * @tc.desc: show starting window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, ShowStartingWindow, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr transitionInfo = new WindowTransitionInfo(); + sptr node = StartingWindow::CreateWindowNode(transitionInfo, 101); // 101 is windowId + node->SetWindowRect({0, 0, 100, 100}); + node->currentVisibility_ = true; + ASSERT_EQ(WMError::WM_ERROR_INVALID_OPERATION, container->ShowStartingWindow(node)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNodeOnWindowTree(node, nullptr)); + node->currentVisibility_ = false; + ASSERT_EQ(WMError::WM_OK, container->ShowStartingWindow(node)); + WindowType invalidType = static_cast(0); + sptr invalidProperty = CreateWindowProperty(110u, "test1", invalidType, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr invalidNode = new WindowNode(invalidProperty, nullptr, nullptr); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container->AddWindowNodeOnWindowTree(invalidNode, nullptr)); + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container->ShowStartingWindow(invalidNode)); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: forbid dock slice move + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, IsForbidDockSliceMove, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + ASSERT_NE(nullptr, container->displayGroupController_); + ASSERT_NE(nullptr, container->displayGroupController_->GetWindowPairByDisplayId(defaultDisplay_->GetId())); + ASSERT_TRUE(!container->IsForbidDockSliceMove(defaultDisplay_->GetId())); +} + +/** + * @tc.name: GetWindowCountByType01 + * @tc.desc: get window count + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, GetWindowCountByType01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + ASSERT_EQ(0, container->GetWindowCountByType(WindowType::BELOW_APP_SYSTEM_WINDOW_BASE)); + sptr property1 = CreateWindowProperty(110u, "test1", WindowType::BELOW_APP_SYSTEM_WINDOW_BASE, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node1 = new WindowNode(property1, nullptr, nullptr); + sptr property2 = CreateWindowProperty(111u, "test2", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node2 = new WindowNode(property2, nullptr, nullptr); + sptr property3 = CreateWindowProperty(112u, "test3", WindowType::ABOVE_APP_SYSTEM_WINDOW_BASE, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node3 = new WindowNode(property3, nullptr, nullptr); + container->belowAppWindowNode_->children_.insert(container->belowAppWindowNode_->children_.end(), node1); + container->appWindowNode_->children_.insert(container->appWindowNode_->children_.end(), node2); + container->aboveAppWindowNode_->children_.insert(container->aboveAppWindowNode_->children_.end(), node3); + ASSERT_EQ(0, container->GetWindowCountByType(WindowType::WINDOW_TYPE_KEYGUARD)); + ASSERT_EQ(1, container->GetWindowCountByType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW)); + ASSERT_EQ(1, container->GetWindowCountByType(WindowType::BELOW_APP_SYSTEM_WINDOW_BASE)); + ASSERT_EQ(1, container->GetWindowCountByType(WindowType::ABOVE_APP_SYSTEM_WINDOW_BASE)); + node1->startingWindowShown_ = true; + node2->startingWindowShown_ = true; + node3->startingWindowShown_ = true; + ASSERT_EQ(0, container->GetWindowCountByType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW)); + ASSERT_EQ(0, container->GetWindowCountByType(WindowType::BELOW_APP_SYSTEM_WINDOW_BASE)); + ASSERT_EQ(0, container->GetWindowCountByType(WindowType::ABOVE_APP_SYSTEM_WINDOW_BASE)); +} + +/** + * @tc.name: IsTileRectSatisfiedWithSizeLimits + * @tc.desc: judge tile rect satisfied with size limits + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, IsTileRectSatisfiedWithSizeLimits, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::ABOVE_APP_SYSTEM_WINDOW_BASE, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + node->SetDisplayId(defaultDisplay_->GetId()); + ASSERT_EQ(defaultDisplay_->GetId(), node->GetDisplayId()); + ASSERT_EQ(WMError::WM_OK, container->IsTileRectSatisfiedWithSizeLimits(node)); + ASSERT_EQ(WMError::WM_OK, container->SwitchLayoutPolicy(WindowLayoutMode::TILE, node->GetDisplayId())); + ASSERT_EQ(WMError::WM_OK, container->IsTileRectSatisfiedWithSizeLimits(node)); +} + +/** + * @tc.name: AddWindowNode01 + * @tc.desc: add main window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, AddWindowNode01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + node->startingWindowShown_ = true; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); +} + +/** + * @tc.name: AddWindowNode02 + * @tc.desc: add sub window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, AddWindowNode02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr subProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_APP_SUB_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + + sptr rootNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(parentNode, rootNode)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNodeOnWindowTree(subNode, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(subNode, parentNode)); +} + +/** + * @tc.name: AddWindowNode03 + * @tc.desc: add system window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, AddWindowNode03, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::ABOVE_APP_SYSTEM_WINDOW_BASE, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); +} + +/** + * @tc.name: RemoveWindowNodeFromWindowTree + * @tc.desc: remove sub window from window tree + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RemoveWindowNodeFromWindowTree, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr subProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_APP_SUB_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + + sptr rootNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(parentNode, rootNode)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNodeOnWindowTree(subNode, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(subNode, parentNode)); + ASSERT_EQ(1, parentNode->children_.size()); + container->RemoveWindowNodeFromWindowTree(subNode); + ASSERT_EQ(0, parentNode->children_.size()); +} + +/** + * @tc.name: RemoveWindowNode01 + * @tc.desc: remove main window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RemoveWindowNode01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr node = nullptr; + ASSERT_EQ(WMError::WM_ERROR_DESTROYED_OBJECT, container->RemoveWindowNode(node)); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->RemoveWindowNode(node)); +} + +/** + * @tc.name: RemoveWindowNode02 + * @tc.desc: remove sub window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RemoveWindowNode02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr subProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_APP_SUB_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + + sptr rootNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(parentNode, rootNode)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNodeOnWindowTree(subNode, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(subNode, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->RemoveWindowNode(subNode)); +} + +/** + * @tc.name: RemoveWindowNode03 + * @tc.desc: remove keyguard window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RemoveWindowNode03, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->RemoveWindowNode(node)); +} + +/** + * @tc.name: RemoveWindowNode04 + * @tc.desc: remove boot animation window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RemoveWindowNode04, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->RemoveWindowNode(node)); +} + +/** + * @tc.name: HandleRemoveWindow01 + * @tc.desc: remove status bar + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, HandleRemoveWindow01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_STATUS_BAR, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->HandleRemoveWindow(node)); +} + +/** + * @tc.name: HandleRemoveWindow02 + * @tc.desc: remove navigation bar + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, HandleRemoveWindow02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_NAVIGATION_BAR, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->HandleRemoveWindow(node)); +} + +/** + * @tc.name: FindDividerNode + * @tc.desc: find divider node + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, FindDividerNode, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + ASSERT_EQ(nullptr, container->FindDividerNode()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->appWindowNode_->children_.size()); + ASSERT_EQ(nullptr, container->FindDividerNode()); + sptr dividerProperty = CreateWindowProperty(112u, "test2", WindowType::WINDOW_TYPE_DOCK_SLICE, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr dividerNode = new WindowNode(dividerProperty, nullptr, nullptr); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(dividerNode, parentNode)); + ASSERT_EQ(2, container->appWindowNode_->children_.size()); + ASSERT_EQ(dividerNode, container->FindDividerNode()); +} + +/** + * @tc.name: RaiseZOrderForAppWindow01 + * @tc.desc: raise main window z order + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RaiseZOrderForAppWindow01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property1 = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node1 = nullptr; + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container->RaiseZOrderForAppWindow(node1, parentNode)); + node1 = new WindowNode(property1, nullptr, nullptr); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node1, parentNode)); + sptr property2 = CreateWindowProperty(112u, "test2", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node2 = new WindowNode(property2, nullptr, nullptr); + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node2, parentNode)); + ASSERT_EQ(WMError::WM_OK, container->RaiseZOrderForAppWindow(node1, parentNode)); +} + +/** + * @tc.name: RaiseZOrderForAppWindow02 + * @tc.desc: raise sub window z order + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RaiseZOrderForAppWindow02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr subProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_APP_SUB_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr subNode = new WindowNode(subProperty, nullptr, nullptr); + sptr rootNode = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container->RaiseZOrderForAppWindow(subNode, rootNode)); + ASSERT_EQ(WMError::WM_OK, container->RaiseZOrderForAppWindow(subNode, parentNode)); +} + +/** + * @tc.name: RaiseZOrderForAppWindow03 + * @tc.desc: raise dialog z order + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RaiseZOrderForAppWindow03, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr parentProperty = CreateWindowProperty(110u, "test1", + WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr parentNode = new WindowNode(parentProperty, nullptr, nullptr); + + sptr dialogProperty = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_DIALOG, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr dialog = new WindowNode(dialogProperty, nullptr, nullptr); + sptr rootNode = nullptr; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container->RaiseZOrderForAppWindow(dialog, rootNode)); + ASSERT_EQ(WMError::WM_OK, container->RaiseZOrderForAppWindow(dialog, parentNode)); +} + +/** + * @tc.name: IsDockSliceInExitSplitModeArea + * @tc.desc: if dock slice in exit split mode area + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, IsDockSliceInExitSplitModeArea, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + ASSERT_NE(nullptr, container->displayGroupController_); + ASSERT_NE(nullptr, container->displayGroupController_->GetWindowPairByDisplayId(defaultDisplay_->GetId())); + ASSERT_TRUE(!container->IsDockSliceInExitSplitModeArea(defaultDisplay_->GetId())); +} + +/** + * @tc.name: ExitSplitMode + * @tc.desc: exit split mode + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, ExitSplitMode, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + ASSERT_NE(nullptr, container->displayGroupController_); + ASSERT_NE(nullptr, container->displayGroupController_->GetWindowPairByDisplayId(defaultDisplay_->GetId())); + container->ExitSplitMode(defaultDisplay_->GetId()); +} + +/** + * @tc.name: MinimizeOldestAppWindow01 + * @tc.desc: minimize main window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, MinimizeOldestAppWindow01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + container->MinimizeOldestAppWindow(); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->appWindowNode_->children_.size()); + container->MinimizeOldestAppWindow(); + ASSERT_EQ(1, MinimizeApp::needMinimizeAppNodes_.size()); + MinimizeApp::needMinimizeAppNodes_.clear(); +} + +/** + * @tc.name: MinimizeOldestAppWindow02 + * @tc.desc: minimize above main window + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, MinimizeOldestAppWindow02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_STATUS_BAR, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->aboveAppWindowNode_->children_.size()); + size_t size = MinimizeApp::needMinimizeAppNodes_.size(); + container->MinimizeOldestAppWindow(); + ASSERT_EQ(size, MinimizeApp::needMinimizeAppNodes_.size()); + MinimizeApp::needMinimizeAppNodes_.clear(); +} + +/** + * @tc.name: ToggleShownStateForAllAppWindows01 + * @tc.desc: toggle shown state for status bar + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, ToggleShownStateForAllAppWindows01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_STATUS_BAR, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr statusBar = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(statusBar, parentNode)); + ASSERT_EQ(1, container->aboveAppWindowNode_->children_.size()); + auto restoreFunc = [](uint32_t windowId, WindowMode mode) { + return false; + }; + ASSERT_EQ(WMError::WM_OK, container->ToggleShownStateForAllAppWindows(restoreFunc, true)); +} + +/** + * @tc.name: ToggleShownStateForAllAppWindows02 + * @tc.desc: toggle shown state for launcher recent + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, ToggleShownStateForAllAppWindows02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test2", + WindowType::WINDOW_TYPE_LAUNCHER_RECENT, WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + sptr statusBar = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(statusBar, parentNode)); + ASSERT_EQ(1, container->aboveAppWindowNode_->children_.size()); + auto restoreFunc = [](uint32_t windowId, WindowMode mode) { + return false; + }; + ASSERT_EQ(WMError::WM_DO_NOTHING, container->ToggleShownStateForAllAppWindows(restoreFunc, true)); +} + +/** + * @tc.name: SetWindowMode01 + * @tc.desc: set main window mode + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, SetWindowMode01, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr node = nullptr; + WindowMode dstMode = WindowMode::WINDOW_MODE_FLOATING; + ASSERT_EQ(WMError::WM_ERROR_NULLPTR, container->SetWindowMode(node, dstMode)); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->appWindowNode_->children_.size()); + dstMode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + container->isScreenLocked_ = false; + ASSERT_EQ(WMError::WM_OK, container->SetWindowMode(node, dstMode)); +} + +/** + * @tc.name: SetWindowMode02 + * @tc.desc: set main window mode with show when locked + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, SetWindowMode02, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + property->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->appWindowNode_->children_.size()); + WindowMode dstMode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY; + container->isScreenLocked_ = true; + ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, container->SetWindowMode(node, dstMode)); +} + +/** + * @tc.name: RemoveSingleUserWindowNodes + * @tc.desc: remove single user window node + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, RemoveSingleUserWindowNodes, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + property->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->appWindowNode_->children_.size()); + int accountId = 0; + container->RemoveSingleUserWindowNodes(accountId); +} + +/** + * @tc.name: TakeWindowPairSnapshot + * @tc.desc: take window pair snapshot + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, TakeWindowPairSnapshot, Function | SmallTest | Level2) +{ + sptr container = new WindowNodeContainer(defaultDisplay_->GetDisplayInfo(), + defaultDisplay_->GetScreenId()); + sptr property = CreateWindowProperty(111u, "test1", WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + WindowMode::WINDOW_MODE_FULLSCREEN, windowRect_); + property->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)); + sptr node = new WindowNode(property, nullptr, nullptr); + sptr parentNode = nullptr; + ASSERT_EQ(WMError::WM_OK, container->AddWindowNode(node, parentNode)); + ASSERT_EQ(1, container->appWindowNode_->children_.size()); + ASSERT_NE(nullptr, container->displayGroupController_); + ASSERT_NE(nullptr, container->displayGroupController_->GetWindowPairByDisplayId(defaultDisplay_->GetId())); + ASSERT_TRUE(!container->TakeWindowPairSnapshot(defaultDisplay_->GetId())); + container->ClearWindowPairSnapshot(defaultDisplay_->GetId()); +} +/** + * @tc.name: Destroy + * @tc.desc: clear vector cache completely, swap with empty vector + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeContainerTest, Destroy, Function | SmallTest | Level2) +{ + ASSERT_EQ(0, container_->Destroy().size()); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_node_test.cpp b/window_manager/wmserver/test/unittest/window_node_test.cpp new file mode 100644 index 0000000..f7b2357 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_node_test.cpp @@ -0,0 +1,868 @@ +/* + * 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 "display_manager.h" +#include "display_manager_config.h" +#include "future.h" +#include "wm_math.h" +#include "window_node.h" +#include "window_node_container.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowNodeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowNodeTest::SetUpTestCase() +{ +} + +void WindowNodeTest::TearDownTestCase() +{ +} + +void WindowNodeTest::SetUp() +{ +} + +void WindowNodeTest::TearDown() +{ +} +class WindowListener : public IWindow { +public: + virtual WMError UpdateWindowRect(const struct Rect& rect, bool decoStatus, WindowSizeChangeReason reason) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateWindowMode(WindowMode mode) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateWindowModeSupportInfo(uint32_t modeSupportInfo) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateFocusStatus(bool focused) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateWindowState(WindowState state) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateWindowDragInfo(const PointInfo& point, DragEvent event) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateDisplayId(DisplayId from, DisplayId to) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateOccupiedAreaChangeInfo(const sptr& info) override + { + return WMError::WM_OK; + }; + virtual WMError UpdateActiveStatus(bool isActive) override + { + return WMError::WM_OK; + }; + virtual sptr GetWindowProperty() override + { + return nullptr; + }; + virtual WMError NotifyTouchOutside() override + { + return WMError::WM_OK; + }; + virtual WMError NotifyScreenshot() override + { + return WMError::WM_OK; + }; + virtual WMError DumpInfo(const std::vector& params) override + { + return WMError::WM_OK; + }; + virtual WMError NotifyDestroy(void) override + { + return WMError::WM_OK; + }; + WMError NotifyForeground(void) override + { + return WMError::WM_OK; + }; + WMError NotifyBackground(void) override + { + return WMError::WM_OK; + }; + virtual WMError NotifyWindowClientPointUp(const std::shared_ptr& pointerEvent) override + { + return WMError::WM_OK; + }; + WMError UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn) override + { + return WMError::WM_OK; + }; + virtual WMError RestoreSplitWindowMode(uint32_t mode) override + { + return WMError::WM_OK; + }; + + virtual sptr AsObject() override + { + return nullptr; + }; +}; + +sptr CreateWindowProperty(uint32_t windowId, const std::string& windowName) +{ + sptr property = new WindowProperty(); + property->SetWindowId(windowId); + property->SetWindowName(windowName); + return property; +} + +RSSurfaceNode::SharedPtr CreateRSSurfaceNode(std::string windowNode) +{ + struct RSSurfaceNodeConfig rsSurfaceNodeConfig; + rsSurfaceNodeConfig.SurfaceNodeName = windowNode; + auto surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig); + return surfaceNode; +} +namespace { +/** + * @tc.name: NewWindowNode01 + * @tc.desc: new window node with WindowProperty + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, NewWindowNode01, Function | SmallTest | Level3) +{ + sptr windowNode1 = new WindowNode(); + ASSERT_NE(nullptr, windowNode1); + ASSERT_EQ("", windowNode1->GetWindowName()); + + std::string windowName = "WindowNode01"; + auto property = CreateWindowProperty(1, windowName); + ASSERT_NE(nullptr, property); + + sptr windowNode2 = new WindowNode(property); + ASSERT_NE(nullptr, windowNode2); + ASSERT_EQ(windowName, windowNode2->GetWindowName()); +} +/** + * @tc.name: NewWindowNode02 + * @tc.desc: new window node with WindowProperty, RSSurfaceNode, IWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, NewWindowNode02, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode02"; + auto property = CreateWindowProperty(2, windowName); + ASSERT_NE(nullptr, property); + + auto surfaceNode = CreateRSSurfaceNode(windowName); + ASSERT_NE(nullptr, surfaceNode); + + sptr iWindow = new WindowListener(); + ASSERT_NE(nullptr, iWindow); + + sptr windowNode = new WindowNode(property, iWindow, surfaceNode); + ASSERT_NE(nullptr, windowNode); + ASSERT_EQ(windowName, windowNode->GetWindowName()); +} +/** + * @tc.name: NewWindowNode03 + * @tc.desc: new window node with WindowProperty, RSSurfaceNode, IWindow, pid , uid + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, NewWindowNode03, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode03"; + auto property = CreateWindowProperty(3, windowName); + ASSERT_NE(nullptr, property); + auto surfaceNode = CreateRSSurfaceNode(windowName); + ASSERT_NE(nullptr, surfaceNode); + sptr iWindow = new Rosen::WindowListener(); + ASSERT_NE(nullptr, iWindow); + + int32_t pid = 1; + int32_t uid = 2; + sptr windowNode = new WindowNode(property, iWindow, surfaceNode, pid, uid); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(1, windowNode->GetInputEventCallingPid()); + ASSERT_EQ(1, windowNode->GetCallingPid()); + ASSERT_EQ(2, windowNode->GetCallingUid()); +} +/** + * @tc.name: SetDisplayId01 + * @tc.desc: SetDisplayId & GetDisplayId + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetDisplayId01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode04"; + auto property = CreateWindowProperty(4, windowName); + ASSERT_NE(nullptr, property); + + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + ASSERT_EQ(0, windowNode->GetDisplayId()); + + windowNode->SetDisplayId(1); + ASSERT_EQ(1, windowNode->GetDisplayId()); +} +/** + * @tc.name: SetEntireWindowTouchHotArea01 + * @tc.desc: SetEntireWindowTouchHotArea & GetEntireWindowTouchHotArea + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetEntireWindowTouchHotArea01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode05"; + auto property = CreateWindowProperty(5, windowName); + ASSERT_NE(nullptr, property); + + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(0, windowNode->GetEntireWindowTouchHotArea().posX_); + ASSERT_EQ(0, windowNode->GetEntireWindowTouchHotArea().posY_); + ASSERT_EQ(0, windowNode->GetEntireWindowTouchHotArea().width_); + ASSERT_EQ(0, windowNode->GetEntireWindowTouchHotArea().height_); + + Rect testValue = { 10, 10, 255, 255 }; + windowNode->SetEntireWindowTouchHotArea(testValue); + ASSERT_EQ(testValue.posX_, windowNode->GetEntireWindowTouchHotArea().posX_); + ASSERT_EQ(testValue.posY_, windowNode->GetEntireWindowTouchHotArea().posY_); + ASSERT_EQ(testValue.width_, windowNode->GetEntireWindowTouchHotArea().width_); + ASSERT_EQ(testValue.height_, windowNode->GetEntireWindowTouchHotArea().height_); +} +/** + * @tc.name: SetEntireWindowPointerHotArea01 + * @tc.desc: SetEntireWindowPointerHotArea & GetEntireWindowPointerHotArea + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetEntireWindowPointerHotArea01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode06"; + auto property = CreateWindowProperty(6, windowName); + ASSERT_NE(nullptr, property); + + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + Rect rect1 = {0, 0, 0, 0}; + windowNode->SetEntireWindowPointerHotArea(rect1); + ASSERT_EQ(0, windowNode->GetEntireWindowPointerHotArea().posX_); + ASSERT_EQ(0, windowNode->GetEntireWindowPointerHotArea().posY_); + ASSERT_EQ(0, windowNode->GetEntireWindowPointerHotArea().width_); + ASSERT_EQ(0, windowNode->GetEntireWindowPointerHotArea().height_); + + Rect rect2 = {10, 10, 255, 255}; + windowNode->SetEntireWindowPointerHotArea(rect2); + ASSERT_EQ(10, windowNode->GetEntireWindowPointerHotArea().posX_); + ASSERT_EQ(10, windowNode->GetEntireWindowPointerHotArea().posY_); + ASSERT_EQ(255, windowNode->GetEntireWindowPointerHotArea().width_); + ASSERT_EQ(255, windowNode->GetEntireWindowPointerHotArea().height_); +} +/** + * @tc.name: SetWindowRect01 + * @tc.desc: SetWindowRect & GetWindowRect + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetWindowRect01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode07"; + auto property = CreateWindowProperty(7, windowName); + ASSERT_NE(nullptr, property); + + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + Rect rect1 = {0, 0, 0, 0}; + windowNode->SetWindowRect(rect1); + ASSERT_EQ(0, windowNode->GetWindowRect().posX_); + ASSERT_EQ(0, windowNode->GetWindowRect().posY_); + ASSERT_EQ(0, windowNode->GetWindowRect().width_); + ASSERT_EQ(0, windowNode->GetWindowRect().height_); + + Rect rect2 = {10, 10, 255, 255}; + windowNode->SetWindowRect(rect2); + ASSERT_EQ(10, windowNode->GetWindowRect().posX_); + ASSERT_EQ(10, windowNode->GetWindowRect().posY_); + ASSERT_EQ(255, windowNode->GetWindowRect().width_); + ASSERT_EQ(255, windowNode->GetWindowRect().height_); +} +/** + * @tc.name: SetDecoStatus01 + * @tc.desc: SetDecoStatus & GetDecoStatus + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetDecoStatus01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode08"; + auto property = CreateWindowProperty(8, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + windowNode->SetDecoStatus(true); + ASSERT_EQ(true, windowNode->GetDecoStatus()); + windowNode->SetDecoStatus(false); + ASSERT_EQ(false, windowNode->GetDecoStatus()); +} +/** + * @tc.name: SetRequestRect01 + * @tc.desc: SetRequestRect & GetRequestRect + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetRequestRect01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode09"; + auto property = CreateWindowProperty(9, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + Rect rect1 = { 0, 0, 0, 0 }; + windowNode->SetRequestRect(rect1); + ASSERT_EQ(0, windowNode->GetRequestRect().posX_); + ASSERT_EQ(0, windowNode->GetRequestRect().posY_); + ASSERT_EQ(0, windowNode->GetRequestRect().width_); + ASSERT_EQ(0, windowNode->GetRequestRect().height_); + + Rect rect2 = { 10, 10, 255, 255 }; + windowNode->SetRequestRect(rect2); + ASSERT_EQ(10, windowNode->GetRequestRect().posX_); + ASSERT_EQ(10, windowNode->GetRequestRect().posY_); + ASSERT_EQ(255, windowNode->GetRequestRect().width_); + ASSERT_EQ(255, windowNode->GetRequestRect().height_); +} +/** + * @tc.name: SetWindowProperty01 + * @tc.desc: SetWindowProperty & GetWindowProperty + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetWindowProperty01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode09"; + auto property = CreateWindowProperty(9, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + ASSERT_EQ(property, windowNode->GetWindowProperty()); + + auto property2 = CreateWindowProperty(10, windowName); + ASSERT_NE(nullptr, property2); + windowNode->SetWindowProperty(property2); + ASSERT_EQ(property2, windowNode->GetWindowProperty()); +} +/** + * @tc.name: SetSystemBarProperty01 + * @tc.desc: SetSystemBarProperty & GetSystemBarProperty + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetSystemBarProperty01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode10"; + auto property = CreateWindowProperty(10, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + SystemBarProperty systemBarProperty1; + SystemBarProperty systemBarProperty2; + SystemBarProperty systemBarProperty3; + windowNode->SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, systemBarProperty1); + windowNode->SetSystemBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_BAR, systemBarProperty2); + windowNode->SetSystemBarProperty(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, systemBarProperty3); + + auto systemBarProperties = windowNode->GetSystemBarProperty(); + ASSERT_EQ(systemBarProperty1, systemBarProperties.find(WindowType::WINDOW_TYPE_STATUS_BAR)->second); + ASSERT_EQ(systemBarProperty2, systemBarProperties.find(WindowType::WINDOW_TYPE_NAVIGATION_BAR)->second); + ASSERT_EQ(systemBarProperties.end(), systemBarProperties.find(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW)); +} +/** + * @tc.name: SetWindowMode01 + * @tc.desc: SetWindowMode & GetWindowMode + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetWindowMode01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode11"; + auto property = CreateWindowProperty(11, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + ASSERT_EQ(WindowMode::WINDOW_MODE_UNDEFINED, windowNode->GetWindowMode()); + + windowNode->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, windowNode->GetWindowMode()); +} +/** + * @tc.name: SetBrightness01 + * @tc.desc: SetBrightness & GetBrightness + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetBrightness01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode12"; + auto property = CreateWindowProperty(12, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(UNDEFINED_BRIGHTNESS, windowNode->GetBrightness()); + + windowNode->SetBrightness(0.5f); + ASSERT_EQ(0.5f, windowNode->GetBrightness()); + windowNode->SetBrightness(1.1f); + ASSERT_EQ(1.1f, windowNode->GetBrightness()); +} +/** + * @tc.name: SetTurnScreenOn01 + * @tc.desc: SetTurnScreenOn & IsTurnScreenOn + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetTurnScreenOn01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode13"; + auto property = CreateWindowProperty(13, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(false, windowNode->IsTurnScreenOn()); + windowNode->SetTurnScreenOn(true); + ASSERT_EQ(true, windowNode->IsTurnScreenOn()); +} +/** + * @tc.name: SetKeepScreenOn01 + * @tc.desc: SetKeepScreenOn & IsKeepScreenOn + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetKeepScreenOn01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode14"; + auto property = CreateWindowProperty(14, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(false, windowNode->IsKeepScreenOn()); + windowNode->SetKeepScreenOn(true); + ASSERT_EQ(true, windowNode->IsKeepScreenOn()); +} +/** + * @tc.name: SetCallingWindow01 + * @tc.desc: SetCallingWindow & GetCallingWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetCallingWindow01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode15"; + auto property = CreateWindowProperty(15, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(INVALID_WINDOW_ID, windowNode->GetCallingWindow()); + windowNode->SetCallingWindow(100); + ASSERT_EQ(100, windowNode->GetCallingWindow()); +} +/** + * @tc.name: SetCallingPid01 + * @tc.desc: SetCallingPid & GetCallingPid, SetInputEventCallingPid & GetInputEventCallingPid + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetCallingPid01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode16"; + auto property = CreateWindowProperty(16, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(0, windowNode->GetCallingPid()); + ASSERT_EQ(0, windowNode->GetInputEventCallingPid()); + + windowNode->SetCallingPid(1); + ASSERT_EQ(1, windowNode->GetCallingPid()); + ASSERT_EQ(1, windowNode->GetInputEventCallingPid()); + + windowNode->SetInputEventCallingPid(2); + ASSERT_EQ(1, windowNode->GetCallingPid()); + ASSERT_EQ(2, windowNode->GetInputEventCallingPid()); +} +/** + * @tc.name: SetCallingUid01 + * @tc.desc: SetCallingUid & GetCallingUid + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetCallingUid01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode17"; + auto property = CreateWindowProperty(17, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(0, windowNode->GetCallingUid()); + + windowNode->SetCallingUid(1); + ASSERT_EQ(1, windowNode->GetCallingUid()); +} +/** + * @tc.name: SetWindowSizeChangeReason01 + * @tc.desc: SetWindowSizeChangeReason & GetWindowSizeChangeReason & ResetWindowSizeChangeReason + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetWindowSizeChangeReason01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode19"; + auto property = CreateWindowProperty(19, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(WindowSizeChangeReason::UNDEFINED, windowNode->GetWindowSizeChangeReason()); + windowNode->SetWindowSizeChangeReason(WindowSizeChangeReason::MAXIMIZE); + ASSERT_EQ(WindowSizeChangeReason::MAXIMIZE, windowNode->GetWindowSizeChangeReason()); + windowNode->ResetWindowSizeChangeReason(); + ASSERT_EQ(WindowSizeChangeReason::UNDEFINED, windowNode->GetWindowSizeChangeReason()); +} +/** + * @tc.name: SetRequestedOrientation01 + * @tc.desc: SetRequestedOrientation & GetRequestedOrientation + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetRequestedOrientation01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode20"; + auto property = CreateWindowProperty(20, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(Orientation::UNSPECIFIED, windowNode->GetRequestedOrientation()); + windowNode->SetRequestedOrientation(Orientation::REVERSE_VERTICAL); + ASSERT_EQ(Orientation::REVERSE_VERTICAL, windowNode->GetRequestedOrientation()); +} +/** + * @tc.name: SetShowingDisplays01 + * @tc.desc: SetShowingDisplays & GetShowingDisplays + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetShowingDisplays01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode21"; + auto property = CreateWindowProperty(21, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + auto displays = windowNode->GetShowingDisplays(); + ASSERT_EQ(true, displays.empty()); + + std::vector emptyDisplayIds; + windowNode->SetShowingDisplays(emptyDisplayIds); + ASSERT_EQ(true, windowNode->GetShowingDisplays().empty()); + + displays.push_back(static_cast(0)); + windowNode->SetShowingDisplays(displays); + ASSERT_EQ(1, windowNode->GetShowingDisplays().size()); +} +/** + * @tc.name: SetModeSupportInfo01 + * @tc.desc: SetModeSupportInfo & GetModeSupportInfo + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetModeSupportInfo01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode22"; + auto property = CreateWindowProperty(22, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(WindowModeSupport::WINDOW_MODE_SUPPORT_ALL, windowNode->GetModeSupportInfo()); + windowNode->SetModeSupportInfo(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN); + ASSERT_EQ(WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN, windowNode->GetModeSupportInfo()); +} +/** + * @tc.name: SetDragType01 + * @tc.desc: SetDragType & GetDragType + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetDragType01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode23"; + auto property = CreateWindowProperty(23, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + ASSERT_EQ(DragType::DRAG_UNDEFINED, windowNode->GetDragType()); + windowNode->SetDragType(DragType::DRAG_BOTTOM_OR_TOP); + ASSERT_EQ(DragType::DRAG_BOTTOM_OR_TOP, windowNode->GetDragType()); +} +/** + * @tc.name: SetOriginRect01 + * @tc.desc: SetOriginRect & GetOriginRect + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetOriginRect01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode24"; + auto property = CreateWindowProperty(24, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + auto defaultRect = windowNode->GetOriginRect(); + ASSERT_EQ(0, defaultRect.posX_); + ASSERT_EQ(0, defaultRect.posX_); + ASSERT_EQ(0, defaultRect.width_); + ASSERT_EQ(0, defaultRect.height_); + + Rect testRect = { 10, 10, 150, 150 }; + windowNode->SetOriginRect(testRect); + auto resultRect = windowNode->GetOriginRect(); + ASSERT_EQ(testRect, resultRect); +} +/** + * @tc.name: SetTouchHotAreas01 + * @tc.desc: SetTouchHotAreas & GetTouchHotAreas + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetTouchHotAreas01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode25"; + auto property = CreateWindowProperty(25, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + std::vector testRects; + windowNode->GetTouchHotAreas(testRects); + ASSERT_EQ(true, testRects.empty()); + + Rect rect1 = { 10, 10, 10, 10 }; + testRects.push_back(rect1); + windowNode->SetTouchHotAreas(testRects); + + std::vector resultRect; + windowNode->GetTouchHotAreas(resultRect); + ASSERT_EQ(1, resultRect.size()); + ASSERT_EQ(rect1, resultRect[0]); +} +/** + * @tc.name: SetPointerHotAreas01 + * @tc.desc: SetPointerHotAreas & GetPointerHotAreas + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetPointerHotAreas01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode26"; + auto property = CreateWindowProperty(26, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + std::vector testRects; + windowNode->GetPointerHotAreas(testRects); + ASSERT_EQ(true, testRects.empty()); + + Rect rect1 = { 10, 10, 10, 10 }; + testRects.push_back(rect1); + windowNode->SetPointerHotAreas(testRects); + std::vector resultRect; + windowNode->GetPointerHotAreas(resultRect); + ASSERT_EQ(1, resultRect.size()); + ASSERT_EQ(rect1, resultRect[0]); +} +/** + * @tc.name: SetPointerHotAreas01 + * @tc.desc: SetWindowSizeLimits & GetWindowSizeLimits + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetWindowSizeLimits01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode27"; + auto property = CreateWindowProperty(27, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + auto defaultValue = windowNode->GetWindowSizeLimits(); + ASSERT_EQ(0, defaultValue.minWidth_); + ASSERT_EQ(0, defaultValue.minHeight_); + ASSERT_EQ(0.0f, defaultValue.minRatio_); + ASSERT_EQ(UINT32_MAX, defaultValue.maxWidth_); + ASSERT_EQ(UINT32_MAX, defaultValue.maxHeight_); + ASSERT_EQ(FLT_MAX, defaultValue.maxRatio_); + + WindowSizeLimits testValue = { 200, 200, 50, 50, 2.0f, 2.0f }; + windowNode->SetWindowSizeLimits(testValue); + + auto resultValue = windowNode->GetWindowSizeLimits(); + ASSERT_EQ(testValue.minWidth_, resultValue.minWidth_); + ASSERT_EQ(testValue.minHeight_, resultValue.minHeight_); + ASSERT_EQ(testValue.minRatio_, resultValue.minRatio_); + ASSERT_EQ(testValue.maxWidth_, resultValue.maxWidth_); + ASSERT_EQ(testValue.maxHeight_, resultValue.maxHeight_); + ASSERT_EQ(testValue.maxRatio_, resultValue.maxRatio_); +} +/** + * @tc.name: SetWindowUpdatedSizeLimits01 + * @tc.desc: SetWindowUpdatedSizeLimits & GetWindowUpdatedSizeLimits + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetWindowUpdatedSizeLimits01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode28"; + auto property = CreateWindowProperty(28, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + auto defaultValue = windowNode->GetWindowUpdatedSizeLimits(); + ASSERT_EQ(0, defaultValue.minWidth_); + ASSERT_EQ(0, defaultValue.minHeight_); + ASSERT_EQ(0.0f, defaultValue.minRatio_); + ASSERT_EQ(UINT32_MAX, defaultValue.maxWidth_); + ASSERT_EQ(UINT32_MAX, defaultValue.maxHeight_); + ASSERT_EQ(FLT_MAX, defaultValue.maxRatio_); + + WindowSizeLimits testValue = { 200, 200, 50, 50, 2.0f, 2.0f }; + windowNode->SetWindowUpdatedSizeLimits(testValue); + + auto resultValue = windowNode->GetWindowUpdatedSizeLimits(); + ASSERT_EQ(testValue.minWidth_, resultValue.minWidth_); + ASSERT_EQ(testValue.minHeight_, resultValue.minHeight_); + ASSERT_EQ(testValue.minRatio_, resultValue.minRatio_); + ASSERT_EQ(testValue.maxWidth_, resultValue.maxWidth_); + ASSERT_EQ(testValue.maxHeight_, resultValue.maxHeight_); + ASSERT_EQ(testValue.maxRatio_, resultValue.maxRatio_); +} +/** + * @tc.name: SetSnapshot01 + * @tc.desc: SetSnapshot & GetSnapshot + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetSnapshot01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode29"; + auto property = CreateWindowProperty(29, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + auto defaultValue = windowNode->GetSnapshot(); + ASSERT_EQ(0, defaultValue.use_count()); + + std::shared_ptr pixelMap = std::make_shared(); + windowNode->SetSnapshot(std::move(pixelMap)); + + auto resultValue = windowNode->GetSnapshot(); + ASSERT_EQ(2, resultValue.use_count()); +} +/** + * @tc.name: UpdateZoomTransform01 + * @tc.desc: UpdateZoomTransform & GetZoomTransform + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, UpdateZoomTransform01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode30"; + auto property = CreateWindowProperty(30, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + Transform transformData; + auto defaultValue = windowNode->GetZoomTransform(); + ASSERT_EQ(transformData, defaultValue); + + transformData.pivotX_ = 1.0f; + transformData.pivotY_ = 1.0f; + windowNode->UpdateZoomTransform(transformData, false); + + auto resultValue = windowNode->GetZoomTransform(); + ASSERT_EQ(1.0f, resultValue.pivotX_); + ASSERT_EQ(1.0f, resultValue.pivotY_); +} +/** + * @tc.name: SetTransform01 + * @tc.desc: SetTransform & ComputeTransform + * @tc.type: FUNC + */ +HWTEST_F(WindowNodeTest, SetTransform01, Function | SmallTest | Level1) +{ + std::string windowName = "WindowNode31"; + auto property = CreateWindowProperty(31, windowName); + ASSERT_NE(nullptr, property); + sptr windowNode = new WindowNode(property); + ASSERT_NE(nullptr, windowNode); + + auto isSameValueMat4 = [](TransformHelper::Matrix4 expectVal, TransformHelper::Matrix4 checkValue) -> bool { + uint32_t m = 0, n = 0; + for (uint32_t i = 0; i < 16; i++) { + m = i / 4; + n = i % 4; + if (m > 4 || n > 4 || (expectVal.mat_[m][n] != checkValue.mat_[m][n])) { + return false; + } + } + return true; + }; + + Transform transformData; + auto defaultTrans = windowNode->property_->trans_; + auto defaultWorldTransformMat4 = windowNode->property_->worldTransformMat_; + ASSERT_EQ(transformData, defaultTrans); + ASSERT_EQ(true, isSameValueMat4(TransformHelper::Matrix4::Identity, defaultWorldTransformMat4)); + + transformData.pivotX_ = 1.0f; + transformData.pivotY_ = 1.0f; + transformData.translateX_ = 1.0f; + transformData.translateY_ = 1.0f; + windowNode->SetTransform(transformData); + windowNode->ComputeTransform(); + + auto resultTrans = windowNode->property_->trans_; + auto resultWorldTransformMat4 = windowNode->property_->worldTransformMat_; + ASSERT_EQ(1.0f, resultTrans.pivotX_); + ASSERT_EQ(1.0f, resultTrans.pivotY_); + + ASSERT_EQ(1.0f, resultWorldTransformMat4.mat_[3][0]); + ASSERT_EQ(1.0f, resultWorldTransformMat4.mat_[3][1]); +} +} +} +} \ No newline at end of file diff --git a/window_manager/wmserver/test/unittest/window_pair_test.cpp b/window_manager/wmserver/test/unittest/window_pair_test.cpp new file mode 100644 index 0000000..ce30bdd --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_pair_test.cpp @@ -0,0 +1,1158 @@ +/* + * 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 "window_pair.h" +#include "minimize_app.h" +#include "common_test_utils.h" +#include "mock_IWindow.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowPairTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void WindowPairTest::SetUpTestCase() +{ +} + +void WindowPairTest::TearDownTestCase() +{ +} + +void WindowPairTest::SetUp() +{ +} + +void WindowPairTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: NotifyShowRecent + * @tc.desc: Send split screen event to notify create recent view. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, NotifyShowRecent01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->primary_ = nullptr; + windowPair->secondary_ = nullptr; + windowPair->NotifyShowRecent(nullptr); + ASSERT_EQ(nullptr, windowPair->primary_); + + sptr property = new WindowProperty(); + property->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr node0 = new WindowNode(property); + windowPair->primary_ = node0; + windowPair->NotifyShowRecent(node0); + + if (windowPair->secondary_ != nullptr) { + ASSERT_EQ(WindowType::WINDOW_TYPE_LAUNCHER_RECENT, windowPair->secondary_->GetWindowType()); + } +} + +/** + * @tc.name: NotifyCreateOrDestroyDivider + * @tc.desc: Send split screen event to notify create or destroy divider window. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, NotifyCreateOrDestroyDivider01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->primary_ = nullptr; + windowPair->NotifyCreateOrDestroyDivider(nullptr, true); + ASSERT_EQ(nullptr, windowPair->primary_); + + sptr property = new WindowProperty(); + property->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr node0 = new WindowNode(property); + windowPair->primary_ = node0; + windowPair->NotifyCreateOrDestroyDivider(node0, true); + ASSERT_EQ(nullptr, windowPair->divider_); +} + +/** + * @tc.name: IsPaired + * @tc.desc: Get whether the window pair is paired + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsPaired01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->primary_ = nullptr; + ASSERT_EQ(false, windowPair->IsPaired()); + windowPair->primary_ = new WindowNode(); + windowPair->secondary_ = nullptr; + ASSERT_EQ(false, windowPair->IsPaired()); +} + +/** + * @tc.name: IsPaired + * @tc.desc: Get whether the window pair is paired + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsPaired02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + windowPair->divider_ = node1; + ASSERT_EQ(true, windowPair->IsPaired()); +} + +/** + * @tc.name: IsPaired + * @tc.desc: Get whether the window pair is paired + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsPaired03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + windowPair->divider_ = nullptr; + ASSERT_EQ(false, windowPair->IsPaired()); +} + +/** + * @tc.name: Find + * @tc.desc: Find window node from window pair + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, Find01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr node1 = nullptr; + ASSERT_EQ(nullptr, windowPair->Find(node1)); +} + +/** + * @tc.name: Find + * @tc.desc: Find window node from window pair + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, Find02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowId(1); + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + ASSERT_EQ(node1, windowPair->Find(node1)); +} + +/** + * @tc.name: Find + * @tc.desc: Find window node from window pair + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, Find03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowId(1); + sptr node1 = new WindowNode(property1); + windowPair->primary_ = nullptr; + windowPair->secondary_ = node1; + ASSERT_EQ(node1, windowPair->Find(node1)); +} + +/** + * @tc.name: Find + * @tc.desc: Find window node from window pair + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, Find04, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowId(1); + sptr node1 = new WindowNode(property1); + windowPair->primary_ = nullptr; + windowPair->secondary_ = nullptr; + windowPair->divider_ = node1; + ASSERT_EQ(node1, windowPair->Find(node1)); +} + +/** + * @tc.name: GetSplitRatio + * @tc.desc: Get split ratio + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetSplitRatio01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->ratio_ = 0; + ASSERT_EQ(0, windowPair->GetSplitRatio()); + windowPair->ratio_ = 5; + ASSERT_EQ(5, windowPair->GetSplitRatio()); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: Get whether dock slice is forbidden to move + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsForbidDockSliceMove01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + ASSERT_EQ(true, windowPair->IsForbidDockSliceMove()); + windowPair->status_ = WindowPairStatus::STATUS_EMPTY; + ASSERT_EQ(false, windowPair->IsForbidDockSliceMove()); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: Get whether dock slice is forbidden to move + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsForbidDockSliceMove02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + sptr property1 = new WindowProperty(); + property1->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + windowPair->primary_ = new WindowNode(property1); + windowPair->secondary_ = new WindowNode(property1); + ASSERT_EQ(false, windowPair->IsForbidDockSliceMove()); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: Get whether dock slice is forbidden to move + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsForbidDockSliceMove03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + sptr property1 = new WindowProperty(); + property1->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + windowPair->primary_ = nullptr; + windowPair->secondary_ = new WindowNode(property1); + ASSERT_EQ(true, windowPair->IsForbidDockSliceMove()); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: Get whether dock slice is forbidden to move + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsForbidDockSliceMove04, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + sptr property1 = new WindowProperty(); + property1->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE)); + windowPair->primary_ = new WindowNode(property1); + windowPair->secondary_ = new WindowNode(property1); + ASSERT_EQ(true, windowPair->IsForbidDockSliceMove()); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: Get whether dock slice is forbidden to move + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsForbidDockSliceMove05, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + sptr property1 = new WindowProperty(); + property1->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + windowPair->primary_ = new WindowNode(property1); + windowPair->secondary_ = nullptr; + ASSERT_EQ(true, windowPair->IsForbidDockSliceMove()); +} + +/** + * @tc.name: IsForbidDockSliceMove + * @tc.desc: Get whether dock slice is forbidden to move + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsForbidDockSliceMove06, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + sptr property1 = new WindowProperty(); + property1->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); + sptr property2 = new WindowProperty(); + property2->SetWindowFlags(static_cast(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE)); + windowPair->primary_ = new WindowNode(property1); + windowPair->secondary_ = new WindowNode(property2); + ASSERT_EQ(true, windowPair->IsForbidDockSliceMove()); +} + +/** + * @tc.name: IsDockSliceInExitSplitModeArea + * @tc.desc: whether dock slice in exit split screen mode area + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsDockSliceInExitSplitModeArea01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + std::vector points {0, 0}; + windowPair->primary_ = nullptr; + ASSERT_EQ(false, windowPair->IsDockSliceInExitSplitModeArea(points)); +} + +/** + * @tc.name: IsDockSliceInExitSplitModeArea + * @tc.desc: whether dock slice in exit split screen mode area + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsDockSliceInExitSplitModeArea02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + std::vector points {2, 0}; + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + sptr property3 = new WindowProperty(); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + Rect rect1 = {1, 1, 10, 20}; + Rect rect2 = {1, 1, 20, 10}; + property2->SetWindowRect(rect1); + property3->SetWindowRect(rect2); + windowPair->divider_ = new WindowNode(property2); + + ASSERT_EQ(true, windowPair->IsPaired()); + ASSERT_EQ(true, windowPair->IsDockSliceInExitSplitModeArea(points)); + windowPair->divider_ = new WindowNode(property3); + ASSERT_EQ(true, windowPair->IsDockSliceInExitSplitModeArea(points)); +} + +/** + * @tc.name: IsDockSliceInExitSplitModeArea + * @tc.desc: whether dock slice in exit split screen mode area + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsDockSliceInExitSplitModeArea03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + std::vector points {0, 50}; + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + Rect rect1 = {1, 1, 10, 20}; + property2->SetWindowRect(rect1); + windowPair->divider_ = new WindowNode(property2); + + ASSERT_EQ(true, windowPair->IsPaired()); + ASSERT_EQ(false, windowPair->IsDockSliceInExitSplitModeArea(points)); +} + +/** + * @tc.name: IsSplitRelated + * @tc.desc: Gets whether the window is related to split window. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsSplitRelated01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr node = nullptr; + ASSERT_EQ(false, windowPair->IsSplitRelated(node)); +} + +/** + * @tc.name: IsSplitRelated + * @tc.desc: Gets whether the window is related to split window. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, IsSplitRelated02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr node1 = new WindowNode(property1); + ASSERT_EQ(true, windowPair->IsSplitRelated(node1)); + property1->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + property1->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + sptr node2 = new WindowNode(property1); + ASSERT_EQ(true, windowPair->IsSplitRelated(node2)); + property1->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + property1->SetWindowType(WindowType::APP_WINDOW_BASE); + sptr node3 = new WindowNode(property1); + ASSERT_EQ(false, windowPair->IsSplitRelated(node3)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr node1 = nullptr; + std::vector> vec; + vec.clear(); + ASSERT_EQ(vec, windowPair->GetOrderedPair(node1)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + + // create window property + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + property0->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + property1->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + + // define primary_, secondary_, divider_ + sptr node1 = new WindowNode(property1); + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property1); + windowPair->divider_ = new WindowNode(property0); + + ASSERT_EQ(3, windowPair->GetOrderedPair(node1).size()); + ASSERT_EQ(windowPair->secondary_, windowPair->GetOrderedPair(node1).at(1)); + ASSERT_EQ(windowPair->primary_, windowPair->GetOrderedPair(node1).at(0)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + + // create window property + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + property0->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + property1->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + + // define primary_, secondary_, divider_ + sptr node1 = new WindowNode(property0); + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property1); + windowPair->divider_ = new WindowNode(property0); + + ASSERT_EQ(3, windowPair->GetOrderedPair(node1).size()); + ASSERT_EQ(windowPair->secondary_, windowPair->GetOrderedPair(node1).at(0)); + ASSERT_EQ(windowPair->primary_, windowPair->GetOrderedPair(node1).at(1)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair04, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + // create window property + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + property0->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + property1->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + // define primary_, secondary_, divider_ + sptr node1 = new WindowNode(property0); + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = nullptr; + windowPair->divider_ = new WindowNode(property0); + ASSERT_EQ(1, windowPair->GetOrderedPair(node1).size()); + ASSERT_EQ(windowPair->divider_, windowPair->GetOrderedPair(node1).at(0)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair05, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + // create window property + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + property0->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + property1->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + // define primary_, secondary_, divider_ + sptr node1 = new WindowNode(property0); + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property0); + windowPair->divider_ = new WindowNode(property0); + ASSERT_EQ(1, windowPair->GetOrderedPair(node1).size()); + ASSERT_EQ(windowPair->divider_, windowPair->GetOrderedPair(node1).at(0)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair06, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + // create window property + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + property0->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + property1->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + // define primary_, secondary_, divider_ + sptr node1 = new WindowNode(property0); + windowPair->primary_ = nullptr; + windowPair->secondary_ = new WindowNode(property1); + windowPair->divider_ = new WindowNode(property0); + ASSERT_EQ(1, windowPair->GetOrderedPair(node1).size()); + ASSERT_EQ(windowPair->divider_, windowPair->GetOrderedPair(node1).at(0)); +} + +/** + * @tc.name: GetOrderedPair + * @tc.desc: Get all window node form pair in Z order. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetOrderedPair07, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + // create window property + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + property0->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + property1->SetWindowType(WindowType::WINDOW_TYPE_DOCK_SLICE); + // define primary_, secondary_, divider_ + sptr node1 = new WindowNode(property0); + windowPair->primary_ = new WindowNode(property1); + windowPair->secondary_ = new WindowNode(property1); + windowPair->divider_ = new WindowNode(property0); + ASSERT_EQ(1, windowPair->GetOrderedPair(node1).size()); + ASSERT_EQ(windowPair->divider_, windowPair->GetOrderedPair(node1).at(0)); +} + +/** + * @tc.name: GetPairedWindows + * @tc.desc: Get all window node form pair. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, GetPairedWindows01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property1); + + // define status_ + windowPair->status_ = WindowPairStatus::STATUS_EMPTY; + + ASSERT_EQ(0, windowPair->GetPairedWindows().size()); + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + ASSERT_EQ(2, windowPair->GetPairedWindows().size()); + ASSERT_EQ(windowPair->secondary_, windowPair->GetPairedWindows().at(1)); + ASSERT_EQ(windowPair->primary_, windowPair->GetPairedWindows().at(0)); +} + +/** + * @tc.name: Clear + * @tc.desc: Clear window pair. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, Clear01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + + // define divider + windowPair->divider_ = new WindowNode(property0); + windowPair->Clear(); + ASSERT_EQ(nullptr, windowPair->divider_); + ASSERT_EQ(WindowPairStatus::STATUS_EMPTY, windowPair->status_); +} + +/** + * @tc.name: UpdateWindowPairStatus + * @tc.desc: Update pair status + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, UpdateWindowPairStatus01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + + // define primary_, secondary_, divider_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property0); + windowPair->divider_ = new WindowNode(property0); + + // define status_ + windowPair->status_ = WindowPairStatus::STATUS_SINGLE_PRIMARY; + + windowPair->UpdateWindowPairStatus(); + ASSERT_EQ(WindowPairStatus::STATUS_PAIRED_DONE, windowPair->status_); +} + +/** + * @tc.name: UpdateWindowPairStatus + * @tc.desc: Update pair status + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, UpdateWindowPairStatus02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + + // define primary_, secondary_, divider_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property0); + windowPair->divider_ = nullptr; + + // define status_ + windowPair->status_ = WindowPairStatus::STATUS_SINGLE_PRIMARY; + + windowPair->UpdateWindowPairStatus(); + ASSERT_EQ(WindowPairStatus::STATUS_PAIRING, windowPair->status_); +} + +/** + * @tc.name: UpdateWindowPairStatus + * @tc.desc: Update pair status + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, UpdateWindowPairStatus03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + + // define primary_, secondary_, divider_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = nullptr; + windowPair->divider_ = new WindowNode(property0); + + // define status_ + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + + windowPair->UpdateWindowPairStatus(); + ASSERT_EQ(WindowPairStatus::STATUS_EMPTY, windowPair->status_); + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(nullptr, windowPair->secondary_); + ASSERT_EQ(nullptr, windowPair->divider_); +} + +/** + * @tc.name: UpdateWindowPairStatus + * @tc.desc: Update pair status + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, UpdateWindowPairStatus04, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + + // define primary_, secondary_, divider_ + windowPair->primary_ = nullptr; + windowPair->secondary_ = new WindowNode(property0); + windowPair->divider_ = new WindowNode(property0); + + // define status_ + windowPair->status_ = WindowPairStatus::STATUS_EMPTY; + + sptr node1 = windowPair->secondary_; + sptr node2 = windowPair->divider_; + windowPair->UpdateWindowPairStatus(); + ASSERT_EQ(WindowPairStatus::STATUS_SINGLE_SECONDARY, windowPair->status_); + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(node1, windowPair->secondary_); + ASSERT_EQ(node2, windowPair->divider_); +} + +/** + * @tc.name: UpdateWindowPairStatus + * @tc.desc: Update pair status + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, UpdateWindowPairStatus05, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + + // define primary_, secondary_, divider_ + windowPair->primary_ = nullptr; + windowPair->secondary_ = nullptr; + windowPair->divider_ = new WindowNode(property0); + + // define status_ + windowPair->status_ = WindowPairStatus::STATUS_SINGLE_PRIMARY; + + sptr node1 = windowPair->divider_; + windowPair->UpdateWindowPairStatus(); + ASSERT_EQ(WindowPairStatus::STATUS_EMPTY, windowPair->status_); + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(nullptr, windowPair->secondary_); + ASSERT_EQ(node1, windowPair->divider_); +} + +/** + * @tc.name: SwitchPosition + * @tc.desc: Switch the position of two paired window. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, SwitchPosition01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + + // define primary_, secondary_, divider_ + windowPair->primary_ = nullptr; + windowPair->secondary_ = nullptr; + windowPair->divider_ = new WindowNode(property0); + + sptr node1 = windowPair->divider_; + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(nullptr, windowPair->secondary_); + ASSERT_EQ(node1, windowPair->divider_); +} + +/** + * @tc.name: SwitchPosition + * @tc.desc: Switch the position of two paired window. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, SwitchPosition02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property1); + + windowPair->SwitchPosition(); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, windowPair->primary_->GetWindowMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, windowPair->secondary_->GetWindowMode()); +} + +/** + * @tc.name: SwitchPosition + * @tc.desc: Switch the position of two paired window. + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, SwitchPosition03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property1); + + windowPair->SwitchPosition(); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, windowPair->primary_->GetWindowMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, windowPair->secondary_->GetWindowMode()); +} + +/** + * @tc.name: HandlePairedNodesChange + * @tc.desc: Update paired window node + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandlePairedNodesChange01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property0); + + windowPair->HandlePairedNodesChange(); + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(nullptr, windowPair->secondary_); + ASSERT_EQ(WindowPairStatus::STATUS_EMPTY, windowPair->status_); +} + +/** + * @tc.name: HandlePairedNodesChange + * @tc.desc: Update paired window node + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandlePairedNodesChange02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property0); + windowPair->secondary_ = new WindowNode(property1); + + sptr tmp_node = windowPair->secondary_; + windowPair->HandlePairedNodesChange(); + ASSERT_EQ(tmp_node, windowPair->primary_); + ASSERT_EQ(nullptr, windowPair->secondary_); + ASSERT_EQ(WindowPairStatus::STATUS_SINGLE_PRIMARY, windowPair->status_); +} + +/** + * @tc.name: HandlePairedNodesChange + * @tc.desc: Update paired window node + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandlePairedNodesChange03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + + // define primary_, secondary_ + windowPair->primary_ = nullptr; + windowPair->secondary_ = new WindowNode(property0); + + windowPair->HandlePairedNodesChange(); + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(nullptr, windowPair->secondary_); + ASSERT_EQ(WindowPairStatus::STATUS_EMPTY, windowPair->status_); +} + +/** + * @tc.name: HandlePairedNodesChange + * @tc.desc: Update paired window node + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandlePairedNodesChange04, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property0 = new WindowProperty(); + property0->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property2); + windowPair->secondary_ = new WindowNode(property0); + + sptr tmp_node = windowPair->primary_; + windowPair->HandlePairedNodesChange(); + ASSERT_EQ(nullptr, windowPair->primary_); + ASSERT_EQ(tmp_node, windowPair->secondary_); + ASSERT_EQ(WindowPairStatus::STATUS_SINGLE_SECONDARY, windowPair->status_); +} + +/** + * @tc.name: HandlePairedNodesChange + * @tc.desc: Update paired window node + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandlePairedNodesChange05, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + + // define primary_, secondary_ + windowPair->primary_ = new WindowNode(property1); + windowPair->secondary_ = new WindowNode(property2); + + windowPair->HandlePairedNodesChange(); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, windowPair->primary_->GetWindowMode()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, windowPair->secondary_->GetWindowMode()); +} + +/** + * @tc.name: HandleRemoveWindow + * @tc.desc: Handle removed window + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandleRemoveWindow01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + windowPair->primary_ = new WindowNode(property1); + + sptr node = nullptr; + windowPair->HandleRemoveWindow(node); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, windowPair->primary_->GetWindowMode()); +} + +/** + * @tc.name: HandleRemoveWindow + * @tc.desc: Handle removed window + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, HandleRemoveWindow02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + + sptr node1 = new WindowNode(property1); + sptr node2 = new WindowNode(property1); + + // define primary_, secondary_, status_ + windowPair->primary_ = nullptr; + windowPair->secondary_ = nullptr; + windowPair->divider_ = nullptr; + windowPair->status_ = WindowPairStatus::STATUS_PAIRING; + + IWindowMocker* w = new IWindowMocker; + sptr window(w); + node1->SetWindowToken(window); + EXPECT_CALL(*w, UpdateWindowMode(_)).Times(1).WillOnce(Return(WMError::WM_OK)); + windowPair->HandleRemoveWindow(node1); + ASSERT_EQ(nullptr, windowPair->primary_); + sptr window1 = nullptr; + node1->SetWindowToken(window1); + windowPair->HandleRemoveWindow(node1); + ASSERT_EQ(nullptr, windowPair->primary_); +} + +/** + * @tc.name: TakePairSnapshot + * @tc.desc: take pair snapsht + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, TakePairSnapshot01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + sptr node1 = new WindowNode(property1); + sptr node2 = new WindowNode(property2); + + // define primary_, secondary_, status_ + windowPair->primary_ = node1; + windowPair->secondary_ = node2; + windowPair->status_ = WindowPairStatus::STATUS_PAIRED_DONE; + + ASSERT_EQ(true, windowPair->TakePairSnapshot()); + windowPair->primary_ = nullptr; + ASSERT_EQ(false, windowPair->TakePairSnapshot()); + windowPair->primary_ = node1; + windowPair->secondary_ = nullptr; + ASSERT_EQ(false, windowPair->TakePairSnapshot()); + windowPair->status_ = WindowPairStatus::STATUS_PAIRING; + ASSERT_EQ(false, windowPair->TakePairSnapshot()); +} + +/** + * @tc.name: ClearPairSnapshot + * @tc.desc: Clear Pair Snapshot + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, ClearPairSnapshot01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + sptr node1 = new WindowNode(property1); + sptr node2 = new WindowNode(property2); + + // define primary_, secondary_, + windowPair->primary_ = node1; + windowPair->secondary_ = node2; + + windowPair->ClearPairSnapshot(); + ASSERT_EQ(nullptr, windowPair->primary_->snapshot_); + ASSERT_EQ(nullptr, windowPair->secondary_->snapshot_); + + windowPair->primary_ = nullptr; + ASSERT_EQ(false, windowPair->TakePairSnapshot()); + windowPair->primary_ = node1; + windowPair->secondary_ = nullptr; + ASSERT_EQ(false, windowPair->TakePairSnapshot()); + windowPair->status_ = WindowPairStatus::STATUS_PAIRING; + ASSERT_EQ(false, windowPair->TakePairSnapshot()); +} +/** + * @tc.name: ExitSplitMode + * @tc.desc: Exit Split Mode + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, ExitSplitMode01, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + windowPair->divider_ = nullptr; + windowPair->ExitSplitMode(); + ASSERT_EQ(nullptr, windowPair->divider_); +} +/** + * @tc.name: ExitSplitMode + * @tc.desc: Exit Split Mode + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, ExitSplitMode02, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + sptr property3 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + sptr node3 = new WindowNode(property3); + const Rect divider_rect2 = {0, 20, 100, 1}; + const Rect primary_rect1 = {0, 0, 20, 20}; + const Rect secondary_rect1 = {0, 20, 50, 70}; + const Rect secondary_rect2 = {0, 20, 10, 10}; + node3->SetWindowRect(divider_rect2); + node1->SetWindowRect(primary_rect1); + node2->SetWindowRect(secondary_rect1); + windowPair->divider_ = node3; + windowPair->primary_ = node1; + windowPair->secondary_ = node2; + windowPair->ExitSplitMode(); + std::vector> vec1 = MinimizeApp::needMinimizeAppNodes_[MinimizeReason::SPLIT_QUIT]; + ASSERT_EQ(0, vec1.size()); + node2->SetWindowRect(secondary_rect2); + windowPair->secondary_ = node2; + windowPair->ExitSplitMode(); + std::vector> vec2 = MinimizeApp::needMinimizeAppNodes_[MinimizeReason::SPLIT_QUIT]; + ASSERT_EQ(0, vec2.size()); + windowPair->Clear(); +} +/** + * @tc.name: ExitSplitMode + * @tc.desc: Exit Split Mode + * @tc.type: FUNC + */ +HWTEST_F(WindowPairTest, ExitSplitMode03, Function | SmallTest | Level2) +{ + sptr windowPair = new WindowPair(0); + sptr property1 = new WindowProperty(); + property1->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY); + sptr property2 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY); + sptr property3 = new WindowProperty(); + property2->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + + sptr node1 = new WindowNode(property1); + windowPair->primary_ = node1; + sptr node2 = new WindowNode(property2); + windowPair->secondary_ = node2; + sptr node3 = new WindowNode(property3); + const Rect divider_rect1 = {20, 0, 1, 100}; + const Rect primary_rect1 = {0, 0, 20, 20}; + const Rect secondary_rect1 = {0, 20, 50, 70}; + const Rect secondary_rect2 = {0, 20, 10, 20}; + node3->SetWindowRect(divider_rect1); // is_vertical false + node2->SetWindowRect(secondary_rect1); + node1->SetWindowRect(primary_rect1); + windowPair->divider_ = node3; + windowPair->primary_ = node1; + windowPair->secondary_ = node2; + windowPair->ExitSplitMode(); + std::vector> vec1 = MinimizeApp::needMinimizeAppNodes_[MinimizeReason::SPLIT_QUIT]; + ASSERT_EQ(0, vec1.size()); + node2->SetWindowRect(secondary_rect2); + windowPair->secondary_ = node2; + std::vector> vec2 = MinimizeApp::needMinimizeAppNodes_[MinimizeReason::SPLIT_QUIT]; + ASSERT_EQ(0, vec2.size()); + windowPair->Clear(); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_root_test.cpp b/window_manager/wmserver/test/unittest/window_root_test.cpp new file mode 100644 index 0000000..ca4b593 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_root_test.cpp @@ -0,0 +1,501 @@ +/* + * 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 "window_root.h" +#include "window_manager.h" +#include "display_manager.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS { +namespace Rosen { + +class WindowRootTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + static sptr windowRoot_; +}; + +sptr WindowRootTest::windowRoot_ = nullptr; + +void WindowRootTest::SetUpTestCase() +{ +} + +void WindowRootTest::TearDownTestCase() +{ +} + +void WindowRootTest::SetUp() +{ + windowRoot_ = new WindowRoot(nullptr); +} + +void WindowRootTest::TearDown() +{ + windowRoot_ = nullptr; +} + +namespace { +/** + * @tc.name: WindowRootTest01 + * @tc.desc: test WindowRoot GetTotalWindowNum + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest01, Function | SmallTest | Level2) +{ + uint32_t size = windowRoot_->GetTotalWindowNum(); + ASSERT_EQ(size, 0); +} + +/** + * @tc.name: WindowRootTest02 + * @tc.desc: test WindowRoot GetWindowForDumpAceHelpInfo + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest02, Function | SmallTest | Level2) +{ + sptr property = new WindowProperty(); + property->SetWindowType(WindowType::WINDOW_TYPE_DESKTOP); + sptr windowNode = new WindowNode(property); + windowRoot_->SaveWindow(windowNode); + sptr node = windowRoot_->GetWindowForDumpAceHelpInfo(); + ASSERT_NE(node, nullptr); + windowRoot_->DestroyWindowInner(windowNode); + + property = new WindowProperty(); + property->SetWindowType(WindowType::WINDOW_TYPE_NAVIGATION_BAR); + windowNode = new WindowNode(property); + windowRoot_->SaveWindow(windowNode); + node = windowRoot_->GetWindowForDumpAceHelpInfo(); + ASSERT_NE(node, nullptr); + windowRoot_->DestroyWindowInner(windowNode); + + property = new WindowProperty(); + property->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR); + windowNode = new WindowNode(property); + windowRoot_->SaveWindow(windowNode); + node = windowRoot_->GetWindowForDumpAceHelpInfo(); + ASSERT_NE(node, nullptr); + windowRoot_->DestroyWindowInner(windowNode); + + property = new WindowProperty(); + property->SetWindowType(WindowType::WINDOW_TYPE_KEYGUARD); + windowNode = new WindowNode(property); + windowRoot_->SaveWindow(windowNode); + node = windowRoot_->GetWindowForDumpAceHelpInfo(); + ASSERT_NE(node, nullptr); + windowRoot_->DestroyWindowInner(windowNode); +} + +/** + * @tc.name: WindowRootTest03 + * @tc.desc: test WindowRoot CreateWindowNodeContainer + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest03, Function | SmallTest | Level2) +{ + sptr displayInfo = new DisplayInfo(); + + displayInfo->SetWidth(49); + auto container = windowRoot_->CreateWindowNodeContainer(displayInfo); + ASSERT_EQ(container, nullptr); + + displayInfo->SetWidth(7681); + container = windowRoot_->CreateWindowNodeContainer(displayInfo); + ASSERT_EQ(container, nullptr); + + displayInfo->SetWidth(50); + displayInfo->SetHeight(49); + container = windowRoot_->CreateWindowNodeContainer(displayInfo); + ASSERT_EQ(container, nullptr); + + displayInfo->SetHeight(7681); + container = windowRoot_->CreateWindowNodeContainer(displayInfo); + ASSERT_EQ(container, nullptr); +} + +/** + * @tc.name: WindowRootTest04 + * @tc.desc: test WindowRoot GetWindowNodeContainer + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest04, Function | SmallTest | Level2) +{ + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_NE(display, nullptr); + sptr displayInfo = display->GetDisplayInfo(); + ASSERT_NE(displayInfo, nullptr); + displayInfo->SetDisplayId(0); + displayInfo->SetScreenGroupId(SCREEN_ID_INVALID); + auto container = windowRoot_->CreateWindowNodeContainer(displayInfo); + ASSERT_NE(container, nullptr); + + windowRoot_->GetWindowNodeContainer(DISPLAY_ID_INVALID); +} + +/** + * @tc.name: WindowRootTest05 + * @tc.desc: test WindowRoot GetBackgroundNodesByScreenId + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest05, Function | SmallTest | Level2) +{ + std::vector> windowNodes; + + sptr property = new WindowProperty(); + property->SetDisplayId(DISPLAY_ID_INVALID); + sptr windowNode1 = new WindowNode(property); + windowRoot_->SaveWindow(windowNode1); + property->SetDisplayId(0); + sptr windowNode2 = new WindowNode(property); + windowRoot_->SaveWindow(windowNode2); + + auto screenGroupId = DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(DISPLAY_ID_INVALID); + windowRoot_->GetBackgroundNodesByScreenId(screenGroupId, windowNodes); + + windowRoot_->DestroyWindowInner(windowNode1); + windowRoot_->DestroyWindowInner(windowNode2); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest06 + * @tc.desc: test WindowRoot AddDeathRecipient + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest06, Function | SmallTest | Level2) +{ + windowRoot_->AddDeathRecipient(nullptr); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest07 + * @tc.desc: test WindowRoot SaveWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest07, Function | SmallTest | Level2) +{ + windowRoot_->SaveWindow(nullptr); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest08 + * @tc.desc: test WindowRoot MinimizeStructuredAppWindowsExceptSelf + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest08, Function | SmallTest | Level2) +{ + sptr property = new WindowProperty(); + property->SetDisplayId(DISPLAY_ID_INVALID); + sptr windowNode = new WindowNode(property); + + WMError ret = windowRoot_->MinimizeStructuredAppWindowsExceptSelf(windowNode); + + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); +} + +/** + * @tc.name: WindowRootTest09 + * @tc.desc: test WindowRoot MinimizeTargetWindows + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest09, Function | SmallTest | Level2) +{ + std::vector windowIds; + + windowRoot_->MinimizeTargetWindows(windowIds); + + windowIds.push_back(INVALID_WINDOW_ID); + windowRoot_->MinimizeTargetWindows(windowIds); + + sptr property = new WindowProperty(); + property->SetWindowId(1); + property->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); + auto windowNode = new WindowNode(property); + windowRoot_->SaveWindow(windowNode); + property = new WindowProperty(); + property->SetWindowId(2); + property->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + windowNode = new WindowNode(property); + windowRoot_->SaveWindow(windowNode); + windowIds.push_back(1); + windowIds.push_back(2); + windowRoot_->MinimizeTargetWindows(windowIds); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest10 + * @tc.desc: test WindowRoot GetSplitScreenWindowNodes + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest10, Function | SmallTest | Level2) +{ + std::vector> windowNodes = windowRoot_->GetSplitScreenWindowNodes(DISPLAY_ID_INVALID); + ASSERT_EQ(windowNodes.empty(), true); +} + +/** + * @tc.name: WindowRootTest11 + * @tc.desc: test WindowRoot IsForbidDockSliceMove + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest11, Function | SmallTest | Level2) +{ + bool ret = windowRoot_->IsForbidDockSliceMove(DISPLAY_ID_INVALID); + ASSERT_EQ(ret, true); + + ret = windowRoot_->IsForbidDockSliceMove(0); + ASSERT_EQ(ret, true); +} + +/** + * @tc.name: WindowRootTest12 + * @tc.desc: test WindowRoot IsDockSliceInExitSplitModeArea + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest12, Function | SmallTest | Level2) +{ + bool ret = windowRoot_->IsDockSliceInExitSplitModeArea(DISPLAY_ID_INVALID); + ASSERT_EQ(ret, false); + + ret = windowRoot_->IsDockSliceInExitSplitModeArea(0); + ASSERT_EQ(ret, false); +} + +/** + * @tc.name: WindowRootTest13 + * @tc.desc: test WindowRoot ExitSplitMode + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest13, Function | SmallTest | Level2) +{ + windowRoot_->ExitSplitMode(DISPLAY_ID_INVALID); + + windowRoot_->ExitSplitMode(0); + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest14 + * @tc.desc: test WindowRoot AddSurfaceNodeIdWindowNodePair + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest14, Function | SmallTest | Level2) +{ + windowRoot_->AddSurfaceNodeIdWindowNodePair(INVALID_WINDOW_ID, nullptr); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest15 + * @tc.desc: test WindowRoot GetVisibilityWindowInfo + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest15, Function | SmallTest | Level2) +{ + std::vector> infos = {}; + + windowRoot_->GetVisibilityWindowInfo(infos); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest16 + * @tc.desc: test WindowRoot GetAvoidAreaByType + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest16, Function | SmallTest | Level2) +{ + AvoidArea emptyArea; + AvoidArea area; + sptr node = new WindowNode(); + + area = windowRoot_->GetAvoidAreaByType(node->GetWindowId(), AvoidAreaType::TYPE_CUTOUT); + ASSERT_EQ(area, emptyArea); + + windowRoot_->windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node)); + area = windowRoot_->GetAvoidAreaByType(node->GetWindowId(), AvoidAreaType::TYPE_CUTOUT); + ASSERT_EQ(area, emptyArea); +} + +/** + * @tc.name: WindowRootTest17 + * @tc.desc: test WindowRoot MinimizeAllAppWindows + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest17, Function | SmallTest | Level2) +{ + windowRoot_->MinimizeAllAppWindows(DISPLAY_ID_INVALID); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest18 + * @tc.desc: test WindowRoot DestroyLeakStartingWindow + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest18, Function | SmallTest | Level2) +{ + windowRoot_->DestroyLeakStartingWindow(); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest19 + * @tc.desc: test WindowRoot PostProcessAddWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest19, Function | SmallTest | Level2) +{ + WMError ret; + sptr node = new WindowNode(); + sptr parentNode = nullptr; + sptr displayInfo = new DisplayInfo(); + sptr container = new WindowNodeContainer(displayInfo, SCREEN_ID_INVALID); + + ret = windowRoot_->PostProcessAddWindowNode(node, parentNode, container); + ASSERT_EQ(ret, WMError::WM_DO_NOTHING); + + node->currentVisibility_ = true; + node->GetWindowProperty()->SetWindowType(WindowType::APP_SUB_WINDOW_BASE); + ret = windowRoot_->PostProcessAddWindowNode(node, parentNode, container); + ASSERT_EQ(ret, WMError::WM_ERROR_INVALID_TYPE); + + node->currentVisibility_ = true; + node->property_->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR); + node->GetWindowProperty()->SetFocusable(false); + sptr child = new WindowNode(); + child->currentVisibility_ = true; + node->children_.push_back(child); + node->children_.push_back(nullptr); + ret = windowRoot_->PostProcessAddWindowNode(node, parentNode, container); + ASSERT_EQ(ret, WMError::WM_OK); +} + +/** + * @tc.name: WindowRootTest20 + * @tc.desc: test WindowRoot LayoutWhenAddWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest20, Function | SmallTest | Level2) +{ + sptr node = nullptr; + windowRoot_->LayoutWhenAddWindowNode(node, true); + + node = new WindowNode(); + windowRoot_->LayoutWhenAddWindowNode(node, true); + + ASSERT_EQ(true, true); +} + +/** + * @tc.name: WindowRootTest21 + * @tc.desc: test WindowRoot AddWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest21, Function | SmallTest | Level2) +{ + WMError ret; + sptr node = nullptr; + + ret = windowRoot_->AddWindowNode(INVALID_WINDOW_ID, node, true); + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); +} + +/** + * @tc.name: WindowRootTest22 + * @tc.desc: test WindowRoot RemoveWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest22, Function | SmallTest | Level2) +{ + WMError ret; + sptr node = new WindowNode(); + + windowRoot_->windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node)); + ret = windowRoot_->RemoveWindowNode(node->GetWindowId(), true); + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); +} + +/** + * @tc.name: WindowRootTest23 + * @tc.desc: test WindowRoot UpdateWindowNode + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest23, Function | SmallTest | Level2) +{ + WMError ret; + + ret = windowRoot_->UpdateWindowNode(INVALID_WINDOW_ID, WindowUpdateReason::UPDATE_MODE); + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); + + sptr node = new WindowNode(); + windowRoot_->windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node)); + ret = windowRoot_->UpdateWindowNode(node->GetWindowId(), WindowUpdateReason::UPDATE_MODE); + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); +} + +/** + * @tc.name: WindowRootTest24 + * @tc.desc: test WindowRoot UpdateSizeChangeReason + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest24, Function | SmallTest | Level2) +{ + WMError ret; + + ret = windowRoot_->UpdateSizeChangeReason(INVALID_WINDOW_ID, WindowSizeChangeReason::UNDEFINED); + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); + + sptr node = new WindowNode(); + windowRoot_->windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node)); + ret = windowRoot_->UpdateSizeChangeReason(node->GetWindowId(), WindowSizeChangeReason::UNDEFINED); + ASSERT_EQ(ret, WMError::WM_ERROR_NULLPTR); +} + +/** + * @tc.name: WindowRootTest25 + * @tc.desc: test WindowRoot SetBrightness + * @tc.type: FUNC + */ +HWTEST_F(WindowRootTest, WindowRootTest25, Function | SmallTest | Level2) +{ + windowRoot_->SetBrightness(INVALID_WINDOW_ID, 0); + + sptr node = new WindowNode(); + windowRoot_->windowNodeMap_.insert(std::make_pair(node->GetWindowId(), node)); + windowRoot_->SetBrightness(node->GetWindowId(), 0); + + ASSERT_EQ(true, true); +} +} +} +} diff --git a/window_manager/wmserver/test/unittest/window_snapshot_test.cpp b/window_manager/wmserver/test/unittest/window_snapshot_test.cpp new file mode 100644 index 0000000..00807a0 --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_snapshot_test.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2021-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 "snapshot_controller.h" +#include "wm_common.h" +#include "iremote_object_mocker.h" +#include "common_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowSnapshotTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowSnapshotTest::SetUpTestCase() +{ +} + +void WindowSnapshotTest::TearDownTestCase() +{ +} + +void WindowSnapshotTest::SetUp() +{ +} + +void WindowSnapshotTest::TearDown() +{ +} + +namespace { +/** + * @tc.name: GetSnapshot + * @tc.desc: GetSnapshot when parameter abilityToken is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSnapshotTest, GetSnapshot01, Function | SmallTest | Level3) +{ + sptr root = nullptr; + std::shared_ptr handler = nullptr; + sptr snapshotController_ = new SnapshotController(root, handler); + AAFwk::Snapshot snapshot_; + ASSERT_EQ(static_cast(WMError::WM_ERROR_NULLPTR), snapshotController_->GetSnapshot(nullptr, snapshot_)); +} + +/** + * @tc.name: GetSnapshot + * @tc.desc: GetSnapshot when parameter abilityToken is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSnapshotTest, GetSnapshot02, Function | SmallTest | Level3) +{ + sptr root = nullptr; + std::shared_ptr handler = nullptr; + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + + sptr snapshotController_ = new SnapshotController(root, handler); + AAFwk::Snapshot snapshot_; + ASSERT_EQ(static_cast(WMError::WM_ERROR_NULLPTR), + snapshotController_->GetSnapshot(iRemoteObjectMocker, snapshot_)); +} + +/** + * @tc.name: GetSnapshot + * @tc.desc: GetSnapshot when parameter abilityToken is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSnapshotTest, GetSnapshot03, Function | SmallTest | Level3) +{ + auto runner = AppExecFwk::EventRunner::Create("TestRunner"); + auto handler = std::make_shared(runner); + sptr root = nullptr; + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + + sptr snapshotController_ = new SnapshotController(root, handler); + AAFwk::Snapshot snapshot_; + ASSERT_EQ(static_cast(WMError::WM_ERROR_NULLPTR), + snapshotController_->GetSnapshot(iRemoteObjectMocker, snapshot_)); +} + +/** + * @tc.name: GetSnapshot + * @tc.desc: GetSnapshot when parameter abilityToken is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSnapshotTest, GetSnapshot04, Function | SmallTest | Level3) +{ + auto runner = AppExecFwk::EventRunner::Create("TestRunner"); + auto handler = std::make_shared(runner); + + sptr root = new WindowRoot([](Event event, const sptr& remoteObject) {}); + sptr node = new WindowNode(); + root->windowNodeMap_.insert(std::make_pair(0, node)); + + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + node->abilityToken_ = iRemoteObjectMocker; + + sptr snapshotController_ = new SnapshotController(root, handler); + AAFwk::Snapshot snapshot_; + ASSERT_EQ(static_cast(WMError::WM_ERROR_NULLPTR), + snapshotController_->GetSnapshot(iRemoteObjectMocker, snapshot_)); + + sptr iRemoteObjectMockerInvalid = new IRemoteObjectMocker(); + ASSERT_EQ(static_cast(WMError::WM_ERROR_NULLPTR), + snapshotController_->GetSnapshot(iRemoteObjectMockerInvalid, snapshot_)); +} + +/** + * @tc.name: GetSnapshot + * @tc.desc: GetSnapshot when parameter abilityToken is nullptr + * @tc.type: FUNC + */ +HWTEST_F(WindowSnapshotTest, GetSnapshot05, Function | SmallTest | Level3) +{ + auto runner = AppExecFwk::EventRunner::Create("TestRunner"); + auto handler = std::make_shared(runner); + + sptr root = new WindowRoot([](Event event, const sptr& remoteObject) {}); + sptr node = new WindowNode(); + root->windowNodeMap_.insert(std::make_pair(0, node)); + + sptr iRemoteObjectMocker = new IRemoteObjectMocker(); + node->abilityToken_ = iRemoteObjectMocker; + node->SetSnapshot(CommonTestUtils::CreatePixelMap()); + + sptr snapshotController_ = new SnapshotController(root, handler); + AAFwk::Snapshot snapshot_; + ASSERT_EQ(static_cast(WMError::WM_OK), snapshotController_->GetSnapshot(iRemoteObjectMocker, snapshot_)); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/window_manager/wmserver/test/unittest/window_zorder_policy_test.cpp b/window_manager/wmserver/test/unittest/window_zorder_policy_test.cpp new file mode 100644 index 0000000..33a21dd --- /dev/null +++ b/window_manager/wmserver/test/unittest/window_zorder_policy_test.cpp @@ -0,0 +1,73 @@ +/* + * 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 "window_zorder_policy.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +class WindowZorderPolicyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; +}; + +void WindowZorderPolicyTest::SetUpTestCase() +{ +} + +void WindowZorderPolicyTest::TearDownTestCase() +{ +} + +void WindowZorderPolicyTest::SetUp() +{ +} + +void WindowZorderPolicyTest::TearDown() +{ +} +namespace { +/** + * @tc.name: GetWindowPriority01 + * @tc.desc: get wallpaper window zorder + * @tc.type: FUNC + */ +HWTEST_F(WindowZorderPolicyTest, GetWindowPriority01, Function | SmallTest | Level2) +{ + sptr zorderPolicy = new WindowZorderPolicy(); + int32_t zorder = zorderPolicy->GetWindowPriority(WindowType::WINDOW_TYPE_DESKTOP); + ASSERT_EQ(zorder, 1); +} + +/** + * @tc.name: GetWindowPriority02 + * @tc.desc: get invalid type window zorder + * @tc.type: FUNC + */ +HWTEST_F(WindowZorderPolicyTest, GetWindowPriority02, Function | SmallTest | Level2) +{ + sptr zorderPolicy = new WindowZorderPolicy(); + int32_t zorder = zorderPolicy->GetWindowPriority(static_cast(3000)); + ASSERT_EQ(zorder, 0); +} +} +} +} \ No newline at end of file -- Gitee