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