1 /*
2 * Copyright 2020 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
22 namespace android {
23 namespace {
24
25 struct DisplayTransactionCommitTest : DisplayTransactionTest {
26 template <typename Case>
27 void setupCommonPreconditions();
28
29 template <typename Case, bool connected>
30 static void expectHotplugReceived(mock::EventThread*);
31
32 template <typename Case>
33 void setupCommonCallExpectationsForConnectProcessing();
34
35 template <typename Case>
36 void setupCommonCallExpectationsForDisconnectProcessing();
37
38 template <typename Case>
39 void processesHotplugConnectCommon();
40
41 template <typename Case>
42 void ignoresHotplugConnectCommon();
43
44 template <typename Case>
45 void processesHotplugDisconnectCommon();
46
47 template <typename Case>
48 void verifyDisplayIsConnected(const sp<IBinder>& displayToken);
49
50 template <typename Case>
51 void verifyPhysicalDisplayIsConnected();
52
53 void verifyDisplayIsNotConnected(const sp<IBinder>& displayToken);
54 };
55
56 template <typename Case>
setupCommonPreconditions()57 void DisplayTransactionCommitTest::setupCommonPreconditions() {
58 // Wide color displays support is configured appropriately
59 Case::WideColorSupport::injectConfigChange(this);
60
61 // SurfaceFlinger will use a test-controlled factory for BufferQueues
62 injectFakeBufferQueueFactory();
63
64 // SurfaceFlinger will use a test-controlled factory for native window
65 // surfaces.
66 injectFakeNativeWindowSurfaceFactory();
67 }
68
69 template <typename Case, bool connected>
expectHotplugReceived(mock::EventThread * eventThread)70 void DisplayTransactionCommitTest::expectHotplugReceived(mock::EventThread* eventThread) {
71 const auto physicalDisplayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
72 ASSERT_TRUE(physicalDisplayId);
73 EXPECT_CALL(*eventThread, onHotplugReceived(*physicalDisplayId, connected)).Times(1);
74 }
75
76 template <typename Case>
setupCommonCallExpectationsForConnectProcessing()77 void DisplayTransactionCommitTest::setupCommonCallExpectationsForConnectProcessing() {
78 Case::Display::setupHwcHotplugCallExpectations(this);
79
80 Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
81 Case::Display::setupFramebufferProducerBufferQueueCallExpectations(this);
82 Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
83 Case::Display::setupHwcGetActiveConfigCallExpectations(this);
84
85 Case::WideColorSupport::setupComposerCallExpectations(this);
86 Case::HdrSupport::setupComposerCallExpectations(this);
87 Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
88
89 expectHotplugReceived<Case, true>(mEventThread);
90 expectHotplugReceived<Case, true>(mSFEventThread);
91 }
92
93 template <typename Case>
setupCommonCallExpectationsForDisconnectProcessing()94 void DisplayTransactionCommitTest::setupCommonCallExpectationsForDisconnectProcessing() {
95 expectHotplugReceived<Case, false>(mEventThread);
96 expectHotplugReceived<Case, false>(mSFEventThread);
97 }
98
99 template <typename Case>
verifyDisplayIsConnected(const sp<IBinder> & displayToken)100 void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) {
101 // The display device should have been set up in the list of displays.
102 ASSERT_TRUE(hasDisplayDevice(displayToken));
103 const auto& display = getDisplayDevice(displayToken);
104
105 EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), display.isSecure());
106 EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), display.isPrimary());
107
108 std::optional<DisplayDeviceState::Physical> expectedPhysical;
109 if (Case::Display::CONNECTION_TYPE::value) {
110 const auto displayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
111 ASSERT_TRUE(displayId);
112 const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
113 ASSERT_TRUE(hwcDisplayId);
114 expectedPhysical = {.id = *displayId, .hwcDisplayId = *hwcDisplayId};
115 }
116
117 // The display should have been set up in the current display state
118 ASSERT_TRUE(hasCurrentDisplayState(displayToken));
119 const auto& current = getCurrentDisplayState(displayToken);
120 EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), current.isVirtual());
121 EXPECT_EQ(expectedPhysical, current.physical);
122
123 // The display should have been set up in the drawing display state
124 ASSERT_TRUE(hasDrawingDisplayState(displayToken));
125 const auto& draw = getDrawingDisplayState(displayToken);
126 EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
127 EXPECT_EQ(expectedPhysical, draw.physical);
128 }
129
130 template <typename Case>
verifyPhysicalDisplayIsConnected()131 void DisplayTransactionCommitTest::verifyPhysicalDisplayIsConnected() {
132 // HWComposer should have an entry for the display
133 EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
134
135 // SF should have a display token.
136 const auto displayIdOpt = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
137 ASSERT_TRUE(displayIdOpt);
138
139 const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(*displayIdOpt);
140 ASSERT_TRUE(displayOpt);
141
142 const auto& display = displayOpt->get();
143 EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, display.snapshot().connectionType());
144
145 verifyDisplayIsConnected<Case>(display.token());
146 }
147
verifyDisplayIsNotConnected(const sp<IBinder> & displayToken)148 void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) {
149 EXPECT_FALSE(hasDisplayDevice(displayToken));
150 EXPECT_FALSE(hasCurrentDisplayState(displayToken));
151 EXPECT_FALSE(hasDrawingDisplayState(displayToken));
152 }
153
154 template <typename Case>
processesHotplugConnectCommon()155 void DisplayTransactionCommitTest::processesHotplugConnectCommon() {
156 // --------------------------------------------------------------------
157 // Preconditions
158
159 setupCommonPreconditions<Case>();
160
161 // A hotplug connect event is enqueued for a display
162 Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
163
164 // --------------------------------------------------------------------
165 // Call Expectations
166
167 setupCommonCallExpectationsForConnectProcessing<Case>();
168
169 // --------------------------------------------------------------------
170 // Invocation
171
172 mFlinger.configureAndCommit();
173
174 // --------------------------------------------------------------------
175 // Postconditions
176
177 verifyPhysicalDisplayIsConnected<Case>();
178
179 // --------------------------------------------------------------------
180 // Cleanup conditions
181
182 EXPECT_CALL(*mComposer,
183 setVsyncEnabled(Case::Display::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
184 .WillOnce(Return(Error::NONE));
185 EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
186 }
187
188 template <typename Case>
ignoresHotplugConnectCommon()189 void DisplayTransactionCommitTest::ignoresHotplugConnectCommon() {
190 // --------------------------------------------------------------------
191 // Preconditions
192
193 setupCommonPreconditions<Case>();
194
195 // A hotplug connect event is enqueued for a display
196 Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
197
198 // --------------------------------------------------------------------
199 // Invocation
200
201 mFlinger.configureAndCommit();
202
203 // --------------------------------------------------------------------
204 // Postconditions
205
206 // HWComposer should not have an entry for the display
207 EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
208 }
209
210 template <typename Case>
processesHotplugDisconnectCommon()211 void DisplayTransactionCommitTest::processesHotplugDisconnectCommon() {
212 // --------------------------------------------------------------------
213 // Preconditions
214
215 setupCommonPreconditions<Case>();
216
217 // A hotplug disconnect event is enqueued for a display
218 Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
219
220 // The display is already completely set up.
221 Case::Display::injectHwcDisplay(this);
222 auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
223 existing.inject();
224
225 // --------------------------------------------------------------------
226 // Call Expectations
227
228 EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _))
229 .Times(0);
230
231 setupCommonCallExpectationsForDisconnectProcessing<Case>();
232
233 // --------------------------------------------------------------------
234 // Invocation
235
236 mFlinger.configureAndCommit();
237
238 // --------------------------------------------------------------------
239 // Postconditions
240
241 // HWComposer should not have an entry for the display
242 EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
243
244 // SF should not have a PhysicalDisplay.
245 const auto physicalDisplayIdOpt = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
246 ASSERT_TRUE(physicalDisplayIdOpt);
247 ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(*physicalDisplayIdOpt));
248
249 // The existing token should have been removed.
250 verifyDisplayIsNotConnected(existing.token());
251 }
252
TEST_F(DisplayTransactionCommitTest,processesHotplugConnectPrimaryDisplay)253 TEST_F(DisplayTransactionCommitTest, processesHotplugConnectPrimaryDisplay) {
254 processesHotplugConnectCommon<SimplePrimaryDisplayCase>();
255 }
256
TEST_F(DisplayTransactionCommitTest,processesHotplugConnectExternalDisplay)257 TEST_F(DisplayTransactionCommitTest, processesHotplugConnectExternalDisplay) {
258 // Inject a primary display.
259 PrimaryDisplayVariant::injectHwcDisplay(this);
260
261 processesHotplugConnectCommon<SimpleExternalDisplayCase>();
262 }
263
TEST_F(DisplayTransactionCommitTest,processesHotplugConnectNonSecureExternalDisplay)264 TEST_F(DisplayTransactionCommitTest, processesHotplugConnectNonSecureExternalDisplay) {
265 // Inject a primary display.
266 PrimaryDisplayVariant::injectHwcDisplay(this);
267
268 processesHotplugConnectCommon<SimpleExternalDisplayNonSecureCase>();
269 }
270
TEST_F(DisplayTransactionCommitTest,ignoresHotplugConnectIfPrimaryAndExternalAlreadyConnected)271 TEST_F(DisplayTransactionCommitTest, ignoresHotplugConnectIfPrimaryAndExternalAlreadyConnected) {
272 // Inject both a primary and external display.
273 PrimaryDisplayVariant::injectHwcDisplay(this);
274 ExternalDisplayVariant::injectHwcDisplay(this);
275
276 // TODO: This is an unnecessary call.
277 EXPECT_CALL(*mComposer,
278 getDisplayIdentificationData(TertiaryDisplayVariant::HWC_DISPLAY_ID, _, _))
279 .WillOnce(DoAll(SetArgPointee<1>(TertiaryDisplay<kSecure>::PORT),
280 SetArgPointee<2>(TertiaryDisplay<kSecure>::GET_IDENTIFICATION_DATA()),
281 Return(Error::NONE)));
282
283 ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>();
284 }
285
TEST_F(DisplayTransactionCommitTest,ignoresHotplugConnectNonSecureIfPrimaryAndExternalAlreadyConnected)286 TEST_F(DisplayTransactionCommitTest,
287 ignoresHotplugConnectNonSecureIfPrimaryAndExternalAlreadyConnected) {
288 // Inject both a primary and external display.
289 PrimaryDisplayVariant::injectHwcDisplay(this);
290 ExternalDisplayVariant::injectHwcDisplay(this);
291
292 // TODO: This is an unnecessary call.
293 EXPECT_CALL(*mComposer,
294 getDisplayIdentificationData(TertiaryDisplayVariant::HWC_DISPLAY_ID, _, _))
295 .WillOnce(DoAll(SetArgPointee<1>(TertiaryDisplay<kSecure>::PORT),
296 SetArgPointee<2>(TertiaryDisplay<kSecure>::GET_IDENTIFICATION_DATA()),
297 Return(Error::NONE)));
298
299 ignoresHotplugConnectCommon<SimpleTertiaryDisplayNonSecureCase>();
300 }
301
TEST_F(DisplayTransactionCommitTest,processesHotplugDisconnectPrimaryDisplay)302 TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectPrimaryDisplay) {
303 EXPECT_EXIT(processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>(),
304 testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
305 }
306
TEST_F(DisplayTransactionCommitTest,processesHotplugDisconnectExternalDisplay)307 TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectExternalDisplay) {
308 processesHotplugDisconnectCommon<SimpleExternalDisplayCase>();
309 }
310
TEST_F(DisplayTransactionCommitTest,processesHotplugDisconnectNonSecureExternalDisplay)311 TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectNonSecureExternalDisplay) {
312 processesHotplugDisconnectCommon<SimpleExternalDisplayNonSecureCase>();
313 }
314
TEST_F(DisplayTransactionCommitTest,processesHotplugConnectThenDisconnectPrimary)315 TEST_F(DisplayTransactionCommitTest, processesHotplugConnectThenDisconnectPrimary) {
316 EXPECT_EXIT(
317 [this] {
318 using Case = SimplePrimaryDisplayCase;
319
320 // --------------------------------------------------------------------
321 // Preconditions
322
323 setupCommonPreconditions<Case>();
324
325 // A hotplug connect event is enqueued for a display
326 Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
327 // A hotplug disconnect event is also enqueued for the same display
328 Case::Display::injectPendingHotplugEvent(this,
329 HWComposer::HotplugEvent::Disconnected);
330
331 // --------------------------------------------------------------------
332 // Call Expectations
333
334 setupCommonCallExpectationsForConnectProcessing<Case>();
335 setupCommonCallExpectationsForDisconnectProcessing<Case>();
336
337 EXPECT_CALL(*mComposer,
338 setVsyncEnabled(Case::Display::HWC_DISPLAY_ID,
339 IComposerClient::Vsync::DISABLE))
340 .WillOnce(Return(Error::NONE));
341 EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
342
343 // --------------------------------------------------------------------
344 // Invocation
345
346 mFlinger.configureAndCommit();
347
348 // --------------------------------------------------------------------
349 // Postconditions
350
351 // HWComposer should not have an entry for the display
352 EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
353
354 // SF should not have a PhysicalDisplay.
355 const auto physicalDisplayIdOpt =
356 asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
357 ASSERT_TRUE(physicalDisplayIdOpt);
358 ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(*physicalDisplayIdOpt));
359 }(),
360 testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
361 }
362
TEST_F(DisplayTransactionCommitTest,processesHotplugDisconnectThenConnectPrimary)363 TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectThenConnectPrimary) {
364 EXPECT_EXIT(
365 [this] {
366 using Case = SimplePrimaryDisplayCase;
367
368 // --------------------------------------------------------------------
369 // Preconditions
370
371 setupCommonPreconditions<Case>();
372
373 // The display is already completely set up.
374 Case::Display::injectHwcDisplay(this);
375 auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
376 existing.inject();
377
378 // A hotplug disconnect event is enqueued for a display
379 Case::Display::injectPendingHotplugEvent(this,
380 HWComposer::HotplugEvent::Disconnected);
381 // A hotplug connect event is also enqueued for the same display
382 Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
383
384 // --------------------------------------------------------------------
385 // Call Expectations
386
387 setupCommonCallExpectationsForConnectProcessing<Case>();
388 setupCommonCallExpectationsForDisconnectProcessing<Case>();
389
390 // --------------------------------------------------------------------
391 // Invocation
392
393 mFlinger.configureAndCommit();
394
395 // --------------------------------------------------------------------
396 // Postconditions
397
398 // The existing token should have been removed.
399 verifyDisplayIsNotConnected(existing.token());
400 const auto physicalDisplayIdOpt =
401 asPhysicalDisplayId(Case::Display::DISPLAY_ID::get());
402 ASSERT_TRUE(physicalDisplayIdOpt);
403
404 const auto displayOpt =
405 mFlinger.mutablePhysicalDisplays().get(*physicalDisplayIdOpt);
406 ASSERT_TRUE(displayOpt);
407 EXPECT_NE(existing.token(), displayOpt->get().token());
408
409 // A new display should be connected in its place.
410 verifyPhysicalDisplayIsConnected<Case>();
411
412 // --------------------------------------------------------------------
413 // Cleanup conditions
414
415 EXPECT_CALL(*mComposer,
416 setVsyncEnabled(Case::Display::HWC_DISPLAY_ID,
417 IComposerClient::Vsync::DISABLE))
418 .WillOnce(Return(Error::NONE));
419 EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
420 }(),
421 testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
422 }
423
TEST_F(DisplayTransactionCommitTest,processesVirtualDisplayAdded)424 TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayAdded) {
425 using Case = HwcVirtualDisplayCase;
426
427 // --------------------------------------------------------------------
428 // Preconditions
429
430 // The HWC supports at least one virtual display
431 injectMockComposer(1);
432
433 setupCommonPreconditions<Case>();
434
435 // A virtual display was added to the current state, and it has a
436 // surface(producer)
437 sp<BBinder> displayToken = sp<BBinder>::make();
438
439 DisplayDeviceState state;
440 state.isSecure = static_cast<bool>(Case::Display::SECURE);
441
442 sp<mock::GraphicBufferProducer> surface{sp<mock::GraphicBufferProducer>::make()};
443 state.surface = surface;
444 mFlinger.mutableCurrentState().displays.add(displayToken, state);
445
446 // --------------------------------------------------------------------
447 // Call Expectations
448
449 Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
450 Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this);
451
452 EXPECT_CALL(*surface, query(NATIVE_WINDOW_WIDTH, _))
453 .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::WIDTH), Return(NO_ERROR)));
454 EXPECT_CALL(*surface, query(NATIVE_WINDOW_HEIGHT, _))
455 .WillRepeatedly(DoAll(SetArgPointee<1>(Case::Display::HEIGHT), Return(NO_ERROR)));
456 EXPECT_CALL(*surface, query(NATIVE_WINDOW_FORMAT, _))
457 .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT),
458 Return(NO_ERROR)));
459 EXPECT_CALL(*surface, query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, _))
460 .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(NO_ERROR)));
461
462 EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
463
464 EXPECT_CALL(*mProducer, connect(_, NATIVE_WINDOW_API_EGL, false, _)).Times(1);
465 EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
466
467 Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
468 Case::WideColorSupport::setupComposerCallExpectations(this);
469 Case::HdrSupport::setupComposerCallExpectations(this);
470 Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
471
472 // --------------------------------------------------------------------
473 // Invocation
474
475 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
476
477 // --------------------------------------------------------------------
478 // Postconditions
479
480 // The display device should have been set up in the list of displays.
481 verifyDisplayIsConnected<Case>(displayToken);
482
483 // --------------------------------------------------------------------
484 // Cleanup conditions
485
486 EXPECT_CALL(*mComposer, destroyVirtualDisplay(Case::Display::HWC_DISPLAY_ID))
487 .WillOnce(Return(Error::NONE));
488 EXPECT_CALL(*mConsumer, consumerDisconnect()).WillOnce(Return(NO_ERROR));
489
490 // Cleanup
491 mFlinger.mutableCurrentState().displays.removeItem(displayToken);
492 mFlinger.mutableDrawingState().displays.removeItem(displayToken);
493 }
494
TEST_F(DisplayTransactionCommitTest,processesVirtualDisplayAddedWithNoSurface)495 TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayAddedWithNoSurface) {
496 using Case = HwcVirtualDisplayCase;
497
498 // --------------------------------------------------------------------
499 // Preconditions
500
501 // The HWC supports at least one virtual display
502 injectMockComposer(1);
503
504 setupCommonPreconditions<Case>();
505
506 // A virtual display was added to the current state, but it does not have a
507 // surface.
508 sp<BBinder> displayToken = sp<BBinder>::make();
509
510 DisplayDeviceState state;
511 state.isSecure = static_cast<bool>(Case::Display::SECURE);
512
513 mFlinger.mutableCurrentState().displays.add(displayToken, state);
514
515 // --------------------------------------------------------------------
516 // Call Expectations
517
518 // --------------------------------------------------------------------
519 // Invocation
520
521 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
522
523 // --------------------------------------------------------------------
524 // Postconditions
525
526 // There will not be a display device set up.
527 EXPECT_FALSE(hasDisplayDevice(displayToken));
528
529 // The drawing display state will be set from the current display state.
530 ASSERT_TRUE(hasDrawingDisplayState(displayToken));
531 const auto& draw = getDrawingDisplayState(displayToken);
532 EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
533 }
534
TEST_F(DisplayTransactionCommitTest,processesVirtualDisplayRemoval)535 TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayRemoval) {
536 using Case = HwcVirtualDisplayCase;
537
538 // --------------------------------------------------------------------
539 // Preconditions
540
541 // A virtual display is set up but is removed from the current state.
542 const auto displayId = asHalDisplayId(Case::Display::DISPLAY_ID::get());
543 ASSERT_TRUE(displayId);
544 mFlinger.mutableHwcDisplayData().try_emplace(*displayId);
545 Case::Display::injectHwcDisplay(this);
546 auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
547 existing.inject();
548 mFlinger.mutableCurrentState().displays.removeItem(existing.token());
549
550 // --------------------------------------------------------------------
551 // Invocation
552
553 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
554
555 // --------------------------------------------------------------------
556 // Postconditions
557
558 // The existing token should have been removed
559 verifyDisplayIsNotConnected(existing.token());
560 }
561
TEST_F(DisplayTransactionCommitTest,processesDisplayLayerStackChanges)562 TEST_F(DisplayTransactionCommitTest, processesDisplayLayerStackChanges) {
563 using Case = NonHwcVirtualDisplayCase;
564
565 constexpr ui::LayerStack oldLayerStack = ui::DEFAULT_LAYER_STACK;
566 constexpr ui::LayerStack newLayerStack{123u};
567
568 // --------------------------------------------------------------------
569 // Preconditions
570
571 // A display is set up
572 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
573 display.inject();
574
575 // There is a change to the layerStack state
576 display.mutableDrawingDisplayState().layerStack = oldLayerStack;
577 display.mutableCurrentDisplayState().layerStack = newLayerStack;
578
579 // --------------------------------------------------------------------
580 // Invocation
581
582 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
583
584 // --------------------------------------------------------------------
585 // Postconditions
586
587 EXPECT_EQ(newLayerStack, display.mutableDisplayDevice()->getLayerStack());
588 }
589
TEST_F(DisplayTransactionCommitTest,processesDisplayTransformChanges)590 TEST_F(DisplayTransactionCommitTest, processesDisplayTransformChanges) {
591 using Case = NonHwcVirtualDisplayCase;
592
593 constexpr ui::Rotation oldTransform = ui::ROTATION_0;
594 constexpr ui::Rotation newTransform = ui::ROTATION_180;
595
596 // --------------------------------------------------------------------
597 // Preconditions
598
599 // A display is set up
600 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
601 display.inject();
602
603 // There is a change to the orientation state
604 display.mutableDrawingDisplayState().orientation = oldTransform;
605 display.mutableCurrentDisplayState().orientation = newTransform;
606
607 // --------------------------------------------------------------------
608 // Invocation
609
610 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
611
612 // --------------------------------------------------------------------
613 // Postconditions
614
615 EXPECT_EQ(newTransform, display.mutableDisplayDevice()->getOrientation());
616 }
617
TEST_F(DisplayTransactionCommitTest,processesDisplayLayerStackRectChanges)618 TEST_F(DisplayTransactionCommitTest, processesDisplayLayerStackRectChanges) {
619 using Case = NonHwcVirtualDisplayCase;
620
621 const Rect oldLayerStackRect(0, 0, 0, 0);
622 const Rect newLayerStackRect(0, 0, 123, 456);
623
624 // --------------------------------------------------------------------
625 // Preconditions
626
627 // A display is set up
628 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
629 display.inject();
630
631 // There is a change to the layerStackSpaceRect state
632 display.mutableDrawingDisplayState().layerStackSpaceRect = oldLayerStackRect;
633 display.mutableCurrentDisplayState().layerStackSpaceRect = newLayerStackRect;
634
635 // --------------------------------------------------------------------
636 // Invocation
637
638 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
639
640 // --------------------------------------------------------------------
641 // Postconditions
642
643 EXPECT_EQ(newLayerStackRect, display.mutableDisplayDevice()->getLayerStackSpaceRect());
644 }
645
TEST_F(DisplayTransactionCommitTest,processesDisplayRectChanges)646 TEST_F(DisplayTransactionCommitTest, processesDisplayRectChanges) {
647 using Case = NonHwcVirtualDisplayCase;
648
649 const Rect oldDisplayRect(0, 0);
650 const Rect newDisplayRect(123, 456);
651
652 // --------------------------------------------------------------------
653 // Preconditions
654
655 // A display is set up
656 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
657 display.inject();
658
659 // There is a change to the layerStackSpaceRect state
660 display.mutableDrawingDisplayState().orientedDisplaySpaceRect = oldDisplayRect;
661 display.mutableCurrentDisplayState().orientedDisplaySpaceRect = newDisplayRect;
662
663 // --------------------------------------------------------------------
664 // Invocation
665
666 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
667
668 // --------------------------------------------------------------------
669 // Postconditions
670
671 EXPECT_EQ(newDisplayRect, display.mutableDisplayDevice()->getOrientedDisplaySpaceRect());
672 }
673
TEST_F(DisplayTransactionCommitTest,processesDisplayWidthChanges)674 TEST_F(DisplayTransactionCommitTest, processesDisplayWidthChanges) {
675 using Case = NonHwcVirtualDisplayCase;
676
677 constexpr int oldWidth = 0;
678 constexpr int oldHeight = 10;
679 constexpr int newWidth = 123;
680
681 // --------------------------------------------------------------------
682 // Preconditions
683
684 // A display is set up
685 auto nativeWindow = sp<mock::NativeWindow>::make();
686 auto displaySurface = sp<compositionengine::mock::DisplaySurface>::make();
687 sp<GraphicBuffer> buf =
688
689 sp<GraphicBuffer>::make();
690 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
691 display.setNativeWindow(nativeWindow);
692 display.setDisplaySurface(displaySurface);
693 // Setup injection expectations
694 EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
695 .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
696 EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
697 .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
698 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
699 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
700 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
701 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
702 display.inject();
703
704 // There is a change to the layerStackSpaceRect state
705 display.mutableDrawingDisplayState().width = oldWidth;
706 display.mutableDrawingDisplayState().height = oldHeight;
707 display.mutableCurrentDisplayState().width = newWidth;
708 display.mutableCurrentDisplayState().height = oldHeight;
709
710 // --------------------------------------------------------------------
711 // Call Expectations
712
713 EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(newWidth, oldHeight))).Times(1);
714
715 // --------------------------------------------------------------------
716 // Invocation
717
718 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
719 }
720
TEST_F(DisplayTransactionCommitTest,processesDisplayHeightChanges)721 TEST_F(DisplayTransactionCommitTest, processesDisplayHeightChanges) {
722 using Case = NonHwcVirtualDisplayCase;
723
724 constexpr int oldWidth = 0;
725 constexpr int oldHeight = 10;
726 constexpr int newHeight = 123;
727
728 // --------------------------------------------------------------------
729 // Preconditions
730
731 // A display is set up
732 auto nativeWindow = sp<mock::NativeWindow>::make();
733 auto displaySurface = sp<compositionengine::mock::DisplaySurface>::make();
734 sp<GraphicBuffer> buf = sp<GraphicBuffer>::make();
735 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
736 display.setNativeWindow(nativeWindow);
737 display.setDisplaySurface(displaySurface);
738 // Setup injection expectations
739 EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
740 .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
741 EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
742 .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
743 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1);
744 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1);
745 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1);
746 EXPECT_CALL(*nativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1);
747 display.inject();
748
749 // There is a change to the layerStackSpaceRect state
750 display.mutableDrawingDisplayState().width = oldWidth;
751 display.mutableDrawingDisplayState().height = oldHeight;
752 display.mutableCurrentDisplayState().width = oldWidth;
753 display.mutableCurrentDisplayState().height = newHeight;
754
755 // --------------------------------------------------------------------
756 // Call Expectations
757
758 EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(oldWidth, newHeight))).Times(1);
759
760 // --------------------------------------------------------------------
761 // Invocation
762
763 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
764 }
765
TEST_F(DisplayTransactionCommitTest,processesDisplaySizeDisplayRectAndLayerStackRectChanges)766 TEST_F(DisplayTransactionCommitTest, processesDisplaySizeDisplayRectAndLayerStackRectChanges) {
767 using Case = NonHwcVirtualDisplayCase;
768
769 constexpr uint32_t kOldWidth = 567;
770 constexpr uint32_t kOldHeight = 456;
771 const auto kOldSize = Rect(kOldWidth, kOldHeight);
772
773 constexpr uint32_t kNewWidth = 234;
774 constexpr uint32_t kNewHeight = 123;
775 const auto kNewSize = Rect(kNewWidth, kNewHeight);
776
777 // --------------------------------------------------------------------
778 // Preconditions
779
780 // A display is set up
781 auto nativeWindow = sp<mock::NativeWindow>::make();
782 auto displaySurface = sp<compositionengine::mock::DisplaySurface>::make();
783 sp<GraphicBuffer> buf = sp<GraphicBuffer>::make();
784 auto display = Case::Display::makeFakeExistingDisplayInjector(this);
785 display.setNativeWindow(nativeWindow);
786 display.setDisplaySurface(displaySurface);
787 // Setup injection expectations
788 EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
789 .WillOnce(DoAll(SetArgPointee<1>(kOldWidth), Return(0)));
790 EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
791 .WillOnce(DoAll(SetArgPointee<1>(kOldHeight), Return(0)));
792 display.inject();
793
794 // There is a change to the layerStackSpaceRect state
795 display.mutableDrawingDisplayState().width = kOldWidth;
796 display.mutableDrawingDisplayState().height = kOldHeight;
797 display.mutableDrawingDisplayState().layerStackSpaceRect = kOldSize;
798 display.mutableDrawingDisplayState().orientedDisplaySpaceRect = kOldSize;
799
800 display.mutableCurrentDisplayState().width = kNewWidth;
801 display.mutableCurrentDisplayState().height = kNewHeight;
802 display.mutableCurrentDisplayState().layerStackSpaceRect = kNewSize;
803 display.mutableCurrentDisplayState().orientedDisplaySpaceRect = kNewSize;
804
805 // --------------------------------------------------------------------
806 // Call Expectations
807
808 EXPECT_CALL(*displaySurface, resizeBuffers(kNewSize.getSize())).Times(1);
809
810 // --------------------------------------------------------------------
811 // Invocation
812
813 mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
814
815 EXPECT_EQ(display.mutableDisplayDevice()->getBounds(), kNewSize);
816 EXPECT_EQ(display.mutableDisplayDevice()->getWidth(), kNewWidth);
817 EXPECT_EQ(display.mutableDisplayDevice()->getHeight(), kNewHeight);
818 EXPECT_EQ(display.mutableDisplayDevice()->getOrientedDisplaySpaceRect(), kNewSize);
819 EXPECT_EQ(display.mutableDisplayDevice()->getLayerStackSpaceRect(), kNewSize);
820 }
821
822 } // namespace
823 } // namespace android
824