1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17 #include <transaction/rs_transaction.h>
18 #include <ui/rs_surface_node.h>
19 #include "display_test_utils.h"
20 #include "display.h"
21 #include "display_manager_proxy.h"
22 #include "screen.h"
23 #include "surface_draw.h"
24 #include "wm_common.h"
25 #include "wm_common_inner.h"
26 #include "window.h"
27 #include "window_option.h"
28 #include "window_manager_hilog.h"
29 #include "display_manager_agent_controller.h"
30
31 using namespace testing;
32 using namespace testing::ext;
33
34 namespace OHOS::Rosen {
35 namespace {
36 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayManagerTest"};
37 const int WAIT_FOR_SYNC_US = 1; // 1s
38 }
39
40 class DisplayChangeEventListener : public DisplayManager::IDisplayListener {
41 public:
OnCreate(DisplayId displayId)42 virtual void OnCreate(DisplayId displayId) {}
43
OnDestroy(DisplayId displayId)44 virtual void OnDestroy(DisplayId displayId) {}
45
OnChange(DisplayId displayId)46 virtual void OnChange(DisplayId displayId) {}
47 };
48
49 class DisplayManagerTest : public testing::Test {
50 public:
51 static void SetUpTestCase();
52 static void TearDownTestCase();
53 virtual void SetUp() override;
54 virtual void TearDown() override;
55
56 sptr<Window> CreateWindow(std::string name, WindowMode mode, Rect rect, uint32_t color = 0xff000000);
57 bool DrawWindowColor(const sptr<Window>& window, uint32_t color, int32_t width, int32_t height);
58 static inline DisplayId displayId_;
59 static inline int32_t displayWidth_;
60 static inline int32_t displayHeight_;
61 };
62
SetUpTestCase()63 void DisplayManagerTest::SetUpTestCase()
64 {
65 displayId_ = DisplayManager::GetInstance().GetDefaultDisplayId();
66 sptr<Display> display = DisplayManager::GetInstance().GetDefaultDisplay();
67 if (display == nullptr) {
68 return;
69 }
70 displayWidth_ = display->GetWidth();
71 displayHeight_ = display->GetHeight();
72 }
73
TearDownTestCase()74 void DisplayManagerTest::TearDownTestCase()
75 {
76 }
77
SetUp()78 void DisplayManagerTest::SetUp()
79 {
80 }
81
TearDown()82 void DisplayManagerTest::TearDown()
83 {
84 }
85
CreateWindow(std::string name,WindowMode mode,Rect rect,uint32_t color)86 sptr<Window> DisplayManagerTest::CreateWindow(std::string name,
87 WindowMode mode, Rect rect, uint32_t color)
88 {
89 sptr<WindowOption> option = new WindowOption();
90 option->SetDisplayId(displayId_);
91 option->SetWindowType(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW);
92 int32_t width = 0;
93 int32_t height = 0;
94 if (mode != WindowMode::WINDOW_MODE_FULLSCREEN) {
95 option->SetWindowRect(rect);
96 } else {
97 width = displayWidth_;
98 height = displayHeight_;
99 }
100 option->SetWindowMode(mode);
101 option->SetWindowName(name);
102 sptr<Window> window = Window::Create(option->GetWindowName(), option);
103 if (window == nullptr) {
104 return nullptr;
105 }
106 window->AddWindowFlag(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED);
107 window->Show();
108 sleep(WAIT_FOR_SYNC_US); // wait for rect updated
109 width = window->GetRect().width_;
110 height = window->GetRect().height_;
111 DrawWindowColor(window, color, width, height); // 0x66000000 color_black
112 RSTransaction::FlushImplicitTransaction();
113 return window;
114 }
115
DrawWindowColor(const sptr<Window> & window,uint32_t color,int32_t width,int32_t height)116 bool DisplayManagerTest::DrawWindowColor(const sptr<Window>& window, uint32_t color, int32_t width, int32_t height)
117 {
118 auto surfaceNode = window->GetSurfaceNode();
119 if (surfaceNode == nullptr) {
120 WLOGFE("Failed to GetSurfaceNode!");
121 return false;
122 }
123 SurfaceDraw::DrawColor(surfaceNode, width, height, color);
124 surfaceNode->SetAbilityBGAlpha(255); // 255 is alpha
125 return true;
126 }
127
128 namespace {
129 /**
130 * @tc.name: HasPrivateWindow
131 * @tc.desc: Check whether there is a private window in the current display
132 * @tc.type: FUNC
133 * @tc.require issueI5HF6V
134 */
135 HWTEST_F(DisplayManagerTest, HasPrivateWindow, Function | SmallTest | Level2)
136 {
137 sptr<Window> window = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0});
138 if (window == nullptr) {
139 return;
140 }
141 ASSERT_NE(nullptr, window);
142 window->SetPrivacyMode(true);
143 sleep(WAIT_FOR_SYNC_US);
144 bool hasPrivateWindow = false;
145 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
146 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
147
148 window->SetPrivacyMode(false);
149 sleep(WAIT_FOR_SYNC_US);
150 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
151 window->Destroy();
152 ASSERT_TRUE(!hasPrivateWindow);
153 }
154
155 /**
156 * @tc.name: HasPrivateWindowCovered
157 * @tc.desc: The private window is covered
158 * @tc.type: FUNC
159 * @tc.require issueI5HF6V
160 */
161 HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered, Function | SmallTest | Level2)
162 {
163 auto displayWidth = DisplayManagerTest::displayWidth_;
164 auto displayHeight = DisplayManagerTest::displayHeight_;
165
166 sptr<Window> window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0});
167 if (window1 == nullptr) {
168 return;
169 }
170 ASSERT_NE(nullptr, window1);
171 // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height
172 sptr<Window> window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING,
173 Rect{0, 0, 300, 300}, 0xffff0000);
174 ASSERT_NE(nullptr, window2);
175 window2->SetPrivacyMode(true);
176 // The window shadows is too large to cover. so, set a special position for cover window easily.
177 sleep(WAIT_FOR_SYNC_US);
178 window2->MoveTo(displayWidth * 0.53, displayHeight * 0.66);
179 sleep(WAIT_FOR_SYNC_US);
180
181 // 10:rect.posX_, 110:rect.posY_, 650:rect.width, 500:rect.height
182 sptr<Window> window3 = CreateWindow("covered", WindowMode::WINDOW_MODE_FLOATING,
183 Rect{0, 0, displayWidth, displayHeight}, 0xff00ff00);
184 ASSERT_NE(nullptr, window3);
185 sleep(WAIT_FOR_SYNC_US);
186 window3->MoveTo(45, 115);
187 sleep(WAIT_FOR_SYNC_US);
188
189 bool hasPrivateWindow = false;
190 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
191 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
192 window1->Destroy();
193 window2->Destroy();
194 window3->Destroy();
195 if (!hasPrivateWindow) {
196 ASSERT_TRUE(!hasPrivateWindow);
197 }
198 }
199
200 /**
201 * @tc.name: HasPrivateWindowCovered01
202 * @tc.desc: The private window is partially covered
203 * @tc.type: FUNC
204 * @tc.require issueI5HF6V
205 */
206 HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered01, Function | SmallTest | Level2)
207 {
208 sptr<Window> window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect{0, 0, 0, 0});
209
210 // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height
211 if (window1 == nullptr)
212 {
213 return;
214 }
215 ASSERT_NE(nullptr, window1);
216 sptr<Window> window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING,
217 Rect{10, 120, 650, 500}, 0xffff0000);
218 ASSERT_NE(nullptr, window2);
219 window2->SetPrivacyMode(true);
220 // 5:rect.posX_, 110:rect.posY_, 650:rect.width, 500:rect.height
221 sptr<Window> window3 = CreateWindow("covered", WindowMode::WINDOW_MODE_FLOATING,
222 Rect{5, 110, 650, 500}, 0xff00ff00);
223 ASSERT_NE(nullptr, window3);
224
225 sleep(WAIT_FOR_SYNC_US);
226 bool hasPrivateWindow = false;
227 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
228 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
229 window1->Destroy();
230 window2->Destroy();
231 window3->Destroy();
232 if (hasPrivateWindow)
233 {
234 ASSERT_TRUE(hasPrivateWindow);
235 }
236 }
237
238 /**
239 * @tc.name: HasPrivateWindowCovered02
240 * @tc.desc: The private window is covered
241 * @tc.type: FUNC
242 * @tc.require issueI5HF6V
243 */
244 HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered02, Function | SmallTest | Level2)
245 {
246 auto displayWidth = DisplayManagerTest::displayWidth_;
247 auto displayHeight = DisplayManagerTest::displayHeight_;
248
249 sptr<Window> window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0});
250 if (window1 == nullptr) {
251 return;
252 }
253 ASSERT_NE(nullptr, window1);
254 // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height
255 sptr<Window> window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING,
256 Rect {0, 0, 300, 300}, 0xffff0000);
257 ASSERT_NE(nullptr, window2);
258 window2->SetPrivacyMode(true);
259 // The window shadows is too large to cover. so, set a special position for cover window easily.
260 sleep(WAIT_FOR_SYNC_US);
261 window2->MoveTo(displayWidth * 0.53, displayHeight * 0.66);
262 sleep(WAIT_FOR_SYNC_US);
263
264 // 5:rect.posX_, 110:rect.posY_, 655:rect.width, 500:rect.height
265 sptr<Window> window3 = CreateWindow("covered1", WindowMode::WINDOW_MODE_FLOATING,
266 Rect { 0, 0, displayWidth, displayHeight / 2}, 0xff00ff00);
267 ASSERT_NE(nullptr, window3);
268 sleep(WAIT_FOR_SYNC_US);
269 window3->MoveTo(45, 115);
270 sleep(WAIT_FOR_SYNC_US);
271
272 // 5:rect.posX_, 300:rect.posY_, 655:rect.width, 500:rect.height
273 sptr<Window> window4 = CreateWindow("covered2", WindowMode::WINDOW_MODE_FLOATING,
274 Rect { 0, 0, displayWidth, displayHeight / 2 + 200 }, 0xff00ff00);
275 ASSERT_NE(nullptr, window4);
276 window4->MoveTo(45, displayHeight / 2 - 95);
277
278 sleep(WAIT_FOR_SYNC_US);
279 bool hasPrivateWindow = false;
280 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
281 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
282 window1->Destroy();
283 window2->Destroy();
284 window3->Destroy();
285 window4->Destroy();
286 if (!hasPrivateWindow) {
287 ASSERT_TRUE(!hasPrivateWindow);
288 }
289 }
290
291 /**
292 * @tc.name: HasPrivateWindowCovered03
293 * @tc.desc: The private window is partially covered
294 * @tc.type: FUNC
295 * @tc.require issueI5HF6V
296 */
297 HWTEST_F(DisplayManagerTest, HasPrivateWindowCovered03, Function | SmallTest | Level2)
298 {
299 sptr<Window> window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0});
300
301 if (window1 == nullptr) {
302 return;
303 }
304 ASSERT_NE(nullptr, window1);
305 // 10:rect.posX_, 120:rect.pos_Y, rect.width_:650, rect.height_:700
306 sptr<Window> window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING,
307 Rect{10, 120, 650, 700}, 0xffff0000);
308 ASSERT_NE(nullptr, window2);
309 window2->SetPrivacyMode(true);
310 // 5:rect.posX_, 110:rect.pos_Y, rect.width_:655, rect.height_:500
311 sptr<Window> window3 = CreateWindow("covered1", WindowMode::WINDOW_MODE_FLOATING,
312 Rect{5, 110, 655, 500}, 0xff00ff00);
313 ASSERT_NE(nullptr, window3);
314 // 5:rect.posX_, 700:rect.pos_Y, rect.width_:655, rect.height_:500
315 sptr<Window> window4 = CreateWindow("covered2", WindowMode::WINDOW_MODE_FLOATING,
316 Rect{5, 700, 655, 500}, 0xff00ff00);
317 ASSERT_NE(nullptr, window4);
318
319 sleep(WAIT_FOR_SYNC_US);
320 bool hasPrivateWindow = false;
321 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
322 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
323 window1->Destroy();
324 window2->Destroy();
325 window3->Destroy();
326 window4->Destroy();
327 if (hasPrivateWindow) {
328 ASSERT_TRUE(hasPrivateWindow);
329 }
330 }
331
332 /**
333 * @tc.name: HasPrivateWindowSkipSnapShot
334 * @tc.desc: set snap shot skip
335 * @tc.type: FUNC
336 * @tc.require issueI5HF6V
337 */
338 HWTEST_F(DisplayManagerTest, HasPrivateWindowSkipSnapShot, Function | SmallTest | Level2)
339 {
340 sptr<Window> window1 = CreateWindow("test", WindowMode::WINDOW_MODE_FULLSCREEN, Rect {0, 0, 0, 0});
341 if (window1 == nullptr) {
342 return;
343 }
344 ASSERT_NE(nullptr, window1);
345 // 10:rect.posX_, 120:rect.posY_, 650:rect.width, 500:rect.height
346 sptr<Window> window2 = CreateWindow("private", WindowMode::WINDOW_MODE_FLOATING,
347 Rect {10, 120, 650, 500}, 0xffff0000);
348 ASSERT_NE(nullptr, window2);
349 window2->SetSnapshotSkip(true);
350 sleep(WAIT_FOR_SYNC_US);
351 bool hasPrivateWindow = false;
352 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
353 DisplayManager::GetInstance().HasPrivateWindow(id, hasPrivateWindow);
354 window1->Destroy();
355 window2->Destroy();
356 if (hasPrivateWindow) {
357 ASSERT_TRUE(hasPrivateWindow);
358 }
359 }
360
361 /**
362 * @tc.name: AddSurfaceNodeToDisplay | RemoveSurfaceNodeFromDisplay
363 * @tc.desc: add/remove surfaceNode to/from display
364 * @tc.type: FUNC
365 */
366 HWTEST_F(DisplayManagerTest, AddAndRemoveSurfaceNode, Function | SmallTest | Level2)
367 {
368 RSSurfaceNodeConfig config;
369 config.SurfaceNodeName = "TestSurfaceNode";
370 auto surfaceNode = RSSurfaceNode::Create(config);
371 DisplayId id = DisplayManager::GetInstance().GetDefaultDisplayId();
372 ASSERT_EQ(DMError::DM_OK, DisplayManager::GetInstance().AddSurfaceNodeToDisplay(id, surfaceNode));
373 sleep(2);
374 ASSERT_EQ(DMError::DM_OK, DisplayManager::GetInstance().RemoveSurfaceNodeFromDisplay(id, surfaceNode));
375 }
376
377 /**
378 * @tc.name: AddSurfaceNodeToDisplay | RemoveSurfaceNodeFromDisplay
379 * @tc.desc: add/remove surfaceNode to/from display
380 * @tc.type: FUNC
381 */
382 HWTEST_F(DisplayManagerTest, SetVirtualScreenSecurityExemption, Function | SmallTest | Level2)
383 {
384 ScreenId id = 0;
385 uint32_t pid = 0;
386 std::vector<uint64_t> windowList;
387 auto ret = DisplayManager::GetInstance().SetVirtualScreenSecurityExemption(id, pid, windowList);
388 ASSERT_NE(DMError::DM_OK, ret); // not virtual screen for id 0
389 sleep(2);
390 }
391
392 }
393 } // namespace OHOS::Rosen
394