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