1/*
2 * Copyright (c) 2021-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// gtest
17#include <gtest/gtest.h>
18#include "window_manager.h"
19#include "window_test_utils.h"
20#include "wm_common.h"
21using namespace testing;
22using namespace testing::ext;
23
24namespace OHOS {
25namespace Rosen {
26namespace {
27constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowImmersiveTest"};
28
29const Rect SYS_BAR_REGION_NULL = { 0, 0, 0, 0 };
30const SystemBarProperty SYS_BAR_PROP_DEFAULT;
31const SystemBarProperty SYS_BAR_PROP_1(true, 0xE5111111, 0xE5222222);
32const SystemBarProperty SYS_BAR_PROP_2(false, 0xE5222222, 0xE5333333);
33const SystemBarProperty SYS_BAR_PROP_3(false, 0xE5333333, 0xE5444444);
34const SystemBarProperty SYS_BAR_PROP_4(true, 0xE5444444, 0x66555555);
35const SystemBarRegionTints TEST_PROPS_DEFAULT = {
36    { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_DEFAULT, SYS_BAR_REGION_NULL },
37    { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_DEFAULT, SYS_BAR_REGION_NULL },
38};
39const SystemBarRegionTints TEST_PROPS_1 = {
40    { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_1, SYS_BAR_REGION_NULL },
41    { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_2, SYS_BAR_REGION_NULL },
42};
43const SystemBarRegionTints TEST_PROPS_2 = {
44    { WindowType::WINDOW_TYPE_STATUS_BAR, SYS_BAR_PROP_1, SYS_BAR_REGION_NULL },
45    { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SYS_BAR_PROP_3, SYS_BAR_REGION_NULL },
46};
47
48const Rect EMPTY_RECT = {0, 0, 0, 0};
49const float RATIO = 0.3;
50}
51
52using Utils = WindowTestUtils;
53const int WAIT_ASYNC_US = 100000;  // 100000us
54
55class TestSystemBarChangedListener : public ISystemBarChangedListener {
56public:
57    SystemBarRegionTints tints_ = TEST_PROPS_DEFAULT;
58    void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) override;
59};
60
61class TestAvoidAreaChangedListener : public IAvoidAreaChangedListener {
62public:
63    AvoidArea avoidArea_;
64    void OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type) override;
65};
66
67class WindowImmersiveTest : public testing::Test {
68public:
69    static void SetUpTestCase();
70    static void TearDownTestCase();
71    virtual void SetUp() override;
72    virtual void TearDown() override;
73    void SetWindowSystemProps(const sptr<Window>& window, const SystemBarRegionTints& props);
74    bool SystemBarPropsEqualsTo(const SystemBarRegionTints& expect);
75    void DumpFailedInfo(const SystemBarRegionTints& expect);
76    void DumpFailedInfo(bool expectStatus, bool expectNav);
77    bool SystemBarEnableState(bool expectStatus, bool expectNav);
78    DisplayId displayId_ = 0;
79    std::vector<sptr<Window>> activeWindows_;
80    static vector<Rect> fullScreenExpecteds_;
81    static sptr<TestSystemBarChangedListener> testSystemBarChangedListener_;
82    static sptr<TestAvoidAreaChangedListener> testAvoidAreaChangedListener_;
83    Utils::TestWindowInfo fullScreenAppinfo_;
84    Utils::TestWindowInfo avoidBarInfo_;
85    uint32_t leftAvoidW_;
86    uint32_t leftAvoidH_;
87    uint32_t topAvoidW_;
88    uint32_t topAvoidH_;
89    sptr<Window> backgroundWindow_;
90};
91
92vector<Rect> WindowImmersiveTest::fullScreenExpecteds_;
93sptr<TestSystemBarChangedListener> WindowImmersiveTest::testSystemBarChangedListener_ =
94    new TestSystemBarChangedListener();
95sptr<TestAvoidAreaChangedListener> WindowImmersiveTest::testAvoidAreaChangedListener_ =
96    new TestAvoidAreaChangedListener();
97
98void WindowImmersiveTest::SetWindowSystemProps(const sptr<Window>& window, const SystemBarRegionTints& tints)
99{
100    for (auto tint : tints) {
101        window->SetSystemBarProperty(tint.type_, tint.prop_);
102    }
103}
104
105void WindowImmersiveTest::DumpFailedInfo(const SystemBarRegionTints& expect)
106{
107    auto act = testSystemBarChangedListener_->tints_;
108    WLOGI("WindowImmersiveTest Expected:");
109    for (auto tint : expect) {
110        WLOGI("WindowType: %{public}4d, Enable: %{public}4d, Color: %{public}x | %{public}x",
111            static_cast<uint32_t>(tint.type_), tint.prop_.enable_,
112            tint.prop_.backgroundColor_, tint.prop_.contentColor_);
113    }
114    WLOGI("WindowImmersiveTest Act: ");
115    for (auto tint : act) {
116        WLOGI("WindowType: %{public}4d, Enable: %{public}4d, Color: %{public}x | %{public}x",
117            static_cast<uint32_t>(tint.type_), tint.prop_.enable_,
118            tint.prop_.backgroundColor_, tint.prop_.contentColor_);
119    }
120}
121
122void WindowImmersiveTest::DumpFailedInfo(bool expectStatus, bool expectNav)
123{
124    auto act = testSystemBarChangedListener_->tints_;
125    WLOGI("WindowImmersiveTest Expected:");
126    WLOGI("expectStatus: %{public}4d, expectNav: %{public}4d", expectStatus, expectNav);
127    WLOGI("WindowImmersiveTest Act: ");
128    for (auto tint : act) {
129        WLOGI("WindowType: %{public}4d, Enable: %{public}4d, Color: %{public}x | %{public}x",
130            static_cast<uint32_t>(tint.type_), tint.prop_.enable_,
131            tint.prop_.backgroundColor_, tint.prop_.contentColor_);
132    }
133}
134
135bool WindowImmersiveTest::SystemBarPropsEqualsTo(const SystemBarRegionTints& expect)
136{
137    usleep(WAIT_ASYNC_US);
138    auto act = testSystemBarChangedListener_->tints_;
139    if (act.size() != expect.size()) {
140        DumpFailedInfo(expect);
141        return false;
142    }
143    for (auto item : expect) {
144        bool check = false;
145        for (auto tint : act) {
146            if (item.prop_ == tint.prop_ && item.type_ == tint.type_) {
147                check = true;
148                break;
149            }
150        }
151        if (!check) {
152            DumpFailedInfo(expect);
153            return false;
154        }
155        check = false;
156    }
157    return true;
158}
159
160bool WindowImmersiveTest::SystemBarEnableState(bool expectStatus, bool expectNav)
161{
162    usleep(WAIT_ASYNC_US);
163    auto act = testSystemBarChangedListener_->tints_;
164    bool check = false;
165    for (auto tint : act) {
166        if ((tint.type_ == WindowType::WINDOW_TYPE_STATUS_BAR && tint.prop_.enable_ == expectStatus)
167            || (tint.type_ == WindowType::WINDOW_TYPE_NAVIGATION_BAR && tint.prop_.enable_ == expectNav)) {
168            check = true;
169        } else {
170            check = false;
171        }
172    }
173    if (!check) {
174        DumpFailedInfo(expectStatus, expectNav);
175    }
176    return check;
177}
178
179void TestSystemBarChangedListener::OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints)
180{
181    WLOGI("TestSystemBarChangedListener Display ID: %{public}" PRIu64"", displayId);
182    WLOGI("TestSystemBarChangedListener tints size: %{public}zu", tints.size());
183    for (auto tint : tints) {
184        auto type = tint.type_;
185        for (uint32_t i = 0; i < tints_.size(); i++) {
186            if (tints_[i].type_ == type) {
187                tints_[i] = tint;
188            }
189        }
190    }
191}
192
193void TestAvoidAreaChangedListener::OnAvoidAreaChanged(const AvoidArea avoidArea, AvoidAreaType type)
194{
195    avoidArea_ = avoidArea;
196}
197
198void WindowImmersiveTest::SetUpTestCase()
199{
200    auto display = DisplayManager::GetInstance().GetDisplayById(0);
201    ASSERT_TRUE((display != nullptr));
202    WLOGI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u",
203        display->GetId(), display->GetWidth(), display->GetHeight(), display->GetRefreshRate());
204    Rect displayRect = {0, 0, display->GetWidth(), display->GetHeight()};
205    Utils::InitByDisplayRect(displayRect);
206}
207
208void WindowImmersiveTest::TearDownTestCase()
209{
210}
211
212void WindowImmersiveTest::SetUp()
213{
214    fullScreenAppinfo_ = {
215        .name = "main",
216        .rect = Utils::customAppRect_,
217        .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW,
218        .mode = WindowMode::WINDOW_MODE_FULLSCREEN, // immersive setting
219        .needAvoid = false, // immersive setting
220        .parentLimit = false,
221        .parentId = INVALID_WINDOW_ID,
222    };
223    avoidBarInfo_ = {
224        .name = "LeftAvoidTest",
225        .rect = EMPTY_RECT,
226        .type = WindowType::WINDOW_TYPE_STATUS_BAR,
227        .mode = WindowMode::WINDOW_MODE_FLOATING,
228    };
229    // makesure left avoid win w < h
230    leftAvoidW_ = std::min(Utils::displayRect_.width_, static_cast<uint32_t>(Utils::displayRect_.height_ * RATIO));
231    leftAvoidH_ = Utils::displayRect_.height_;
232    // makesure top avoid win h < w
233    topAvoidW_ = Utils::displayRect_.width_;
234    topAvoidH_ = std::min(Utils::displayRect_.height_, static_cast<uint32_t>(Utils::displayRect_.width_ * RATIO));
235
236    WindowManager::GetInstance().RegisterSystemBarChangedListener(testSystemBarChangedListener_);
237    activeWindows_.clear();
238    sleep(1);
239}
240
241void WindowImmersiveTest::TearDown()
242{
243    while (!activeWindows_.empty()) {
244        ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy());
245        activeWindows_.pop_back();
246    }
247    WindowManager::GetInstance().UnregisterSystemBarChangedListener(testSystemBarChangedListener_);
248    sleep(1);
249}
250
251namespace {
252/**
253 * @tc.name: ImmersiveTest01
254 * @tc.desc: Add one immersive window and hide
255 * @tc.type: FUNC
256 */
257HWTEST_F(WindowImmersiveTest, ImmersiveTest01, Function | MediumTest | Level3)
258{
259    fullScreenAppinfo_.name = "immer01";
260    const sptr<Window>& window = Utils::CreateTestWindow(fullScreenAppinfo_);
261    if (window == nullptr) {
262        return;
263    }
264    activeWindows_.push_back(window);
265    SetWindowSystemProps(window, TEST_PROPS_1);
266    ASSERT_EQ(WMError::WM_OK, window->Show());
267    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
268    ASSERT_EQ(WMError::WM_OK, window->Hide());
269}
270
271/**
272 * @tc.name: ImmersiveTest02
273 * @tc.desc: Add two immersive window and switch
274 * @tc.type: FUNC
275 */
276HWTEST_F(WindowImmersiveTest, ImmersiveTest02, Function | MediumTest | Level3)
277{
278    const sptr<Window>& window1 = Utils::CreateTestWindow(fullScreenAppinfo_);
279    if (window1 == nullptr) {
280        return;
281    }
282    activeWindows_.push_back(window1);
283    SetWindowSystemProps(window1, TEST_PROPS_1);
284    fullScreenAppinfo_.name = "Immer02";
285    const sptr<Window>& window2 = Utils::CreateTestWindow(fullScreenAppinfo_);
286    ASSERT_NE(nullptr, window2);
287    activeWindows_.push_back(window2);
288    SetWindowSystemProps(window2, TEST_PROPS_2);
289    ASSERT_EQ(WMError::WM_OK, window1->Show());
290    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
291    ASSERT_EQ(WMError::WM_OK, window2->Show());
292
293    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_2));
294    ASSERT_EQ(WMError::WM_OK, window2->Hide());
295    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
296    ASSERT_EQ(WMError::WM_OK, window1->Hide());
297}
298
299/**
300 * @tc.name: ImmersiveTest03
301 * @tc.desc: Add one no immersive window
302 * @tc.type: FUNC
303 */
304HWTEST_F(WindowImmersiveTest, ImmersiveTest03, Function | MediumTest | Level3)
305{
306    const sptr<Window>& window1 = Utils::CreateTestWindow(fullScreenAppinfo_);
307    if (window1 == nullptr) {
308        return;
309    }
310    activeWindows_.push_back(window1);
311    SetWindowSystemProps(window1, TEST_PROPS_1);
312    fullScreenAppinfo_.name = "Immer03";
313    fullScreenAppinfo_.needAvoid = true; // no immersive setting
314    const sptr<Window>& window2 = Utils::CreateTestWindow(fullScreenAppinfo_);
315    ASSERT_NE(nullptr, window2);
316    activeWindows_.push_back(window2);
317    SetWindowSystemProps(window2, TEST_PROPS_2);
318    ASSERT_EQ(WMError::WM_OK, window1->Show());
319    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
320    ASSERT_EQ(WMError::WM_OK, window2->Show());
321    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_2));
322    ASSERT_EQ(WMError::WM_OK, window1->Hide());
323    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_2));
324}
325
326/**
327 * @tc.name: ImmersiveTest04
328 * @tc.desc: SetLayoutFullScreen
329 * @tc.type: FUNC
330 */
331HWTEST_F(WindowImmersiveTest, ImmersiveTest04, Function | MediumTest | Level3)
332{
333    fullScreenAppinfo_.needAvoid = true; // no immersive setting
334    const sptr<Window>& window1 = Utils::CreateTestWindow(fullScreenAppinfo_);
335    if (window1 == nullptr) {
336        return;
337    }
338    activeWindows_.push_back(window1);
339    SetWindowSystemProps(window1, TEST_PROPS_1);
340    ASSERT_EQ(WMError::WM_OK, window1->Show());
341    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
342    ASSERT_EQ(WMError::WM_OK, window1->SetLayoutFullScreen(true));
343    ASSERT_EQ(true, window1->IsLayoutFullScreen());
344    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
345    ASSERT_EQ(WMError::WM_OK, window1->SetLayoutFullScreen(false));
346    ASSERT_EQ(false, window1->IsLayoutFullScreen());
347    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
348    ASSERT_EQ(WMError::WM_OK, window1->Hide());
349}
350
351/**
352 * @tc.name: ImmersiveTest05
353 * @tc.desc: SetFullScreen
354 * @tc.type: FUNC
355 */
356HWTEST_F(WindowImmersiveTest, ImmersiveTest05, Function | MediumTest | Level3)
357{
358    fullScreenAppinfo_.needAvoid = true; // no immersive setting
359    const sptr<Window>& window1 = Utils::CreateTestWindow(fullScreenAppinfo_);
360    if (window1 == nullptr) {
361        return;
362    }
363    activeWindows_.push_back(window1);
364    SetWindowSystemProps(window1, TEST_PROPS_1);
365    ASSERT_EQ(WMError::WM_OK, window1->Show());
366    ASSERT_TRUE(SystemBarPropsEqualsTo(TEST_PROPS_1));
367    ASSERT_EQ(WMError::WM_OK, window1->SetFullScreen(true));
368    ASSERT_EQ(true, window1->IsFullScreen());
369    ASSERT_TRUE(SystemBarEnableState(false, false));
370    ASSERT_EQ(WMError::WM_OK, window1->SetFullScreen(false));
371    ASSERT_EQ(false, window1->IsFullScreen());
372    ASSERT_EQ(WMError::WM_OK, window1->Hide());
373}
374
375/**
376 * @tc.name: ImmersiveNegativeTest01
377 * @tc.desc: set systembar props with wrong window type
378 * @tc.type: FUNC
379 */
380HWTEST_F(WindowImmersiveTest, ImmersiveNegativeTest01, Function | MediumTest | Level3)
381{
382    const SystemBarRegionTints TEST_PROPS_NEGATIVE = {
383        { WindowType::WINDOW_TYPE_KEYGUARD, SYS_BAR_PROP_1, SYS_BAR_REGION_NULL },
384        { WindowType::WINDOW_TYPE_POINTER, SYS_BAR_PROP_2, SYS_BAR_REGION_NULL },
385    };
386    const sptr<Window>& window = Utils::CreateTestWindow(fullScreenAppinfo_);
387    if (window == nullptr) {
388        return;
389    }
390    activeWindows_.push_back(window);
391    SetWindowSystemProps(window, TEST_PROPS_NEGATIVE);
392    ASSERT_EQ(WMError::WM_OK, window->Show());
393    ASSERT_FALSE(SystemBarPropsEqualsTo(TEST_PROPS_NEGATIVE));
394    ASSERT_EQ(WMError::WM_OK, window->Hide());
395    ASSERT_FALSE(SystemBarPropsEqualsTo(TEST_PROPS_NEGATIVE));
396}
397
398/**
399 * @tc.name: GetAvoidAreaByTypeTest01
400 * @tc.desc: Test GetAvoidArea use unsupported Type(TYPE_CUTOUT).
401 * @tc.type: FUNC
402 */
403HWTEST_F(WindowImmersiveTest, GetAvoidAreaByTypeTest01, Function | MediumTest | Level3)
404{
405    // Add full screenwindow for call GetAvoidArea, and push_back in activeWindows_
406    const sptr<Window>& win = Utils::CreateTestWindow(fullScreenAppinfo_);
407    if (win == nullptr) {
408        return;
409    }
410    activeWindows_.push_back(win);
411
412    // Test GetAvoidArea
413    AvoidArea avoidarea;
414    WMError ret = win->GetAvoidAreaByType(AvoidAreaType::TYPE_CUTOUT, avoidarea);
415    ASSERT_EQ(WMError::WM_OK, ret);
416    ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.leftRect_));
417    ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.rightRect_));
418    ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.topRect_));
419    ASSERT_TRUE(Utils::RectEqualToRect(EMPTY_RECT, avoidarea.bottomRect_));
420    ASSERT_EQ(WMError::WM_OK, win->Hide());
421}
422
423/**
424 * @tc.name: DockWindowTest01
425 * @tc.desc: Add unexistavoid and remove this avoid. Test OnAvoidAreaChanged listener
426 * @tc.type: FUNC
427 */
428HWTEST_F(WindowImmersiveTest, DockWindowTest01, Function | MediumTest | Level3)
429{
430    const sptr<Window>& dockWindow = Utils::CreateDockWindow();
431    if (dockWindow == nullptr) {
432        return;
433    }
434
435    if (WMError::WM_ERROR_INVALID_WINDOW == dockWindow->Show()) {
436        ASSERT_EQ(WMError::WM_ERROR_INVALID_WINDOW, dockWindow->Show());
437    } else if (WMError::WM_OK == dockWindow->Show()) {
438        ASSERT_EQ(WMError::WM_OK, dockWindow->Show());
439    }
440
441    const sptr<Window>& window = Utils::CreateTestWindow(fullScreenAppinfo_);
442    if (window == nullptr) {
443        return;
444    }
445    usleep(WAIT_ASYNC_US);
446    auto act = testSystemBarChangedListener_->tints_;
447    for (SystemBarRegionTint tint : act) {
448        if (tint.type_ == WindowType::WINDOW_TYPE_LAUNCHER_DOCK) {
449            ASSERT_FALSE(tint.prop_.enable_);
450        }
451    }
452
453    ASSERT_EQ(WMError::WM_OK, window->Hide());
454
455    usleep(WAIT_ASYNC_US);
456    act = testSystemBarChangedListener_->tints_;
457    for (SystemBarRegionTint tint : act) {
458        if (tint.type_ == WindowType::WINDOW_TYPE_LAUNCHER_DOCK) {
459            ASSERT_TRUE(tint.prop_.enable_);
460        }
461    }
462    ASSERT_EQ(WMError::WM_OK, dockWindow->Destroy());
463}
464}
465} // namespace Rosen
466} // namespace OHOS
467