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

Commit 8b196599 authored by Marin Shalamanov's avatar Marin Shalamanov
Browse files

HWComposer: Unset mPrimaryHwcDisplayId after disconnectDisplay

We should unset mPrimaryHwcDisplayId when disconnectDisplay()
is called for the primary display. This can happen during
display change and it will cause isHeadless() to be false.
This way SurfaceFlinger will call getPrimaryDisplayId()
which will crash.

Test: HWComposerTest
Test: libsurfaceflinger_unittest
Bug: 195900759
Change-Id: I3c00e3b864fef6f1b088ffae0539c1ad16b7492b
parent eb03b050
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -669,6 +669,13 @@ void HWComposer::disconnectDisplay(HalDisplayId displayId) {

    mPhysicalDisplayIdMap.erase(hwcDisplayId);
    mDisplayData.erase(displayId);

    // Reset the primary display ID if we're disconnecting it.
    // This way isHeadless() will return false, which is necessary
    // because getPrimaryDisplayId() will crash.
    if (mPrimaryHwcDisplayId == hwcDisplayId) {
        mPrimaryHwcDisplayId.reset();
    }
}

status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
+6 −3
Original line number Diff line number Diff line
@@ -231,9 +231,12 @@ public:

    virtual Hwc2::Composer* getComposer() const = 0;

    // Returns the first display connected at boot. It cannot be disconnected, which implies an
    // internal connection type. Its connection via HWComposer::onHotplug, which in practice is
    // immediately after HWComposer construction, must occur before any call to this function.
    // Returns the first display connected at boot. Its connection via HWComposer::onHotplug,
    // which in practice is immediately after HWComposer construction, must occur before any
    // call to this function.
    // The primary display can be temporarily disconnected from the perspective
    // of this class. Callers must not call getPrimaryHwcDisplayId() or getPrimaryDisplayId()
    // if isHeadless().
    //
    // TODO(b/182939859): Remove special cases for primary display.
    virtual hal::HWDisplayId getPrimaryHwcDisplayId() const = 0;
+24 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
#include "DisplayIdentificationTest.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockHWC2.h"

@@ -57,6 +58,29 @@ using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrictMock;

TEST(HWComposerTest, isHeadless) {
    Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
    impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
    ASSERT_TRUE(hwc.isHeadless());

    const hal::HWDisplayId hwcId = 1;

    EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
            .WillOnce(DoAll(SetArgPointee<2>(getExternalEdid()),
                            Return(hardware::graphics::composer::V2_1::Error::NONE)));

    EXPECT_CALL(*mHal, setVsyncEnabled(_, _));
    EXPECT_CALL(*mHal, setClientTargetSlotCount(_));

    auto info = hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
    ASSERT_TRUE(info);
    auto displayId = info->id;
    ASSERT_FALSE(hwc.isHeadless());

    hwc.disconnectDisplay(displayId);
    ASSERT_TRUE(hwc.isHeadless());
}

struct MockHWC2ComposerCallback final : StrictMock<HWC2::ComposerCallback> {
    MOCK_METHOD2(onComposerHalHotplug, void(hal::HWDisplayId, hal::Connection));
    MOCK_METHOD1(onComposerHalRefresh, void(hal::HWDisplayId));