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