blob: 01cdb2896fde9461129d70395ef04b12767b5304 [file] [log] [blame]
Marin Shalamanov07b1ff32020-10-07 16:57:22 +02001/*
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#pragma once
18
19// TODO(b/129481165): remove the #pragma below and fix conversion issues
20#pragma clang diagnostic push
21#pragma clang diagnostic ignored "-Wconversion"
22
23#include <type_traits>
24#include "DisplayIdentificationTest.h"
25
26#include <binder/IPCThreadState.h>
27#include <compositionengine/Display.h>
28#include <compositionengine/DisplayColorProfile.h>
29#include <compositionengine/impl/Display.h>
30#include <compositionengine/impl/OutputCompositionState.h>
31#include <compositionengine/mock/Display.h>
32#include <compositionengine/mock/DisplayColorProfile.h>
33#include <compositionengine/mock/DisplaySurface.h>
34#include <compositionengine/mock/RenderSurface.h>
35#include <gmock/gmock.h>
36#include <gtest/gtest.h>
37#include <gui/mock/GraphicBufferConsumer.h>
38#include <gui/mock/GraphicBufferProducer.h>
39#include <log/log.h>
40#include <private/android_filesystem_config.h>
41#include <renderengine/mock/RenderEngine.h>
42#include <ui/DebugUtils.h>
43
44#include "TestableScheduler.h"
45#include "TestableSurfaceFlinger.h"
46#include "mock/DisplayHardware/MockComposer.h"
47#include "mock/DisplayHardware/MockPowerAdvisor.h"
48#include "mock/MockEventThread.h"
49#include "mock/MockMessageQueue.h"
50#include "mock/MockNativeWindowSurface.h"
51#include "mock/MockSchedulerCallback.h"
52#include "mock/MockSurfaceInterceptor.h"
53#include "mock/MockVsyncController.h"
54#include "mock/system/window/MockNativeWindow.h"
55
56namespace android {
57
58// TODO: Do not polute the android namespace
59namespace hal = android::hardware::graphics::composer::hal;
60
61using testing::_;
62using testing::AnyNumber;
63using testing::DoAll;
64using testing::Mock;
65using testing::ResultOf;
66using testing::Return;
67using testing::SetArgPointee;
68
69using hal::ColorMode;
70using hal::Connection;
71using hal::DisplayCapability;
72using hal::DisplayType;
73using hal::Error;
74using hal::Hdr;
75using hal::HWDisplayId;
76using hal::IComposer;
77using hal::IComposerClient;
78using hal::PerFrameMetadataKey;
79using hal::PowerMode;
80
81class DisplayTransactionTest : public testing::Test {
82public:
83 ~DisplayTransactionTest() override;
84
85 // --------------------------------------------------------------------
86 // Mock/Fake injection
87
88 void injectMockScheduler();
89 void injectMockComposer(int virtualDisplayCount);
90 void injectFakeBufferQueueFactory();
91 void injectFakeNativeWindowSurfaceFactory();
92 sp<DisplayDevice> injectDefaultInternalDisplay(
93 std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)>);
94
95 // --------------------------------------------------------------------
96 // Postcondition helpers
97
98 bool hasPhysicalHwcDisplay(hal::HWDisplayId hwcDisplayId);
99 bool hasTransactionFlagSet(int flag);
100 bool hasDisplayDevice(sp<IBinder> displayToken);
101 sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken);
102 bool hasCurrentDisplayState(sp<IBinder> displayToken);
103 const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken);
104 bool hasDrawingDisplayState(sp<IBinder> displayToken);
105 const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken);
106
107 // --------------------------------------------------------------------
108 // Test instances
109
110 TestableSurfaceFlinger mFlinger;
111 sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
112 sp<GraphicBuffer> mBuffer = new GraphicBuffer();
113 Hwc2::mock::PowerAdvisor mPowerAdvisor;
114
115 // These mocks are created by the test, but are destroyed by SurfaceFlinger
116 // by virtue of being stored into a std::unique_ptr. However we still need
117 // to keep a reference to them for use in setting up call expectations.
118 renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
119 Hwc2::mock::Composer* mComposer = nullptr;
120 mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
121 sp<mock::SurfaceInterceptor> mSurfaceInterceptor = new mock::SurfaceInterceptor;
122
123 mock::VsyncController* mVsyncController = new mock::VsyncController;
124 mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
125 mock::SchedulerCallback mSchedulerCallback;
126 mock::EventThread* mEventThread = new mock::EventThread;
127 mock::EventThread* mSFEventThread = new mock::EventThread;
128
129 // These mocks are created only when expected to be created via a factory.
130 sp<mock::GraphicBufferConsumer> mConsumer;
131 sp<mock::GraphicBufferProducer> mProducer;
132 surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
133
134protected:
135 DisplayTransactionTest();
136};
137
138constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
139constexpr int32_t DEFAULT_DPI = 320;
140constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
141
142constexpr int POWER_MODE_LEET = 1337; // An out of range power mode value
143
144/* ------------------------------------------------------------------------
145 * Boolean avoidance
146 *
147 * To make calls and template instantiations more readable, we define some
148 * local enums along with an implicit bool conversion.
149 */
150
151#define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true };
152
153BOOL_SUBSTITUTE(Async);
154BOOL_SUBSTITUTE(Critical);
155BOOL_SUBSTITUTE(Primary);
156BOOL_SUBSTITUTE(Secure);
157BOOL_SUBSTITUTE(Virtual);
158
159template <typename PhysicalDisplay>
160struct PhysicalDisplayIdType {};
161
162template <uint64_t displayId>
163using HalVirtualDisplayIdType = std::integral_constant<uint64_t, displayId>;
164
165struct GpuVirtualDisplayIdType {};
166
167template <typename>
168struct IsPhysicalDisplayId : std::bool_constant<false> {};
169
170template <typename PhysicalDisplay>
171struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {};
172
173template <typename>
174struct DisplayIdGetter;
175
176template <typename PhysicalDisplay>
177struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
178 static PhysicalDisplayId get() {
179 if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
180 return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
181 ? LEGACY_DISPLAY_TYPE_PRIMARY
182 : LEGACY_DISPLAY_TYPE_EXTERNAL);
183 }
184
185 const auto info =
186 parseDisplayIdentificationData(PhysicalDisplay::PORT,
187 PhysicalDisplay::GET_IDENTIFICATION_DATA());
188 return info ? info->id : PhysicalDisplayId::fromPort(PhysicalDisplay::PORT);
189 }
190};
191
192template <uint64_t displayId>
193struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
194 static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
195};
196
197template <>
198struct DisplayIdGetter<GpuVirtualDisplayIdType> {
199 static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); }
200};
201
202template <typename>
203struct DisplayConnectionTypeGetter {
204 static constexpr std::optional<DisplayConnectionType> value;
205};
206
207template <typename PhysicalDisplay>
208struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
209 static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
210};
211
212template <typename>
213struct HwcDisplayIdGetter {
214 static constexpr std::optional<HWDisplayId> value;
215};
216
217constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
218
219template <uint64_t displayId>
220struct HwcDisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
221 static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
222};
223
224template <typename PhysicalDisplay>
225struct HwcDisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
226 static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
227};
228
229// DisplayIdType can be:
230// 1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC.
231// 2) HalVirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC.
232// 3) GpuVirtualDisplayIdType for virtual display without HWC backing.
233template <typename DisplayIdType, int width, int height, Critical critical, Async async,
234 Secure secure, Primary primary, int grallocUsage>
235struct DisplayVariant {
236 using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
237 using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
238 using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
239
240 // The display width and height
241 static constexpr int WIDTH = width;
242 static constexpr int HEIGHT = height;
243
244 static constexpr int GRALLOC_USAGE = grallocUsage;
245
246 // Whether the display is virtual or physical
247 static constexpr Virtual VIRTUAL =
248 IsPhysicalDisplayId<DisplayIdType>{} ? Virtual::FALSE : Virtual::TRUE;
249
250 // When creating native window surfaces for the framebuffer, whether those should be critical
251 static constexpr Critical CRITICAL = critical;
252
253 // When creating native window surfaces for the framebuffer, whether those should be async
254 static constexpr Async ASYNC = async;
255
256 // Whether the display should be treated as secure
257 static constexpr Secure SECURE = secure;
258
259 // Whether the display is primary
260 static constexpr Primary PRIMARY = primary;
261
262 static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
263 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
264 if (auto displayId = PhysicalDisplayId::tryCast(DISPLAY_ID::get())) {
265 ceDisplayArgs.setPhysical({*displayId, DisplayConnectionType::Internal});
266 } else {
267 // We turn off the use of HwcVirtualDisplays, to prevent Composition Engine
268 // from calling into HWComposer. This way all virtual displays will get
269 // a GpuVirtualDisplayId, even if we are in the HwcVirtualDisplayVariant.
270 // In this case we later override it by calling display.setDisplayIdForTesting().
271 ceDisplayArgs.setUseHwcVirtualDisplays(false);
272
273 GpuVirtualDisplayId desiredDisplayId = GpuVirtualDisplayId::tryCast(DISPLAY_ID::get())
274 .value_or(GpuVirtualDisplayId(0));
275
276 ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
277 .WillByDefault(Return(desiredDisplayId));
278
279 auto& generator = test->mFlinger.gpuVirtualDisplayIdGenerator();
280 ceDisplayArgs.setGpuVirtualDisplayIdGenerator(generator);
281 }
282 ceDisplayArgs.setPixels({WIDTH, HEIGHT}).setPowerAdvisor(&test->mPowerAdvisor);
283
284 auto compositionDisplay =
285 compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
286 ceDisplayArgs.build());
287
288 if (HalVirtualDisplayId::tryCast(DISPLAY_ID::get())) {
289 // CompositionEngine has assigned a placeholder GpuVirtualDisplayId and we need to
290 // override it with the correct HalVirtualDisplayId.
291 compositionDisplay->setDisplayIdForTesting(DISPLAY_ID::get());
292 }
293
294 auto injector =
295 TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger,
296 compositionDisplay,
297 CONNECTION_TYPE::value,
298 HWC_DISPLAY_ID_OPT::value,
299 static_cast<bool>(PRIMARY));
300
301 injector.setSecure(static_cast<bool>(SECURE));
302 injector.setNativeWindow(test->mNativeWindow);
303
304 // Creating a DisplayDevice requires getting default dimensions from the
305 // native window along with some other initial setup.
306 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
307 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
308 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
309 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
310 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
311 .WillRepeatedly(Return(0));
312 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
313 .WillRepeatedly(Return(0));
314 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
315 .WillRepeatedly(Return(0));
316 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
317 .WillRepeatedly(Return(0));
318
319 return injector;
320 }
321
322 // Called by tests to set up any native window creation call expectations.
323 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
324 EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
325 .WillOnce(Return(test->mNativeWindow));
326
327 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
328 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
329 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
330 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
331 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
332 .WillRepeatedly(Return(0));
333 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
334 .WillRepeatedly(Return(0));
335 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
336 .WillRepeatedly(Return(0));
337 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
338 .WillRepeatedly(Return(0));
339 }
340
341 static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
342 EXPECT_CALL(*test->mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
343 EXPECT_CALL(*test->mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
344 EXPECT_CALL(*test->mConsumer, setConsumerUsageBits(GRALLOC_USAGE))
345 .WillRepeatedly(Return(NO_ERROR));
346 EXPECT_CALL(*test->mConsumer, setDefaultBufferSize(WIDTH, HEIGHT))
347 .WillRepeatedly(Return(NO_ERROR));
348 EXPECT_CALL(*test->mConsumer, setMaxAcquiredBufferCount(_))
349 .WillRepeatedly(Return(NO_ERROR));
350 }
351
352 static void setupFramebufferProducerBufferQueueCallExpectations(DisplayTransactionTest* test) {
353 EXPECT_CALL(*test->mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
354 }
355};
356
357template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant,
358 typename PhysicalDisplay = void>
359struct HwcDisplayVariant {
360 // The display id supplied by the HWC
361 static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId;
362
363 // The HWC display type
364 static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
365
366 // The HWC active configuration id
367 static constexpr int HWC_ACTIVE_CONFIG_ID = 2001;
368 static constexpr PowerMode INIT_POWER_MODE = hal::PowerMode::ON;
369
370 static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
371 test->mFlinger.mutablePendingHotplugEvents().emplace_back(
372 TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection});
373 }
374
375 // Called by tests to inject a HWC display setup
376 static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
377 const auto displayId = DisplayVariant::DISPLAY_ID::get();
378 ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId));
379 TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
380 static_cast<bool>(DisplayVariant::PRIMARY))
381 .setHwcDisplayId(HWC_DISPLAY_ID)
382 .setWidth(DisplayVariant::WIDTH)
383 .setHeight(DisplayVariant::HEIGHT)
384 .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
385 .setPowerMode(INIT_POWER_MODE)
386 .inject(&test->mFlinger, test->mComposer);
387 }
388
389 // Called by tests to inject a HWC display setup
390 static void injectHwcDisplay(DisplayTransactionTest* test) {
391 EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
392 .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
393 Return(Error::NONE)));
394 EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE))
395 .WillOnce(Return(Error::NONE));
396 injectHwcDisplayWithNoDefaultCapabilities(test);
397 }
398
399 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
400 DisplayTransactionTest* test) {
401 const ::testing::TestInfo* const test_info =
402 ::testing::UnitTest::GetInstance()->current_test_info();
403
404 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
405 .setPhysical({DisplayVariant::DISPLAY_ID::get(),
406 PhysicalDisplay::CONNECTION_TYPE})
407 .setPixels({DisplayVariant::WIDTH, DisplayVariant::HEIGHT})
408 .setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
409 .setPowerAdvisor(&test->mPowerAdvisor)
410 .setName(std::string("Injected display for ") +
411 test_info->test_case_name() + "." + test_info->name())
412 .build();
413
414 return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
415 ceDisplayArgs);
416 }
417
418 static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
419 constexpr auto CONNECTION_TYPE =
420 PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal
421 ? IComposerClient::DisplayConnectionType::INTERNAL
422 : IComposerClient::DisplayConnectionType::EXTERNAL;
423
424 EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
425 .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE), Return(hal::V2_4::Error::NONE)));
426
427 EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
428 .WillOnce(Return(hal::Error::NONE));
429 EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
430 .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}),
431 Return(Error::NONE)));
432 EXPECT_CALL(*test->mComposer,
433 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
434 IComposerClient::Attribute::WIDTH, _))
435 .WillOnce(DoAll(SetArgPointee<3>(DisplayVariant::WIDTH), Return(Error::NONE)));
436 EXPECT_CALL(*test->mComposer,
437 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
438 IComposerClient::Attribute::HEIGHT, _))
439 .WillOnce(DoAll(SetArgPointee<3>(DisplayVariant::HEIGHT), Return(Error::NONE)));
440 EXPECT_CALL(*test->mComposer,
441 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
442 IComposerClient::Attribute::VSYNC_PERIOD, _))
443 .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
444 EXPECT_CALL(*test->mComposer,
445 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
446 IComposerClient::Attribute::DPI_X, _))
447 .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
448 EXPECT_CALL(*test->mComposer,
449 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
450 IComposerClient::Attribute::DPI_Y, _))
451 .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
452 EXPECT_CALL(*test->mComposer,
453 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
454 IComposerClient::Attribute::CONFIG_GROUP, _))
455 .WillOnce(DoAll(SetArgPointee<3>(-1), Return(Error::NONE)));
456
457 if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
458 EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
459 .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT),
460 SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()),
461 Return(Error::NONE)));
462 } else {
463 EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
464 .WillOnce(Return(Error::UNSUPPORTED));
465 }
466 }
467
468 // Called by tests to set up HWC call expectations
469 static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
470 EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _))
471 .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE)));
472 }
473};
474
475// Physical displays are expected to be synchronous, secure, and have a HWC display for output.
476constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
477 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
478
479template <typename PhysicalDisplay, int width, int height, Critical critical>
480struct PhysicalDisplayVariant
481 : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
482 Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
483 GRALLOC_USAGE_PHYSICAL_DISPLAY>,
484 HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
485 DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height,
486 critical, Async::FALSE, Secure::TRUE,
487 PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
488 PhysicalDisplay> {};
489
490template <bool hasIdentificationData>
491struct PrimaryDisplay {
492 static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
493 static constexpr Primary PRIMARY = Primary::TRUE;
494 static constexpr uint8_t PORT = 255;
495 static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
496 static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
497 static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
498};
499
500template <bool hasIdentificationData>
501struct ExternalDisplay {
502 static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
503 static constexpr Primary PRIMARY = Primary::FALSE;
504 static constexpr uint8_t PORT = 254;
505 static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
506 static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
507 static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
508};
509
510struct TertiaryDisplay {
511 static constexpr Primary PRIMARY = Primary::FALSE;
512 static constexpr uint8_t PORT = 253;
513 static constexpr HWDisplayId HWC_DISPLAY_ID = 1003;
514 static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
515};
516
517// A primary display is a physical display that is critical
518using PrimaryDisplayVariant =
519 PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
520
521// An external display is physical display that is not critical.
522using ExternalDisplayVariant =
523 PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
524
525using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
526
527// A virtual display not supported by the HWC.
528constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
529
530template <int width, int height, Secure secure>
531struct NonHwcVirtualDisplayVariant
532 : DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE, secure,
533 Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY> {
534 using Base =
535 DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE,
536 secure, Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY>;
537
538 static void injectHwcDisplay(DisplayTransactionTest*) {}
539
540 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
541 DisplayTransactionTest* test) {
542 const ::testing::TestInfo* const test_info =
543 ::testing::UnitTest::GetInstance()->current_test_info();
544
545 ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
546 .WillByDefault(Return(Base::DISPLAY_ID::get()));
547
548 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
549 .setPixels({Base::WIDTH, Base::HEIGHT})
550 .setIsSecure(static_cast<bool>(Base::SECURE))
551 .setPowerAdvisor(&test->mPowerAdvisor)
552 .setName(std::string("Injected display for ") +
553 test_info->test_case_name() + "." + test_info->name())
554 .setGpuVirtualDisplayIdGenerator(
555 test->mFlinger.gpuVirtualDisplayIdGenerator())
556 .build();
557
558 return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
559 ceDisplayArgs);
560 }
561
562 static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
563 EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0);
564 }
565
566 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
567 Base::setupNativeWindowSurfaceCreationCallExpectations(test);
568 EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
569 }
570};
571
572// A virtual display supported by the HWC.
573constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER;
574
575template <int width, int height, Secure secure>
576struct HwcVirtualDisplayVariant
577 : DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE, Async::TRUE,
578 secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
579 HwcDisplayVariant<HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
580 DisplayVariant<HalVirtualDisplayIdType<42>, width, height,
581 Critical::FALSE, Async::TRUE, secure, Primary::FALSE,
582 GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
583 using Base = DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
584 Async::TRUE, secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>;
585 using Self = HwcVirtualDisplayVariant<width, height, secure>;
586
587 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
588 DisplayTransactionTest* test) {
589 const ::testing::TestInfo* const test_info =
590 ::testing::UnitTest::GetInstance()->current_test_info();
591
592 // In order to prevent compostition engine calling into HWComposer, we
593 // 1. turn off the use of HWC virtual displays,
594 // 2. provide a GpuVirtualDisplayIdGenerator which always returns some fake ID
595 // 3. override the ID by calling setDisplayIdForTesting()
596
597 ON_CALL(test->mFlinger.gpuVirtualDisplayIdGenerator(), nextId())
598 .WillByDefault(Return(GpuVirtualDisplayId(0)));
599
600 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
601 .setUseHwcVirtualDisplays(false)
602 .setPixels({Base::WIDTH, Base::HEIGHT})
603 .setIsSecure(static_cast<bool>(Base::SECURE))
604 .setPowerAdvisor(&test->mPowerAdvisor)
605 .setName(std::string("Injected display for ") +
606 test_info->test_case_name() + "." + test_info->name())
607 .setGpuVirtualDisplayIdGenerator(
608 test->mFlinger.gpuVirtualDisplayIdGenerator())
609 .build();
610
611 auto compositionDisplay =
612 compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
613 ceDisplayArgs);
614 compositionDisplay->setDisplayIdForTesting(Base::DISPLAY_ID::get());
615
616 // Insert display data so that the HWC thinks it created the virtual display.
617 if (const auto displayId = Base::DISPLAY_ID::get();
618 HalVirtualDisplayId::tryCast(displayId)) {
619 test->mFlinger.mutableHwcDisplayData().try_emplace(displayId);
620 }
621
622 return compositionDisplay;
623 }
624
625 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
626 Base::setupNativeWindowSurfaceCreationCallExpectations(test);
627 EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
628 }
629
630 static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) {
631 EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _))
632 .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE)));
633 EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
634 }
635};
636
637// For this variant, the display is not a HWC display, so no HDR support should
638// be configured.
639struct NonHwcDisplayHdrSupportVariant {
640 static constexpr bool HDR10_PLUS_SUPPORTED = false;
641 static constexpr bool HDR10_SUPPORTED = false;
642 static constexpr bool HDR_HLG_SUPPORTED = false;
643 static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
644 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
645 EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)).Times(0);
646 }
647};
648
649// For this variant, the composer should respond with am empty list of HDR
650// modes, so no HDR support should be configured.
651template <typename Display>
652struct HdrNotSupportedVariant {
653 static constexpr bool HDR10_PLUS_SUPPORTED = false;
654 static constexpr bool HDR10_SUPPORTED = false;
655 static constexpr bool HDR_HLG_SUPPORTED = false;
656 static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
657 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
658 EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
659 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
660 }
661};
662
663struct NonHwcPerFrameMetadataSupportVariant {
664 static constexpr int PER_FRAME_METADATA_KEYS = 0;
665 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
666 EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0);
667 }
668};
669
670template <typename Display>
671struct NoPerFrameMetadataSupportVariant {
672 static constexpr int PER_FRAME_METADATA_KEYS = 0;
673 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
674 EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
675 .WillOnce(Return(std::vector<PerFrameMetadataKey>()));
676 }
677};
678
679// For this variant, SurfaceFlinger should configure itself with wide display
680// support, but the display should respond with an empty list of supported color
681// modes. Wide-color support for the display should not be configured.
682template <typename Display>
683struct WideColorNotSupportedVariant {
684 static constexpr bool WIDE_COLOR_SUPPORTED = false;
685
686 static void injectConfigChange(DisplayTransactionTest* test) {
687 test->mFlinger.mutableUseColorManagement() = true;
688 test->mFlinger.mutableHasWideColorDisplay() = true;
689 }
690
691 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
692 EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _))
693 .WillOnce(DoAll(SetArgPointee<1>(std::vector<ColorMode>()), Return(Error::NONE)));
694 EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
695 }
696};
697
698// For this variant, SurfaceFlinger should not configure itself with wide
699// display support, so the display should not be configured for wide-color
700// support.
701struct WideColorSupportNotConfiguredVariant {
702 static constexpr bool WIDE_COLOR_SUPPORTED = false;
703
704 static void injectConfigChange(DisplayTransactionTest* test) {
705 test->mFlinger.mutableHasWideColorDisplay() = false;
706 test->mFlinger.mutableUseColorManagement() = false;
707 test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
708 }
709
710 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
711 EXPECT_CALL(*test->mComposer, getColorModes(_, _)).Times(0);
712 EXPECT_CALL(*test->mComposer, getRenderIntents(_, _, _)).Times(0);
713 EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
714 }
715};
716
717/* ------------------------------------------------------------------------
718 * Typical display configurations to test
719 */
720
721template <typename DisplayPolicy, typename WideColorSupportPolicy, typename HdrSupportPolicy,
722 typename PerFrameMetadataSupportPolicy>
723struct Case {
724 using Display = DisplayPolicy;
725 using WideColorSupport = WideColorSupportPolicy;
726 using HdrSupport = HdrSupportPolicy;
727 using PerFrameMetadataSupport = PerFrameMetadataSupportPolicy;
728};
729
730using SimplePrimaryDisplayCase =
731 Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
732 HdrNotSupportedVariant<PrimaryDisplayVariant>,
733 NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
734using SimpleExternalDisplayCase =
735 Case<ExternalDisplayVariant, WideColorNotSupportedVariant<ExternalDisplayVariant>,
736 HdrNotSupportedVariant<ExternalDisplayVariant>,
737 NoPerFrameMetadataSupportVariant<ExternalDisplayVariant>>;
738using SimpleTertiaryDisplayCase =
739 Case<TertiaryDisplayVariant, WideColorNotSupportedVariant<TertiaryDisplayVariant>,
740 HdrNotSupportedVariant<TertiaryDisplayVariant>,
741 NoPerFrameMetadataSupportVariant<TertiaryDisplayVariant>>;
742
743using NonHwcVirtualDisplayCase =
744 Case<NonHwcVirtualDisplayVariant<1024, 768, Secure::FALSE>,
745 WideColorSupportNotConfiguredVariant, NonHwcDisplayHdrSupportVariant,
746 NonHwcPerFrameMetadataSupportVariant>;
747using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
748using HwcVirtualDisplayCase =
749 Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
750 HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
751 NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
752
753} // namespace android
754
755// TODO(b/129481165): remove the #pragma below and fix conversion issues
756#pragma clang diagnostic pop // ignored "-Wconversion"