• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 #include "mock/DisplayHardware/MockDisplayMode.h"
22 #include "mock/MockDisplayModeSpecs.h"
23 
24 #include <com_android_graphics_surfaceflinger_flags.h>
25 #include <common/test/FlagUtils.h>
26 #include <ftl/fake_guard.h>
27 #include <scheduler/Fps.h>
28 
29 using namespace com::android::graphics::surfaceflinger;
30 
31 #define EXPECT_SET_ACTIVE_CONFIG(displayId, modeId)                                 \
32     EXPECT_CALL(*mComposer,                                                         \
33                 setActiveConfigWithConstraints(displayId,                           \
34                                                static_cast<hal::HWConfigId>(        \
35                                                        ftl::to_underlying(modeId)), \
36                                                _, _))                               \
37             .WillOnce(DoAll(SetArgPointee<3>(timeline), Return(hal::Error::NONE)))
38 
39 namespace android {
40 namespace {
41 
42 using android::hardware::graphics::composer::V2_4::Error;
43 using android::hardware::graphics::composer::V2_4::VsyncPeriodChangeTimeline;
44 
45 MATCHER_P2(ModeSettledTo, dmc, modeId, "") {
46     const auto displayId = arg->getPhysicalId();
47 
48     if (const auto desiredOpt = dmc->getDesiredMode(displayId)) {
49         *result_listener << "Unsettled desired mode "
50                          << ftl::to_underlying(desiredOpt->mode.modePtr->getId());
51         return false;
52     }
53 
54     if (dmc->getActiveMode(displayId).modePtr->getId() != modeId) {
55         *result_listener << "Settled to unexpected active mode " << ftl::to_underlying(modeId);
56         return false;
57     }
58 
59     return true;
60 }
61 
62 MATCHER_P2(ModeSwitchingTo, flinger, modeId, "") {
63     const auto displayId = arg->getPhysicalId();
64     auto& dmc = flinger->mutableDisplayModeController();
65 
66     if (!dmc.getDesiredMode(displayId)) {
67         *result_listener << "No desired mode";
68         return false;
69     }
70 
71     if (dmc.getDesiredMode(displayId)->mode.modePtr->getId() != modeId) {
72         *result_listener << "Unexpected desired mode " << ftl::to_underlying(modeId);
73         return false;
74     }
75 
76     // VsyncModulator should react to mode switches on the pacesetter display.
77     if (displayId == flinger->scheduler()->pacesetterDisplayId() &&
78         !flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) {
79         *result_listener << "VsyncModulator did not shift to early phase";
80         return false;
81     }
82 
83     return true;
84 }
85 
86 class DisplayModeSwitchingTest : public DisplayTransactionTest {
87 public:
SetUp()88     void SetUp() override {
89         injectFakeBufferQueueFactory();
90         injectFakeNativeWindowSurfaceFactory();
91 
92         PrimaryDisplayVariant::setupHwcHotplugCallExpectations(this);
93         PrimaryDisplayVariant::setupFramebufferConsumerBufferQueueCallExpectations(this);
94         PrimaryDisplayVariant::setupFramebufferProducerBufferQueueCallExpectations(this);
95         PrimaryDisplayVariant::setupNativeWindowSurfaceCreationCallExpectations(this);
96         PrimaryDisplayVariant::setupHwcGetActiveConfigCallExpectations(this);
97 
98         auto selectorPtr = std::make_shared<scheduler::RefreshRateSelector>(kModes, kModeId60);
99 
100         setupScheduler(selectorPtr);
101 
102         mFlinger.onComposerHalHotplugEvent(kInnerDisplayHwcId, DisplayHotplugEvent::CONNECTED);
103         mFlinger.configureAndCommit();
104 
105         auto vsyncController = std::make_unique<mock::VsyncController>();
106         auto vsyncTracker = std::make_shared<mock::VSyncTracker>();
107 
108         EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_, _)).WillRepeatedly(Return(0));
109         EXPECT_CALL(*vsyncTracker, currentPeriod())
110                 .WillRepeatedly(Return(
111                         TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
112         EXPECT_CALL(*vsyncTracker, minFramePeriod())
113                 .WillRepeatedly(Return(Period::fromNs(
114                         TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)));
115 
116         mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
117                            .setRefreshRateSelector(std::move(selectorPtr))
118                            .inject(std::move(vsyncController), std::move(vsyncTracker));
119         mDisplayId = mDisplay->getPhysicalId();
120 
121         // isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy
122         // will call setActiveConfig instead of setActiveConfigWithConstraints.
123         ON_CALL(*mComposer, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
124                 .WillByDefault(Return(true));
125     }
126 
127     static constexpr HWDisplayId kInnerDisplayHwcId = PrimaryDisplayVariant::HWC_DISPLAY_ID;
128     static constexpr HWDisplayId kOuterDisplayHwcId = kInnerDisplayHwcId + 1;
129     static constexpr uint8_t kOuterDisplayPort = 254u;
130     static constexpr PhysicalDisplayId kOuterDisplayId =
131             PhysicalDisplayId::fromPort(kOuterDisplayPort);
132 
injectOuterDisplay()133     auto injectOuterDisplay() {
134         // For the inner display, this is handled by setupHwcHotplugCallExpectations.
135         EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _))
136                 .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL),
137                                 Return(hal::V2_4::Error::NONE)));
138 
139         constexpr bool kIsPrimary = false;
140         TestableSurfaceFlinger::FakeHwcDisplayInjector(kOuterDisplayId, hal::DisplayType::PHYSICAL,
141                                                        kIsPrimary)
142                 .setHwcDisplayId(kOuterDisplayHwcId)
143                 .setPowerMode(hal::PowerMode::OFF)
144                 .inject(&mFlinger, mComposer);
145 
146         mOuterDisplay = mFakeDisplayInjector.injectInternalDisplay(
147                 [&](FakeDisplayDeviceInjector& injector) {
148                     injector.setPowerMode(hal::PowerMode::OFF);
149                     injector.setDisplayModes(mock::cloneForDisplay(kOuterDisplayId, kModes),
150                                              kModeId120);
151                 },
152                 {.displayId = kOuterDisplayId,
153                  .port = kOuterDisplayPort,
154                  .hwcDisplayId = kOuterDisplayHwcId,
155                  .isPrimary = kIsPrimary});
156 
157         return std::forward_as_tuple(mDisplay, mOuterDisplay);
158     }
159 
160 protected:
161     void setupScheduler(std::shared_ptr<scheduler::RefreshRateSelector>);
162 
dmc()163     auto& dmc() { return mFlinger.mutableDisplayModeController(); }
164 
165     sp<DisplayDevice> mDisplay, mOuterDisplay;
166     PhysicalDisplayId mDisplayId;
167 
168     mock::EventThread* mAppEventThread;
169 
170     static constexpr DisplayModeId kModeId60{0};
171     static constexpr DisplayModeId kModeId90{1};
172     static constexpr DisplayModeId kModeId120{2};
173     static constexpr DisplayModeId kModeId90_4K{3};
174     static constexpr DisplayModeId kModeId60_8K{4};
175 
176     static inline const DisplayModePtr kMode60 = createDisplayMode(kModeId60, 60_Hz, 0);
177     static inline const DisplayModePtr kMode90 = createDisplayMode(kModeId90, 90_Hz, 1);
178     static inline const DisplayModePtr kMode120 = createDisplayMode(kModeId120, 120_Hz, 2);
179 
180     static constexpr ui::Size kResolution4K{3840, 2160};
181     static constexpr ui::Size kResolution8K{7680, 4320};
182 
183     static inline const DisplayModePtr kMode90_4K =
184             createDisplayMode(kModeId90_4K, 90_Hz, 3, kResolution4K);
185     static inline const DisplayModePtr kMode60_8K =
186             createDisplayMode(kModeId60_8K, 60_Hz, 4, kResolution8K);
187 
188     static inline const DisplayModes kModes =
189             makeModes(kMode60, kMode90, kMode120, kMode90_4K, kMode60_8K);
190 };
191 
setupScheduler(std::shared_ptr<scheduler::RefreshRateSelector> selectorPtr)192 void DisplayModeSwitchingTest::setupScheduler(
193         std::shared_ptr<scheduler::RefreshRateSelector> selectorPtr) {
194     auto eventThread = std::make_unique<mock::EventThread>();
195     mAppEventThread = eventThread.get();
196     auto sfEventThread = std::make_unique<mock::EventThread>();
197 
198     auto vsyncController = std::make_unique<mock::VsyncController>();
199     auto vsyncTracker = std::make_shared<mock::VSyncTracker>();
200 
201     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_, _)).WillRepeatedly(Return(0));
202     EXPECT_CALL(*vsyncTracker, currentPeriod())
203             .WillRepeatedly(
204                     Return(TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
205     EXPECT_CALL(*vsyncTracker, minFramePeriod())
206             .WillRepeatedly(Return(Period::fromNs(
207                     TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)));
208     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_, _)).WillRepeatedly(Return(0));
209     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
210                             std::move(eventThread), std::move(sfEventThread),
211                             std::move(selectorPtr),
212                             TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp);
213 }
214 
TEST_F(DisplayModeSwitchingTest,changeRefreshRateWithRefreshRequired)215 TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithRefreshRequired) {
216     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
217 
218     EXPECT_EQ(NO_ERROR,
219               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
220                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
221 
222     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
223 
224     // Verify that next commit will call setActiveConfigWithConstraints in HWC
225     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
226     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
227 
228     mFlinger.commit();
229     Mock::VerifyAndClearExpectations(mComposer);
230 
231     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
232 
233     // Verify that the next commit will complete the mode change and send
234     // a onModeChanged event to the framework.
235 
236     EXPECT_CALL(*mAppEventThread,
237                 onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)}));
238 
239     mFlinger.commit();
240     Mock::VerifyAndClearExpectations(mAppEventThread);
241 
242     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90));
243 }
244 
TEST_F(DisplayModeSwitchingTest,changeRefreshRateWithoutRefreshRequired)245 TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithoutRefreshRequired) {
246     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
247 
248     constexpr bool kAllowGroupSwitching = true;
249     EXPECT_EQ(NO_ERROR,
250               mFlinger.setDesiredDisplayModeSpecs(
251                       mDisplay->getDisplayToken().promote(),
252                       mock::createDisplayModeSpecs(kModeId90, 120_Hz, kAllowGroupSwitching)));
253 
254     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
255 
256     // Verify that next commit will call setActiveConfigWithConstraints in HWC
257     // and complete the mode change.
258     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
259     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
260 
261     EXPECT_CALL(*mAppEventThread,
262                 onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)}));
263 
264     mFlinger.commit();
265 
266     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90));
267 }
268 
TEST_F(DisplayModeSwitchingTest,changeRefreshRateOnTwoDisplaysWithoutRefreshRequired)269 TEST_F(DisplayModeSwitchingTest, changeRefreshRateOnTwoDisplaysWithoutRefreshRequired) {
270     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
271 
272     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
273     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
274 
275     EXPECT_EQ(NO_ERROR,
276               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
277                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz,
278                                                                                true)));
279     EXPECT_EQ(NO_ERROR,
280               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
281                                                   mock::createDisplayModeSpecs(kModeId60, 60_Hz,
282                                                                                true)));
283 
284     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
285     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
286 
287     // Verify that next commit will call setActiveConfigWithConstraints in HWC
288     // and complete the mode change.
289     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
290     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
291     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
292 
293     EXPECT_CALL(*mAppEventThread, onModeChanged(_)).Times(2);
294 
295     mFlinger.commit();
296 
297     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
298     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
299 }
300 
TEST_F(DisplayModeSwitchingTest,twoConsecutiveSetDesiredDisplayModeSpecs)301 TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) {
302     // Test that if we call setDesiredDisplayModeSpecs while a previous mode change
303     // is still being processed the later call will be respected.
304 
305     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
306 
307     EXPECT_EQ(NO_ERROR,
308               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
309                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
310 
311     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
312     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
313 
314     mFlinger.commit();
315 
316     EXPECT_EQ(NO_ERROR,
317               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
318                                                   mock::createDisplayModeSpecs(kModeId120,
319                                                                                180_Hz)));
320 
321     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
322 
323     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId120);
324 
325     mFlinger.commit();
326 
327     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
328 
329     mFlinger.commit();
330 
331     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId120));
332 }
333 
TEST_F(DisplayModeSwitchingTest,changeResolutionWithoutRefreshRequired)334 TEST_F(DisplayModeSwitchingTest, changeResolutionWithoutRefreshRequired) {
335     SET_FLAG_FOR_TEST(flags::synced_resolution_switch, false);
336 
337     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
338 
339     EXPECT_EQ(NO_ERROR,
340               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
341                                                   mock::createDisplayModeSpecs(kModeId90_4K,
342                                                                                120_Hz)));
343 
344     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90_4K));
345 
346     // Verify that next commit will call setActiveConfigWithConstraints in HWC
347     // and complete the mode change.
348     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
349     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90_4K);
350 
351     EXPECT_CALL(*mAppEventThread, onHotplugReceived(mDisplayId, true));
352 
353     // Override expectations set up by PrimaryDisplayVariant.
354     EXPECT_CALL(*mConsumer,
355                 setDefaultBufferSize(static_cast<uint32_t>(kResolution4K.getWidth()),
356                                      static_cast<uint32_t>(kResolution4K.getHeight())))
357             .WillOnce(Return(NO_ERROR));
358     EXPECT_CALL(*mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
359     EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(hal::Error::NONE));
360 
361     // Create a new native surface to be used by the recreated display.
362     mNativeWindowSurface = nullptr;
363     injectFakeNativeWindowSurfaceFactory();
364     PrimaryDisplayVariant::setupNativeWindowSurfaceCreationCallExpectations(this);
365 
366     mFlinger.commit();
367 
368     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90_4K));
369 }
370 
TEST_F(DisplayModeSwitchingTest,changeResolutionSynced)371 TEST_F(DisplayModeSwitchingTest, changeResolutionSynced) {
372     SET_FLAG_FOR_TEST(flags::synced_resolution_switch, true);
373 
374     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
375 
376     // PrimaryDisplayVariant has a 4K size, so switch to 8K.
377     EXPECT_EQ(NO_ERROR,
378               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
379                                                   mock::createDisplayModeSpecs(kModeId60_8K,
380                                                                                60_Hz)));
381 
382     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId60_8K));
383 
384     // The mode should not be set until the commit that resizes the display.
385     mFlinger.commit();
386     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId60_8K));
387     mFlinger.commit();
388     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId60_8K));
389 
390     // Set the display size to match the resolution.
391     DisplayState state;
392     state.what = DisplayState::eDisplaySizeChanged;
393     state.token = mDisplay->getDisplayToken().promote();
394     state.width = static_cast<uint32_t>(kResolution8K.width);
395     state.height = static_cast<uint32_t>(kResolution8K.height);
396 
397     // The next commit should set the mode and resize the framebuffer.
398     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
399     EXPECT_CALL(*mDisplaySurface, resizeBuffers(kResolution8K));
400     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60_8K);
401 
402     constexpr bool kModeset = true;
403     mFlinger.setDisplayStateLocked(state);
404     mFlinger.configureAndCommit(kModeset);
405 
406     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60_8K));
407 }
408 
TEST_F(DisplayModeSwitchingTest,innerXorOuterDisplay)409 TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) {
410     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
411 
412     EXPECT_TRUE(innerDisplay->isPoweredOn());
413     EXPECT_FALSE(outerDisplay->isPoweredOn());
414 
415     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
416     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
417 
418     mFlinger.setPhysicalDisplayPowerMode(outerDisplay, hal::PowerMode::OFF);
419     mFlinger.setPhysicalDisplayPowerMode(innerDisplay, hal::PowerMode::ON);
420 
421     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
422     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
423 
424     EXPECT_EQ(NO_ERROR,
425               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
426                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
427 
428     EXPECT_EQ(NO_ERROR,
429               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
430                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
431 
432     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
433     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
434 
435     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
436     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
437     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
438 
439     mFlinger.commit();
440 
441     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
442     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
443 
444     mFlinger.commit();
445 
446     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
447     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
448 
449     mFlinger.setPhysicalDisplayPowerMode(innerDisplay, hal::PowerMode::OFF);
450     mFlinger.setPhysicalDisplayPowerMode(outerDisplay, hal::PowerMode::ON);
451 
452     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
453     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
454 
455     EXPECT_EQ(NO_ERROR,
456               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
457                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
458 
459     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
460     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60);
461 
462     mFlinger.commit();
463 
464     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
465     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
466 
467     mFlinger.commit();
468 
469     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
470     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
471 }
472 
TEST_F(DisplayModeSwitchingTest,innerAndOuterDisplay)473 TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) {
474     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
475 
476     EXPECT_TRUE(innerDisplay->isPoweredOn());
477     EXPECT_FALSE(outerDisplay->isPoweredOn());
478 
479     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
480     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
481 
482     mFlinger.setPhysicalDisplayPowerMode(innerDisplay, hal::PowerMode::ON);
483     mFlinger.setPhysicalDisplayPowerMode(outerDisplay, hal::PowerMode::ON);
484 
485     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
486     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
487 
488     EXPECT_EQ(NO_ERROR,
489               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
490                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
491 
492     EXPECT_EQ(NO_ERROR,
493               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
494                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
495 
496     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
497     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
498 
499     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
500     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
501     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
502 
503     mFlinger.commit();
504 
505     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
506     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
507 
508     mFlinger.commit();
509 
510     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
511     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
512 }
513 
TEST_F(DisplayModeSwitchingTest,powerOffDuringModeSet)514 TEST_F(DisplayModeSwitchingTest, powerOffDuringModeSet) {
515     EXPECT_TRUE(mDisplay->isPoweredOn());
516     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
517 
518     EXPECT_EQ(NO_ERROR,
519               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
520                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
521 
522     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
523 
524     // Power off the display before the mode has been set.
525     mFlinger.setPhysicalDisplayPowerMode(mDisplay, hal::PowerMode::OFF);
526 
527     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
528     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
529 
530     mFlinger.commit();
531 
532     // Powering off should not abort the mode set.
533     EXPECT_FALSE(mDisplay->isPoweredOn());
534     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
535 
536     mFlinger.commit();
537 
538     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90));
539 }
540 
TEST_F(DisplayModeSwitchingTest,powerOffDuringConcurrentModeSet)541 TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) {
542     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
543 
544     EXPECT_TRUE(innerDisplay->isPoweredOn());
545     EXPECT_FALSE(outerDisplay->isPoweredOn());
546 
547     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
548     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
549 
550     mFlinger.setPhysicalDisplayPowerMode(innerDisplay, hal::PowerMode::ON);
551     mFlinger.setPhysicalDisplayPowerMode(outerDisplay, hal::PowerMode::ON);
552 
553     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
554     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
555 
556     EXPECT_EQ(NO_ERROR,
557               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
558                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
559 
560     EXPECT_EQ(NO_ERROR,
561               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
562                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
563 
564     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
565     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
566 
567     // Power off the outer display before the mode has been set.
568     mFlinger.setPhysicalDisplayPowerMode(outerDisplay, hal::PowerMode::OFF);
569 
570     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
571     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
572     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
573 
574     mFlinger.commit();
575 
576     // Powering off the inactive display should not abort the mode set.
577     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
578     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
579 
580     mFlinger.commit();
581 
582     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
583     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
584 
585     mFlinger.setPhysicalDisplayPowerMode(innerDisplay, hal::PowerMode::OFF);
586     mFlinger.setPhysicalDisplayPowerMode(outerDisplay, hal::PowerMode::ON);
587 
588     EXPECT_EQ(NO_ERROR,
589               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
590                                                   mock::createDisplayModeSpecs(kModeId120,
591                                                                                120_Hz)));
592 
593     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId120);
594 
595     mFlinger.commit();
596 
597     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
598     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
599 
600     mFlinger.commit();
601 
602     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
603     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
604 }
605 
606 } // namespace
607 } // namespace android
608