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#include <gtest/gtest.h>
17
18#include "display_cutout_controller.h"
19#include "display_info.h"
20#include "display_manager.h"
21#include "display_manager_proxy.h"
22#include "screen_manager.h"
23#include "screen_manager/rs_screen_mode_info.h"
24#include "window_manager_hilog.h"
25
26using namespace testing;
27using namespace testing::ext;
28
29namespace OHOS {
30namespace Rosen {
31namespace {
32constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayChangeTest"};
33constexpr uint32_t MAX_TIME_WAITING_FOR_CALLBACK = 20;
34constexpr uint32_t SLEEP_TIME_IN_US = 10000; // 10ms
35constexpr uint32_t SPLIT_TEST_SLEEP_S = 2;
36}
37
38class DisplayChangeEventListener : public DisplayManager::IDisplayListener {
39public:
40    virtual void OnCreate(DisplayId displayId)
41    {
42        WLOGI("DisplayChangeEventListener::OnCreate displayId=%{public}" PRIu64"", displayId);
43    }
44
45    virtual void OnDestroy(DisplayId displayId)
46    {
47        WLOGI("DisplayChangeEventListener::OnDestroy displayId=%{public}" PRIu64"", displayId);
48    }
49
50    virtual void OnChange(DisplayId displayId)
51    {
52        WLOGI("DisplayChangeEventListener::OnChange displayId=%{public}" PRIu64"", displayId);
53        isCallbackCalled_ = true;
54        displayId_ = displayId;
55    }
56    bool isCallbackCalled_ = false;
57    DisplayId displayId_ = DISPLAY_ID_INVALID;
58};
59
60class DisplayChangeTest : public testing::Test {
61public:
62    static void SetUpTestCase();
63    static void TearDownTestCase();
64    virtual void SetUp() override;
65    virtual void TearDown() override;
66    void ResetDisplayChangeListener();
67    bool CheckDisplayChangeEventCallback(bool valueExpected);
68    bool ScreenSizeEqual(const sptr<Screen> screen, const sptr<SupportedScreenModes> curInfo) const;
69    bool DisplaySizeEqual(const sptr<Display> display, const sptr<SupportedScreenModes> curInfo) const;
70    inline bool CheckModeSizeChange(const sptr<SupportedScreenModes> usedInfo,
71        const sptr<SupportedScreenModes> curInfo) const;
72
73    static DisplayId defaultDisplayId_;
74    static sptr<Screen> defaultScreen_;
75    static sptr<DisplayChangeEventListener> listener_;
76    static uint32_t originalDisplayDpi;
77    static inline uint32_t times_ = 0;
78};
79DisplayId DisplayChangeTest::defaultDisplayId_ = DISPLAY_ID_INVALID;
80sptr<Screen> DisplayChangeTest::defaultScreen_ = nullptr;
81sptr<DisplayChangeEventListener> DisplayChangeTest::listener_ = new DisplayChangeEventListener();
82uint32_t DisplayChangeTest::originalDisplayDpi = 0;
83
84void DisplayChangeTest::SetUpTestCase()
85{
86    defaultDisplayId_ = DisplayManager::GetInstance().GetDefaultDisplayId();
87    ASSERT_NE(DISPLAY_ID_INVALID, defaultDisplayId_);
88    sptr<Display> defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultDisplayId_);
89    ASSERT_NE(nullptr, defaultDisplay);
90    ScreenId screenId = defaultDisplay->GetScreenId();
91    ASSERT_NE(INVALID_SCREEN_ID, screenId);
92    defaultScreen_ = ScreenManager::GetInstance().GetScreenById(screenId);
93    ASSERT_NE(nullptr, defaultScreen_);
94
95    ASSERT_EQ(DMError::DM_OK, DisplayManager::GetInstance().RegisterDisplayListener(listener_));
96}
97
98void DisplayChangeTest::TearDownTestCase()
99{
100    DisplayManager::GetInstance().UnregisterDisplayListener(listener_);
101}
102
103void DisplayChangeTest::SetUp()
104{
105    times_ = 0;
106    ResetDisplayChangeListener();
107}
108
109void DisplayChangeTest::TearDown()
110{
111}
112
113void DisplayChangeTest::ResetDisplayChangeListener()
114{
115    ASSERT_NE(nullptr, listener_);
116    listener_->isCallbackCalled_ = false;
117    listener_->displayId_ = DISPLAY_ID_INVALID;
118}
119
120bool DisplayChangeTest::CheckDisplayChangeEventCallback(bool valueExpected)
121{
122    WLOGI("CheckDisplayChangeEventCallback in");
123    do {
124        if (listener_->isCallbackCalled_ == valueExpected) {
125            WLOGI("CheckDisplayChangeEventCallback: get valueExpected %{public}d for display %{public}" PRIu64"",
126                static_cast<int>(valueExpected), listener_->displayId_);
127            WLOGI("CheckDisplayChangeEventCallback: already wait times %{public}d", times_);
128            return true;
129        }
130        usleep(SLEEP_TIME_IN_US);
131        ++times_;
132    } while (times_ <= MAX_TIME_WAITING_FOR_CALLBACK);
133    WLOGI("CheckDisplayChangeEventCallback: cannot get valueExpected");
134    return false;
135}
136
137bool DisplayChangeTest::ScreenSizeEqual(const sptr<Screen> screen, const sptr<SupportedScreenModes> curInfo) const
138{
139    if (screen == nullptr || curInfo == nullptr) {
140        WLOGI("param is nullptr");
141        return false;
142    }
143    uint32_t sWidth = screen->GetWidth();
144    uint32_t sHeight = screen->GetHeight();
145    WLOGI("ScreenSizeEqual: ScreenSize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u",
146        sWidth, sHeight, curInfo->width_, curInfo->height_);
147    return ((curInfo->width_ == sWidth) && (curInfo->height_ == sHeight));
148}
149
150bool DisplayChangeTest::DisplaySizeEqual(const sptr<Display> display, const sptr<SupportedScreenModes> curInfo) const
151{
152    if (display == nullptr || curInfo == nullptr) {
153        WLOGI("param is nullptr");
154        return false;
155    }
156    uint32_t dWidth = static_cast<uint32_t>(display->GetWidth());
157    uint32_t dHeight = static_cast<uint32_t>(display->GetHeight());
158    WLOGI("DisplaySizeEqual:: DisplaySize: %{public}u %{public}u, ActiveModeInfoSize: %{public}u %{public}u",
159        dWidth, dHeight, curInfo->width_, curInfo->height_);
160    return ((curInfo->width_ == dWidth) && (curInfo->height_ == dHeight));
161}
162
163
164inline bool DisplayChangeTest::CheckModeSizeChange(const sptr<SupportedScreenModes> usedInfo,
165    const sptr<SupportedScreenModes> curInfo) const
166{
167    if (usedInfo == nullptr || curInfo == nullptr) {
168        return false;
169    }
170    return (usedInfo->width_ != curInfo->width_ || usedInfo->height_ != curInfo->height_);
171}
172
173namespace {
174/**
175 * @tc.name: RegisterDisplayChangeListener01
176 * @tc.desc: Register displayChangeListener with valid listener and check return true
177 * @tc.type: FUNC
178 */
179HWTEST_F(DisplayChangeTest, RegisterDisplayChangeListener01, Function | SmallTest | Level2)
180{
181    sptr<DisplayChangeEventListener> listener = new DisplayChangeEventListener();
182    DMError ret = DisplayManager::GetInstance().RegisterDisplayListener(listener);
183    ASSERT_EQ(DMError::DM_OK, ret);
184}
185
186/**
187 * @tc.name: RegisterDisplayChangeListener02
188 * @tc.desc: Register displayChangeListener with nullptr and check return false
189 * @tc.type: FUNC
190 */
191HWTEST_F(DisplayChangeTest, RegisterDisplayChangeListener02, Function | SmallTest | Level2)
192{
193    DMError ret = DisplayManager::GetInstance().RegisterDisplayListener(nullptr);
194    ASSERT_EQ(DMError::DM_ERROR_NULLPTR, ret);
195}
196
197/**
198 * @tc.name: UnregisterDisplayChangeListener01
199 * @tc.desc: Unregister displayChangeListener with valid listener and check return true
200 * @tc.type: FUNC
201 */
202HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener01, Function | SmallTest | Level2)
203{
204    sptr<DisplayChangeEventListener> listener = new DisplayChangeEventListener();
205    DisplayManager::GetInstance().RegisterDisplayListener(listener);
206    DMError ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener);
207    ASSERT_EQ(DMError::DM_OK, ret);
208}
209
210/**
211 * @tc.name: UnregisterDisplayChangeListener02
212 * @tc.desc: Register displayChangeListener with nullptr and check return false
213 * @tc.type: FUNC
214 */
215HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener02, Function | SmallTest | Level2)
216{
217    DMError ret = DisplayManager::GetInstance().UnregisterDisplayListener(nullptr);
218    ASSERT_EQ(DMError::DM_ERROR_NULLPTR, ret);
219}
220
221/**
222 * @tc.name: UnregisterDisplayChangeListener03
223 * @tc.desc: Register displayChangeListener with invalid listener and check return false
224 * @tc.type: FUNC
225 */
226HWTEST_F(DisplayChangeTest, UnregisterDisplayChangeListener03, Function | SmallTest | Level2)
227{
228    sptr<DisplayChangeEventListener> listener = new DisplayChangeEventListener();
229    DMError ret = DisplayManager::GetInstance().UnregisterDisplayListener(listener);
230    ASSERT_EQ(DMError::DM_ERROR_NULLPTR, ret);
231}
232
233/**
234 * @tc.name: CheckDisplayStateChange01
235 * @tc.desc: DisplayState not change if screen sets same mode
236 * @tc.type: FUNC
237 */
238HWTEST_F(DisplayChangeTest, CheckDisplayStateChange01, Function | SmallTest | Level2)
239{
240    WLOGI("CheckDisplayStateChange01");
241    uint32_t usedModeIdx = defaultScreen_->GetModeId();
242    defaultScreen_->SetScreenActiveMode(usedModeIdx);
243    WLOGI("SetScreenActiveMode: %{public}u", usedModeIdx);
244    if (CheckDisplayChangeEventCallback(true)) {
245        ASSERT_EQ(true, CheckDisplayChangeEventCallback(true));
246    }
247}
248
249/**
250 * @tc.name: CheckDisplaySizeChange01
251 * @tc.desc: Check screen size change as screen mode set if screen sets another mode
252 * @tc.type: FUNC
253 */
254HWTEST_F(DisplayChangeTest, CheckDisplaySizeChange01, Function | MediumTest | Level2)
255{
256    WLOGI("CheckDisplaySizeChange01");
257    auto modes = defaultScreen_->GetSupportedModes();
258    uint32_t usedModeIdx = defaultScreen_->GetModeId();
259    WLOGI("usedModeIdx / SupportMode size: %{public}u %{public}zu", usedModeIdx, modes.size());
260
261    for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) {
262        if (modeIdx != usedModeIdx && CheckModeSizeChange(modes[usedModeIdx], modes[modeIdx])) {
263            defaultScreen_->SetScreenActiveMode(modeIdx);
264            WLOGI("SetScreenActiveMode: %{public}u -> %{public}u", usedModeIdx, modeIdx);
265            ASSERT_EQ(true, ScreenSizeEqual(defaultScreen_, modes[modeIdx]));
266            ASSERT_EQ(true, CheckDisplayChangeEventCallback(true));
267            // reset usedMode
268            ResetDisplayChangeListener();
269            defaultScreen_->SetScreenActiveMode(usedModeIdx);
270            CheckDisplayChangeEventCallback(true);
271            break;
272        }
273    }
274}
275
276/**
277 * @tc.name: CheckDisplaySizeChange02
278 * @tc.desc: Check display size change as screen mode set if screen sets another mode
279 * @tc.type: FUNC
280 */
281HWTEST_F(DisplayChangeTest, CheckDisplaySizeChange02, Function | MediumTest | Level2)
282{
283    WLOGI("CheckDisplaySizeChange02");
284    auto modes = defaultScreen_->GetSupportedModes();
285    uint32_t usedModeIdx = defaultScreen_->GetModeId();
286    WLOGI("usedModeIdx / SupportMode size: %{public}u %{public}zu", usedModeIdx, modes.size());
287
288    for (uint32_t modeIdx = 0; modeIdx < modes.size(); modeIdx++) {
289        if (modeIdx != usedModeIdx && CheckModeSizeChange(modes[usedModeIdx], modes[modeIdx])) {
290            defaultScreen_->SetScreenActiveMode(modeIdx);
291            WLOGI("SetScreenActiveMode: %{public}u -> %{public}u", usedModeIdx, modeIdx);
292            ASSERT_EQ(true, ScreenSizeEqual(defaultScreen_, modes[modeIdx]));
293            ASSERT_EQ(true, CheckDisplayChangeEventCallback(true));
294            sptr<Display> defaultDisplay = DisplayManager::GetInstance().GetDisplayById(defaultDisplayId_);
295            ASSERT_NE(nullptr, defaultDisplay);
296            ASSERT_EQ(true, DisplaySizeEqual(defaultDisplay, modes[modeIdx]));
297            // reset usedMode
298            ResetDisplayChangeListener();
299            defaultScreen_->SetScreenActiveMode(usedModeIdx);
300            CheckDisplayChangeEventCallback(true);
301            break;
302        }
303    }
304}
305
306/**
307 * @tc.name: CheckScreenDensityChange01
308 * @tc.desc: Check screen density change as set another density for screen
309 * @tc.type: FUNC
310 */
311HWTEST_F(DisplayChangeTest, CheckScreenDensityChange01, Function | SmallTest | Level2)
312{
313    DisplayChangeTest::originalDisplayDpi = static_cast<uint32_t>(DisplayManager::GetInstance().
314        GetDisplayById(defaultDisplayId_)->GetVirtualPixelRatio() * BASELINE_DENSITY);
315    ASSERT_NE(0, DisplayChangeTest::originalDisplayDpi);
316    uint32_t densityDpi = 320;
317    ASSERT_EQ(DMError::DM_OK, defaultScreen_->SetDensityDpi(densityDpi));
318    sleep(SPLIT_TEST_SLEEP_S);
319}
320
321/**
322 * @tc.name: CheckScreenDensityChange02
323 * @tc.desc: Check screen density change as set another density for screen
324 * @tc.type: FUNC
325 */
326HWTEST_F(DisplayChangeTest, CheckScreenDensityChange02, Function | SmallTest | Level2)
327{
328    uint32_t densityDpi = 80;
329    ASSERT_EQ(DMError::DM_OK, defaultScreen_->SetDensityDpi(densityDpi));
330    sleep(SPLIT_TEST_SLEEP_S);
331}
332
333/**
334 * @tc.name: CheckScreenDensityChange03
335 * @tc.desc: Check screen density change as set an invalid density for screen
336 * @tc.type: FUNC
337 */
338HWTEST_F(DisplayChangeTest, CheckScreenDensityChange03, Function | SmallTest | Level2)
339{
340    uint32_t densityDpi = DOT_PER_INCH_MAXIMUM_VALUE + 1;
341    ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, defaultScreen_->SetDensityDpi(densityDpi));
342}
343
344/**
345 * @tc.name: CheckScreenDensityChange04
346 * @tc.desc: Check screen density change as set an invalid density for screen
347 * @tc.type: FUNC
348 */
349HWTEST_F(DisplayChangeTest, CheckScreenDensityChange04, Function | SmallTest | Level2)
350{
351    uint32_t densityDpi = 40;
352    ASSERT_EQ(DMError::DM_ERROR_INVALID_PARAM, defaultScreen_->SetDensityDpi(densityDpi));
353}
354
355/**
356 * @tc.name: CheckScreenDensityChange05
357 * @tc.desc: Restore original display density
358 * @tc.type: FUNC
359 */
360HWTEST_F(DisplayChangeTest, CheckScreenDensityChange05, Function | SmallTest | Level2)
361{
362    ASSERT_EQ(DMError::DM_OK, defaultScreen_->SetDensityDpi(DisplayChangeTest::originalDisplayDpi));
363    sleep(SPLIT_TEST_SLEEP_S);
364}
365
366/**
367 * @tc.name: CheckWaterfallCompression01
368 * @tc.desc: check function of waterfall display compression.
369 * @tc.type: FUNC
370 */
371HWTEST_F(DisplayChangeTest, CheckWaterfallCompression01, Function | SmallTest | Level2)
372{
373    bool originWaterfallEnable = DisplayCutoutController::IsWaterfallDisplay();
374    DisplayCutoutController::SetIsWaterfallDisplay(true);
375
376    bool originStatus = DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal();
377    DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(true);
378
379    uint32_t originSize = DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal();
380    uint32_t testSizeInVp = 24;
381    DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(testSizeInVp);
382
383    ASSERT_EQ(true, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal());
384    ASSERT_EQ(testSizeInVp, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal());
385
386    Orientation originOrientation = defaultScreen_->GetOrientation();
387    DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(originSize);
388    ASSERT_EQ(originSize, DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal());
389    DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(originStatus);
390    ASSERT_EQ(originStatus, DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal());
391    DisplayCutoutController::SetIsWaterfallDisplay(originWaterfallEnable);
392    ASSERT_EQ(originOrientation, defaultScreen_->GetOrientation());
393}
394}
395} // namespace Rosen
396} // namespace OHOS