1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19
20 #include "DisplayTransactionTestHelpers.h"
21
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24
25 namespace android {
26 namespace {
27
28 struct FoldableTest : DisplayTransactionTest {
29 static constexpr bool kWithMockScheduler = false;
FoldableTestandroid::__anone93903d90111::FoldableTest30 FoldableTest() : DisplayTransactionTest(kWithMockScheduler) {}
31
SetUpandroid::__anone93903d90111::FoldableTest32 void SetUp() override {
33 injectMockScheduler(kInnerDisplayId);
34
35 // Inject inner and outer displays with uninitialized power modes.
36 constexpr bool kInitPowerMode = false;
37 {
38 InnerDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
39 auto injector = InnerDisplayVariant::makeFakeExistingDisplayInjector(this);
40 injector.setPowerMode(std::nullopt);
41 injector.setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector());
42 mInnerDisplay = injector.inject();
43 }
44 {
45 OuterDisplayVariant::injectHwcDisplay<kInitPowerMode>(this);
46 auto injector = OuterDisplayVariant::makeFakeExistingDisplayInjector(this);
47 injector.setPowerMode(std::nullopt);
48 mOuterDisplay = injector.inject();
49 }
50 }
51
52 static inline PhysicalDisplayId kInnerDisplayId = InnerDisplayVariant::DISPLAY_ID::get();
53 static inline PhysicalDisplayId kOuterDisplayId = OuterDisplayVariant::DISPLAY_ID::get();
54
55 sp<DisplayDevice> mInnerDisplay, mOuterDisplay;
56 };
57
TEST_F(FoldableTest,promotesPacesetterOnBoot)58 TEST_F(FoldableTest, promotesPacesetterOnBoot) {
59 // When the device boots, the inner display should be the pacesetter.
60 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
61
62 // ...and should still be after powering on.
63 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
64 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
65 }
66
TEST_F(FoldableTest,promotesPacesetterOnFoldUnfold)67 TEST_F(FoldableTest, promotesPacesetterOnFoldUnfold) {
68 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
69
70 // The outer display should become the pacesetter after folding.
71 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF);
72 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
73 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId);
74
75 // The inner display should become the pacesetter after unfolding.
76 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::OFF);
77 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
78 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
79 }
80
TEST_F(FoldableTest,promotesPacesetterOnConcurrentPowerOn)81 TEST_F(FoldableTest, promotesPacesetterOnConcurrentPowerOn) {
82 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
83
84 // The inner display should stay the pacesetter if both are powered on.
85 // TODO(b/255635821): The pacesetter should depend on the displays' refresh rates.
86 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
87 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
88
89 // The outer display should become the pacesetter if designated.
90 mFlinger.scheduler()->setPacesetterDisplay(kOuterDisplayId);
91 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId);
92
93 // The inner display should become the pacesetter if designated.
94 mFlinger.scheduler()->setPacesetterDisplay(kInnerDisplayId);
95 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
96 }
97
TEST_F(FoldableTest,promotesPacesetterOnConcurrentPowerOff)98 TEST_F(FoldableTest, promotesPacesetterOnConcurrentPowerOff) {
99 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
100 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
101
102 // The outer display should become the pacesetter if the inner display powers off.
103 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF);
104 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId);
105
106 // The outer display should stay the pacesetter if both are powered on.
107 // TODO(b/255635821): The pacesetter should depend on the displays' refresh rates.
108 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
109 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId);
110
111 // The inner display should become the pacesetter if the outer display powers off.
112 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::OFF);
113 ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
114 }
115
TEST_F(FoldableTest,doesNotRequestHardwareVsyncIfPoweredOff)116 TEST_F(FoldableTest, doesNotRequestHardwareVsyncIfPoweredOff) {
117 // Both displays are powered off.
118 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kInnerDisplayId, _))
119 .Times(0);
120 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kOuterDisplayId, _))
121 .Times(0);
122
123 EXPECT_FALSE(mInnerDisplay->isPoweredOn());
124 EXPECT_FALSE(mOuterDisplay->isPoweredOn());
125
126 auto& scheduler = *mFlinger.scheduler();
127 scheduler.onHardwareVsyncRequest(kInnerDisplayId, true);
128 scheduler.onHardwareVsyncRequest(kOuterDisplayId, true);
129 }
130
TEST_F(FoldableTest,requestsHardwareVsyncForInnerDisplay)131 TEST_F(FoldableTest, requestsHardwareVsyncForInnerDisplay) {
132 // Only inner display is powered on.
133 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kInnerDisplayId, true))
134 .Times(1);
135 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kOuterDisplayId, _))
136 .Times(0);
137
138 // The injected VsyncSchedule uses TestableScheduler::mockRequestHardwareVsync, so no calls to
139 // ISchedulerCallback::requestHardwareVsync are expected during setPowerModeInternal.
140 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
141
142 EXPECT_TRUE(mInnerDisplay->isPoweredOn());
143 EXPECT_FALSE(mOuterDisplay->isPoweredOn());
144
145 auto& scheduler = *mFlinger.scheduler();
146 scheduler.onHardwareVsyncRequest(kInnerDisplayId, true);
147 scheduler.onHardwareVsyncRequest(kOuterDisplayId, true);
148 }
149
TEST_F(FoldableTest,requestsHardwareVsyncForOuterDisplay)150 TEST_F(FoldableTest, requestsHardwareVsyncForOuterDisplay) {
151 // Only outer display is powered on.
152 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kInnerDisplayId, _))
153 .Times(0);
154 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kOuterDisplayId, true))
155 .Times(1);
156
157 // The injected VsyncSchedule uses TestableScheduler::mockRequestHardwareVsync, so no calls to
158 // ISchedulerCallback::requestHardwareVsync are expected during setPowerModeInternal.
159 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
160 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF);
161 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
162
163 EXPECT_FALSE(mInnerDisplay->isPoweredOn());
164 EXPECT_TRUE(mOuterDisplay->isPoweredOn());
165
166 auto& scheduler = *mFlinger.scheduler();
167 scheduler.onHardwareVsyncRequest(kInnerDisplayId, true);
168 scheduler.onHardwareVsyncRequest(kOuterDisplayId, true);
169 }
170
TEST_F(FoldableTest,requestsHardwareVsyncForBothDisplays)171 TEST_F(FoldableTest, requestsHardwareVsyncForBothDisplays) {
172 // Both displays are powered on.
173 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kInnerDisplayId, true))
174 .Times(1);
175 EXPECT_CALL(mFlinger.mockSchedulerCallback(), requestHardwareVsync(kOuterDisplayId, true))
176 .Times(1);
177
178 // The injected VsyncSchedule uses TestableScheduler::mockRequestHardwareVsync, so no calls to
179 // ISchedulerCallback::requestHardwareVsync are expected during setPowerModeInternal.
180 mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
181 mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
182
183 EXPECT_TRUE(mInnerDisplay->isPoweredOn());
184 EXPECT_TRUE(mOuterDisplay->isPoweredOn());
185
186 auto& scheduler = *mFlinger.scheduler();
187 scheduler.onHardwareVsyncRequest(mInnerDisplay->getPhysicalId(), true);
188 scheduler.onHardwareVsyncRequest(mOuterDisplay->getPhysicalId(), true);
189 }
190
191 } // namespace
192 } // namespace android
193