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