Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc79209c authored by Lloyd Pique's avatar Lloyd Pique
Browse files

SF: Switch to internal display setup

Rather than call the public hotplug() functions, which may have
undesired effects, set the internal state directly for a display in the
middle of being connected.

[Test execution time not significantly reduced]

Test: libsurfaceflinger_unittest passes on Pixel XL
Bug: 74827900
Change-Id: I604ff7267e7ea3af94095ca05e288ef18e248ee5
(cherry picked from commit a618d855)
parent f7a23bd9
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height,

    auto display = std::make_unique<Display>(
            *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
    display->setConnected(true);
    *outDisplay = display.get();
    *format = static_cast<android_pixel_format_t>(intFormat);
    mDisplays.emplace(displayId, std::move(display));
@@ -168,6 +169,7 @@ void Device::onHotplug(hwc2_display_t displayId, Connection connection) {

        auto newDisplay = std::make_unique<Display>(
                *mComposer.get(), mCapabilities, displayId, displayType);
        newDisplay->setConnected(true);
        mDisplays.emplace(displayId, std::move(newDisplay));
    } else if (connection == Connection::Disconnected) {
        // The display will later be destroyed by a call to
@@ -209,16 +211,14 @@ Error Device::flushCommands()
// Display methods

Display::Display(android::Hwc2::Composer& composer,
                 const std::unordered_set<Capability>& capabilities,
                 hwc2_display_t id, DisplayType type)
                 const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
                 DisplayType type)
      : mComposer(composer),
        mCapabilities(capabilities),
        mId(id),
        mIsConnected(false),
    mType(type)
{
        mType(type) {
    ALOGV("Created display %" PRIu64, id);
    setConnected(true);
}

Display::~Display() {
+5 −2
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ namespace android {
    namespace Hwc2 {
        class Composer;
    }

    class TestableSurfaceFlinger;
}

namespace HWC2 {
@@ -126,8 +128,7 @@ private:
class Display
{
public:
    Display(android::Hwc2::Composer& composer,
            const std::unordered_set<Capability>& capabilities,
    Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities,
            hwc2_display_t id, DisplayType type);
    ~Display();

@@ -263,6 +264,8 @@ private:
    // on this display
    Layer* getLayerById(hwc2_layer_t id) const;

    friend android::TestableSurfaceFlinger;

    // Member variables

    // These are references to data owned by HWC2::Device, which will outlive
+21 −33
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ using android::Hwc2::Error;
using android::Hwc2::IComposer;
using android::Hwc2::IComposerClient;

using HWC2Display = TestableSurfaceFlinger::HWC2Display;

constexpr int32_t DEFAULT_REFRESH_RATE = 1666666666;
constexpr int32_t DEFAULT_DPI = 320;

@@ -57,6 +59,8 @@ protected:

    void expectFramebufferQueuePairCreation(int width, int height);

    std::unordered_set<HWC2::Capability> mCapabilities;

    TestableSurfaceFlinger mFlinger;
    mock::EventThread* mEventThread = new mock::EventThread();

@@ -69,6 +73,7 @@ protected:
    // These mocks are created only when expected to be created via a factory.
    sp<mock::GraphicBufferConsumer> mConsumer;
    sp<mock::GraphicBufferProducer> mProducer;
    std::unique_ptr<HWC2Display> mDisplay;
};

DisplayTransactionTest::DisplayTransactionTest() {
@@ -102,36 +107,22 @@ void DisplayTransactionTest::setupComposer(int virtualDisplayCount) {
}

void DisplayTransactionTest::setupPrimaryDisplay(int width, int height) {
    EXPECT_CALL(*mComposer, getDisplayType(DisplayDevice::DISPLAY_PRIMARY, _))
            .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
                            Return(Error::NONE)));
    EXPECT_CALL(*mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
    EXPECT_CALL(*mComposer, getDisplayConfigs(_, _))
            .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{0}), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
                                    IComposerClient::Attribute::WIDTH, _))
            .WillOnce(DoAll(SetArgPointee<3>(width), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
                                    IComposerClient::Attribute::HEIGHT, _))
            .WillOnce(DoAll(SetArgPointee<3>(height), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
                                    IComposerClient::Attribute::VSYNC_PERIOD, _))
            .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_REFRESH_RATE), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
                                    IComposerClient::Attribute::DPI_X, _))
            .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
    EXPECT_CALL(*mComposer,
                getDisplayAttribute(DisplayDevice::DISPLAY_PRIMARY, 0,
                                    IComposerClient::Attribute::DPI_Y, _))
            .WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));

    mFlinger.setupPrimaryDisplay();

    Mock::VerifyAndClear(mComposer);
    mDisplay = std::make_unique<HWC2Display>(*mComposer, mCapabilities, 0,
                                             HWC2::DisplayType::Physical);

    mDisplay->mutableIsConnected() = true;
    mDisplay->mutableConfigs().emplace(0,
                                       HWC2::Display::Config::Builder(*mDisplay, 0)
                                               .setWidth(width)
                                               .setHeight(height)
                                               .setVsyncPeriod(DEFAULT_REFRESH_RATE)
                                               .setDpiX(DEFAULT_DPI)
                                               .setDpiY(DEFAULT_DPI)
                                               .build());

    mFlinger.mutableHwcDisplayData()[DisplayDevice::DISPLAY_PRIMARY].reset();
    mFlinger.mutableHwcDisplayData()[DisplayDevice::DISPLAY_PRIMARY].hwcDisplay = mDisplay.get();
    mFlinger.mutableHwcDisplaySlots().emplace(0, DisplayDevice::DISPLAY_PRIMARY);
}

void DisplayTransactionTest::expectFramebufferQueuePairCreation(int width, int height) {
@@ -196,9 +187,6 @@ TEST_F(DisplayTransactionTest, processDisplayChangesLockedProcessesPrimaryDispla
    const auto& draw = mFlinger.mutableDrawingState().displays[i];
    EXPECT_EQ(DisplayDevice::DISPLAY_PRIMARY, draw.type);

    EXPECT_CALL(*mComposer, setVsyncEnabled(0, IComposerClient::Vsync::DISABLE))
            .WillOnce(Return(Error::NONE));

    EXPECT_CALL(*mConsumer, consumerDisconnect()).Times(1);
}

+21 −6
Original line number Diff line number Diff line
@@ -44,12 +44,6 @@ public:
        mFlinger->getBE().mHwc.reset(new HWComposer(std::move(composer)));
    }

    void setupPrimaryDisplay() {
        mFlinger->getBE().mHwc->mHwcDevice->onHotplug(0, HWC2::Connection::Connected);
        mFlinger->getBE().mHwc->onHotplug(0, DisplayDevice::DISPLAY_PRIMARY,
                                          HWC2::Connection::Connected);
    }

    using CreateBufferQueueFunction = SurfaceFlinger::CreateBufferQueueFunction;

    void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
@@ -72,6 +66,9 @@ public:
    auto& mutableEventThread() { return mFlinger->mEventThread; }
    auto& mutableEventQueue() { return mFlinger->mEventQueue; }

    auto& mutableHwcDisplayData() { return mFlinger->getBE().mHwc->mDisplayData; }
    auto& mutableHwcDisplaySlots() { return mFlinger->getBE().mHwc->mHwcDisplaySlots; }

    ~TestableSurfaceFlinger() {
        // All these pointer and container clears help ensure that GMock does
        // not report a leaked object, since the SurfaceFlinger instance may
@@ -83,6 +80,24 @@ public:
        mFlinger->getBE().mRenderEngine.reset();
    }

    /* ------------------------------------------------------------------------
     * Wrapper classes for Read-write access to private data to set up
     * preconditions and assert post-conditions.
     */
    struct HWC2Display : public HWC2::Display {
        HWC2Display(Hwc2::Composer& composer,
                    const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
                    HWC2::DisplayType type)
              : HWC2::Display(composer, capabilities, id, type) {}
        ~HWC2Display() {
            // Prevents a call to disable vsyncs.
            mType = HWC2::DisplayType::Invalid;
        }

        auto& mutableIsConnected() { return this->mIsConnected; }
        auto& mutableConfigs() { return this->mConfigs; }
    };

    sp<SurfaceFlinger> mFlinger = new SurfaceFlinger();
};