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