blob: d58e644506d717a3669dd0a4c4b5afcb3e2e04c4 [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
Dominik Laskowski327d6092022-10-11 18:05:08 -040045#include "FakeDisplayInjector.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020046#include "TestableScheduler.h"
47#include "TestableSurfaceFlinger.h"
48#include "mock/DisplayHardware/MockComposer.h"
Dominik Laskowskib0054a22022-03-03 09:03:06 -080049#include "mock/DisplayHardware/MockDisplayMode.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020050#include "mock/DisplayHardware/MockPowerAdvisor.h"
51#include "mock/MockEventThread.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020052#include "mock/MockNativeWindowSurface.h"
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020053#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
Leon Scroggins III5967aec2021-12-29 11:14:22 -050069using aidl::android::hardware::graphics::composer3::DisplayCapability;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020070using hal::ColorMode;
71using hal::Connection;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020072using 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();
Dominik Laskowski327d6092022-10-11 18:05:08 -040092
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020093 sp<DisplayDevice> injectDefaultInternalDisplay(
Dominik Laskowski327d6092022-10-11 18:05:08 -040094 std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)> injectExtra) {
95 return mFakeDisplayInjector.injectInternalDisplay(injectExtra);
96 }
Marin Shalamanov07b1ff32020-10-07 16:57:22 +020097
98 // --------------------------------------------------------------------
99 // Postcondition helpers
100
Dominik Laskowskieb627312022-04-07 09:13:16 -0700101 bool hasPhysicalHwcDisplay(hal::HWDisplayId) const;
102 bool hasTransactionFlagSet(int32_t flag) const;
103
104 bool hasDisplayDevice(const sp<IBinder>& displayToken) const;
105 const DisplayDevice& getDisplayDevice(const sp<IBinder>& displayToken) const;
106
107 bool hasCurrentDisplayState(const sp<IBinder>& displayToken) const;
108 const DisplayDeviceState& getCurrentDisplayState(const sp<IBinder>& displayToken) const;
109
110 bool hasDrawingDisplayState(const sp<IBinder>& displayToken) const;
111 const DisplayDeviceState& getDrawingDisplayState(const sp<IBinder>& displayToken) const;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200112
113 // --------------------------------------------------------------------
114 // Test instances
115
116 TestableSurfaceFlinger mFlinger;
Ady Abrahamd11bade2022-08-01 16:18:03 -0700117 sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
118 sp<GraphicBuffer> mBuffer = sp<GraphicBuffer>::make();
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200119 Hwc2::mock::PowerAdvisor mPowerAdvisor;
120
Dominik Laskowski327d6092022-10-11 18:05:08 -0400121 FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
122
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200123 // These mocks are created by the test, but are destroyed by SurfaceFlinger
124 // by virtue of being stored into a std::unique_ptr. However we still need
125 // to keep a reference to them for use in setting up call expectations.
126 renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
127 Hwc2::mock::Composer* mComposer = nullptr;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200128
129 mock::VsyncController* mVsyncController = new mock::VsyncController;
130 mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200131 mock::EventThread* mEventThread = new mock::EventThread;
132 mock::EventThread* mSFEventThread = new mock::EventThread;
133
134 // These mocks are created only when expected to be created via a factory.
135 sp<mock::GraphicBufferConsumer> mConsumer;
136 sp<mock::GraphicBufferProducer> mProducer;
137 surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
138
139protected:
140 DisplayTransactionTest();
141};
142
Marin Shalamanova903d032020-12-29 20:35:13 +0100143constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'667;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200144constexpr int32_t DEFAULT_DPI = 320;
145constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
146
147constexpr int POWER_MODE_LEET = 1337; // An out of range power mode value
148
149/* ------------------------------------------------------------------------
150 * Boolean avoidance
151 *
152 * To make calls and template instantiations more readable, we define some
153 * local enums along with an implicit bool conversion.
154 */
155
156#define BOOL_SUBSTITUTE(TYPENAME) enum class TYPENAME : bool { FALSE = false, TRUE = true };
157
158BOOL_SUBSTITUTE(Async);
159BOOL_SUBSTITUTE(Critical);
160BOOL_SUBSTITUTE(Primary);
161BOOL_SUBSTITUTE(Secure);
162BOOL_SUBSTITUTE(Virtual);
163
164template <typename PhysicalDisplay>
165struct PhysicalDisplayIdType {};
166
167template <uint64_t displayId>
168using HalVirtualDisplayIdType = std::integral_constant<uint64_t, displayId>;
169
170struct GpuVirtualDisplayIdType {};
171
172template <typename>
173struct IsPhysicalDisplayId : std::bool_constant<false> {};
174
175template <typename PhysicalDisplay>
176struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {};
177
178template <typename>
179struct DisplayIdGetter;
180
181template <typename PhysicalDisplay>
182struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
183 static PhysicalDisplayId get() {
184 if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
185 return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY)
186 ? LEGACY_DISPLAY_TYPE_PRIMARY
187 : LEGACY_DISPLAY_TYPE_EXTERNAL);
188 }
189
190 const auto info =
191 parseDisplayIdentificationData(PhysicalDisplay::PORT,
192 PhysicalDisplay::GET_IDENTIFICATION_DATA());
193 return info ? info->id : PhysicalDisplayId::fromPort(PhysicalDisplay::PORT);
194 }
195};
196
197template <uint64_t displayId>
198struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
199 static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
200};
201
202template <>
203struct DisplayIdGetter<GpuVirtualDisplayIdType> {
204 static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); }
205};
206
207template <typename>
208struct DisplayConnectionTypeGetter {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100209 static constexpr std::optional<ui::DisplayConnectionType> value;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200210};
211
212template <typename PhysicalDisplay>
213struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100214 static constexpr std::optional<ui::DisplayConnectionType> value =
215 PhysicalDisplay::CONNECTION_TYPE;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200216};
217
218template <typename>
219struct HwcDisplayIdGetter {
220 static constexpr std::optional<HWDisplayId> value;
221};
222
223constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
224
225template <uint64_t displayId>
226struct HwcDisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
227 static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
228};
229
230template <typename PhysicalDisplay>
231struct HwcDisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
232 static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
233};
234
235// DisplayIdType can be:
236// 1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC.
237// 2) HalVirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC.
238// 3) GpuVirtualDisplayIdType for virtual display without HWC backing.
239template <typename DisplayIdType, int width, int height, Critical critical, Async async,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700240 Secure secure, Primary primary, int grallocUsage, int displayFlags>
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200241struct DisplayVariant {
242 using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
243 using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
244 using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
245
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200246 static constexpr int WIDTH = width;
247 static constexpr int HEIGHT = height;
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800248 static constexpr ui::Size RESOLUTION{WIDTH, HEIGHT};
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200249
250 static constexpr int GRALLOC_USAGE = grallocUsage;
251
252 // Whether the display is virtual or physical
253 static constexpr Virtual VIRTUAL =
254 IsPhysicalDisplayId<DisplayIdType>{} ? Virtual::FALSE : Virtual::TRUE;
255
256 // When creating native window surfaces for the framebuffer, whether those should be critical
257 static constexpr Critical CRITICAL = critical;
258
259 // When creating native window surfaces for the framebuffer, whether those should be async
260 static constexpr Async ASYNC = async;
261
262 // Whether the display should be treated as secure
263 static constexpr Secure SECURE = secure;
264
265 // Whether the display is primary
266 static constexpr Primary PRIMARY = primary;
267
Vishnu Naira119aaa2021-09-24 07:19:35 -0700268 static constexpr int DISPLAY_FLAGS = displayFlags;
269
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200270 static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
271 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
Dominik Laskowski13948602021-03-08 20:48:28 -0800272 ceDisplayArgs.setId(DISPLAY_ID::get())
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800273 .setPixels(RESOLUTION)
Dominik Laskowski13948602021-03-08 20:48:28 -0800274 .setPowerAdvisor(&test->mPowerAdvisor);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200275
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200276 auto compositionDisplay =
277 compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
278 ceDisplayArgs.build());
279
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200280 auto injector =
281 TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger,
282 compositionDisplay,
Dominik Laskowski29fa1462021-04-27 15:51:50 -0700283 CONNECTION_TYPE::value,
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200284 HWC_DISPLAY_ID_OPT::value,
285 static_cast<bool>(PRIMARY));
286
287 injector.setSecure(static_cast<bool>(SECURE));
288 injector.setNativeWindow(test->mNativeWindow);
289
290 // Creating a DisplayDevice requires getting default dimensions from the
291 // native window along with some other initial setup.
292 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
293 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
294 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
295 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
296 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
297 .WillRepeatedly(Return(0));
298 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
299 .WillRepeatedly(Return(0));
300 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
301 .WillRepeatedly(Return(0));
302 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
303 .WillRepeatedly(Return(0));
304
305 return injector;
306 }
307
308 // Called by tests to set up any native window creation call expectations.
309 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
310 EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
311 .WillOnce(Return(test->mNativeWindow));
312
313 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
314 .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
315 EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
316 .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
317 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT))
318 .WillRepeatedly(Return(0));
319 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT))
320 .WillRepeatedly(Return(0));
321 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64))
322 .WillRepeatedly(Return(0));
323 EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT))
324 .WillRepeatedly(Return(0));
325 }
326
327 static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
328 EXPECT_CALL(*test->mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR));
329 EXPECT_CALL(*test->mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR));
330 EXPECT_CALL(*test->mConsumer, setConsumerUsageBits(GRALLOC_USAGE))
331 .WillRepeatedly(Return(NO_ERROR));
332 EXPECT_CALL(*test->mConsumer, setDefaultBufferSize(WIDTH, HEIGHT))
333 .WillRepeatedly(Return(NO_ERROR));
334 EXPECT_CALL(*test->mConsumer, setMaxAcquiredBufferCount(_))
335 .WillRepeatedly(Return(NO_ERROR));
336 }
337
338 static void setupFramebufferProducerBufferQueueCallExpectations(DisplayTransactionTest* test) {
339 EXPECT_CALL(*test->mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return());
340 }
341};
342
343template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant,
344 typename PhysicalDisplay = void>
345struct HwcDisplayVariant {
346 // The display id supplied by the HWC
347 static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId;
348
349 // The HWC display type
350 static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType;
351
352 // The HWC active configuration id
Marin Shalamanov6e840172020-12-14 22:13:28 +0100353 static constexpr hal::HWConfigId HWC_ACTIVE_CONFIG_ID = 2001;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200354 static constexpr PowerMode INIT_POWER_MODE = hal::PowerMode::ON;
355
356 static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
357 test->mFlinger.mutablePendingHotplugEvents().emplace_back(
358 TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection});
359 }
360
361 // Called by tests to inject a HWC display setup
Dominik Laskowskic132a152022-11-30 15:44:52 -0500362 template <bool kInitPowerMode = true>
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200363 static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) {
364 const auto displayId = DisplayVariant::DISPLAY_ID::get();
365 ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId));
366 TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE,
367 static_cast<bool>(DisplayVariant::PRIMARY))
368 .setHwcDisplayId(HWC_DISPLAY_ID)
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800369 .setResolution(DisplayVariant::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200370 .setActiveConfig(HWC_ACTIVE_CONFIG_ID)
Dominik Laskowskic132a152022-11-30 15:44:52 -0500371 .setPowerMode(kInitPowerMode ? std::make_optional(INIT_POWER_MODE) : std::nullopt)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200372 .inject(&test->mFlinger, test->mComposer);
373 }
374
375 // Called by tests to inject a HWC display setup
Dominik Laskowskic132a152022-11-30 15:44:52 -0500376 template <bool kInitPowerMode = true>
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200377 static void injectHwcDisplay(DisplayTransactionTest* test) {
378 EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _))
379 .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})),
380 Return(Error::NONE)));
Dominik Laskowskic132a152022-11-30 15:44:52 -0500381 if constexpr (kInitPowerMode) {
382 EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE))
383 .WillOnce(Return(Error::NONE));
384 }
385 injectHwcDisplayWithNoDefaultCapabilities<kInitPowerMode>(test);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200386 }
387
388 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
389 DisplayTransactionTest* test) {
390 const ::testing::TestInfo* const test_info =
391 ::testing::UnitTest::GetInstance()->current_test_info();
392
393 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
Dominik Laskowski13948602021-03-08 20:48:28 -0800394 .setId(DisplayVariant::DISPLAY_ID::get())
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800395 .setPixels(DisplayVariant::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200396 .setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
397 .setPowerAdvisor(&test->mPowerAdvisor)
398 .setName(std::string("Injected display for ") +
399 test_info->test_case_name() + "." + test_info->name())
400 .build();
401
402 return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
403 ceDisplayArgs);
404 }
405
Marin Shalamanov6e840172020-12-14 22:13:28 +0100406 static void setupHwcGetConfigsCallExpectations(DisplayTransactionTest* test) {
407 if (HWC_DISPLAY_TYPE == DisplayType::PHYSICAL) {
408 EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
409 .WillRepeatedly(DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{
410 HWC_ACTIVE_CONFIG_ID}),
411 Return(Error::NONE)));
412 EXPECT_CALL(*test->mComposer,
413 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
414 IComposerClient::Attribute::WIDTH, _))
415 .WillRepeatedly(
416 DoAll(SetArgPointee<3>(DisplayVariant::WIDTH), Return(Error::NONE)));
417 EXPECT_CALL(*test->mComposer,
418 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
419 IComposerClient::Attribute::HEIGHT, _))
420 .WillRepeatedly(
421 DoAll(SetArgPointee<3>(DisplayVariant::HEIGHT), Return(Error::NONE)));
422 EXPECT_CALL(*test->mComposer,
423 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
424 IComposerClient::Attribute::VSYNC_PERIOD, _))
425 .WillRepeatedly(
Marin Shalamanova903d032020-12-29 20:35:13 +0100426 DoAll(SetArgPointee<3>(DEFAULT_VSYNC_PERIOD), Return(Error::NONE)));
Marin Shalamanov6e840172020-12-14 22:13:28 +0100427 EXPECT_CALL(*test->mComposer,
428 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
429 IComposerClient::Attribute::DPI_X, _))
430 .WillRepeatedly(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
431 EXPECT_CALL(*test->mComposer,
432 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
433 IComposerClient::Attribute::DPI_Y, _))
434 .WillRepeatedly(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
435 EXPECT_CALL(*test->mComposer,
436 getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
437 IComposerClient::Attribute::CONFIG_GROUP, _))
438 .WillRepeatedly(DoAll(SetArgPointee<3>(-1), Return(Error::NONE)));
439 } else {
440 EXPECT_CALL(*test->mComposer, getDisplayConfigs(_, _)).Times(0);
441 EXPECT_CALL(*test->mComposer, getDisplayAttribute(_, _, _, _)).Times(0);
442 }
443 }
444
Dominik Laskowskibab51282022-08-12 09:28:55 -0700445 template <bool kFailedHotplug = false>
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200446 static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
Dominik Laskowskibab51282022-08-12 09:28:55 -0700447 if constexpr (!kFailedHotplug) {
448 constexpr auto CONNECTION_TYPE =
449 PhysicalDisplay::CONNECTION_TYPE == ui::DisplayConnectionType::Internal
450 ? IComposerClient::DisplayConnectionType::INTERNAL
451 : IComposerClient::DisplayConnectionType::EXTERNAL;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200452
Dominik Laskowskibab51282022-08-12 09:28:55 -0700453 EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
454 .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE),
455 Return(hal::V2_4::Error::NONE)));
456 }
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200457
458 EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
459 .WillOnce(Return(hal::Error::NONE));
Marin Shalamanov6e840172020-12-14 22:13:28 +0100460
461 setupHwcGetConfigsCallExpectations(test);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200462
463 if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) {
464 EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
465 .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT),
466 SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()),
467 Return(Error::NONE)));
468 } else {
469 EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
470 .WillOnce(Return(Error::UNSUPPORTED));
471 }
472 }
473
474 // Called by tests to set up HWC call expectations
475 static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
476 EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _))
477 .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE)));
478 }
479};
480
481// Physical displays are expected to be synchronous, secure, and have a HWC display for output.
482constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
483 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
484
Vishnu Naira119aaa2021-09-24 07:19:35 -0700485constexpr int PHYSICAL_DISPLAY_FLAGS = 0x1;
486
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200487template <typename PhysicalDisplay, int width, int height, Critical critical>
488struct PhysicalDisplayVariant
489 : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
490 Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700491 GRALLOC_USAGE_PHYSICAL_DISPLAY, PHYSICAL_DISPLAY_FLAGS>,
492 HwcDisplayVariant<
493 PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL,
494 DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, critical,
495 Async::FALSE, Secure::TRUE, PhysicalDisplay::PRIMARY,
496 GRALLOC_USAGE_PHYSICAL_DISPLAY, PHYSICAL_DISPLAY_FLAGS>,
497 PhysicalDisplay> {};
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200498
499template <bool hasIdentificationData>
500struct PrimaryDisplay {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100501 static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::Internal;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200502 static constexpr Primary PRIMARY = Primary::TRUE;
503 static constexpr uint8_t PORT = 255;
504 static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
505 static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
506 static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
507};
508
509template <bool hasIdentificationData>
510struct ExternalDisplay {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100511 static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::External;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200512 static constexpr Primary PRIMARY = Primary::FALSE;
513 static constexpr uint8_t PORT = 254;
514 static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
515 static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
516 static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
517};
518
519struct TertiaryDisplay {
520 static constexpr Primary PRIMARY = Primary::FALSE;
521 static constexpr uint8_t PORT = 253;
522 static constexpr HWDisplayId HWC_DISPLAY_ID = 1003;
523 static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
524};
525
526// A primary display is a physical display that is critical
527using PrimaryDisplayVariant =
528 PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
529
530// An external display is physical display that is not critical.
531using ExternalDisplayVariant =
532 PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
533
534using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
535
536// A virtual display not supported by the HWC.
537constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
538
Vishnu Naira119aaa2021-09-24 07:19:35 -0700539constexpr int VIRTUAL_DISPLAY_FLAGS = 0x0;
540
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200541template <int width, int height, Secure secure>
542struct NonHwcVirtualDisplayVariant
543 : DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE, Async::TRUE, secure,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700544 Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY,
545 VIRTUAL_DISPLAY_FLAGS> {
546 using Base = DisplayVariant<GpuVirtualDisplayIdType, width, height, Critical::FALSE,
547 Async::TRUE, secure, Primary::FALSE,
548 GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY, VIRTUAL_DISPLAY_FLAGS>;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200549
550 static void injectHwcDisplay(DisplayTransactionTest*) {}
551
552 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
553 DisplayTransactionTest* test) {
554 const ::testing::TestInfo* const test_info =
555 ::testing::UnitTest::GetInstance()->current_test_info();
556
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200557 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
Dominik Laskowski13948602021-03-08 20:48:28 -0800558 .setId(Base::DISPLAY_ID::get())
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800559 .setPixels(Base::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200560 .setIsSecure(static_cast<bool>(Base::SECURE))
561 .setPowerAdvisor(&test->mPowerAdvisor)
562 .setName(std::string("Injected display for ") +
563 test_info->test_case_name() + "." + test_info->name())
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200564 .build();
565
566 return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
567 ceDisplayArgs);
568 }
569
Marin Shalamanov6e840172020-12-14 22:13:28 +0100570 static void setupHwcGetConfigsCallExpectations(DisplayTransactionTest* test) {
571 EXPECT_CALL(*test->mComposer, getDisplayConfigs(_, _)).Times(0);
572 EXPECT_CALL(*test->mComposer, getDisplayAttribute(_, _, _, _)).Times(0);
573 }
574
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200575 static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) {
576 EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0);
577 }
578
579 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
580 Base::setupNativeWindowSurfaceCreationCallExpectations(test);
581 EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
582 }
583};
584
585// A virtual display supported by the HWC.
586constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER;
587
588template <int width, int height, Secure secure>
589struct HwcVirtualDisplayVariant
590 : DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE, Async::TRUE,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700591 secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY,
592 VIRTUAL_DISPLAY_FLAGS>,
593 HwcDisplayVariant<
594 HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL,
595 DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
596 Async::TRUE, secure, Primary::FALSE,
597 GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY, VIRTUAL_DISPLAY_FLAGS>> {
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200598 using Base = DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Critical::FALSE,
Vishnu Naira119aaa2021-09-24 07:19:35 -0700599 Async::TRUE, secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER,
600 VIRTUAL_DISPLAY_FLAGS>;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200601 using Self = HwcVirtualDisplayVariant<width, height, secure>;
602
603 static std::shared_ptr<compositionengine::Display> injectCompositionDisplay(
604 DisplayTransactionTest* test) {
605 const ::testing::TestInfo* const test_info =
606 ::testing::UnitTest::GetInstance()->current_test_info();
607
Dominik Laskowski13948602021-03-08 20:48:28 -0800608 const auto displayId = Base::DISPLAY_ID::get();
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200609 auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
Dominik Laskowski13948602021-03-08 20:48:28 -0800610 .setId(displayId)
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800611 .setPixels(Base::RESOLUTION)
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200612 .setIsSecure(static_cast<bool>(Base::SECURE))
613 .setPowerAdvisor(&test->mPowerAdvisor)
614 .setName(std::string("Injected display for ") +
615 test_info->test_case_name() + "." + test_info->name())
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200616 .build();
617
618 auto compositionDisplay =
619 compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
620 ceDisplayArgs);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200621
622 // Insert display data so that the HWC thinks it created the virtual display.
Dominik Laskowski13948602021-03-08 20:48:28 -0800623 test->mFlinger.mutableHwcDisplayData().try_emplace(displayId);
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200624
625 return compositionDisplay;
626 }
627
628 static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
629 Base::setupNativeWindowSurfaceCreationCallExpectations(test);
630 EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1);
631 }
632
633 static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) {
Dominik Laskowski263eec42021-07-21 23:13:24 -0700634 EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _))
635 .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE)));
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200636 EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
637 }
638};
639
640// For this variant, the display is not a HWC display, so no HDR support should
641// be configured.
642struct NonHwcDisplayHdrSupportVariant {
643 static constexpr bool HDR10_PLUS_SUPPORTED = false;
644 static constexpr bool HDR10_SUPPORTED = false;
645 static constexpr bool HDR_HLG_SUPPORTED = false;
646 static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
647 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
648 EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)).Times(0);
649 }
650};
651
652// For this variant, the composer should respond with am empty list of HDR
653// modes, so no HDR support should be configured.
654template <typename Display>
655struct HdrNotSupportedVariant {
656 static constexpr bool HDR10_PLUS_SUPPORTED = false;
657 static constexpr bool HDR10_SUPPORTED = false;
658 static constexpr bool HDR_HLG_SUPPORTED = false;
659 static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false;
660 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
661 EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _))
662 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE)));
663 }
664};
665
666struct NonHwcPerFrameMetadataSupportVariant {
667 static constexpr int PER_FRAME_METADATA_KEYS = 0;
668 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
669 EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0);
670 }
671};
672
673template <typename Display>
674struct NoPerFrameMetadataSupportVariant {
675 static constexpr int PER_FRAME_METADATA_KEYS = 0;
676 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
677 EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID))
678 .WillOnce(Return(std::vector<PerFrameMetadataKey>()));
679 }
680};
681
682// For this variant, SurfaceFlinger should configure itself with wide display
683// support, but the display should respond with an empty list of supported color
684// modes. Wide-color support for the display should not be configured.
685template <typename Display>
686struct WideColorNotSupportedVariant {
687 static constexpr bool WIDE_COLOR_SUPPORTED = false;
688
689 static void injectConfigChange(DisplayTransactionTest* test) {
Dominik Laskowski788945b2022-08-30 12:10:56 -0700690 test->mFlinger.mutableSupportsWideColor() = true;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200691 }
692
693 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200694 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) {
Dominik Laskowski788945b2022-08-30 12:10:56 -0700705 test->mFlinger.mutableSupportsWideColor() = false;
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200706 test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
707 }
708
709 static void setupComposerCallExpectations(DisplayTransactionTest* test) {
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200710 EXPECT_CALL(*test->mComposer, getRenderIntents(_, _, _)).Times(0);
711 EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0);
712 }
713};
714
715/* ------------------------------------------------------------------------
716 * Typical display configurations to test
717 */
718
719template <typename DisplayPolicy, typename WideColorSupportPolicy, typename HdrSupportPolicy,
720 typename PerFrameMetadataSupportPolicy>
721struct Case {
722 using Display = DisplayPolicy;
723 using WideColorSupport = WideColorSupportPolicy;
724 using HdrSupport = HdrSupportPolicy;
725 using PerFrameMetadataSupport = PerFrameMetadataSupportPolicy;
726};
727
728using SimplePrimaryDisplayCase =
729 Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
730 HdrNotSupportedVariant<PrimaryDisplayVariant>,
731 NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
732using SimpleExternalDisplayCase =
733 Case<ExternalDisplayVariant, WideColorNotSupportedVariant<ExternalDisplayVariant>,
734 HdrNotSupportedVariant<ExternalDisplayVariant>,
735 NoPerFrameMetadataSupportVariant<ExternalDisplayVariant>>;
736using SimpleTertiaryDisplayCase =
737 Case<TertiaryDisplayVariant, WideColorNotSupportedVariant<TertiaryDisplayVariant>,
738 HdrNotSupportedVariant<TertiaryDisplayVariant>,
739 NoPerFrameMetadataSupportVariant<TertiaryDisplayVariant>>;
740
741using NonHwcVirtualDisplayCase =
742 Case<NonHwcVirtualDisplayVariant<1024, 768, Secure::FALSE>,
743 WideColorSupportNotConfiguredVariant, NonHwcDisplayHdrSupportVariant,
744 NonHwcPerFrameMetadataSupportVariant>;
745using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
746using HwcVirtualDisplayCase =
747 Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
748 HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
749 NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
750
Dominik Laskowskib0054a22022-03-03 09:03:06 -0800751inline DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0,
752 ui::Size resolution = ui::Size(1920, 1080)) {
753 return mock::createDisplayMode(modeId, refreshRate, group, resolution,
754 PrimaryDisplayVariant::DISPLAY_ID::get());
755}
756
Marin Shalamanov07b1ff32020-10-07 16:57:22 +0200757} // namespace android
758
759// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +0100760#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"