blob: 9cceb5e4df25f22de111e95f37e9a0b1e846f008 [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"
Marin Shalamanovbed7fd32020-12-21 20:02:20 +010022#pragma clang diagnostic ignored "-Wextra"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020023
24#include <type_traits>
Alec Mouriff793872022-01-13 17:45:06 -080025#include "DisplayIdentificationTestHelpers.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020026
27#include <binder/IPCThreadState.h>
28#include <compositionengine/Display.h>
29#include <compositionengine/DisplayColorProfile.h>
30#include <compositionengine/impl/Display.h>
31#include <compositionengine/impl/OutputCompositionState.h>
32#include <compositionengine/mock/Display.h>
33#include <compositionengine/mock/DisplayColorProfile.h>
34#include <compositionengine/mock/DisplaySurface.h>
35#include <compositionengine/mock/RenderSurface.h>
36#include <gmock/gmock.h>
37#include <gtest/gtest.h>
38#include <gui/mock/GraphicBufferConsumer.h>
39#include <gui/mock/GraphicBufferProducer.h>
40#include <log/log.h>
41#include <private/android_filesystem_config.h>
42#include <renderengine/mock/RenderEngine.h>
43#include <ui/DebugUtils.h>
44
45#include "TestableScheduler.h"
46#include "TestableSurfaceFlinger.h"
47#include "mock/DisplayHardware/MockComposer.h"
Dominik Laskowskib0054a22022-03-03 09:03:06 -080048#include "mock/DisplayHardware/MockDisplayMode.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020049#include "mock/DisplayHardware/MockPowerAdvisor.h"
50#include "mock/MockEventThread.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020051#include "mock/MockNativeWindowSurface.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020052#include "mock/MockVsyncController.h"
53#include "mock/system/window/MockNativeWindow.h"
54
55namespace android {
56
57// TODO: Do not polute the android namespace
58namespace hal = android::hardware::graphics::composer::hal;
59
60using testing::_;
61using testing::AnyNumber;
62using testing::DoAll;
63using testing::Mock;
64using testing::ResultOf;
65using testing::Return;
66using testing::SetArgPointee;
67
Leon Scroggins III5967aec2021-12-29 11:14:22 -050068using aidl::android::hardware::graphics::composer3::DisplayCapability;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020069using hal::ColorMode;
70using hal::Connection;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020071using hal::DisplayType;
72using hal::Error;
73using hal::Hdr;
74using hal::HWDisplayId;
75using hal::IComposer;
76using hal::IComposerClient;
77using hal::PerFrameMetadataKey;
78using hal::PowerMode;
79
80class DisplayTransactionTest : public testing::Test {
81public:
82 ~DisplayTransactionTest() override;
83
84 // --------------------------------------------------------------------
85 // Mock/Fake injection
86
87 void injectMockScheduler();
88 void injectMockComposer(int virtualDisplayCount);
89 void injectFakeBufferQueueFactory();
90 void injectFakeNativeWindowSurfaceFactory();
91 sp<DisplayDevice> injectDefaultInternalDisplay(
92 std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)>);
93
94 // --------------------------------------------------------------------
95 // Postcondition helpers
96
Dominik Laskowskieb627312022-04-07 09:13:16 -070097 bool hasPhysicalHwcDisplay(hal::HWDisplayId) const;
98 bool hasTransactionFlagSet(int32_t flag) const;
99
100 bool hasDisplayDevice(const sp<IBinder>& displayToken) const;
101 const DisplayDevice& getDisplayDevice(const sp<IBinder>& displayToken) const;
102
103 bool hasCurrentDisplayState(const sp<IBinder>& displayToken) const;
104 const DisplayDeviceState& getCurrentDisplayState(const sp<IBinder>& displayToken) const;
105
106 bool hasDrawingDisplayState(const sp<IBinder>& displayToken) const;
107 const DisplayDeviceState& getDrawingDisplayState(const sp<IBinder>& displayToken) const;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200108
109 // --------------------------------------------------------------------
110 // Test instances
111
112 TestableSurfaceFlinger mFlinger;
Ady Abrahamd11bade2022-08-01 16:18:03 -0700113 sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
114 sp<GraphicBuffer> mBuffer = sp<GraphicBuffer>::make();
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200115 Hwc2::mock::PowerAdvisor mPowerAdvisor;
116
117 // These mocks are created by the test, but are destroyed by SurfaceFlinger
118 // by virtue of being stored into a std::unique_ptr. However we still need
119 // to keep a reference to them for use in setting up call expectations.
120 renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
121 Hwc2::mock::Composer* mComposer = nullptr;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200122
123 mock::VsyncController* mVsyncController = new mock::VsyncController;
124 mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200125 mock::EventThread* mEventThread = new mock::EventThread;
126 mock::EventThread* mSFEventThread = new mock::EventThread;
127
128 // These mocks are created only when expected to be created via a factory.
129 sp<mock::GraphicBufferConsumer> mConsumer;
130 sp<mock::GraphicBufferProducer> mProducer;
131 surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
132
133protected:
134 DisplayTransactionTest();
135};
136
Marin Shalamanova903d032020-12-29 20:35:13 +0100137constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'667;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200138constexpr int32_t DEFAULT_DPI = 320;
139constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
140
141constexpr int POWER_MODE_LEET = 1337; // An out of range power mode value
142
143/* ------------------------------------------------------------------------
144 * Boolean avoidance
145 *
146 * To make calls and template instantiations more readable, we define some
147 * local enums along with an implicit bool conversion.
148 */
149
150#define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true };
151
152BOOL_SUBSTITUTE(Async);
153BOOL_SUBSTITUTE(Critical);
154BOOL_SUBSTITUTE(Primary);
155BOOL_SUBSTITUTE(Secure);
156BOOL_SUBSTITUTE(Virtual);
157
158template <typename PhysicalDisplay>
159struct PhysicalDisplayIdType {};
160
161template <uint64_t displayId>
162using HalVirtualDisplayIdType = std::integral_constant<uint64_t, displayId>;
163
164struct GpuVirtualDisplayIdType {};
165
166template <typename>
167struct IsPhysicalDisplayId : std::bool_constant<false> {};
168
169template <typename PhysicalDisplay>
170struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {};
171
172template <typename>
173struct DisplayIdGetter;
174
175template <typename PhysicalDisplay>
176struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
177 static PhysicalDisplayId get() {
178 if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
179 return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
180 ? LEGACY_DISPLAY_TYPE_PRIMARY
181 : LEGACY_DISPLAY_TYPE_EXTERNAL);
182 }
183
184 const auto info =
185 parseDisplayIdentificationData(PhysicalDisplay::PORT,
186 PhysicalDisplay::GET_IDENTIFICATION_DATA());
187 return info ? info->id : PhysicalDisplayId::fromPort(PhysicalDisplay::PORT);
188 }
189};
190
191template <uint64_t displayId>
192struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
193 static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
194};
195
196template <>
197struct DisplayIdGetter<GpuVirtualDisplayIdType> {
198 static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); }
199};
200
201template <typename>
202struct DisplayConnectionTypeGetter {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100203 static constexpr std::optional<ui::DisplayConnectionType> value;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200204};
205
206template <typename PhysicalDisplay>
207struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100208 static constexpr std::optional<ui::DisplayConnectionType> value =
209 PhysicalDisplay::CONNECTION_TYPE;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200210};
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,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700234 Secure secure, Primary primary, int grallocUsage, int displayFlags>
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200235struct DisplayVariant {
236 using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
237 using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
238 using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
239
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200240 static constexpr int WIDTH = width;
241 static constexpr int HEIGHT = height;
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800242 static constexpr ui::Size RESOLUTION{WIDTH, HEIGHT};
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200243
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
Vishnu Naira119aaa2021-09-24 07:19:35 -0700262 static constexpr int DISPLAY_FLAGS = displayFlags;
263
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200264 static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
265 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
Dominik Laskowski13948602021-03-08 20:48:28 -0800266 ceDisplayArgs.setId(DISPLAY_ID::get())
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800267 .setPixels(RESOLUTION)
Dominik Laskowski13948602021-03-08 20:48:28 -0800268 .setPowerAdvisor(&test->mPowerAdvisor);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200269
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200270 auto compositionDisplay =
271 compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
272 ceDisplayArgs.build());
273
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200274 auto injector =
275 TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger,
276 compositionDisplay,
Dominik Laskowski29fa1462021-04-27 15:51:50 -0700277 CONNECTION_TYPE::value,
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200278 HWC_DISPLAY_ID_OPT::value,
279 static_cast<bool>(PRIMARY));
280
281 injector.setSecure(static_cast<bool>(SECURE));
282 injector.setNativeWindow(test->mNativeWindow);
283
284 // Creating a DisplayDevice requires getting default dimensions from the
285 // native window along with some other initial setup.
286 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
287 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
288 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
289 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
290 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
291 .WillRepeatedly(Return(0));
292 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
293 .WillRepeatedly(Return(0));
294 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
295 .WillRepeatedly(Return(0));
296 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
297 .WillRepeatedly(Return(0));
298
299 return injector;
300 }
301
302 // Called by tests to set up any native window creation call expectations.
303 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
304 EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
305 .WillOnce(Return(test->mNativeWindow));
306
307 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
308 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
309 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
310 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
311 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
312 .WillRepeatedly(Return(0));
313 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
314 .WillRepeatedly(Return(0));
315 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
316 .WillRepeatedly(Return(0));
317 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
318 .WillRepeatedly(Return(0));
319 }
320
321 static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
322 EXPECT_CALL(*test->mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
323 EXPECT_CALL(*test->mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
324 EXPECT_CALL(*test->mConsumer, setConsumerUsageBits(GRALLOC_USAGE))
325 .WillRepeatedly(Return(NO_ERROR));
326 EXPECT_CALL(*test->mConsumer, setDefaultBufferSize(WIDTH, HEIGHT))
327 .WillRepeatedly(Return(NO_ERROR));
328 EXPECT_CALL(*test->mConsumer, setMaxAcquiredBufferCount(_))
329 .WillRepeatedly(Return(NO_ERROR));
330 }
331
332 static void setupFramebufferProducerBufferQueueCallExpectations(DisplayTransactionTest* test) {
333 EXPECT_CALL(*test->mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
334 }
335};
336
337template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant,
338 typename PhysicalDisplay = void>
339struct HwcDisplayVariant {
340 // The display id supplied by the HWC
341 static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId;
342
343 // The HWC display type
344 static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
345
346 // The HWC active configuration id
Marin Shalamanov6e840172020-12-14 22:13:28 +0100347 static constexpr hal::HWConfigId HWC_ACTIVE_CONFIG_ID = 2001;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200348 static constexpr PowerMode INIT_POWER_MODE = hal::PowerMode::ON;
349
350 static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
351 test->mFlinger.mutablePendingHotplugEvents().emplace_back(
352 TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection});
353 }
354
355 // Called by tests to inject a HWC display setup
356 static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
357 const auto displayId = DisplayVariant::DISPLAY_ID::get();
358 ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId));
359 TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
360 static_cast<bool>(DisplayVariant::PRIMARY))
361 .setHwcDisplayId(HWC_DISPLAY_ID)
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800362 .setResolution(DisplayVariant::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200363 .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
364 .setPowerMode(INIT_POWER_MODE)
365 .inject(&test->mFlinger, test->mComposer);
366 }
367
368 // Called by tests to inject a HWC display setup
369 static void injectHwcDisplay(DisplayTransactionTest* test) {
370 EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
371 .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
372 Return(Error::NONE)));
373 EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE))
374 .WillOnce(Return(Error::NONE));
375 injectHwcDisplayWithNoDefaultCapabilities(test);
376 }
377
378 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
379 DisplayTransactionTest* test) {
380 const ::testing::TestInfo* const test_info =
381 ::testing::UnitTest::GetInstance()->current_test_info();
382
383 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
Dominik Laskowski13948602021-03-08 20:48:28 -0800384 .setId(DisplayVariant::DISPLAY_ID::get())
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800385 .setPixels(DisplayVariant::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200386 .setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
387 .setPowerAdvisor(&test->mPowerAdvisor)
388 .setName(std::string("Injected display for ") +
389 test_info->test_case_name() + "." + test_info->name())
390 .build();
391
392 return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
393 ceDisplayArgs);
394 }
395
Marin Shalamanov6e840172020-12-14 22:13:28 +0100396 static void setupHwcGetConfigsCallExpectations(DisplayTransactionTest* test) {
397 if (HWC_DISPLAY_TYPE == DisplayType::PHYSICAL) {
398 EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
399 .WillRepeatedly(DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{
400 HWC_ACTIVE_CONFIG_ID}),
401 Return(Error::NONE)));
402 EXPECT_CALL(*test->mComposer,
403 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
404 IComposerClient::Attribute::WIDTH, _))
405 .WillRepeatedly(
406 DoAll(SetArgPointee<3>(DisplayVariant::WIDTH), Return(Error::NONE)));
407 EXPECT_CALL(*test->mComposer,
408 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
409 IComposerClient::Attribute::HEIGHT, _))
410 .WillRepeatedly(
411 DoAll(SetArgPointee<3>(DisplayVariant::HEIGHT), Return(Error::NONE)));
412 EXPECT_CALL(*test->mComposer,
413 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
414 IComposerClient::Attribute::VSYNC_PERIOD, _))
415 .WillRepeatedly(
Marin Shalamanova903d032020-12-29 20:35:13 +0100416 DoAll(SetArgPointee<3>(DEFAULT_VSYNC_PERIOD), Return(Error::NONE)));
Marin Shalamanov6e840172020-12-14 22:13:28 +0100417 EXPECT_CALL(*test->mComposer,
418 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
419 IComposerClient::Attribute::DPI_X, _))
420 .WillRepeatedly(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
421 EXPECT_CALL(*test->mComposer,
422 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
423 IComposerClient::Attribute::DPI_Y, _))
424 .WillRepeatedly(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
425 EXPECT_CALL(*test->mComposer,
426 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
427 IComposerClient::Attribute::CONFIG_GROUP, _))
428 .WillRepeatedly(DoAll(SetArgPointee<3>(-1), Return(Error::NONE)));
429 } else {
430 EXPECT_CALL(*test->mComposer, getDisplayConfigs(_, _)).Times(0);
431 EXPECT_CALL(*test->mComposer, getDisplayAttribute(_, _, _, _)).Times(0);
432 }
433 }
434
Dominik Laskowskibab51282022-08-12 09:28:55 -0700435 template <bool kFailedHotplug = false>
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200436 static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
Dominik Laskowskibab51282022-08-12 09:28:55 -0700437 if constexpr (!kFailedHotplug) {
438 constexpr auto CONNECTION_TYPE =
439 PhysicalDisplay::CONNECTION_TYPE == ui::DisplayConnectionType::Internal
440 ? IComposerClient::DisplayConnectionType::INTERNAL
441 : IComposerClient::DisplayConnectionType::EXTERNAL;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200442
Dominik Laskowskibab51282022-08-12 09:28:55 -0700443 EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
444 .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE),
445 Return(hal::V2_4::Error::NONE)));
446 }
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200447
448 EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
449 .WillOnce(Return(hal::Error::NONE));
Marin Shalamanov6e840172020-12-14 22:13:28 +0100450
451 setupHwcGetConfigsCallExpectations(test);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200452
453 if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
454 EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
455 .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT),
456 SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()),
457 Return(Error::NONE)));
458 } else {
459 EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
460 .WillOnce(Return(Error::UNSUPPORTED));
461 }
462 }
463
464 // Called by tests to set up HWC call expectations
465 static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
466 EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _))
467 .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE)));
468 }
469};
470
471// Physical displays are expected to be synchronous, secure, and have a HWC display for output.
472constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
473 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
474
Vishnu Naira119aaa2021-09-24 07:19:35 -0700475constexpr int PHYSICAL_DISPLAY_FLAGS = 0x1;
476
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200477template <typename PhysicalDisplay, int width, int height, Critical critical>
478struct PhysicalDisplayVariant
479 : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
480 Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700481 GRALLOC_USAGE_PHYSICAL_DISPLAY, PHYSICAL_DISPLAY_FLAGS>,
482 HwcDisplayVariant<
483 PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
484 DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
485 Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
486 GRALLOC_USAGE_PHYSICAL_DISPLAY, PHYSICAL_DISPLAY_FLAGS>,
487 PhysicalDisplay> {};
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200488
489template <bool hasIdentificationData>
490struct PrimaryDisplay {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100491 static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::Internal;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200492 static constexpr Primary PRIMARY = Primary::TRUE;
493 static constexpr uint8_t PORT = 255;
494 static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
495 static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
496 static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
497};
498
499template <bool hasIdentificationData>
500struct ExternalDisplay {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100501 static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::External;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200502 static constexpr Primary PRIMARY = Primary::FALSE;
503 static constexpr uint8_t PORT = 254;
504 static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
505 static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
506 static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
507};
508
509struct TertiaryDisplay {
510 static constexpr Primary PRIMARY = Primary::FALSE;
511 static constexpr uint8_t PORT = 253;
512 static constexpr HWDisplayId HWC_DISPLAY_ID = 1003;
513 static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
514};
515
516// A primary display is a physical display that is critical
517using PrimaryDisplayVariant =
518 PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
519
520// An external display is physical display that is not critical.
521using ExternalDisplayVariant =
522 PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
523
524using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
525
526// A virtual display not supported by the HWC.
527constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
528
Vishnu Naira119aaa2021-09-24 07:19:35 -0700529constexpr int VIRTUAL_DISPLAY_FLAGS = 0x0;
530
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200531template <int width, int height, Secure secure>
532struct NonHwcVirtualDisplayVariant
533 : DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE, secure,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700534 Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY,
535 VIRTUAL_DISPLAY_FLAGS> {
536 using Base = DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE,
537 Async::TRUE, secure, Primary::FALSE,
538 GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY, VIRTUAL_DISPLAY_FLAGS>;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200539
540 static void injectHwcDisplay(DisplayTransactionTest*) {}
541
542 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
543 DisplayTransactionTest* test) {
544 const ::testing::TestInfo* const test_info =
545 ::testing::UnitTest::GetInstance()->current_test_info();
546
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200547 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
Dominik Laskowski13948602021-03-08 20:48:28 -0800548 .setId(Base::DISPLAY_ID::get())
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800549 .setPixels(Base::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200550 .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())
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200554 .build();
555
556 return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
557 ceDisplayArgs);
558 }
559
Marin Shalamanov6e840172020-12-14 22:13:28 +0100560 static void setupHwcGetConfigsCallExpectations(DisplayTransactionTest* test) {
561 EXPECT_CALL(*test->mComposer, getDisplayConfigs(_, _)).Times(0);
562 EXPECT_CALL(*test->mComposer, getDisplayAttribute(_, _, _, _)).Times(0);
563 }
564
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200565 static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
566 EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0);
567 }
568
569 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
570 Base::setupNativeWindowSurfaceCreationCallExpectations(test);
571 EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
572 }
573};
574
575// A virtual display supported by the HWC.
576constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER;
577
578template <int width, int height, Secure secure>
579struct HwcVirtualDisplayVariant
580 : DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE, Async::TRUE,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700581 secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY,
582 VIRTUAL_DISPLAY_FLAGS>,
583 HwcDisplayVariant<
584 HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
585 DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
586 Async::TRUE, secure, Primary::FALSE,
587 GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY, VIRTUAL_DISPLAY_FLAGS>> {
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200588 using Base = DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700589 Async::TRUE, secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER,
590 VIRTUAL_DISPLAY_FLAGS>;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200591 using Self = HwcVirtualDisplayVariant<width, height, secure>;
592
593 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
594 DisplayTransactionTest* test) {
595 const ::testing::TestInfo* const test_info =
596 ::testing::UnitTest::GetInstance()->current_test_info();
597
Dominik Laskowski13948602021-03-08 20:48:28 -0800598 const auto displayId = Base::DISPLAY_ID::get();
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200599 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
Dominik Laskowski13948602021-03-08 20:48:28 -0800600 .setId(displayId)
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800601 .setPixels(Base::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200602 .setIsSecure(static_cast<bool>(Base::SECURE))
603 .setPowerAdvisor(&test->mPowerAdvisor)
604 .setName(std::string("Injected display for ") +
605 test_info->test_case_name() + "." + test_info->name())
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200606 .build();
607
608 auto compositionDisplay =
609 compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
610 ceDisplayArgs);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200611
612 // Insert display data so that the HWC thinks it created the virtual display.
Dominik Laskowski13948602021-03-08 20:48:28 -0800613 test->mFlinger.mutableHwcDisplayData().try_emplace(displayId);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200614
615 return compositionDisplay;
616 }
617
618 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
619 Base::setupNativeWindowSurfaceCreationCallExpectations(test);
620 EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
621 }
622
623 static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) {
Dominik Laskowski263eec42021-07-21 23:13:24 -0700624 EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _))
625 .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE)));
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200626 EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
627 }
628};
629
630// For this variant, the display is not a HWC display, so no HDR support should
631// be configured.
632struct NonHwcDisplayHdrSupportVariant {
633 static constexpr bool HDR10_PLUS_SUPPORTED = false;
634 static constexpr bool HDR10_SUPPORTED = false;
635 static constexpr bool HDR_HLG_SUPPORTED = false;
636 static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
637 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
638 EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)).Times(0);
639 }
640};
641
642// For this variant, the composer should respond with am empty list of HDR
643// modes, so no HDR support should be configured.
644template <typename Display>
645struct HdrNotSupportedVariant {
646 static constexpr bool HDR10_PLUS_SUPPORTED = false;
647 static constexpr bool HDR10_SUPPORTED = false;
648 static constexpr bool HDR_HLG_SUPPORTED = false;
649 static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
650 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
651 EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
652 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
653 }
654};
655
656struct NonHwcPerFrameMetadataSupportVariant {
657 static constexpr int PER_FRAME_METADATA_KEYS = 0;
658 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
659 EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0);
660 }
661};
662
663template <typename Display>
664struct NoPerFrameMetadataSupportVariant {
665 static constexpr int PER_FRAME_METADATA_KEYS = 0;
666 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
667 EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
668 .WillOnce(Return(std::vector<PerFrameMetadataKey>()));
669 }
670};
671
672// For this variant, SurfaceFlinger should configure itself with wide display
673// support, but the display should respond with an empty list of supported color
674// modes. Wide-color support for the display should not be configured.
675template <typename Display>
676struct WideColorNotSupportedVariant {
677 static constexpr bool WIDE_COLOR_SUPPORTED = false;
678
679 static void injectConfigChange(DisplayTransactionTest* test) {
Dominik Laskowski788945b2022-08-30 12:10:56 -0700680 test->mFlinger.mutableSupportsWideColor() = true;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200681 }
682
683 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200684 EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
685 }
686};
687
688// For this variant, SurfaceFlinger should not configure itself with wide
689// display support, so the display should not be configured for wide-color
690// support.
691struct WideColorSupportNotConfiguredVariant {
692 static constexpr bool WIDE_COLOR_SUPPORTED = false;
693
694 static void injectConfigChange(DisplayTransactionTest* test) {
Dominik Laskowski788945b2022-08-30 12:10:56 -0700695 test->mFlinger.mutableSupportsWideColor() = false;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200696 test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
697 }
698
699 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200700 EXPECT_CALL(*test->mComposer, getRenderIntents(_, _, _)).Times(0);
701 EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
702 }
703};
704
705/* ------------------------------------------------------------------------
706 * Typical display configurations to test
707 */
708
709template <typename DisplayPolicy, typename WideColorSupportPolicy, typename HdrSupportPolicy,
710 typename PerFrameMetadataSupportPolicy>
711struct Case {
712 using Display = DisplayPolicy;
713 using WideColorSupport = WideColorSupportPolicy;
714 using HdrSupport = HdrSupportPolicy;
715 using PerFrameMetadataSupport = PerFrameMetadataSupportPolicy;
716};
717
718using SimplePrimaryDisplayCase =
719 Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
720 HdrNotSupportedVariant<PrimaryDisplayVariant>,
721 NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
722using SimpleExternalDisplayCase =
723 Case<ExternalDisplayVariant, WideColorNotSupportedVariant<ExternalDisplayVariant>,
724 HdrNotSupportedVariant<ExternalDisplayVariant>,
725 NoPerFrameMetadataSupportVariant<ExternalDisplayVariant>>;
726using SimpleTertiaryDisplayCase =
727 Case<TertiaryDisplayVariant, WideColorNotSupportedVariant<TertiaryDisplayVariant>,
728 HdrNotSupportedVariant<TertiaryDisplayVariant>,
729 NoPerFrameMetadataSupportVariant<TertiaryDisplayVariant>>;
730
731using NonHwcVirtualDisplayCase =
732 Case<NonHwcVirtualDisplayVariant<1024, 768, Secure::FALSE>,
733 WideColorSupportNotConfiguredVariant, NonHwcDisplayHdrSupportVariant,
734 NonHwcPerFrameMetadataSupportVariant>;
735using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
736using HwcVirtualDisplayCase =
737 Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
738 HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
739 NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
740
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800741inline DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
742 ui::Size resolution = ui::Size(1920, 1080)) {
743 return mock::createDisplayMode(modeId, refreshRate, group, resolution,
744 PrimaryDisplayVariant::DISPLAY_ID::get());
745}
746
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200747} // namespace android
748
749// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +0100750#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"