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