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