Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #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 Shalamanov | bed7fd3 | 2020-12-21 20:02:20 +0100 | [diff] [blame] | 22 | #pragma clang diagnostic ignored "-Wextra" |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 23 | |
| 24 | #include <type_traits> |
Alec Mouri | ff79387 | 2022-01-13 17:45:06 -0800 | [diff] [blame] | 25 | #include "DisplayIdentificationTestHelpers.h" |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 26 | |
| 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 Laskowski | 327d609 | 2022-10-11 18:05:08 -0400 | [diff] [blame] | 45 | #include "FakeDisplayInjector.h" |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 46 | #include "TestableScheduler.h" |
| 47 | #include "TestableSurfaceFlinger.h" |
| 48 | #include "mock/DisplayHardware/MockComposer.h" |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 49 | #include "mock/DisplayHardware/MockDisplayMode.h" |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 50 | #include "mock/DisplayHardware/MockPowerAdvisor.h" |
| 51 | #include "mock/MockEventThread.h" |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 52 | #include "mock/MockNativeWindowSurface.h" |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 53 | #include "mock/MockVsyncController.h" |
| 54 | #include "mock/system/window/MockNativeWindow.h" |
| 55 | |
| 56 | namespace android { |
| 57 | |
| 58 | // TODO: Do not polute the android namespace |
| 59 | namespace hal = android::hardware::graphics::composer::hal; |
| 60 | |
| 61 | using testing::_; |
| 62 | using testing::AnyNumber; |
| 63 | using testing::DoAll; |
| 64 | using testing::Mock; |
| 65 | using testing::ResultOf; |
| 66 | using testing::Return; |
| 67 | using testing::SetArgPointee; |
| 68 | |
Leon Scroggins III | 5967aec | 2021-12-29 11:14:22 -0500 | [diff] [blame] | 69 | using aidl::android::hardware::graphics::composer3::DisplayCapability; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 70 | using hal::ColorMode; |
| 71 | using hal::Connection; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 72 | using hal::DisplayType; |
| 73 | using hal::Error; |
| 74 | using hal::Hdr; |
| 75 | using hal::HWDisplayId; |
| 76 | using hal::IComposer; |
| 77 | using hal::IComposerClient; |
| 78 | using hal::PerFrameMetadataKey; |
| 79 | using hal::PowerMode; |
| 80 | |
| 81 | class DisplayTransactionTest : public testing::Test { |
| 82 | public: |
| 83 | ~DisplayTransactionTest() override; |
| 84 | |
| 85 | // -------------------------------------------------------------------- |
| 86 | // Mock/Fake injection |
| 87 | |
Dominik Laskowski | aee9a62 | 2023-02-11 14:24:19 -0500 | [diff] [blame] | 88 | void injectMockScheduler(PhysicalDisplayId); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 89 | void injectMockComposer(int virtualDisplayCount); |
| 90 | void injectFakeBufferQueueFactory(); |
| 91 | void injectFakeNativeWindowSurfaceFactory(); |
Dominik Laskowski | 327d609 | 2022-10-11 18:05:08 -0400 | [diff] [blame] | 92 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 93 | sp<DisplayDevice> injectDefaultInternalDisplay( |
Dominik Laskowski | 327d609 | 2022-10-11 18:05:08 -0400 | [diff] [blame] | 94 | std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)> injectExtra) { |
| 95 | return mFakeDisplayInjector.injectInternalDisplay(injectExtra); |
| 96 | } |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 97 | |
| 98 | // -------------------------------------------------------------------- |
| 99 | // Postcondition helpers |
| 100 | |
Dominik Laskowski | eb62731 | 2022-04-07 09:13:16 -0700 | [diff] [blame] | 101 | 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 Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 112 | |
| 113 | // -------------------------------------------------------------------- |
| 114 | // Test instances |
| 115 | |
| 116 | TestableSurfaceFlinger mFlinger; |
Ady Abraham | d11bade | 2022-08-01 16:18:03 -0700 | [diff] [blame] | 117 | sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make(); |
Brian Lindahl | f5ab5ae | 2022-12-21 14:27:15 -0700 | [diff] [blame] | 118 | sp<GraphicBuffer> mBuffer = |
| 119 | sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888, |
| 120 | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 121 | Hwc2::mock::PowerAdvisor mPowerAdvisor; |
| 122 | |
Dominik Laskowski | 327d609 | 2022-10-11 18:05:08 -0400 | [diff] [blame] | 123 | FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow}; |
| 124 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 125 | // These mocks are created by the test, but are destroyed by SurfaceFlinger |
| 126 | // by virtue of being stored into a std::unique_ptr. However we still need |
| 127 | // to keep a reference to them for use in setting up call expectations. |
| 128 | renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); |
| 129 | Hwc2::mock::Composer* mComposer = nullptr; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 130 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 131 | 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 | |
| 139 | protected: |
Dominik Laskowski | aee9a62 | 2023-02-11 14:24:19 -0500 | [diff] [blame] | 140 | DisplayTransactionTest(bool withMockScheduler = true); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 141 | }; |
| 142 | |
Marin Shalamanov | a903d03 | 2020-12-29 20:35:13 +0100 | [diff] [blame] | 143 | constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'667; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 144 | constexpr int32_t DEFAULT_DPI = 320; |
| 145 | constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565; |
| 146 | |
| 147 | constexpr 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 | |
| 158 | BOOL_SUBSTITUTE(Async); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 159 | BOOL_SUBSTITUTE(Primary); |
| 160 | BOOL_SUBSTITUTE(Secure); |
| 161 | BOOL_SUBSTITUTE(Virtual); |
| 162 | |
| 163 | template <typename PhysicalDisplay> |
| 164 | struct PhysicalDisplayIdType {}; |
| 165 | |
| 166 | template <uint64_t displayId> |
| 167 | using HalVirtualDisplayIdType = std::integral_constant<uint64_t, displayId>; |
| 168 | |
| 169 | struct GpuVirtualDisplayIdType {}; |
| 170 | |
| 171 | template <typename> |
| 172 | struct IsPhysicalDisplayId : std::bool_constant<false> {}; |
| 173 | |
| 174 | template <typename PhysicalDisplay> |
| 175 | struct IsPhysicalDisplayId<PhysicalDisplayIdType<PhysicalDisplay>> : std::bool_constant<true> {}; |
| 176 | |
| 177 | template <typename> |
| 178 | struct DisplayIdGetter; |
| 179 | |
| 180 | template <typename PhysicalDisplay> |
| 181 | struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> { |
| 182 | static PhysicalDisplayId get() { |
| 183 | if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) { |
| 184 | return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY) |
| 185 | ? LEGACY_DISPLAY_TYPE_PRIMARY |
| 186 | : LEGACY_DISPLAY_TYPE_EXTERNAL); |
| 187 | } |
| 188 | |
| 189 | const auto info = |
| 190 | parseDisplayIdentificationData(PhysicalDisplay::PORT, |
| 191 | PhysicalDisplay::GET_IDENTIFICATION_DATA()); |
| 192 | return info ? info->id : PhysicalDisplayId::fromPort(PhysicalDisplay::PORT); |
| 193 | } |
| 194 | }; |
| 195 | |
| 196 | template <uint64_t displayId> |
| 197 | struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> { |
| 198 | static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); } |
| 199 | }; |
| 200 | |
| 201 | template <> |
| 202 | struct DisplayIdGetter<GpuVirtualDisplayIdType> { |
| 203 | static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); } |
| 204 | }; |
| 205 | |
| 206 | template <typename> |
| 207 | struct DisplayConnectionTypeGetter { |
Marin Shalamanov | 228f46b | 2021-01-28 21:11:45 +0100 | [diff] [blame] | 208 | static constexpr std::optional<ui::DisplayConnectionType> value; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 209 | }; |
| 210 | |
| 211 | template <typename PhysicalDisplay> |
| 212 | struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> { |
Marin Shalamanov | 228f46b | 2021-01-28 21:11:45 +0100 | [diff] [blame] | 213 | static constexpr std::optional<ui::DisplayConnectionType> value = |
| 214 | PhysicalDisplay::CONNECTION_TYPE; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 215 | }; |
| 216 | |
| 217 | template <typename> |
| 218 | struct HwcDisplayIdGetter { |
| 219 | static constexpr std::optional<HWDisplayId> value; |
| 220 | }; |
| 221 | |
| 222 | constexpr HWDisplayId HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010; |
| 223 | |
| 224 | template <uint64_t displayId> |
| 225 | struct HwcDisplayIdGetter<HalVirtualDisplayIdType<displayId>> { |
| 226 | static constexpr std::optional<HWDisplayId> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID; |
| 227 | }; |
| 228 | |
| 229 | template <typename PhysicalDisplay> |
| 230 | struct HwcDisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> { |
| 231 | static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID; |
| 232 | }; |
| 233 | |
| 234 | // DisplayIdType can be: |
| 235 | // 1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC. |
| 236 | // 2) HalVirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC. |
| 237 | // 3) GpuVirtualDisplayIdType for virtual display without HWC backing. |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 238 | template <typename DisplayIdType, int width, int height, Async async, Secure secure, |
| 239 | Primary primary, int grallocUsage, int displayFlags> |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 240 | struct DisplayVariant { |
| 241 | using DISPLAY_ID = DisplayIdGetter<DisplayIdType>; |
| 242 | using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>; |
| 243 | using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>; |
| 244 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 245 | static constexpr int WIDTH = width; |
| 246 | static constexpr int HEIGHT = height; |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 247 | static constexpr ui::Size RESOLUTION{WIDTH, HEIGHT}; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 248 | |
| 249 | static constexpr int GRALLOC_USAGE = grallocUsage; |
| 250 | |
| 251 | // Whether the display is virtual or physical |
| 252 | static constexpr Virtual VIRTUAL = |
| 253 | IsPhysicalDisplayId<DisplayIdType>{} ? Virtual::FALSE : Virtual::TRUE; |
| 254 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 255 | // When creating native window surfaces for the framebuffer, whether those should be async |
| 256 | static constexpr Async ASYNC = async; |
| 257 | |
| 258 | // Whether the display should be treated as secure |
| 259 | static constexpr Secure SECURE = secure; |
| 260 | |
| 261 | // Whether the display is primary |
| 262 | static constexpr Primary PRIMARY = primary; |
| 263 | |
Vishnu Nair | a119aaa | 2021-09-24 07:19:35 -0700 | [diff] [blame] | 264 | static constexpr int DISPLAY_FLAGS = displayFlags; |
| 265 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 266 | static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { |
| 267 | auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder(); |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 268 | ceDisplayArgs.setId(DISPLAY_ID::get()) |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 269 | .setPixels(RESOLUTION) |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 270 | .setPowerAdvisor(&test->mPowerAdvisor); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 271 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 272 | auto compositionDisplay = |
| 273 | compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), |
| 274 | ceDisplayArgs.build()); |
| 275 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 276 | auto injector = |
| 277 | TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger, |
| 278 | compositionDisplay, |
Dominik Laskowski | 29fa146 | 2021-04-27 15:51:50 -0700 | [diff] [blame] | 279 | CONNECTION_TYPE::value, |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 280 | HWC_DISPLAY_ID_OPT::value, |
| 281 | static_cast<bool>(PRIMARY)); |
| 282 | |
| 283 | injector.setSecure(static_cast<bool>(SECURE)); |
| 284 | injector.setNativeWindow(test->mNativeWindow); |
| 285 | |
| 286 | // Creating a DisplayDevice requires getting default dimensions from the |
| 287 | // native window along with some other initial setup. |
| 288 | EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _)) |
| 289 | .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0))); |
| 290 | EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _)) |
| 291 | .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0))); |
| 292 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)) |
| 293 | .WillRepeatedly(Return(0)); |
| 294 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)) |
| 295 | .WillRepeatedly(Return(0)); |
| 296 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)) |
| 297 | .WillRepeatedly(Return(0)); |
| 298 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)) |
| 299 | .WillRepeatedly(Return(0)); |
| 300 | |
| 301 | return injector; |
| 302 | } |
| 303 | |
| 304 | // Called by tests to set up any native window creation call expectations. |
| 305 | static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { |
| 306 | EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow()) |
| 307 | .WillOnce(Return(test->mNativeWindow)); |
| 308 | |
| 309 | EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _)) |
| 310 | .WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0))); |
| 311 | EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _)) |
| 312 | .WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0))); |
| 313 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)) |
| 314 | .WillRepeatedly(Return(0)); |
| 315 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)) |
| 316 | .WillRepeatedly(Return(0)); |
| 317 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)) |
| 318 | .WillRepeatedly(Return(0)); |
| 319 | EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)) |
| 320 | .WillRepeatedly(Return(0)); |
| 321 | } |
| 322 | |
| 323 | static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) { |
| 324 | EXPECT_CALL(*test->mConsumer, consumerConnect(_, false)).WillOnce(Return(NO_ERROR)); |
| 325 | EXPECT_CALL(*test->mConsumer, setConsumerName(_)).WillRepeatedly(Return(NO_ERROR)); |
| 326 | EXPECT_CALL(*test->mConsumer, setConsumerUsageBits(GRALLOC_USAGE)) |
| 327 | .WillRepeatedly(Return(NO_ERROR)); |
| 328 | EXPECT_CALL(*test->mConsumer, setDefaultBufferSize(WIDTH, HEIGHT)) |
| 329 | .WillRepeatedly(Return(NO_ERROR)); |
| 330 | EXPECT_CALL(*test->mConsumer, setMaxAcquiredBufferCount(_)) |
| 331 | .WillRepeatedly(Return(NO_ERROR)); |
| 332 | } |
| 333 | |
| 334 | static void setupFramebufferProducerBufferQueueCallExpectations(DisplayTransactionTest* test) { |
| 335 | EXPECT_CALL(*test->mProducer, allocateBuffers(0, 0, 0, 0)).WillRepeatedly(Return()); |
| 336 | } |
| 337 | }; |
| 338 | |
| 339 | template <HWDisplayId hwcDisplayId, DisplayType hwcDisplayType, typename DisplayVariant, |
| 340 | typename PhysicalDisplay = void> |
| 341 | struct HwcDisplayVariant { |
| 342 | // The display id supplied by the HWC |
| 343 | static constexpr HWDisplayId HWC_DISPLAY_ID = hwcDisplayId; |
| 344 | |
| 345 | // The HWC display type |
| 346 | static constexpr DisplayType HWC_DISPLAY_TYPE = hwcDisplayType; |
| 347 | |
| 348 | // The HWC active configuration id |
Marin Shalamanov | 6e84017 | 2020-12-14 22:13:28 +0100 | [diff] [blame] | 349 | static constexpr hal::HWConfigId HWC_ACTIVE_CONFIG_ID = 2001; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 350 | static constexpr PowerMode INIT_POWER_MODE = hal::PowerMode::ON; |
| 351 | |
| 352 | static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) { |
| 353 | test->mFlinger.mutablePendingHotplugEvents().emplace_back( |
| 354 | TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection}); |
| 355 | } |
| 356 | |
| 357 | // Called by tests to inject a HWC display setup |
Dominik Laskowski | c132a15 | 2022-11-30 15:44:52 -0500 | [diff] [blame] | 358 | template <bool kInitPowerMode = true> |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 359 | static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) { |
| 360 | const auto displayId = DisplayVariant::DISPLAY_ID::get(); |
| 361 | ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId)); |
| 362 | TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE, |
| 363 | static_cast<bool>(DisplayVariant::PRIMARY)) |
| 364 | .setHwcDisplayId(HWC_DISPLAY_ID) |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 365 | .setResolution(DisplayVariant::RESOLUTION) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 366 | .setActiveConfig(HWC_ACTIVE_CONFIG_ID) |
Dominik Laskowski | c132a15 | 2022-11-30 15:44:52 -0500 | [diff] [blame] | 367 | .setPowerMode(kInitPowerMode ? std::make_optional(INIT_POWER_MODE) : std::nullopt) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 368 | .inject(&test->mFlinger, test->mComposer); |
| 369 | } |
| 370 | |
| 371 | // Called by tests to inject a HWC display setup |
Dominik Laskowski | c132a15 | 2022-11-30 15:44:52 -0500 | [diff] [blame] | 372 | template <bool kInitPowerMode = true> |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 373 | static void injectHwcDisplay(DisplayTransactionTest* test) { |
Dominik Laskowski | c132a15 | 2022-11-30 15:44:52 -0500 | [diff] [blame] | 374 | if constexpr (kInitPowerMode) { |
Dominik Laskowski | 6629543 | 2023-03-14 12:25:36 -0400 | [diff] [blame] | 375 | EXPECT_CALL(*test->mComposer, getDisplayCapabilities(HWC_DISPLAY_ID, _)) |
| 376 | .WillOnce(DoAll(SetArgPointee<1>(std::vector<DisplayCapability>({})), |
| 377 | Return(Error::NONE))); |
| 378 | |
Dominik Laskowski | c132a15 | 2022-11-30 15:44:52 -0500 | [diff] [blame] | 379 | EXPECT_CALL(*test->mComposer, setPowerMode(HWC_DISPLAY_ID, INIT_POWER_MODE)) |
| 380 | .WillOnce(Return(Error::NONE)); |
| 381 | } |
| 382 | injectHwcDisplayWithNoDefaultCapabilities<kInitPowerMode>(test); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 383 | } |
| 384 | |
| 385 | static std::shared_ptr<compositionengine::Display> injectCompositionDisplay( |
| 386 | DisplayTransactionTest* test) { |
| 387 | const ::testing::TestInfo* const test_info = |
| 388 | ::testing::UnitTest::GetInstance()->current_test_info(); |
| 389 | |
| 390 | auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 391 | .setId(DisplayVariant::DISPLAY_ID::get()) |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 392 | .setPixels(DisplayVariant::RESOLUTION) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 393 | .setIsSecure(static_cast<bool>(DisplayVariant::SECURE)) |
| 394 | .setPowerAdvisor(&test->mPowerAdvisor) |
| 395 | .setName(std::string("Injected display for ") + |
| 396 | test_info->test_case_name() + "." + test_info->name()) |
| 397 | .build(); |
| 398 | |
| 399 | return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), |
| 400 | ceDisplayArgs); |
| 401 | } |
| 402 | |
Marin Shalamanov | 6e84017 | 2020-12-14 22:13:28 +0100 | [diff] [blame] | 403 | static void setupHwcGetConfigsCallExpectations(DisplayTransactionTest* test) { |
| 404 | if (HWC_DISPLAY_TYPE == DisplayType::PHYSICAL) { |
| 405 | EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _)) |
| 406 | .WillRepeatedly(DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{ |
| 407 | HWC_ACTIVE_CONFIG_ID}), |
| 408 | Return(Error::NONE))); |
| 409 | EXPECT_CALL(*test->mComposer, |
| 410 | getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, |
| 411 | IComposerClient::Attribute::WIDTH, _)) |
| 412 | .WillRepeatedly( |
| 413 | DoAll(SetArgPointee<3>(DisplayVariant::WIDTH), Return(Error::NONE))); |
| 414 | EXPECT_CALL(*test->mComposer, |
| 415 | getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, |
| 416 | IComposerClient::Attribute::HEIGHT, _)) |
| 417 | .WillRepeatedly( |
| 418 | DoAll(SetArgPointee<3>(DisplayVariant::HEIGHT), Return(Error::NONE))); |
| 419 | EXPECT_CALL(*test->mComposer, |
| 420 | getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, |
| 421 | IComposerClient::Attribute::VSYNC_PERIOD, _)) |
| 422 | .WillRepeatedly( |
Marin Shalamanov | a903d03 | 2020-12-29 20:35:13 +0100 | [diff] [blame] | 423 | DoAll(SetArgPointee<3>(DEFAULT_VSYNC_PERIOD), Return(Error::NONE))); |
Marin Shalamanov | 6e84017 | 2020-12-14 22:13:28 +0100 | [diff] [blame] | 424 | EXPECT_CALL(*test->mComposer, |
| 425 | getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, |
| 426 | IComposerClient::Attribute::DPI_X, _)) |
| 427 | .WillRepeatedly(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE))); |
| 428 | EXPECT_CALL(*test->mComposer, |
| 429 | getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, |
| 430 | IComposerClient::Attribute::DPI_Y, _)) |
| 431 | .WillRepeatedly(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE))); |
| 432 | EXPECT_CALL(*test->mComposer, |
| 433 | getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID, |
| 434 | IComposerClient::Attribute::CONFIG_GROUP, _)) |
| 435 | .WillRepeatedly(DoAll(SetArgPointee<3>(-1), Return(Error::NONE))); |
| 436 | } else { |
| 437 | EXPECT_CALL(*test->mComposer, getDisplayConfigs(_, _)).Times(0); |
| 438 | EXPECT_CALL(*test->mComposer, getDisplayAttribute(_, _, _, _)).Times(0); |
| 439 | } |
| 440 | } |
| 441 | |
Dominik Laskowski | bab5128 | 2022-08-12 09:28:55 -0700 | [diff] [blame] | 442 | template <bool kFailedHotplug = false> |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 443 | static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) { |
Dominik Laskowski | bab5128 | 2022-08-12 09:28:55 -0700 | [diff] [blame] | 444 | if constexpr (!kFailedHotplug) { |
| 445 | constexpr auto CONNECTION_TYPE = |
| 446 | PhysicalDisplay::CONNECTION_TYPE == ui::DisplayConnectionType::Internal |
| 447 | ? IComposerClient::DisplayConnectionType::INTERNAL |
| 448 | : IComposerClient::DisplayConnectionType::EXTERNAL; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 449 | |
Dominik Laskowski | bab5128 | 2022-08-12 09:28:55 -0700 | [diff] [blame] | 450 | EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _)) |
| 451 | .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE), |
| 452 | Return(hal::V2_4::Error::NONE))); |
| 453 | } |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 454 | |
| 455 | EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)) |
| 456 | .WillOnce(Return(hal::Error::NONE)); |
Marin Shalamanov | 6e84017 | 2020-12-14 22:13:28 +0100 | [diff] [blame] | 457 | |
| 458 | setupHwcGetConfigsCallExpectations(test); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 459 | |
| 460 | if (PhysicalDisplay::HAS_IDENTIFICATION_DATA) { |
| 461 | EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) |
| 462 | .WillOnce(DoAll(SetArgPointee<1>(PhysicalDisplay::PORT), |
| 463 | SetArgPointee<2>(PhysicalDisplay::GET_IDENTIFICATION_DATA()), |
| 464 | Return(Error::NONE))); |
| 465 | } else { |
| 466 | EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _)) |
| 467 | .WillOnce(Return(Error::UNSUPPORTED)); |
| 468 | } |
| 469 | } |
| 470 | |
| 471 | // Called by tests to set up HWC call expectations |
| 472 | static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { |
| 473 | EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _)) |
| 474 | .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE))); |
| 475 | } |
| 476 | }; |
| 477 | |
| 478 | // Physical displays are expected to be synchronous, secure, and have a HWC display for output. |
| 479 | constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY = |
| 480 | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB; |
| 481 | |
Vishnu Nair | a119aaa | 2021-09-24 07:19:35 -0700 | [diff] [blame] | 482 | constexpr int PHYSICAL_DISPLAY_FLAGS = 0x1; |
| 483 | |
Huihong Luo | 9ebb7a7 | 2023-06-27 17:01:50 -0700 | [diff] [blame] | 484 | template <typename PhysicalDisplay, int width, int height, |
| 485 | Secure secure = (PhysicalDisplay::CONNECTION_TYPE == ui::DisplayConnectionType::Internal) |
| 486 | ? Secure::TRUE |
| 487 | : Secure::FALSE> |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 488 | struct PhysicalDisplayVariant |
Huihong Luo | 9ebb7a7 | 2023-06-27 17:01:50 -0700 | [diff] [blame] | 489 | : DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, Async::FALSE, secure, |
| 490 | PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY, |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 491 | PHYSICAL_DISPLAY_FLAGS>, |
| 492 | HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, DisplayType::PHYSICAL, |
| 493 | DisplayVariant<PhysicalDisplayIdType<PhysicalDisplay>, width, height, |
Huihong Luo | 9ebb7a7 | 2023-06-27 17:01:50 -0700 | [diff] [blame] | 494 | Async::FALSE, secure, PhysicalDisplay::PRIMARY, |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 495 | GRALLOC_USAGE_PHYSICAL_DISPLAY, PHYSICAL_DISPLAY_FLAGS>, |
| 496 | PhysicalDisplay> {}; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 497 | |
| 498 | template <bool hasIdentificationData> |
| 499 | struct PrimaryDisplay { |
Marin Shalamanov | 228f46b | 2021-01-28 21:11:45 +0100 | [diff] [blame] | 500 | static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::Internal; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 501 | static constexpr Primary PRIMARY = Primary::TRUE; |
| 502 | static constexpr uint8_t PORT = 255; |
| 503 | static constexpr HWDisplayId HWC_DISPLAY_ID = 1001; |
| 504 | static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData; |
| 505 | static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid; |
| 506 | }; |
| 507 | |
Dominik Laskowski | 06e5db0 | 2023-02-11 16:55:47 -0500 | [diff] [blame] | 508 | template <ui::DisplayConnectionType connectionType, bool hasIdentificationData> |
| 509 | struct SecondaryDisplay { |
| 510 | static constexpr auto CONNECTION_TYPE = connectionType; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 511 | static constexpr Primary PRIMARY = Primary::FALSE; |
| 512 | static constexpr uint8_t PORT = 254; |
| 513 | static constexpr HWDisplayId HWC_DISPLAY_ID = 1002; |
| 514 | static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData; |
Dominik Laskowski | 06e5db0 | 2023-02-11 16:55:47 -0500 | [diff] [blame] | 515 | static constexpr auto GET_IDENTIFICATION_DATA = |
| 516 | connectionType == ui::DisplayConnectionType::Internal ? getInternalEdid |
| 517 | : getExternalEdid; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 518 | }; |
| 519 | |
| 520 | struct TertiaryDisplay { |
Huihong Luo | 9ebb7a7 | 2023-06-27 17:01:50 -0700 | [diff] [blame] | 521 | static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::External; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 522 | static constexpr Primary PRIMARY = Primary::FALSE; |
| 523 | static constexpr uint8_t PORT = 253; |
| 524 | static constexpr HWDisplayId HWC_DISPLAY_ID = 1003; |
| 525 | static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid; |
| 526 | }; |
| 527 | |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 528 | using PrimaryDisplayVariant = PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160>; |
Dominik Laskowski | 06e5db0 | 2023-02-11 16:55:47 -0500 | [diff] [blame] | 529 | |
| 530 | using InnerDisplayVariant = PhysicalDisplayVariant<PrimaryDisplay<true>, 1840, 2208>; |
| 531 | using OuterDisplayVariant = |
| 532 | PhysicalDisplayVariant<SecondaryDisplay<ui::DisplayConnectionType::Internal, true>, 1080, |
| 533 | 2092>; |
| 534 | |
| 535 | using ExternalDisplayVariant = |
| 536 | PhysicalDisplayVariant<SecondaryDisplay<ui::DisplayConnectionType::External, false>, 1920, |
| 537 | 1280>; |
| 538 | |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 539 | using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200>; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 540 | |
| 541 | // A virtual display not supported by the HWC. |
| 542 | constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0; |
| 543 | |
Vishnu Nair | a119aaa | 2021-09-24 07:19:35 -0700 | [diff] [blame] | 544 | constexpr int VIRTUAL_DISPLAY_FLAGS = 0x0; |
| 545 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 546 | template <int width, int height, Secure secure> |
| 547 | struct NonHwcVirtualDisplayVariant |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 548 | : DisplayVariant<GpuVirtualDisplayIdType, width, height, Async::TRUE, secure, Primary::FALSE, |
| 549 | GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY, VIRTUAL_DISPLAY_FLAGS> { |
| 550 | using Base = DisplayVariant<GpuVirtualDisplayIdType, width, height, Async::TRUE, secure, |
| 551 | Primary::FALSE, GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY, |
| 552 | VIRTUAL_DISPLAY_FLAGS>; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 553 | |
| 554 | static void injectHwcDisplay(DisplayTransactionTest*) {} |
| 555 | |
| 556 | static std::shared_ptr<compositionengine::Display> injectCompositionDisplay( |
| 557 | DisplayTransactionTest* test) { |
| 558 | const ::testing::TestInfo* const test_info = |
| 559 | ::testing::UnitTest::GetInstance()->current_test_info(); |
| 560 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 561 | auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 562 | .setId(Base::DISPLAY_ID::get()) |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 563 | .setPixels(Base::RESOLUTION) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 564 | .setIsSecure(static_cast<bool>(Base::SECURE)) |
| 565 | .setPowerAdvisor(&test->mPowerAdvisor) |
| 566 | .setName(std::string("Injected display for ") + |
| 567 | test_info->test_case_name() + "." + test_info->name()) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 568 | .build(); |
| 569 | |
| 570 | return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), |
| 571 | ceDisplayArgs); |
| 572 | } |
| 573 | |
Marin Shalamanov | 6e84017 | 2020-12-14 22:13:28 +0100 | [diff] [blame] | 574 | static void setupHwcGetConfigsCallExpectations(DisplayTransactionTest* test) { |
| 575 | EXPECT_CALL(*test->mComposer, getDisplayConfigs(_, _)).Times(0); |
| 576 | EXPECT_CALL(*test->mComposer, getDisplayAttribute(_, _, _, _)).Times(0); |
| 577 | } |
| 578 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 579 | static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { |
| 580 | EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0); |
| 581 | } |
| 582 | |
| 583 | static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { |
| 584 | Base::setupNativeWindowSurfaceCreationCallExpectations(test); |
| 585 | EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1); |
| 586 | } |
| 587 | }; |
| 588 | |
| 589 | // A virtual display supported by the HWC. |
| 590 | constexpr uint32_t GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY = GRALLOC_USAGE_HW_COMPOSER; |
| 591 | |
| 592 | template <int width, int height, Secure secure> |
| 593 | struct HwcVirtualDisplayVariant |
Dominik Laskowski | e80bd31 | 2023-02-11 16:23:34 -0500 | [diff] [blame] | 594 | : DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Async::TRUE, secure, |
| 595 | Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY, VIRTUAL_DISPLAY_FLAGS>, |
| 596 | HwcDisplayVariant<HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, DisplayType::VIRTUAL, |
| 597 | DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Async::TRUE, |
| 598 | secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY, |
| 599 | VIRTUAL_DISPLAY_FLAGS>> { |
| 600 | using Base = DisplayVariant<HalVirtualDisplayIdType<42>, width, height, Async::TRUE, secure, |
| 601 | Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER, VIRTUAL_DISPLAY_FLAGS>; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 602 | using Self = HwcVirtualDisplayVariant<width, height, secure>; |
| 603 | |
| 604 | static std::shared_ptr<compositionengine::Display> injectCompositionDisplay( |
| 605 | DisplayTransactionTest* test) { |
| 606 | const ::testing::TestInfo* const test_info = |
| 607 | ::testing::UnitTest::GetInstance()->current_test_info(); |
| 608 | |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 609 | const auto displayId = Base::DISPLAY_ID::get(); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 610 | auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 611 | .setId(displayId) |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 612 | .setPixels(Base::RESOLUTION) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 613 | .setIsSecure(static_cast<bool>(Base::SECURE)) |
| 614 | .setPowerAdvisor(&test->mPowerAdvisor) |
| 615 | .setName(std::string("Injected display for ") + |
| 616 | test_info->test_case_name() + "." + test_info->name()) |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 617 | .build(); |
| 618 | |
| 619 | auto compositionDisplay = |
| 620 | compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), |
| 621 | ceDisplayArgs); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 622 | |
| 623 | // Insert display data so that the HWC thinks it created the virtual display. |
Dominik Laskowski | 1394860 | 2021-03-08 20:48:28 -0800 | [diff] [blame] | 624 | test->mFlinger.mutableHwcDisplayData().try_emplace(displayId); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 625 | |
| 626 | return compositionDisplay; |
| 627 | } |
| 628 | |
| 629 | static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { |
| 630 | Base::setupNativeWindowSurfaceCreationCallExpectations(test); |
| 631 | EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1); |
| 632 | } |
| 633 | |
| 634 | static void setupHwcVirtualDisplayCreationCallExpectations(DisplayTransactionTest* test) { |
Dominik Laskowski | 263eec4 | 2021-07-21 23:13:24 -0700 | [diff] [blame] | 635 | EXPECT_CALL(*test->mComposer, createVirtualDisplay(Base::WIDTH, Base::HEIGHT, _, _)) |
| 636 | .WillOnce(DoAll(SetArgPointee<3>(Self::HWC_DISPLAY_ID), Return(Error::NONE))); |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 637 | EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE)); |
| 638 | } |
| 639 | }; |
| 640 | |
| 641 | // For this variant, the display is not a HWC display, so no HDR support should |
| 642 | // be configured. |
| 643 | struct NonHwcDisplayHdrSupportVariant { |
| 644 | static constexpr bool HDR10_PLUS_SUPPORTED = false; |
| 645 | static constexpr bool HDR10_SUPPORTED = false; |
| 646 | static constexpr bool HDR_HLG_SUPPORTED = false; |
| 647 | static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false; |
| 648 | static void setupComposerCallExpectations(DisplayTransactionTest* test) { |
| 649 | EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)).Times(0); |
| 650 | } |
| 651 | }; |
| 652 | |
| 653 | // For this variant, the composer should respond with am empty list of HDR |
| 654 | // modes, so no HDR support should be configured. |
| 655 | template <typename Display> |
| 656 | struct HdrNotSupportedVariant { |
| 657 | static constexpr bool HDR10_PLUS_SUPPORTED = false; |
| 658 | static constexpr bool HDR10_SUPPORTED = false; |
| 659 | static constexpr bool HDR_HLG_SUPPORTED = false; |
| 660 | static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false; |
| 661 | static void setupComposerCallExpectations(DisplayTransactionTest* test) { |
| 662 | EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _)) |
| 663 | .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hdr>()), Return(Error::NONE))); |
| 664 | } |
| 665 | }; |
| 666 | |
| 667 | struct NonHwcPerFrameMetadataSupportVariant { |
| 668 | static constexpr int PER_FRAME_METADATA_KEYS = 0; |
| 669 | static void setupComposerCallExpectations(DisplayTransactionTest* test) { |
| 670 | EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(_)).Times(0); |
| 671 | } |
| 672 | }; |
| 673 | |
| 674 | template <typename Display> |
| 675 | struct NoPerFrameMetadataSupportVariant { |
| 676 | static constexpr int PER_FRAME_METADATA_KEYS = 0; |
| 677 | static void setupComposerCallExpectations(DisplayTransactionTest* test) { |
| 678 | EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) |
| 679 | .WillOnce(Return(std::vector<PerFrameMetadataKey>())); |
| 680 | } |
| 681 | }; |
| 682 | |
| 683 | // For this variant, SurfaceFlinger should configure itself with wide display |
| 684 | // support, but the display should respond with an empty list of supported color |
| 685 | // modes. Wide-color support for the display should not be configured. |
| 686 | template <typename Display> |
| 687 | struct WideColorNotSupportedVariant { |
| 688 | static constexpr bool WIDE_COLOR_SUPPORTED = false; |
| 689 | |
| 690 | static void injectConfigChange(DisplayTransactionTest* test) { |
Lloyd Pique | 30db640 | 2023-06-26 18:56:51 +0000 | [diff] [blame] | 691 | test->mFlinger.mutableSupportsWideColor() = true; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 692 | } |
| 693 | |
| 694 | static void setupComposerCallExpectations(DisplayTransactionTest* test) { |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 695 | EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0); |
| 696 | } |
| 697 | }; |
| 698 | |
| 699 | // For this variant, SurfaceFlinger should not configure itself with wide |
| 700 | // display support, so the display should not be configured for wide-color |
| 701 | // support. |
| 702 | struct WideColorSupportNotConfiguredVariant { |
| 703 | static constexpr bool WIDE_COLOR_SUPPORTED = false; |
| 704 | |
| 705 | static void injectConfigChange(DisplayTransactionTest* test) { |
Lloyd Pique | 30db640 | 2023-06-26 18:56:51 +0000 | [diff] [blame] | 706 | test->mFlinger.mutableSupportsWideColor() = false; |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 707 | test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; |
| 708 | } |
| 709 | |
| 710 | static void setupComposerCallExpectations(DisplayTransactionTest* test) { |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 711 | EXPECT_CALL(*test->mComposer, getRenderIntents(_, _, _)).Times(0); |
| 712 | EXPECT_CALL(*test->mComposer, setColorMode(_, _, _)).Times(0); |
| 713 | } |
| 714 | }; |
| 715 | |
| 716 | /* ------------------------------------------------------------------------ |
| 717 | * Typical display configurations to test |
| 718 | */ |
| 719 | |
| 720 | template <typename DisplayPolicy, typename WideColorSupportPolicy, typename HdrSupportPolicy, |
| 721 | typename PerFrameMetadataSupportPolicy> |
| 722 | struct Case { |
| 723 | using Display = DisplayPolicy; |
| 724 | using WideColorSupport = WideColorSupportPolicy; |
| 725 | using HdrSupport = HdrSupportPolicy; |
| 726 | using PerFrameMetadataSupport = PerFrameMetadataSupportPolicy; |
| 727 | }; |
| 728 | |
| 729 | using SimplePrimaryDisplayCase = |
| 730 | Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>, |
| 731 | HdrNotSupportedVariant<PrimaryDisplayVariant>, |
| 732 | NoPerFrameMetadataSupportVariant<PrimaryDisplayVariant>>; |
| 733 | using SimpleExternalDisplayCase = |
| 734 | Case<ExternalDisplayVariant, WideColorNotSupportedVariant<ExternalDisplayVariant>, |
| 735 | HdrNotSupportedVariant<ExternalDisplayVariant>, |
| 736 | NoPerFrameMetadataSupportVariant<ExternalDisplayVariant>>; |
| 737 | using SimpleTertiaryDisplayCase = |
| 738 | Case<TertiaryDisplayVariant, WideColorNotSupportedVariant<TertiaryDisplayVariant>, |
| 739 | HdrNotSupportedVariant<TertiaryDisplayVariant>, |
| 740 | NoPerFrameMetadataSupportVariant<TertiaryDisplayVariant>>; |
| 741 | |
| 742 | using NonHwcVirtualDisplayCase = |
| 743 | Case<NonHwcVirtualDisplayVariant<1024, 768, Secure::FALSE>, |
| 744 | WideColorSupportNotConfiguredVariant, NonHwcDisplayHdrSupportVariant, |
| 745 | NonHwcPerFrameMetadataSupportVariant>; |
| 746 | using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>; |
| 747 | using HwcVirtualDisplayCase = |
| 748 | Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant, |
| 749 | HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>, |
| 750 | NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>; |
| 751 | |
Dominik Laskowski | b0054a2 | 2022-03-03 09:03:06 -0800 | [diff] [blame] | 752 | inline DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0, |
| 753 | ui::Size resolution = ui::Size(1920, 1080)) { |
| 754 | return mock::createDisplayMode(modeId, refreshRate, group, resolution, |
| 755 | PrimaryDisplayVariant::DISPLAY_ID::get()); |
| 756 | } |
| 757 | |
Marin Shalamanov | 07b1ff3 | 2020-10-07 16:57:22 +0200 | [diff] [blame] | 758 | } // namespace android |
| 759 | |
| 760 | // TODO(b/129481165): remove the #pragma below and fix conversion issues |
Marin Shalamanov | bed7fd3 | 2020-12-21 20:02:20 +0100 | [diff] [blame] | 761 | #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" |