• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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