/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #include "DisplayHardware/DisplayMode.h" #include "DisplayTransactionTestHelpers.h" namespace android { namespace { using hal::RenderIntent; // For this variant, SurfaceFlinger should configure itself with wide display // support, and the display should respond with an non-empty list of supported // color modes. Wide-color support should be configured. template struct WideColorP3ColorimetricSupportedVariant { static constexpr bool WIDE_COLOR_SUPPORTED = true; static void injectConfigChange(DisplayTransactionTest* test) { test->mFlinger.mutableUseColorManagement() = true; test->mFlinger.mutableHasWideColorDisplay() = true; test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_DATASPACE)).Times(1); EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _)) .WillOnce(DoAll(SetArgPointee<1>(std::vector({ColorMode::DISPLAY_P3})), Return(Error::NONE))); EXPECT_CALL(*test->mComposer, getRenderIntents(Display::HWC_DISPLAY_ID, ColorMode::DISPLAY_P3, _)) .WillOnce(DoAll(SetArgPointee<2>( std::vector({RenderIntent::COLORIMETRIC})), Return(Error::NONE))); EXPECT_CALL(*test->mComposer, setColorMode(Display::HWC_DISPLAY_ID, ColorMode::SRGB, RenderIntent::COLORIMETRIC)) .WillOnce(Return(Error::NONE)); } }; template struct Hdr10PlusSupportedVariant { static constexpr bool HDR10_PLUS_SUPPORTED = true; static constexpr bool HDR10_SUPPORTED = true; static constexpr bool HDR_HLG_SUPPORTED = false; static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getHdrCapabilities(_, _, _, _, _)) .WillOnce(DoAll(SetArgPointee<1>(std::vector({ Hdr::HDR10_PLUS, Hdr::HDR10, })), Return(Error::NONE))); } }; // For this variant, the composer should respond with a non-empty list of HDR // modes containing HDR10, so HDR10 support should be configured. template struct Hdr10SupportedVariant { static constexpr bool HDR10_PLUS_SUPPORTED = false; static constexpr bool HDR10_SUPPORTED = true; static constexpr bool HDR_HLG_SUPPORTED = false; static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _)) .WillOnce(DoAll(SetArgPointee<1>(std::vector({Hdr::HDR10})), Return(Error::NONE))); } }; // For this variant, the composer should respond with a non-empty list of HDR // modes containing HLG, so HLG support should be configured. template struct HdrHlgSupportedVariant { static constexpr bool HDR10_PLUS_SUPPORTED = false; static constexpr bool HDR10_SUPPORTED = false; static constexpr bool HDR_HLG_SUPPORTED = true; static constexpr bool HDR_DOLBY_VISION_SUPPORTED = false; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _)) .WillOnce( DoAll(SetArgPointee<1>(std::vector({Hdr::HLG})), Return(Error::NONE))); } }; // For this variant, the composer should respond with a non-empty list of HDR // modes containing DOLBY_VISION, so DOLBY_VISION support should be configured. template struct HdrDolbyVisionSupportedVariant { static constexpr bool HDR10_PLUS_SUPPORTED = false; static constexpr bool HDR10_SUPPORTED = false; static constexpr bool HDR_HLG_SUPPORTED = false; static constexpr bool HDR_DOLBY_VISION_SUPPORTED = true; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getHdrCapabilities(Display::HWC_DISPLAY_ID, _, _, _, _)) .WillOnce(DoAll(SetArgPointee<1>(std::vector({Hdr::DOLBY_VISION})), Return(Error::NONE))); } }; template struct Smpte2086PerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::SMPTE2086; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) .WillOnce(Return(std::vector({ PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, PerFrameMetadataKey::WHITE_POINT_X, PerFrameMetadataKey::WHITE_POINT_Y, PerFrameMetadataKey::MAX_LUMINANCE, PerFrameMetadataKey::MIN_LUMINANCE, }))); } }; template struct Cta861_3_PerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::CTA861_3; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) .WillOnce(Return(std::vector({ PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, }))); } }; template struct Hdr10_Plus_PerFrameMetadataSupportVariant { static constexpr int PER_FRAME_METADATA_KEYS = HdrMetadata::Type::HDR10PLUS; static void setupComposerCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getPerFrameMetadataKeys(Display::HWC_DISPLAY_ID)) .WillOnce(Return(std::vector({ PerFrameMetadataKey::HDR10_PLUS_SEI, }))); } }; using WideColorP3ColorimetricDisplayCase = Case, HdrNotSupportedVariant, NoPerFrameMetadataSupportVariant>; using Hdr10PlusDisplayCase = Case, Hdr10SupportedVariant, Hdr10_Plus_PerFrameMetadataSupportVariant>; using Hdr10DisplayCase = Case, Hdr10SupportedVariant, NoPerFrameMetadataSupportVariant>; using HdrHlgDisplayCase = Case, HdrHlgSupportedVariant, NoPerFrameMetadataSupportVariant>; using HdrDolbyVisionDisplayCase = Case, HdrDolbyVisionSupportedVariant, NoPerFrameMetadataSupportVariant>; using HdrSmpte2086DisplayCase = Case, HdrNotSupportedVariant, Smpte2086PerFrameMetadataSupportVariant>; using HdrCta861_3_DisplayCase = Case, HdrNotSupportedVariant, Cta861_3_PerFrameMetadataSupportVariant>; class SetupNewDisplayDeviceInternalTest : public DisplayTransactionTest { public: template void setupNewDisplayDeviceInternalTest(); }; template void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { const sp displayToken = new BBinder(); const sp displaySurface = new compositionengine::mock::DisplaySurface(); const sp producer = new mock::GraphicBufferProducer(); // -------------------------------------------------------------------- // Preconditions // Wide color displays support is configured appropriately Case::WideColorSupport::injectConfigChange(this); // The display is setup with the HWC. Case::Display::injectHwcDisplay(this); // SurfaceFlinger will use a test-controlled factory for native window // surfaces. injectFakeNativeWindowSurfaceFactory(); // A compositionengine::Display has already been created auto compositionDisplay = Case::Display::injectCompositionDisplay(this); // -------------------------------------------------------------------- // Call Expectations // Various native window calls will be made. Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this); Case::Display::setupHwcGetActiveConfigCallExpectations(this); Case::Display::setupHwcGetConfigsCallExpectations(this); Case::WideColorSupport::setupComposerCallExpectations(this); Case::HdrSupport::setupComposerCallExpectations(this); Case::PerFrameMetadataSupport::setupComposerCallExpectations(this); // -------------------------------------------------------------------- // Invocation DisplayDeviceState state; if constexpr (constexpr auto connectionType = Case::Display::CONNECTION_TYPE::value) { const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get()); ASSERT_TRUE(displayId); const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value; ASSERT_TRUE(hwcDisplayId); mFlinger.getHwComposer().allocatePhysicalDisplay(*hwcDisplayId, *displayId); DisplayModePtr activeMode = DisplayMode::Builder(Case::Display::HWC_ACTIVE_CONFIG_ID) .setWidth(Case::Display::WIDTH) .setHeight(Case::Display::HEIGHT) .setVsyncPeriod(DEFAULT_VSYNC_PERIOD) .setDpiX(DEFAULT_DPI) .setDpiY(DEFAULT_DPI) .setGroup(0) .build(); DisplayModes modes{activeMode}; state.physical = {.id = *displayId, .type = *connectionType, .hwcDisplayId = *hwcDisplayId, .supportedModes = modes, .activeMode = activeMode}; } state.isSecure = static_cast(Case::Display::SECURE); auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, displaySurface, producer); // -------------------------------------------------------------------- // Postconditions ASSERT_TRUE(device != nullptr); EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId()); EXPECT_EQ(Case::Display::CONNECTION_TYPE::value, device->getConnectionType()); EXPECT_EQ(static_cast(Case::Display::VIRTUAL), device->isVirtual()); EXPECT_EQ(static_cast(Case::Display::SECURE), device->isSecure()); EXPECT_EQ(static_cast(Case::Display::PRIMARY), device->isPrimary()); EXPECT_EQ(Case::Display::WIDTH, device->getWidth()); EXPECT_EQ(Case::Display::HEIGHT, device->getHeight()); EXPECT_EQ(Case::WideColorSupport::WIDE_COLOR_SUPPORTED, device->hasWideColorGamut()); EXPECT_EQ(Case::HdrSupport::HDR10_PLUS_SUPPORTED, device->hasHDR10PlusSupport()); EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support()); EXPECT_EQ(Case::HdrSupport::HDR_HLG_SUPPORTED, device->hasHLGSupport()); EXPECT_EQ(Case::HdrSupport::HDR_DOLBY_VISION_SUPPORTED, device->hasDolbyVisionSupport()); EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS, device->getSupportedPerFrameMetadata()); if constexpr (Case::Display::CONNECTION_TYPE::value) { EXPECT_EQ(1, device->getSupportedModes().size()); EXPECT_NE(nullptr, device->getActiveMode()); EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveMode()->getHwcId()); } } TEST_F(SetupNewDisplayDeviceInternalTest, createSimplePrimaryDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createSimpleExternalDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10PlusDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10Display) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHdrHlgDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHdrDolbyVisionDisplay) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHdrSmpte2086DisplayCase) { setupNewDisplayDeviceInternalTest(); } TEST_F(SetupNewDisplayDeviceInternalTest, createHdrCta816_3_DisplayCase) { setupNewDisplayDeviceInternalTest(); } } // namespace } // namespace android