diff options
15 files changed, 772 insertions, 360 deletions
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 27922900cf..fda451bd9e 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -104,6 +104,7 @@ cc_test { static_libs: [ "libcompositionengine", "libcompositionengine_mocks", + "libgui_mocks", "librenderengine_mocks", "libgmock", "libgtest", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index ced4227b44..6bc677d432 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -18,6 +18,11 @@ #include <cstdint> #include <optional> +#include <string> + +#include <ui/DisplayInfo.h> +#include <ui/PixelFormat.h> +#include <ui/Size.h> #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/PowerAdvisor.h" @@ -30,47 +35,86 @@ class CompositionEngine; * A parameter object for creating Display instances */ struct DisplayCreationArgs { - // True if this display is a virtual display - bool isVirtual = false; + struct Physical { + DisplayId id; + DisplayConnectionType type; + }; + + // Required for physical displays. Gives the HWC display id for the existing + // display along with the connection type. + std::optional<Physical> physical; + + // Size of the display in pixels + ui::Size pixels = ui::Size::INVALID; + + // Pixel format of the display + ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN); - // Identifies the display to the HWC, if composition is supported by it - std::optional<DisplayId> displayId; + // True if virtual displays should be created with the HWC API if possible + bool useHwcVirtualDisplays = false; + + // True if this display should be considered secure + bool isSecure = false; + + // Gives the initial layer stack id to be used for the display + uint32_t layerStackId = ~0u; // Optional pointer to the power advisor interface, if one is needed for // this display. Hwc2::PowerAdvisor* powerAdvisor = nullptr; + + // Debugging. Human readable name for the display. + std::string name; }; /** * A helper for setting up a DisplayCreationArgs value in-line. * Prefer this builder over raw structure initialization. - * - * Instead of: - * - * DisplayCreationArgs{false, false, displayId} - * - * Prefer: - * - * DisplayCreationArgsBuilder().setIsVirtual(false) - * .setDisplayId(displayId).build(); */ class DisplayCreationArgsBuilder { public: DisplayCreationArgs build() { return std::move(mArgs); } - DisplayCreationArgsBuilder& setIsVirtual(bool isVirtual) { - mArgs.isVirtual = isVirtual; + DisplayCreationArgsBuilder& setPhysical(DisplayCreationArgs::Physical physical) { + mArgs.physical = physical; + return *this; + } + + DisplayCreationArgsBuilder& setPixels(ui::Size pixels) { + mArgs.pixels = pixels; return *this; } - DisplayCreationArgsBuilder& setDisplayId(std::optional<DisplayId> displayId) { - mArgs.displayId = displayId; + + DisplayCreationArgsBuilder& setPixelFormat(ui::PixelFormat pixelFormat) { + mArgs.pixelFormat = pixelFormat; + return *this; + } + + DisplayCreationArgsBuilder& setUseHwcVirtualDisplays(bool useHwcVirtualDisplays) { + mArgs.useHwcVirtualDisplays = useHwcVirtualDisplays; + return *this; + } + + DisplayCreationArgsBuilder& setIsSecure(bool isSecure) { + mArgs.isSecure = isSecure; return *this; } + + DisplayCreationArgsBuilder& setLayerStackId(uint32_t layerStackId) { + mArgs.layerStackId = layerStackId; + return *this; + } + DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) { mArgs.powerAdvisor = powerAdvisor; return *this; } + DisplayCreationArgsBuilder& setName(std::string name) { + mArgs.name = std::move(name); + return *this; + } + private: DisplayCreationArgs mArgs; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index fb597ce1ff..9ca7d2f9fb 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -16,11 +16,15 @@ #pragma once +#include <memory> + #include <compositionengine/Display.h> +#include <compositionengine/DisplayColorProfile.h> #include <compositionengine/DisplayCreationArgs.h> +#include <compositionengine/RenderSurface.h> #include <compositionengine/impl/Output.h> - -#include <memory> +#include <ui/PixelFormat.h> +#include <ui/Size.h> #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/HWComposer.h" @@ -36,11 +40,11 @@ namespace impl { // actually contain the final display state. class Display : public compositionengine::impl::Output, public virtual compositionengine::Display { public: - explicit Display(const compositionengine::DisplayCreationArgs&); virtual ~Display(); // compositionengine::Output overrides std::optional<DisplayId> getDisplayId() const override; + bool isValid() const override; void dump(std::string&) const override; using compositionengine::impl::Output::setReleasedLayers; void setReleasedLayers(const CompositionRefreshArgs&) override; @@ -73,22 +77,33 @@ public: virtual void applyLayerRequestsToLayers(const LayerRequests&); // Internal + virtual void setConfiguration(const compositionengine::DisplayCreationArgs&); + virtual std::optional<DisplayId> maybeAllocateDisplayIdForVirtualDisplay(ui::Size, + ui::PixelFormat) const; std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const; + // Testing + void setDisplayIdForTesting(std::optional<DisplayId> displayId); + private: - const bool mIsVirtual; + bool mIsVirtual = false; std::optional<DisplayId> mId; - Hwc2::PowerAdvisor* const mPowerAdvisor{nullptr}; + Hwc2::PowerAdvisor* mPowerAdvisor = nullptr; }; // This template factory function standardizes the implementation details of the // final class using the types actually required by the implementation. This is // not possible to do in the base class as those types may not even be visible // to the base code. -template <typename BaseDisplay, typename CompositionEngine, typename DisplayCreationArgs> -std::shared_ptr<BaseDisplay> createDisplayTemplated(const CompositionEngine& compositionEngine, - const DisplayCreationArgs& args) { - return createOutputTemplated<BaseDisplay>(compositionEngine, args); +template <typename BaseDisplay, typename CompositionEngine> +std::shared_ptr<BaseDisplay> createDisplayTemplated( + const CompositionEngine& compositionEngine, + const compositionengine::DisplayCreationArgs& args) { + auto display = createOutputTemplated<BaseDisplay>(compositionEngine); + + display->setConfiguration(args); + + return display; } std::shared_ptr<Display> createDisplay(const compositionengine::CompositionEngine&, diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 1d8a23f460..c3454059aa 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -47,11 +47,36 @@ std::shared_ptr<Display> createDisplay( return createDisplayTemplated<Display>(compositionEngine, args); } -Display::Display(const DisplayCreationArgs& args) - : mIsVirtual(args.isVirtual), mId(args.displayId), mPowerAdvisor(args.powerAdvisor) {} - Display::~Display() = default; +void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) { + mIsVirtual = !args.physical; + mId = args.physical ? std::make_optional(args.physical->id) : std::nullopt; + mPowerAdvisor = args.powerAdvisor; + + editState().isSecure = args.isSecure; + + setLayerStackFilter(args.layerStackId, + args.physical ? args.physical->type == DisplayConnectionType::Internal + : false); + setName(args.name); + + if (!args.physical && args.useHwcVirtualDisplays) { + mId = maybeAllocateDisplayIdForVirtualDisplay(args.pixels, args.pixelFormat); + } +} + +std::optional<DisplayId> Display::maybeAllocateDisplayIdForVirtualDisplay( + ui::Size pixels, ui::PixelFormat pixelFormat) const { + auto& hwc = getCompositionEngine().getHwComposer(); + return hwc.allocateVirtualDisplay(static_cast<uint32_t>(pixels.width), + static_cast<uint32_t>(pixels.height), &pixelFormat); +} + +bool Display::isValid() const { + return Output::isValid() && mPowerAdvisor; +} + const std::optional<DisplayId>& Display::getId() const { return mId; } @@ -68,6 +93,10 @@ std::optional<DisplayId> Display::getDisplayId() const { return mId; } +void Display::setDisplayIdForTesting(std::optional<DisplayId> displayId) { + mId = displayId; +} + void Display::disconnect() { if (!mId) { return; diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 16f7a4ef46..88f2686aca 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -30,6 +30,8 @@ #include <compositionengine/mock/OutputLayer.h> #include <compositionengine/mock/RenderSurface.h> #include <gtest/gtest.h> +#include <ui/DisplayInfo.h> +#include <ui/Rect.h> #include "MockHWC2.h" #include "MockHWComposer.h" @@ -40,8 +42,11 @@ namespace { using testing::_; using testing::DoAll; +using testing::Eq; using testing::InSequence; using testing::NiceMock; +using testing::Pointee; +using testing::Ref; using testing::Return; using testing::ReturnRef; using testing::Sequence; @@ -49,8 +54,10 @@ using testing::SetArgPointee; using testing::StrictMock; constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42}; +constexpr DisplayId VIRTUAL_DISPLAY_ID = DisplayId{43}; constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920; constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080; +constexpr int32_t DEFAULT_LAYER_STACK = 123; struct Layer { Layer() { @@ -73,25 +80,126 @@ struct LayerNoHWC2Layer { StrictMock<mock::OutputLayer>* outputLayer = new StrictMock<mock::OutputLayer>(); }; -struct DisplayTest : public testing::Test { - class Display : public impl::Display { +struct DisplayTestCommon : public testing::Test { + // Uses the full implementation of a display + class FullImplDisplay : public impl::Display { public: - explicit Display(const compositionengine::DisplayCreationArgs& args) - : impl::Display(args) {} - using impl::Display::injectOutputLayerForTest; virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0; + + using impl::Display::maybeAllocateDisplayIdForVirtualDisplay; + }; + + // Uses a special implementation with key internal member functions set up + // as mock implementations, to allow for easier testing. + struct PartialMockDisplay : public impl::Display { + PartialMockDisplay(const compositionengine::CompositionEngine& compositionEngine) + : mCompositionEngine(compositionEngine) {} + + // compositionengine::Output overrides + const OutputCompositionState& getState() const override { return mState; } + OutputCompositionState& editState() override { return mState; } + + // compositionengine::impl::Output overrides + const CompositionEngine& getCompositionEngine() const override { + return mCompositionEngine; + }; + + // Mock implementation overrides + MOCK_CONST_METHOD0(getOutputLayerCount, size_t()); + MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, + compositionengine::OutputLayer*(size_t)); + MOCK_METHOD2(ensureOutputLayer, + compositionengine::OutputLayer*(std::optional<size_t>, const sp<LayerFE>&)); + MOCK_METHOD0(finalizePendingOutputLayers, void()); + MOCK_METHOD0(clearOutputLayers, void()); + MOCK_CONST_METHOD1(dumpState, void(std::string&)); + MOCK_METHOD1(injectOutputLayerForTest, compositionengine::OutputLayer*(const sp<LayerFE>&)); + MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>)); + MOCK_CONST_METHOD0(anyLayersRequireClientComposition, bool()); + MOCK_CONST_METHOD0(allLayersRequireClientComposition, bool()); + MOCK_METHOD1(applyChangedTypesToLayers, void(const impl::Display::ChangedTypes&)); + MOCK_METHOD1(applyDisplayRequests, void(const impl::Display::DisplayRequests&)); + MOCK_METHOD1(applyLayerRequestsToLayers, void(const impl::Display::LayerRequests&)); + + const compositionengine::CompositionEngine& mCompositionEngine; + impl::OutputCompositionState mState; }; + static std::string getDisplayNameFromCurrentTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + return std::string("display for ") + test_info->test_case_name() + "." + test_info->name(); + } + + template <typename Display> static std::shared_ptr<Display> createDisplay( const compositionengine::CompositionEngine& compositionEngine, - compositionengine::DisplayCreationArgs&& args) { + compositionengine::DisplayCreationArgs args) { + args.name = getDisplayNameFromCurrentTest(); return impl::createDisplayTemplated<Display>(compositionEngine, args); } - DisplayTest() { + template <typename Display> + static std::shared_ptr<StrictMock<Display>> createPartialMockDisplay( + const compositionengine::CompositionEngine& compositionEngine, + compositionengine::DisplayCreationArgs args) { + args.name = getDisplayNameFromCurrentTest(); + auto display = std::make_shared<StrictMock<Display>>(compositionEngine); + + display->setConfiguration(args); + + return display; + } + + DisplayTestCommon() { EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); + } + + DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { + return DisplayCreationArgsBuilder() + .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(true) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .build(); + } + DisplayCreationArgs getDisplayCreationArgsForNonHWCVirtualDisplay() { + return DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(false) + .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(false) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .build(); + } + + StrictMock<android::mock::HWComposer> mHwComposer; + StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; + StrictMock<mock::CompositionEngine> mCompositionEngine; + sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); +}; + +struct PartialMockDisplayTestCommon : public DisplayTestCommon { + using Display = DisplayTestCommon::PartialMockDisplay; + std::shared_ptr<Display> mDisplay = + createPartialMockDisplay<Display>(mCompositionEngine, + getDisplayCreationArgsForPhysicalHWCDisplay()); +}; + +struct FullDisplayImplTestCommon : public DisplayTestCommon { + using Display = DisplayTestCommon::FullImplDisplay; + std::shared_ptr<Display> mDisplay = + createDisplay<Display>(mCompositionEngine, + getDisplayCreationArgsForPhysicalHWCDisplay()); +}; + +struct DisplayWithLayersTestCommon : public FullDisplayImplTestCommon { + DisplayWithLayersTestCommon() { mDisplay->injectOutputLayerForTest( std::unique_ptr<compositionengine::OutputLayer>(mLayer1.outputLayer)); mDisplay->injectOutputLayerForTest( @@ -100,65 +208,166 @@ struct DisplayTest : public testing::Test { std::unique_ptr<compositionengine::OutputLayer>(mLayer3.outputLayer)); } - StrictMock<android::mock::HWComposer> mHwComposer; - StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor; - StrictMock<mock::CompositionEngine> mCompositionEngine; - sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>(); Layer mLayer1; Layer mLayer2; LayerNoHWC2Layer mLayer3; StrictMock<HWC2::mock::Layer> hwc2LayerUnknown; - - std::shared_ptr<Display> mDisplay = createDisplay(mCompositionEngine, - DisplayCreationArgsBuilder() - .setDisplayId(DEFAULT_DISPLAY_ID) - .setPowerAdvisor(&mPowerAdvisor) - .build()); + std::shared_ptr<Display> mDisplay = + createDisplay<Display>(mCompositionEngine, + getDisplayCreationArgsForPhysicalHWCDisplay()); }; /* * Basic construction */ -TEST_F(DisplayTest, canInstantiateDisplay) { - { - constexpr DisplayId display1 = DisplayId{123u}; - auto display = - impl::createDisplay(mCompositionEngine, - DisplayCreationArgsBuilder().setDisplayId(display1).build()); - EXPECT_FALSE(display->isSecure()); - EXPECT_FALSE(display->isVirtual()); - EXPECT_EQ(display1, display->getId()); - } +struct DisplayCreationTest : public DisplayTestCommon { + using Display = DisplayTestCommon::FullImplDisplay; +}; - { - constexpr DisplayId display2 = DisplayId{546u}; - auto display = - impl::createDisplay(mCompositionEngine, - DisplayCreationArgsBuilder().setDisplayId(display2).build()); - EXPECT_FALSE(display->isSecure()); - EXPECT_FALSE(display->isVirtual()); - EXPECT_EQ(display2, display->getId()); - } +TEST_F(DisplayCreationTest, createPhysicalInternalDisplay) { + auto display = + impl::createDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalHWCDisplay()); + EXPECT_TRUE(display->isSecure()); + EXPECT_FALSE(display->isVirtual()); + EXPECT_EQ(DEFAULT_DISPLAY_ID, display->getId()); +} - { - constexpr DisplayId display3 = DisplayId{789u}; - auto display = impl::createDisplay(mCompositionEngine, - DisplayCreationArgsBuilder() - .setIsVirtual(true) - .setDisplayId(display3) - .build()); - EXPECT_FALSE(display->isSecure()); - EXPECT_TRUE(display->isVirtual()); - EXPECT_EQ(display3, display->getId()); - } +TEST_F(DisplayCreationTest, createNonHwcVirtualDisplay) { + auto display = impl::createDisplay(mCompositionEngine, + getDisplayCreationArgsForNonHWCVirtualDisplay()); + EXPECT_FALSE(display->isSecure()); + EXPECT_TRUE(display->isVirtual()); + EXPECT_EQ(std::nullopt, display->getId()); +} + +/* + * Display::setConfiguration() + */ + +using DisplaySetConfigurationTest = PartialMockDisplayTestCommon; + +TEST_F(DisplaySetConfigurationTest, configuresInternalSecurePhysicalDisplay) { + mDisplay->setConfiguration( + DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(true) + .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(true) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .setName(getDisplayNameFromCurrentTest()) + .build()); + + EXPECT_EQ(DEFAULT_DISPLAY_ID, mDisplay->getId()); + EXPECT_TRUE(mDisplay->isSecure()); + EXPECT_FALSE(mDisplay->isVirtual()); + EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId); + EXPECT_TRUE(mDisplay->getState().layerStackInternal); + EXPECT_FALSE(mDisplay->isValid()); +} + +TEST_F(DisplaySetConfigurationTest, configuresExternalInsecurePhysicalDisplay) { + mDisplay->setConfiguration( + DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(true) + .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::External}) + .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(false) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .setName(getDisplayNameFromCurrentTest()) + .build()); + + EXPECT_EQ(DEFAULT_DISPLAY_ID, mDisplay->getId()); + EXPECT_FALSE(mDisplay->isSecure()); + EXPECT_FALSE(mDisplay->isVirtual()); + EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId); + EXPECT_FALSE(mDisplay->getState().layerStackInternal); + EXPECT_FALSE(mDisplay->isValid()); +} + +TEST_F(DisplaySetConfigurationTest, configuresHwcBackedVirtualDisplay) { + EXPECT_CALL(mHwComposer, + allocateVirtualDisplay(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH, + Pointee(Eq(static_cast<ui::PixelFormat>( + PIXEL_FORMAT_RGBA_8888))))) + .WillOnce(Return(VIRTUAL_DISPLAY_ID)); + + mDisplay->setConfiguration( + DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(true) + .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(false) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .setName(getDisplayNameFromCurrentTest()) + .build()); + + EXPECT_EQ(VIRTUAL_DISPLAY_ID, mDisplay->getId()); + EXPECT_FALSE(mDisplay->isSecure()); + EXPECT_TRUE(mDisplay->isVirtual()); + EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId); + EXPECT_FALSE(mDisplay->getState().layerStackInternal); + EXPECT_FALSE(mDisplay->isValid()); +} + +TEST_F(DisplaySetConfigurationTest, configuresNonHwcBackedVirtualDisplayIfHwcAllocationFails) { + EXPECT_CALL(mHwComposer, + allocateVirtualDisplay(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH, + Pointee(Eq(static_cast<ui::PixelFormat>( + PIXEL_FORMAT_RGBA_8888))))) + .WillOnce(Return(std::nullopt)); + + mDisplay->setConfiguration( + DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(true) + .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(false) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .setName(getDisplayNameFromCurrentTest()) + .build()); + + EXPECT_EQ(std::nullopt, mDisplay->getId()); + EXPECT_FALSE(mDisplay->isSecure()); + EXPECT_TRUE(mDisplay->isVirtual()); + EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId); + EXPECT_FALSE(mDisplay->getState().layerStackInternal); + EXPECT_FALSE(mDisplay->isValid()); +} + +TEST_F(DisplaySetConfigurationTest, configuresNonHwcBackedVirtualDisplayIfShouldNotUseHwc) { + mDisplay->setConfiguration( + DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(false) + .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(false) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .setName(getDisplayNameFromCurrentTest()) + .build()); + + EXPECT_EQ(std::nullopt, mDisplay->getId()); + EXPECT_FALSE(mDisplay->isSecure()); + EXPECT_TRUE(mDisplay->isVirtual()); + EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId); + EXPECT_FALSE(mDisplay->getState().layerStackInternal); + EXPECT_FALSE(mDisplay->isValid()); } /* * Display::disconnect() */ -TEST_F(DisplayTest, disconnectDisconnectsDisplay) { +using DisplayDisconnectTest = PartialMockDisplayTestCommon; + +TEST_F(DisplayDisconnectTest, disconnectsDisplay) { // The first call to disconnect will disconnect the display with the HWC and // set mHwcId to -1. EXPECT_CALL(mHwComposer, disconnectDisplay(DEFAULT_DISPLAY_ID)).Times(1); @@ -175,7 +384,9 @@ TEST_F(DisplayTest, disconnectDisconnectsDisplay) { * Display::setColorTransform() */ -TEST_F(DisplayTest, setColorTransformSetsTransform) { +using DisplaySetColorTransformTest = PartialMockDisplayTestCommon; + +TEST_F(DisplaySetColorTransformTest, setsTransform) { // No change does nothing CompositionRefreshArgs refreshArgs; refreshArgs.colorTransformMatrix = std::nullopt; @@ -202,7 +413,9 @@ TEST_F(DisplayTest, setColorTransformSetsTransform) { * Display::setColorMode() */ -TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { +using DisplaySetColorModeTest = PartialMockDisplayTestCommon; + +TEST_F(DisplaySetColorModeTest, setsModeUnlessNoChange) { using ColorProfile = Output::ColorProfile; mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); @@ -245,11 +458,11 @@ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay->getState().targetDataspace); } -TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) { +TEST_F(DisplaySetColorModeTest, doesNothingForVirtualDisplay) { using ColorProfile = Output::ColorProfile; - std::shared_ptr<impl::Display> virtualDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgs{true, DEFAULT_DISPLAY_ID})}; + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + std::shared_ptr<impl::Display> virtualDisplay = impl::createDisplay(mCompositionEngine, args); mock::DisplayColorProfile* colorProfile = new StrictMock<mock::DisplayColorProfile>(); virtualDisplay->setDisplayColorProfileForTest( @@ -274,7 +487,9 @@ TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) { * Display::createDisplayColorProfile() */ -TEST_F(DisplayTest, createDisplayColorProfileSetsDisplayColorProfile) { +using DisplayCreateColorProfileTest = PartialMockDisplayTestCommon; + +TEST_F(DisplayCreateColorProfileTest, setsDisplayColorProfile) { EXPECT_TRUE(mDisplay->getDisplayColorProfile() == nullptr); mDisplay->createDisplayColorProfile( DisplayColorProfileCreationArgs{false, HdrCapabilities(), 0, @@ -286,7 +501,9 @@ TEST_F(DisplayTest, createDisplayColorProfileSetsDisplayColorProfile) { * Display::createRenderSurface() */ -TEST_F(DisplayTest, createRenderSurfaceSetsRenderSurface) { +using DisplayCreateRenderSurfaceTest = PartialMockDisplayTestCommon; + +TEST_F(DisplayCreateRenderSurfaceTest, setsRenderSurface) { EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL)).WillRepeatedly(Return(NO_ERROR)); EXPECT_TRUE(mDisplay->getRenderSurface() == nullptr); mDisplay->createRenderSurface(RenderSurfaceCreationArgs{640, 480, mNativeWindow, nullptr}); @@ -297,7 +514,9 @@ TEST_F(DisplayTest, createRenderSurfaceSetsRenderSurface) { * Display::createOutputLayer() */ -TEST_F(DisplayTest, createOutputLayerSetsHwcLayer) { +using DisplayCreateOutputLayerTest = FullDisplayImplTestCommon; + +TEST_F(DisplayCreateOutputLayerTest, setsHwcLayer) { sp<mock::LayerFE> layerFE = new StrictMock<mock::LayerFE>(); StrictMock<HWC2::mock::Layer> hwcLayer; @@ -315,9 +534,11 @@ TEST_F(DisplayTest, createOutputLayerSetsHwcLayer) { * Display::setReleasedLayers() */ -TEST_F(DisplayTest, setReleasedLayersDoesNothingIfNotHwcDisplay) { - std::shared_ptr<impl::Display> nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; +using DisplaySetReleasedLayersTest = DisplayWithLayersTestCommon; + +TEST_F(DisplaySetReleasedLayersTest, doesNothingIfNotHwcDisplay) { + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + std::shared_ptr<impl::Display> nonHwcDisplay = impl::createDisplay(mCompositionEngine, args); sp<mock::LayerFE> layerXLayerFE = new StrictMock<mock::LayerFE>(); @@ -336,7 +557,7 @@ TEST_F(DisplayTest, setReleasedLayersDoesNothingIfNotHwcDisplay) { ASSERT_EQ(1, releasedLayers.size()); } -TEST_F(DisplayTest, setReleasedLayersDoesNothingIfNoLayersWithQueuedFrames) { +TEST_F(DisplaySetReleasedLayersTest, doesNothingIfNoLayersWithQueuedFrames) { sp<mock::LayerFE> layerXLayerFE = new StrictMock<mock::LayerFE>(); { @@ -352,7 +573,7 @@ TEST_F(DisplayTest, setReleasedLayersDoesNothingIfNoLayersWithQueuedFrames) { ASSERT_EQ(1, releasedLayers.size()); } -TEST_F(DisplayTest, setReleasedLayers) { +TEST_F(DisplaySetReleasedLayersTest, setReleasedLayers) { sp<mock::LayerFE> unknownLayer = new StrictMock<mock::LayerFE>(); CompositionRefreshArgs refreshArgs; @@ -372,59 +593,12 @@ TEST_F(DisplayTest, setReleasedLayers) { * Display::chooseCompositionStrategy() */ -struct DisplayChooseCompositionStrategyTest : public testing::Test { - struct DisplayPartialMock : public impl::Display { - DisplayPartialMock(const compositionengine::CompositionEngine& compositionEngine, - const compositionengine::DisplayCreationArgs& args) - : impl::Display(args), mCompositionEngine(compositionEngine) {} - - // Sets up the helper functions called by chooseCompositionStrategy to - // use a mock implementations. - MOCK_CONST_METHOD0(anyLayersRequireClientComposition, bool()); - MOCK_CONST_METHOD0(allLayersRequireClientComposition, bool()); - MOCK_METHOD1(applyChangedTypesToLayers, void(const impl::Display::ChangedTypes&)); - MOCK_METHOD1(applyDisplayRequests, void(const impl::Display::DisplayRequests&)); - MOCK_METHOD1(applyLayerRequestsToLayers, void(const impl::Display::LayerRequests&)); - - // compositionengine::Output overrides - const OutputCompositionState& getState() const override { return mState; } - OutputCompositionState& editState() override { return mState; } - - // compositionengine::impl::Output overrides - const CompositionEngine& getCompositionEngine() const override { - return mCompositionEngine; - }; - - // These need implementations though are not expected to be called. - MOCK_CONST_METHOD0(getOutputLayerCount, size_t()); - MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, - compositionengine::OutputLayer*(size_t)); - MOCK_METHOD2(ensureOutputLayer, - compositionengine::OutputLayer*(std::optional<size_t>, const sp<LayerFE>&)); - MOCK_METHOD0(finalizePendingOutputLayers, void()); - MOCK_METHOD0(clearOutputLayers, void()); - MOCK_CONST_METHOD1(dumpState, void(std::string&)); - MOCK_METHOD1(injectOutputLayerForTest, compositionengine::OutputLayer*(const sp<LayerFE>&)); - MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>)); - - const compositionengine::CompositionEngine& mCompositionEngine; - impl::OutputCompositionState mState; - }; - - DisplayChooseCompositionStrategyTest() { - EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); - } - - StrictMock<android::mock::HWComposer> mHwComposer; - StrictMock<mock::CompositionEngine> mCompositionEngine; - StrictMock<DisplayPartialMock> - mDisplay{mCompositionEngine, - DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()}; -}; +using DisplayChooseCompositionStrategyTest = PartialMockDisplayTestCommon; TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfNotAHwcDisplay) { - std::shared_ptr<impl::Display> nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + std::shared_ptr<Display> nonHwcDisplay = + createPartialMockDisplay<Display>(mCompositionEngine, args); EXPECT_FALSE(nonHwcDisplay->getId()); nonHwcDisplay->chooseCompositionStrategy(); @@ -435,33 +609,36 @@ TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfNotAHwcDisplay) { } TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutOnHwcError) { - EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()).WillOnce(Return(false)); + EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()).WillOnce(Return(false)); EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(DEFAULT_DISPLAY_ID, false, _)) .WillOnce(Return(INVALID_OPERATION)); - mDisplay.chooseCompositionStrategy(); + mDisplay->chooseCompositionStrategy(); - auto& state = mDisplay.getState(); + auto& state = mDisplay->getState(); EXPECT_TRUE(state.usesClientComposition); EXPECT_FALSE(state.usesDeviceComposition); } TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) { - // Since two calls are made to anyLayersRequireClientComposition with different return values, - // use a Sequence to control the matching so the values are returned in a known order. + // Since two calls are made to anyLayersRequireClientComposition with different return + // values, use a Sequence to control the matching so the values are returned in a known + // order. Sequence s; - EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()).InSequence(s).WillOnce(Return(true)); - EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()) + EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()) + .InSequence(s) + .WillOnce(Return(true)); + EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()) .InSequence(s) .WillOnce(Return(false)); EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(DEFAULT_DISPLAY_ID, true, _)) .WillOnce(Return(NO_ERROR)); - EXPECT_CALL(mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); + EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); - mDisplay.chooseCompositionStrategy(); + mDisplay->chooseCompositionStrategy(); - auto& state = mDisplay.getState(); + auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); EXPECT_TRUE(state.usesDeviceComposition); } @@ -473,24 +650,27 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { {{nullptr, HWC2::LayerRequest::ClearClientTarget}}, }; - // Since two calls are made to anyLayersRequireClientComposition with different return values, - // use a Sequence to control the matching so the values are returned in a known order. + // Since two calls are made to anyLayersRequireClientComposition with different return + // values, use a Sequence to control the matching so the values are returned in a known + // order. Sequence s; - EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()).InSequence(s).WillOnce(Return(true)); - EXPECT_CALL(mDisplay, anyLayersRequireClientComposition()) + EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()) + .InSequence(s) + .WillOnce(Return(true)); + EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()) .InSequence(s) .WillOnce(Return(false)); EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(DEFAULT_DISPLAY_ID, true, _)) .WillOnce(DoAll(SetArgPointee<2>(changes), Return(NO_ERROR))); - EXPECT_CALL(mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1); - EXPECT_CALL(mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1); - EXPECT_CALL(mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1); - EXPECT_CALL(mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); + EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1); + EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1); + EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1); + EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); - mDisplay.chooseCompositionStrategy(); + mDisplay->chooseCompositionStrategy(); - auto& state = mDisplay.getState(); + auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); EXPECT_TRUE(state.usesDeviceComposition); } @@ -499,13 +679,15 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { * Display::getSkipColorTransform() */ -TEST_F(DisplayTest, getSkipColorTransformDoesNothingIfNonHwcDisplay) { - auto nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; +using DisplayGetSkipColorTransformTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayGetSkipColorTransformTest, doesNothingIfNonHwcDisplay) { + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + auto nonHwcDisplay{impl::createDisplay(mCompositionEngine, args)}; EXPECT_FALSE(nonHwcDisplay->getSkipColorTransform()); } -TEST_F(DisplayTest, getSkipColorTransformChecksHwcCapability) { +TEST_F(DisplayGetSkipColorTransformTest, checksHwcCapability) { EXPECT_CALL(mHwComposer, hasDisplayCapability(std::make_optional(DEFAULT_DISPLAY_ID), HWC2::DisplayCapability::SkipClientColorTransform)) @@ -517,7 +699,9 @@ TEST_F(DisplayTest, getSkipColorTransformChecksHwcCapability) { * Display::anyLayersRequireClientComposition() */ -TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsFalse) { +using DisplayAnyLayersRequireClientCompositionTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayAnyLayersRequireClientCompositionTest, returnsFalse) { EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(false)); EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(false)); EXPECT_CALL(*mLayer3.outputLayer, requiresClientComposition()).WillOnce(Return(false)); @@ -525,7 +709,7 @@ TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsFalse) { EXPECT_FALSE(mDisplay->anyLayersRequireClientComposition()); } -TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsTrue) { +TEST_F(DisplayAnyLayersRequireClientCompositionTest, returnsTrue) { EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(false)); EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(true)); @@ -536,7 +720,9 @@ TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsTrue) { * Display::allLayersRequireClientComposition() */ -TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsTrue) { +using DisplayAllLayersRequireClientCompositionTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayAllLayersRequireClientCompositionTest, returnsTrue) { EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(true)); EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(true)); EXPECT_CALL(*mLayer3.outputLayer, requiresClientComposition()).WillOnce(Return(true)); @@ -544,7 +730,7 @@ TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsTrue) { EXPECT_TRUE(mDisplay->allLayersRequireClientComposition()); } -TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsFalse) { +TEST_F(DisplayAllLayersRequireClientCompositionTest, returnsFalse) { EXPECT_CALL(*mLayer1.outputLayer, requiresClientComposition()).WillOnce(Return(true)); EXPECT_CALL(*mLayer2.outputLayer, requiresClientComposition()).WillOnce(Return(false)); @@ -555,11 +741,13 @@ TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsFalse) { * Display::applyChangedTypesToLayers() */ -TEST_F(DisplayTest, applyChangedTypesToLayersTakesEarlyOutIfNoChangedLayers) { +using DisplayApplyChangedTypesToLayersTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayApplyChangedTypesToLayersTest, takesEarlyOutIfNoChangedLayers) { mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes()); } -TEST_F(DisplayTest, applyChangedTypesToLayersAppliesChanges) { +TEST_F(DisplayApplyChangedTypesToLayersTest, appliesChanges) { EXPECT_CALL(*mLayer1.outputLayer, applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT)) .Times(1); @@ -578,28 +766,30 @@ TEST_F(DisplayTest, applyChangedTypesToLayersAppliesChanges) { * Display::applyDisplayRequests() */ -TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesNoRequests) { +using DisplayApplyDisplayRequestsTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayApplyDisplayRequestsTest, handlesNoRequests) { mDisplay->applyDisplayRequests(static_cast<HWC2::DisplayRequest>(0)); auto& state = mDisplay->getState(); EXPECT_FALSE(state.flipClientTarget); } -TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesFlipClientTarget) { +TEST_F(DisplayApplyDisplayRequestsTest, handlesFlipClientTarget) { mDisplay->applyDisplayRequests(HWC2::DisplayRequest::FlipClientTarget); auto& state = mDisplay->getState(); EXPECT_TRUE(state.flipClientTarget); } -TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesWriteClientTargetToOutput) { +TEST_F(DisplayApplyDisplayRequestsTest, handlesWriteClientTargetToOutput) { mDisplay->applyDisplayRequests(HWC2::DisplayRequest::WriteClientTargetToOutput); auto& state = mDisplay->getState(); EXPECT_FALSE(state.flipClientTarget); } -TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesAllRequestFlagsSet) { +TEST_F(DisplayApplyDisplayRequestsTest, handlesAllRequestFlagsSet) { mDisplay->applyDisplayRequests(static_cast<HWC2::DisplayRequest>(~0)); auto& state = mDisplay->getState(); @@ -610,7 +800,9 @@ TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesAllRequestFlagsSet) { * Display::applyLayerRequestsToLayers() */ -TEST_F(DisplayTest, applyLayerRequestsToLayersPreparesAllLayers) { +using DisplayApplyLayerRequestsToLayersTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayApplyLayerRequestsToLayersTest, preparesAllLayers) { EXPECT_CALL(*mLayer1.outputLayer, prepareForDeviceLayerRequests()).Times(1); EXPECT_CALL(*mLayer2.outputLayer, prepareForDeviceLayerRequests()).Times(1); EXPECT_CALL(*mLayer3.outputLayer, prepareForDeviceLayerRequests()).Times(1); @@ -618,7 +810,7 @@ TEST_F(DisplayTest, applyLayerRequestsToLayersPreparesAllLayers) { mDisplay->applyLayerRequestsToLayers(impl::Display::LayerRequests()); } -TEST_F(DisplayTest, applyLayerRequestsToLayers2) { +TEST_F(DisplayApplyLayerRequestsToLayersTest, appliesDeviceLayerRequests) { EXPECT_CALL(*mLayer1.outputLayer, prepareForDeviceLayerRequests()).Times(1); EXPECT_CALL(*mLayer2.outputLayer, prepareForDeviceLayerRequests()).Times(1); EXPECT_CALL(*mLayer3.outputLayer, prepareForDeviceLayerRequests()).Times(1); @@ -637,9 +829,11 @@ TEST_F(DisplayTest, applyLayerRequestsToLayers2) { * Display::presentAndGetFrameFences() */ -TEST_F(DisplayTest, presentAndGetFrameFencesReturnsNoFencesOnNonHwcDisplay) { - auto nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; +using DisplayPresentAndGetFrameFencesTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayPresentAndGetFrameFencesTest, returnsNoFencesOnNonHwcDisplay) { + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + auto nonHwcDisplay{impl::createDisplay(mCompositionEngine, args)}; auto result = nonHwcDisplay->presentAndGetFrameFences(); @@ -648,7 +842,7 @@ TEST_F(DisplayTest, presentAndGetFrameFencesReturnsNoFencesOnNonHwcDisplay) { EXPECT_EQ(0u, result.layerFences.size()); } -TEST_F(DisplayTest, presentAndGetFrameFencesReturnsPresentAndLayerFences) { +TEST_F(DisplayPresentAndGetFrameFencesTest, returnsPresentAndLayerFences) { sp<Fence> presentFence = new Fence(); sp<Fence> layer1Fence = new Fence(); sp<Fence> layer2Fence = new Fence(); @@ -676,7 +870,9 @@ TEST_F(DisplayTest, presentAndGetFrameFencesReturnsPresentAndLayerFences) { * Display::setExpensiveRenderingExpected() */ -TEST_F(DisplayTest, setExpensiveRenderingExpectedForwardsToPowerAdvisor) { +using DisplaySetExpensiveRenderingExpectedTest = DisplayWithLayersTestCommon; + +TEST_F(DisplaySetExpensiveRenderingExpectedTest, forwardsToPowerAdvisor) { EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, true)).Times(1); mDisplay->setExpensiveRenderingExpected(true); @@ -688,7 +884,9 @@ TEST_F(DisplayTest, setExpensiveRenderingExpectedForwardsToPowerAdvisor) { * Display::finishFrame() */ -TEST_F(DisplayTest, finishFrameDoesNotSkipCompositionIfNotDirtyOnHwcDisplay) { +using DisplayFinishFrameTest = DisplayWithLayersTestCommon; + +TEST_F(DisplayFinishFrameTest, doesNotSkipCompositionIfNotDirtyOnHwcDisplay) { mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); mDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); @@ -709,9 +907,9 @@ TEST_F(DisplayTest, finishFrameDoesNotSkipCompositionIfNotDirtyOnHwcDisplay) { mDisplay->finishFrame(refreshArgs); } -TEST_F(DisplayTest, finishFrameSkipsCompositionIfNotDirty) { - std::shared_ptr<impl::Display> nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; +TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + std::shared_ptr<impl::Display> nonHwcDisplay = impl::createDisplay(mCompositionEngine, args); mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); nonHwcDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); @@ -730,9 +928,9 @@ TEST_F(DisplayTest, finishFrameSkipsCompositionIfNotDirty) { nonHwcDisplay->finishFrame(refreshArgs); } -TEST_F(DisplayTest, finishFramePerformsCompositionIfDirty) { - std::shared_ptr<impl::Display> nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; +TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + std::shared_ptr<impl::Display> nonHwcDisplay = impl::createDisplay(mCompositionEngine, args); mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); nonHwcDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); @@ -751,9 +949,9 @@ TEST_F(DisplayTest, finishFramePerformsCompositionIfDirty) { nonHwcDisplay->finishFrame(refreshArgs); } -TEST_F(DisplayTest, finishFramePerformsCompositionIfRepaintEverything) { - std::shared_ptr<impl::Display> nonHwcDisplay{ - impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; +TEST_F(DisplayFinishFrameTest, performsCompositionIfRepaintEverything) { + auto args = getDisplayCreationArgsForNonHWCVirtualDisplay(); + std::shared_ptr<impl::Display> nonHwcDisplay = impl::createDisplay(mCompositionEngine, args); mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); nonHwcDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); @@ -779,19 +977,10 @@ TEST_F(DisplayTest, finishFramePerformsCompositionIfRepaintEverything) { struct DisplayFunctionalTest : public testing::Test { class Display : public impl::Display { public: - explicit Display(const compositionengine::DisplayCreationArgs& args) - : impl::Display(args) {} - using impl::Display::injectOutputLayerForTest; virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0; }; - static std::shared_ptr<Display> createDisplay( - const compositionengine::CompositionEngine& compositionEngine, - compositionengine::DisplayCreationArgs&& args) { - return impl::createDisplayTemplated<Display>(compositionEngine, args); - } - DisplayFunctionalTest() { EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); @@ -803,11 +992,18 @@ struct DisplayFunctionalTest : public testing::Test { NiceMock<mock::CompositionEngine> mCompositionEngine; sp<mock::NativeWindow> mNativeWindow = new NiceMock<mock::NativeWindow>(); sp<mock::DisplaySurface> mDisplaySurface = new NiceMock<mock::DisplaySurface>(); - std::shared_ptr<Display> mDisplay = createDisplay(mCompositionEngine, - DisplayCreationArgsBuilder() - .setDisplayId(DEFAULT_DISPLAY_ID) - .setPowerAdvisor(&mPowerAdvisor) - .build()); + std::shared_ptr<Display> mDisplay = impl::createDisplayTemplated< + Display>(mCompositionEngine, + DisplayCreationArgsBuilder() + .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) + .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888)) + .setIsSecure(true) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&mPowerAdvisor) + .build() + + ); impl::RenderSurface* mRenderSurface = new impl::RenderSurface{mCompositionEngine, *mDisplay, RenderSurfaceCreationArgs{DEFAULT_DISPLAY_WIDTH, diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index cd6bbd1716..b72214d307 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -47,19 +47,17 @@ using android::base::StringAppendF; ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0; -DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp<SurfaceFlinger>& flinger, - const wp<IBinder>& displayToken, - std::optional<DisplayId> displayId) - : flinger(flinger), displayToken(displayToken), displayId(displayId) {} +DisplayDeviceCreationArgs::DisplayDeviceCreationArgs( + const sp<SurfaceFlinger>& flinger, const wp<IBinder>& displayToken, + std::shared_ptr<compositionengine::Display> compositionDisplay) + : flinger(flinger), displayToken(displayToken), compositionDisplay(compositionDisplay) {} -DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) +DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) : mFlinger(args.flinger), mDisplayToken(args.displayToken), mSequenceId(args.sequenceId), mConnectionType(args.connectionType), - mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay( - compositionengine::DisplayCreationArgs{args.isVirtual(), args.displayId, - args.powerAdvisor})}, + mCompositionDisplay{args.compositionDisplay}, mPhysicalOrientation(args.physicalOrientation), mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d970b821e8..fb6c817133 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -64,7 +64,7 @@ public: constexpr static float sDefaultMinLumiance = 0.0; constexpr static float sDefaultMaxLumiance = 500.0; - explicit DisplayDevice(DisplayDeviceCreationArgs&& args); + explicit DisplayDevice(DisplayDeviceCreationArgs& args); virtual ~DisplayDevice(); std::shared_ptr<compositionengine::Display> getCompositionDisplay() const { @@ -211,13 +211,10 @@ struct DisplayDeviceCreationArgs { // We use a constructor to ensure some of the values are set, without // assuming a default value. DisplayDeviceCreationArgs(const sp<SurfaceFlinger>&, const wp<IBinder>& displayToken, - std::optional<DisplayId>); - - bool isVirtual() const { return !connectionType; } - + std::shared_ptr<compositionengine::Display>); const sp<SurfaceFlinger> flinger; const wp<IBinder> displayToken; - const std::optional<DisplayId> displayId; + const std::shared_ptr<compositionengine::Display> compositionDisplay; int32_t sequenceId{0}; std::optional<DisplayConnectionType> connectionType; @@ -231,7 +228,6 @@ struct DisplayDeviceCreationArgs { std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hwcColorModes; int initialPowerMode{HWC_POWER_MODE_NORMAL}; bool isPrimary{false}; - Hwc2::PowerAdvisor* powerAdvisor{nullptr}; }; class DisplayRenderArea : public RenderArea { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ce0a8a1ac0..236a30f65d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -47,6 +47,7 @@ #include <compositionengine/CompositionRefreshArgs.h> #include <compositionengine/Display.h> #include <compositionengine/DisplayColorProfile.h> +#include <compositionengine/DisplayCreationArgs.h> #include <compositionengine/LayerFECompositionState.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/RenderSurface.h> @@ -2325,16 +2326,17 @@ void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bo } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( - const wp<IBinder>& displayToken, const std::optional<DisplayId>& displayId, + const wp<IBinder>& displayToken, + std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { - DisplayDeviceCreationArgs creationArgs(this, displayToken, displayId); + auto displayId = compositionDisplay->getDisplayId(); + DisplayDeviceCreationArgs creationArgs(this, displayToken, compositionDisplay); creationArgs.sequenceId = state.sequenceId; creationArgs.isSecure = state.isSecure; creationArgs.displaySurface = dispSurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; - creationArgs.powerAdvisor = displayId ? &mPowerAdvisor : nullptr; if (const auto& physical = state.physical) { creationArgs.connectionType = physical->type; @@ -2379,7 +2381,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( // virtual displays are always considered enabled creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; - sp<DisplayDevice> display = getFactory().createDisplayDevice(std::move(creationArgs)); + sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -2485,53 +2487,68 @@ void SurfaceFlinger::processDisplayChangesLocked() { if (draw.indexOfKey(curr.keyAt(i)) < 0) { const DisplayDeviceState& state(curr[i]); + int width = 0; + int height = 0; + ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN); + if (state.physical) { + const auto& activeConfig = + getCompositionEngine().getHwComposer().getActiveConfig( + state.physical->id); + width = activeConfig->getWidth(); + height = activeConfig->getHeight(); + pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888); + } else if (state.surface != nullptr) { + int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width); + ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status); + status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height); + ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status); + int intPixelFormat; + status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat); + ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); + pixelFormat = static_cast<ui::PixelFormat>(intPixelFormat); + } else { + // Virtual displays without a surface are dormant: + // they have external state (layer stack, projection, + // etc.) but no internal state (i.e. a DisplayDevice). + continue; + } + + compositionengine::DisplayCreationArgsBuilder builder; + if (const auto& physical = state.physical) { + builder.setPhysical({physical->id, physical->type}); + } + builder.setPixels(ui::Size(width, height)); + builder.setPixelFormat(pixelFormat); + builder.setIsSecure(state.isSecure); + builder.setLayerStackId(state.layerStack); + builder.setPowerAdvisor(&mPowerAdvisor); + builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || + getHwComposer().isUsingVrComposer()); + builder.setName(state.displayName); + auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); + sp<compositionengine::DisplaySurface> dispSurface; sp<IGraphicBufferProducer> producer; sp<IGraphicBufferProducer> bqProducer; sp<IGraphicBufferConsumer> bqConsumer; getFactory().createBufferQueue(&bqProducer, &bqConsumer, false); - std::optional<DisplayId> displayId; - if (state.isVirtual()) { - // Virtual displays without a surface are dormant: - // they have external state (layer stack, projection, - // etc.) but no internal state (i.e. a DisplayDevice). - if (state.surface != nullptr) { - // Allow VR composer to use virtual displays. - if (mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()) { - int width = 0; - int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width); - ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status); - int height = 0; - status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height); - ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status); - int intFormat = 0; - status = state.surface->query(NATIVE_WINDOW_FORMAT, &intFormat); - ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); - auto format = static_cast<ui::PixelFormat>(intFormat); - - displayId = - getHwComposer().allocateVirtualDisplay(width, height, &format); - } - - // TODO: Plumb requested format back up to consumer + std::optional<DisplayId> displayId = compositionDisplay->getId(); - sp<VirtualDisplaySurface> vds = - new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, - bqProducer, bqConsumer, - state.displayName); + if (state.isVirtual()) { + sp<VirtualDisplaySurface> vds = + new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, + bqProducer, bqConsumer, state.displayName); - dispSurface = vds; - producer = vds; - } + dispSurface = vds; + producer = vds; } else { ALOGE_IF(state.surface != nullptr, "adding a supported display, but rendering " "surface is provided (%p), ignoring it", state.surface.get()); - LOG_FATAL_IF(!state.physical); - displayId = state.physical->id; + LOG_ALWAYS_FATAL_IF(!displayId); dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer); producer = bqProducer; } @@ -2539,7 +2556,8 @@ void SurfaceFlinger::processDisplayChangesLocked() { const wp<IBinder>& displayToken = curr.keyAt(i); if (dispSurface != nullptr) { mDisplays.emplace(displayToken, - setupNewDisplayDeviceInternal(displayToken, displayId, state, + setupNewDisplayDeviceInternal(displayToken, + compositionDisplay, state, dispSurface, producer)); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c79621b1fa..9b16a28f7c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -810,7 +810,8 @@ private: * Display management */ sp<DisplayDevice> setupNewDisplayDeviceInternal( - const wp<IBinder>& displayToken, const std::optional<DisplayId>& displayId, + const wp<IBinder>& displayToken, + std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer); diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index d49133d1fc..033e54232d 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -90,8 +90,8 @@ sp<StartPropertySetThread> DefaultFactory::createStartPropertySetThread( return new StartPropertySetThread(timestampPropertyValue); } -sp<DisplayDevice> DefaultFactory::createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) { - return new DisplayDevice(std::move(creationArgs)); +sp<DisplayDevice> DefaultFactory::createDisplayDevice(DisplayDeviceCreationArgs& creationArgs) { + return new DisplayDevice(creationArgs); } sp<GraphicBuffer> DefaultFactory::createGraphicBuffer(uint32_t width, uint32_t height, diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h index 89194c7ad1..bd40cfbcf2 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h @@ -37,7 +37,7 @@ public: ISchedulerCallback&) override; std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) override; sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override; - sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&&) override; + sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&) override; sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, uint64_t usage, std::string requestorName) override; diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h index 209bd0caba..6f4fcc6900 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.h +++ b/services/surfaceflinger/SurfaceFlingerFactory.h @@ -83,7 +83,7 @@ public: virtual sp<StartPropertySetThread> createStartPropertySetThread( bool timestampPropertyValue) = 0; - virtual sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&&) = 0; + virtual sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&) = 0; virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, uint64_t usage, std::string requestorName) = 0; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 06ef8e78c2..680b0a038e 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -39,6 +39,7 @@ #include "Layer.h" #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" +#include "mock/DisplayHardware/MockPowerAdvisor.h" #include "mock/MockDispSync.h" #include "mock/MockEventControlThread.h" #include "mock/MockEventThread.h" @@ -186,6 +187,7 @@ public: renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); mock::TimeStats* mTimeStats = new mock::TimeStats(); mock::MessageQueue* mMessageQueue = new mock::MessageQueue(); + Hwc2::mock::PowerAdvisor mPowerAdvisor; sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE; @@ -284,8 +286,27 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1); EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1); EXPECT_CALL(*test->mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1); + + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + auto ceDisplayArgs = + compositionengine::DisplayCreationArgsBuilder() + .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) + .setIsSecure(Derived::IS_SECURE) + .setLayerStackId(DEFAULT_LAYER_STACK) + .setPowerAdvisor(&test->mPowerAdvisor) + .setName(std::string("Injected display for ") + + test_info->test_case_name() + "." + test_info->name()) + .build(); + + auto compositionDisplay = + compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), + ceDisplayArgs); + test->mDisplay = - FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID, + FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay, DisplayConnectionType::Internal, true /* isPrimary */) .setDisplaySurface(test->mDisplaySurface) .setNativeWindow(test->mNativeWindow) @@ -325,18 +346,17 @@ struct BaseDisplayVariant { template <typename Case> static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) - .WillRepeatedly( - [](const renderengine::DisplaySettings& displaySettings, - const std::vector<const renderengine::LayerSettings*>&, - ANativeWindowBuffer*, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { - EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); - EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), - displaySettings.physicalDisplay); - EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), - displaySettings.clip); - return NO_ERROR; - }); + .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, + const std::vector<const renderengine::LayerSettings*>&, + ANativeWindowBuffer*, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { + EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); + EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), + displaySettings.physicalDisplay); + EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), + displaySettings.clip); + return NO_ERROR; + }); } static void setupNonEmptyFrameCompositionCallExpectations(CompositionTest* test) { @@ -375,19 +395,18 @@ struct BaseDisplayVariant { .WillOnce(DoAll(SetArgPointee<0>(test->mNativeWindowBuffer), SetArgPointee<1>(-1), Return(0))); EXPECT_CALL(*test->mRenderEngine, drawLayers) - .WillRepeatedly( - [](const renderengine::DisplaySettings& displaySettings, - const std::vector<const renderengine::LayerSettings*>&, - ANativeWindowBuffer*, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { - EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); - EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), - displaySettings.physicalDisplay); - EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), - displaySettings.clip); - EXPECT_EQ(ui::Dataspace::UNKNOWN, displaySettings.outputDataspace); - return NO_ERROR; - }); + .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, + const std::vector<const renderengine::LayerSettings*>&, + ANativeWindowBuffer*, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { + EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); + EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), + displaySettings.physicalDisplay); + EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), + displaySettings.clip); + EXPECT_EQ(ui::Dataspace::UNKNOWN, displaySettings.outputDataspace); + return NO_ERROR; + }); } template <typename Case> diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 4da064766c..6d00cccb48 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -25,8 +25,12 @@ #include <compositionengine/Display.h> #include <compositionengine/DisplayColorProfile.h> +#include <compositionengine/impl/Display.h> #include <compositionengine/impl/OutputCompositionState.h> +#include <compositionengine/mock/Display.h> +#include <compositionengine/mock/DisplayColorProfile.h> #include <compositionengine/mock/DisplaySurface.h> +#include <compositionengine/mock/RenderSurface.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <gui/mock/GraphicBufferConsumer.h> @@ -39,6 +43,7 @@ #include "TestableScheduler.h" #include "TestableSurfaceFlinger.h" #include "mock/DisplayHardware/MockComposer.h" +#include "mock/DisplayHardware/MockPowerAdvisor.h" #include "mock/MockDispSync.h" #include "mock/MockEventControlThread.h" #include "mock/MockEventThread.h" @@ -51,11 +56,14 @@ namespace android { namespace { using testing::_; +using testing::AnyNumber; using testing::DoAll; using testing::Mock; using testing::ResultOf; using testing::Return; +using testing::ReturnRefOfCopy; using testing::SetArgPointee; +using testing::StrictMock; using android::Hwc2::ColorMode; using android::Hwc2::Error; @@ -107,6 +115,7 @@ public: void injectMockComposer(int virtualDisplayCount); void injectFakeBufferQueueFactory(); void injectFakeNativeWindowSurfaceFactory(); + sp<DisplayDevice> injectDefaultInternalDisplay(std::function<void(FakeDisplayDeviceInjector&)>); // -------------------------------------------------------------------- // Postcondition helpers @@ -126,6 +135,7 @@ public: TestableSurfaceFlinger mFlinger; sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow(); sp<GraphicBuffer> mBuffer = new GraphicBuffer(); + Hwc2::mock::PowerAdvisor mPowerAdvisor; // These mocks are created by the test, but are destroyed by SurfaceFlinger // by virtue of being stored into a std::unique_ptr. However we still need @@ -231,6 +241,49 @@ void DisplayTransactionTest::injectFakeNativeWindowSurfaceFactory() { }); } +sp<DisplayDevice> DisplayTransactionTest::injectDefaultInternalDisplay( + std::function<void(FakeDisplayDeviceInjector&)> injectExtra) { + constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777}; + constexpr int DEFAULT_DISPLAY_WIDTH = 1080; + constexpr int DEFAULT_DISPLAY_HEIGHT = 1920; + + // The DisplayDevice is required to have a framebuffer (behind the + // ANativeWindow interface) which uses the actual hardware display + // size. + EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0))); + EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0))); + EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)); + EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)); + EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)); + EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(AnyNumber()); + + auto compositionDisplay = compositionengine::impl:: + createDisplay(mFlinger.getCompositionEngine(), + compositionengine::DisplayCreationArgsBuilder() + .setPhysical( + {DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) + .setPowerAdvisor(&mPowerAdvisor) + .build()); + + auto injector = + FakeDisplayDeviceInjector(mFlinger, compositionDisplay, DisplayConnectionType::Internal, + true /* isPrimary */); + + injector.setNativeWindow(mNativeWindow); + if (injectExtra) { + injectExtra(injector); + } + + auto displayDevice = injector.inject(); + + Mock::VerifyAndClear(mNativeWindow.get()); + + return displayDevice; +} + bool DisplayTransactionTest::hasPhysicalHwcDisplay(hwc2_display_t hwcDisplayId) { return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; } @@ -353,9 +406,21 @@ struct DisplayVariant { static constexpr Primary PRIMARY = primary; static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { + auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder(); + if (auto displayId = DISPLAY_ID::get()) { + ceDisplayArgs.setPhysical({*displayId, DisplayConnectionType::Internal}); + } else { + ceDisplayArgs.setUseHwcVirtualDisplays(false); + } + ceDisplayArgs.setPixels({WIDTH, HEIGHT}).setPowerAdvisor(&test->mPowerAdvisor).build(); + + auto compositionDisplay = + compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), + ceDisplayArgs.build()); + auto injector = - FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(), CONNECTION_TYPE::value, - static_cast<bool>(PRIMARY)); + FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay, + CONNECTION_TYPE::value, static_cast<bool>(PRIMARY)); injector.setSecure(static_cast<bool>(SECURE)); injector.setNativeWindow(test->mNativeWindow); @@ -458,6 +523,25 @@ struct HwcDisplayVariant { injectHwcDisplayWithNoDefaultCapabilities(test); } + static std::shared_ptr<compositionengine::Display> injectCompositionDisplay( + DisplayTransactionTest* test) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() + .setPhysical({*DisplayVariant::DISPLAY_ID::get(), + PhysicalDisplay::CONNECTION_TYPE}) + .setPixels({DisplayVariant::WIDTH, DisplayVariant::HEIGHT}) + .setIsSecure(static_cast<bool>(DisplayVariant::SECURE)) + .setPowerAdvisor(&test->mPowerAdvisor) + .setName(std::string("Injected display for ") + + test_info->test_case_name() + "." + test_info->name()) + .build(); + + return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), + ceDisplayArgs); + } + static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) { constexpr auto CONNECTION_TYPE = PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal @@ -577,6 +661,23 @@ struct NonHwcVirtualDisplayVariant static void injectHwcDisplay(DisplayTransactionTest*) {} + static std::shared_ptr<compositionengine::Display> injectCompositionDisplay( + DisplayTransactionTest* test) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() + .setPixels({Base::WIDTH, Base::HEIGHT}) + .setIsSecure(static_cast<bool>(Base::SECURE)) + .setPowerAdvisor(&test->mPowerAdvisor) + .setName(std::string("Injected display for ") + + test_info->test_case_name() + "." + test_info->name()) + .build(); + + return compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), + ceDisplayArgs); + } + static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getActiveConfig(_, _)).Times(0); } @@ -602,6 +703,33 @@ struct HwcVirtualDisplayVariant secure, Primary::FALSE, GRALLOC_USAGE_HW_COMPOSER>; using Self = HwcVirtualDisplayVariant<width, height, secure>; + static std::shared_ptr<compositionengine::Display> injectCompositionDisplay( + DisplayTransactionTest* test) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() + .setUseHwcVirtualDisplays(false) + .setPixels({Base::WIDTH, Base::HEIGHT}) + .setIsSecure(static_cast<bool>(Base::SECURE)) + .setPowerAdvisor(&test->mPowerAdvisor) + .setName(std::string("Injected display for ") + + test_info->test_case_name() + "." + test_info->name()) + .build(); + + auto compositionDisplay = + compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(), + ceDisplayArgs); + compositionDisplay->setDisplayIdForTesting(Base::DISPLAY_ID::get()); + + // Insert display data so that the HWC thinks it created the virtual display. + if (const auto displayId = Base::DISPLAY_ID::get()) { + test->mFlinger.mutableHwcDisplayData().try_emplace(*displayId); + } + + return compositionDisplay; + } + static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) { Base::setupNativeWindowSurfaceCreationCallExpectations(test); EXPECT_CALL(*test->mNativeWindow, setSwapInterval(0)).Times(1); @@ -1199,14 +1327,6 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { */ class GetBestColorModeTest : public DisplayTransactionTest { public: - static constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777}; - - GetBestColorModeTest() - : DisplayTransactionTest(), - mInjector(FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID, - DisplayConnectionType::Internal, - true /* isPrimary */)) {} - void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; } void addHwcColorModesMapping(ui::ColorMode colorMode, @@ -1219,21 +1339,12 @@ public: void setInputRenderIntent(ui::RenderIntent renderIntent) { mInputRenderIntent = renderIntent; } void getBestColorMode() { - mInjector.setHwcColorModes(mHwcColorModes); - mInjector.setHasWideColorGamut(mHasWideColorGamut); - mInjector.setNativeWindow(mNativeWindow); - - // Creating a DisplayDevice requires getting default dimensions from the - // native window. - EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(1080 /* arbitrary */), Return(0))); - EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(1920 /* arbitrary */), Return(0))); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)).Times(1); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)).Times(1); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)).Times(1); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(1); - auto displayDevice = mInjector.inject(); + auto displayDevice = + injectDefaultInternalDisplay([this](FakeDisplayDeviceInjector& injector) { + injector.setHwcColorModes(mHwcColorModes); + injector.setHasWideColorGamut(mHasWideColorGamut); + injector.setNativeWindow(mNativeWindow); + }); displayDevice->getCompositionDisplay() ->getDisplayColorProfile() @@ -1250,7 +1361,6 @@ private: ui::RenderIntent mInputRenderIntent; bool mHasWideColorGamut = false; std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> mHwcColorModes; - FakeDisplayDeviceInjector mInjector; }; TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeSRGB) { @@ -1305,7 +1415,6 @@ TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDISPLAY_BT2020) { class DisplayDeviceSetProjectionTest : public DisplayTransactionTest { public: - static constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777}; static constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1080; // arbitrary static constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1920; // arbitrary @@ -1323,23 +1432,9 @@ public: mDisplayDevice(createDisplayDevice()) {} sp<DisplayDevice> createDisplayDevice() { - // The DisplayDevice is required to have a framebuffer (behind the - // ANativeWindow interface) which uses the actual hardware display - // size. - EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(mHardwareDisplaySize.width), Return(0))); - EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(mHardwareDisplaySize.height), Return(0))); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)); - EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)); - - return FakeDisplayDeviceInjector(mFlinger, DEFAULT_DISPLAY_ID, - DisplayConnectionType::Internal, true /* isPrimary */) - .setNativeWindow(mNativeWindow) - .setPhysicalOrientation(mPhysicalOrientation) - .inject(); + return injectDefaultInternalDisplay([this](FakeDisplayDeviceInjector& injector) { + injector.setPhysicalOrientation(mPhysicalOrientation); + }); } ui::Size SwapWH(const ui::Size size) const { return ui::Size(size.height, size.width); } @@ -1652,6 +1747,9 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // surfaces. injectFakeNativeWindowSurfaceFactory(); + // A compositionengine::Display has already been created + auto compositionDisplay = Case::Display::injectCompositionDisplay(this); + // -------------------------------------------------------------------- // Call Expectations @@ -1674,9 +1772,8 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { state.isSecure = static_cast<bool>(Case::Display::SECURE); - auto device = - mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::DISPLAY_ID::get(), - state, displaySurface, producer); + auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, + displaySurface, producer); // -------------------------------------------------------------------- // Postconditions @@ -1715,14 +1812,7 @@ TEST_F(SetupNewDisplayDeviceInternalTest, createNonHwcVirtualDisplay) { } TEST_F(SetupNewDisplayDeviceInternalTest, createHwcVirtualDisplay) { - using Case = HwcVirtualDisplayCase; - - // Insert display data so that the HWC thinks it created the virtual display. - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(displayId); - mFlinger.mutableHwcDisplayData().try_emplace(*displayId); - - setupNewDisplayDeviceInternalTest<Case>(); + setupNewDisplayDeviceInternalTest<HwcVirtualDisplayCase>(); } TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) { diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 3a4f349d45..84e55ae07c 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -20,6 +20,7 @@ #include <compositionengine/LayerFECompositionState.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/impl/CompositionEngine.h> +#include <compositionengine/impl/Display.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/mock/DisplaySurface.h> @@ -97,8 +98,8 @@ public: return new StartPropertySetThread(timestampPropertyValue); } - sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) override { - return new DisplayDevice(std::move(creationArgs)); + sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs& creationArgs) override { + return new DisplayDevice(creationArgs); } sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, @@ -277,13 +278,14 @@ public: auto resetDisplayState() { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, - const std::optional<DisplayId>& displayId, - const DisplayDeviceState& state, - const sp<compositionengine::DisplaySurface>& dispSurface, - const sp<IGraphicBufferProducer>& producer) { - return mFlinger->setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, - producer); + auto setupNewDisplayDeviceInternal( + const wp<IBinder>& displayToken, + std::shared_ptr<compositionengine::Display> compositionDisplay, + const DisplayDeviceState& state, + const sp<compositionengine::DisplaySurface>& dispSurface, + const sp<IGraphicBufferProducer>& producer) { + return mFlinger->setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, + dispSurface, producer); } auto handleTransactionLocked(uint32_t transactionFlags) { @@ -359,6 +361,7 @@ public: auto& getHwComposer() const { return static_cast<impl::HWComposer&>(mFlinger->getHwComposer()); } + auto& getCompositionEngine() const { return mFlinger->getCompositionEngine(); } const auto& getCompositorTiming() const { return mFlinger->getBE().mCompositorTiming; } @@ -543,10 +546,11 @@ public: class FakeDisplayDeviceInjector { public: FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, - std::optional<DisplayId> displayId, + std::shared_ptr<compositionengine::Display> compositionDisplay, std::optional<DisplayConnectionType> connectionType, bool isPrimary) - : mFlinger(flinger), mCreationArgs(flinger.mFlinger.get(), mDisplayToken, displayId) { + : mFlinger(flinger), + mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay) { mCreationArgs.connectionType = connectionType; mCreationArgs.isPrimary = isPrimary; } @@ -609,16 +613,17 @@ public: } sp<DisplayDevice> inject() { + const auto displayId = mCreationArgs.compositionDisplay->getDisplayId(); + DisplayDeviceState state; if (const auto type = mCreationArgs.connectionType) { - const auto id = mCreationArgs.displayId; - LOG_ALWAYS_FATAL_IF(!id); - state.physical = {*id, *type}; + LOG_ALWAYS_FATAL_IF(!displayId); + state.physical = {*displayId, *type}; } state.isSecure = mCreationArgs.isSecure; - sp<DisplayDevice> device = new DisplayDevice(std::move(mCreationArgs)); + sp<DisplayDevice> device = new DisplayDevice(mCreationArgs); mFlinger.mutableDisplays().emplace(mDisplayToken, device); mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); |