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 
130     static constexpr PhysicalDisplayId kOuterDisplayId = PhysicalDisplayId::fromPort(254u);
131 
injectOuterDisplay()132     auto injectOuterDisplay() {
133         // For the inner display, this is handled by setupHwcHotplugCallExpectations.
134         EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _))
135                 .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL),
136                                 Return(hal::V2_4::Error::NONE)));
137 
138         constexpr bool kIsPrimary = false;
139         TestableSurfaceFlinger::FakeHwcDisplayInjector(kOuterDisplayId, hal::DisplayType::PHYSICAL,
140                                                        kIsPrimary)
141                 .setHwcDisplayId(kOuterDisplayHwcId)
142                 .setPowerMode(hal::PowerMode::OFF)
143                 .inject(&mFlinger, mComposer);
144 
145         mOuterDisplay = mFakeDisplayInjector.injectInternalDisplay(
146                 [&](FakeDisplayDeviceInjector& injector) {
147                     injector.setPowerMode(hal::PowerMode::OFF);
148                     injector.setDisplayModes(mock::cloneForDisplay(kOuterDisplayId, kModes),
149                                              kModeId120);
150                 },
151                 {.displayId = kOuterDisplayId,
152                  .hwcDisplayId = kOuterDisplayHwcId,
153                  .isPrimary = kIsPrimary});
154 
155         return std::forward_as_tuple(mDisplay, mOuterDisplay);
156     }
157 
158 protected:
159     void setupScheduler(std::shared_ptr<scheduler::RefreshRateSelector>);
160 
dmc()161     auto& dmc() { return mFlinger.mutableDisplayModeController(); }
162 
163     sp<DisplayDevice> mDisplay, mOuterDisplay;
164     PhysicalDisplayId mDisplayId;
165 
166     mock::EventThread* mAppEventThread;
167 
168     static constexpr DisplayModeId kModeId60{0};
169     static constexpr DisplayModeId kModeId90{1};
170     static constexpr DisplayModeId kModeId120{2};
171     static constexpr DisplayModeId kModeId90_4K{3};
172 
173     static inline const DisplayModePtr kMode60 = createDisplayMode(kModeId60, 60_Hz, 0);
174     static inline const DisplayModePtr kMode90 = createDisplayMode(kModeId90, 90_Hz, 1);
175     static inline const DisplayModePtr kMode120 = createDisplayMode(kModeId120, 120_Hz, 2);
176 
177     static constexpr ui::Size kResolution4K{3840, 2160};
178     static inline const DisplayModePtr kMode90_4K =
179             createDisplayMode(kModeId90_4K, 90_Hz, 3, kResolution4K);
180 
181     static inline const DisplayModes kModes = makeModes(kMode60, kMode90, kMode120, kMode90_4K);
182 };
183 
setupScheduler(std::shared_ptr<scheduler::RefreshRateSelector> selectorPtr)184 void DisplayModeSwitchingTest::setupScheduler(
185         std::shared_ptr<scheduler::RefreshRateSelector> selectorPtr) {
186     auto eventThread = std::make_unique<mock::EventThread>();
187     mAppEventThread = eventThread.get();
188     auto sfEventThread = std::make_unique<mock::EventThread>();
189 
190     auto vsyncController = std::make_unique<mock::VsyncController>();
191     auto vsyncTracker = std::make_shared<mock::VSyncTracker>();
192 
193     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_, _)).WillRepeatedly(Return(0));
194     EXPECT_CALL(*vsyncTracker, currentPeriod())
195             .WillRepeatedly(
196                     Return(TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
197     EXPECT_CALL(*vsyncTracker, minFramePeriod())
198             .WillRepeatedly(Return(Period::fromNs(
199                     TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)));
200     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_, _)).WillRepeatedly(Return(0));
201     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
202                             std::move(eventThread), std::move(sfEventThread),
203                             std::move(selectorPtr),
204                             TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp);
205 }
206 
TEST_F(DisplayModeSwitchingTest,changeRefreshRateWithRefreshRequired)207 TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithRefreshRequired) {
208     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
209 
210     EXPECT_EQ(NO_ERROR,
211               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
212                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
213 
214     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
215 
216     // Verify that next commit will call setActiveConfigWithConstraints in HWC
217     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
218     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
219 
220     mFlinger.commit();
221     Mock::VerifyAndClearExpectations(mComposer);
222 
223     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
224 
225     // Verify that the next commit will complete the mode change and send
226     // a onModeChanged event to the framework.
227 
228     EXPECT_CALL(*mAppEventThread,
229                 onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)}));
230 
231     mFlinger.commit();
232     Mock::VerifyAndClearExpectations(mAppEventThread);
233 
234     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90));
235 }
236 
TEST_F(DisplayModeSwitchingTest,changeRefreshRateWithoutRefreshRequired)237 TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithoutRefreshRequired) {
238     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
239 
240     constexpr bool kAllowGroupSwitching = true;
241     EXPECT_EQ(NO_ERROR,
242               mFlinger.setDesiredDisplayModeSpecs(
243                       mDisplay->getDisplayToken().promote(),
244                       mock::createDisplayModeSpecs(kModeId90, 120_Hz, kAllowGroupSwitching)));
245 
246     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
247 
248     // Verify that next commit will call setActiveConfigWithConstraints in HWC
249     // and complete the mode change.
250     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
251     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
252 
253     EXPECT_CALL(*mAppEventThread,
254                 onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)}));
255 
256     mFlinger.commit();
257 
258     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90));
259 }
260 
TEST_F(DisplayModeSwitchingTest,changeRefreshRateOnTwoDisplaysWithoutRefreshRequired)261 TEST_F(DisplayModeSwitchingTest, changeRefreshRateOnTwoDisplaysWithoutRefreshRequired) {
262     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
263 
264     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
265     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
266 
267     EXPECT_EQ(NO_ERROR,
268               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
269                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz,
270                                                                                true)));
271     EXPECT_EQ(NO_ERROR,
272               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
273                                                   mock::createDisplayModeSpecs(kModeId60, 60_Hz,
274                                                                                true)));
275 
276     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
277     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
278 
279     // Verify that next commit will call setActiveConfigWithConstraints in HWC
280     // and complete the mode change.
281     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
282     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
283     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
284 
285     EXPECT_CALL(*mAppEventThread, onModeChanged(_)).Times(2);
286 
287     mFlinger.commit();
288 
289     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
290     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
291 }
292 
TEST_F(DisplayModeSwitchingTest,twoConsecutiveSetDesiredDisplayModeSpecs)293 TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) {
294     // Test that if we call setDesiredDisplayModeSpecs while a previous mode change
295     // is still being processed the later call will be respected.
296 
297     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
298 
299     EXPECT_EQ(NO_ERROR,
300               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
301                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
302 
303     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
304     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
305 
306     mFlinger.commit();
307 
308     EXPECT_EQ(NO_ERROR,
309               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
310                                                   mock::createDisplayModeSpecs(kModeId120,
311                                                                                180_Hz)));
312 
313     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
314 
315     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId120);
316 
317     mFlinger.commit();
318 
319     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
320 
321     mFlinger.commit();
322 
323     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId120));
324 }
325 
TEST_F(DisplayModeSwitchingTest,changeResolutionWithoutRefreshRequired)326 TEST_F(DisplayModeSwitchingTest, changeResolutionWithoutRefreshRequired) {
327     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
328 
329     EXPECT_EQ(NO_ERROR,
330               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
331                                                   mock::createDisplayModeSpecs(kModeId90_4K,
332                                                                                120_Hz)));
333 
334     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90_4K));
335 
336     // Verify that next commit will call setActiveConfigWithConstraints in HWC
337     // and complete the mode change.
338     const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
339     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90_4K);
340 
341     EXPECT_CALL(*mAppEventThread, onHotplugReceived(mDisplayId, true));
342 
343     // Override expectations set up by PrimaryDisplayVariant.
344     EXPECT_CALL(*mConsumer,
345                 setDefaultBufferSize(static_cast<uint32_t>(kResolution4K.getWidth()),
346                                      static_cast<uint32_t>(kResolution4K.getHeight())))
347             .WillOnce(Return(NO_ERROR));
348     EXPECT_CALL(*mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
349     EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(hal::Error::NONE));
350 
351     // Create a new native surface to be used by the recreated display.
352     mNativeWindowSurface = nullptr;
353     injectFakeNativeWindowSurfaceFactory();
354     PrimaryDisplayVariant::setupNativeWindowSurfaceCreationCallExpectations(this);
355 
356     mFlinger.commit();
357 
358     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90_4K));
359 }
360 
TEST_F(DisplayModeSwitchingTest,innerXorOuterDisplay)361 TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) {
362     SET_FLAG_FOR_TEST(flags::connected_display, true);
363 
364     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
365 
366     EXPECT_TRUE(innerDisplay->isPoweredOn());
367     EXPECT_FALSE(outerDisplay->isPoweredOn());
368 
369     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
370     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
371 
372     mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::OFF);
373     mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
374 
375     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
376     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
377 
378     EXPECT_EQ(NO_ERROR,
379               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
380                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
381 
382     EXPECT_EQ(NO_ERROR,
383               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
384                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
385 
386     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
387     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
388 
389     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
390     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
391     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
392 
393     mFlinger.commit();
394 
395     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
396     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
397 
398     mFlinger.commit();
399 
400     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
401     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
402 
403     mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::OFF);
404     mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
405 
406     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
407     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
408 
409     EXPECT_EQ(NO_ERROR,
410               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
411                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
412 
413     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
414     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60);
415 
416     mFlinger.commit();
417 
418     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
419     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
420 
421     mFlinger.commit();
422 
423     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
424     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
425 }
426 
TEST_F(DisplayModeSwitchingTest,innerAndOuterDisplay)427 TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) {
428     SET_FLAG_FOR_TEST(flags::connected_display, true);
429 
430     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
431 
432     EXPECT_TRUE(innerDisplay->isPoweredOn());
433     EXPECT_FALSE(outerDisplay->isPoweredOn());
434 
435     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
436     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
437 
438     mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
439     mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
440 
441     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
442     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
443 
444     EXPECT_EQ(NO_ERROR,
445               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
446                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
447 
448     EXPECT_EQ(NO_ERROR,
449               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
450                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
451 
452     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
453     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
454 
455     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
456     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
457     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
458 
459     mFlinger.commit();
460 
461     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
462     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
463 
464     mFlinger.commit();
465 
466     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
467     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
468 }
469 
TEST_F(DisplayModeSwitchingTest,powerOffDuringModeSet)470 TEST_F(DisplayModeSwitchingTest, powerOffDuringModeSet) {
471     EXPECT_TRUE(mDisplay->isPoweredOn());
472     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
473 
474     EXPECT_EQ(NO_ERROR,
475               mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
476                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
477 
478     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
479 
480     // Power off the display before the mode has been set.
481     mFlinger.setPowerModeInternal(mDisplay, hal::PowerMode::OFF);
482 
483     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
484     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
485 
486     mFlinger.commit();
487 
488     // Powering off should not abort the mode set.
489     EXPECT_FALSE(mDisplay->isPoweredOn());
490     EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
491 
492     mFlinger.commit();
493 
494     EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90));
495 }
496 
TEST_F(DisplayModeSwitchingTest,powerOffDuringConcurrentModeSet)497 TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) {
498     SET_FLAG_FOR_TEST(flags::connected_display, true);
499 
500     const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
501 
502     EXPECT_TRUE(innerDisplay->isPoweredOn());
503     EXPECT_FALSE(outerDisplay->isPoweredOn());
504 
505     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
506     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
507 
508     mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::ON);
509     mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
510 
511     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60));
512     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
513 
514     EXPECT_EQ(NO_ERROR,
515               mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(),
516                                                   mock::createDisplayModeSpecs(kModeId90, 120_Hz)));
517 
518     EXPECT_EQ(NO_ERROR,
519               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
520                                                   mock::createDisplayModeSpecs(kModeId60, 120_Hz)));
521 
522     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
523     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
524 
525     // Power off the outer display before the mode has been set.
526     mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::OFF);
527 
528     const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
529     EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90);
530     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60);
531 
532     mFlinger.commit();
533 
534     // Powering off the inactive display should not abort the mode set.
535     EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90));
536     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60));
537 
538     mFlinger.commit();
539 
540     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
541     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60));
542 
543     mFlinger.setPowerModeInternal(innerDisplay, hal::PowerMode::OFF);
544     mFlinger.setPowerModeInternal(outerDisplay, hal::PowerMode::ON);
545 
546     EXPECT_EQ(NO_ERROR,
547               mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(),
548                                                   mock::createDisplayModeSpecs(kModeId120,
549                                                                                120_Hz)));
550 
551     EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId120);
552 
553     mFlinger.commit();
554 
555     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
556     EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId120));
557 
558     mFlinger.commit();
559 
560     EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90));
561     EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120));
562 }
563 
564 } // namespace
565 } // namespace android
566