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