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

Commit a0a16278 authored by Ady Abraham's avatar Ady Abraham
Browse files

Fix memory leaks in libsurfaceflinger_unittest

Every class that inherits from RefBase must be held by an sp<>.
Creating a RefBAse object without an sp<> causes a memory leak.

Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Bug: 181807839
Change-Id: I37ec274b01c5212a5a3cecc2e1eb5b4c9d6122f4
parent eca9d75c
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ namespace android {

class SlotGenerationTest : public testing::Test {
protected:
    BufferStateLayer::HwcSlotGenerator mHwcSlotGenerator;
    sp<BufferStateLayer::HwcSlotGenerator> mHwcSlotGenerator =
            sp<BufferStateLayer::HwcSlotGenerator>::make();
    sp<GraphicBuffer> mBuffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
    sp<GraphicBuffer> mBuffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
    sp<GraphicBuffer> mBuffer3{new GraphicBuffer(10, 10, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
@@ -41,7 +42,7 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Invalid) {
    sp<IBinder> binder = new BBinder();
    // test getting invalid client_cache_id
    client_cache_t id;
    uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
    uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
    EXPECT_EQ(BufferQueue::INVALID_BUFFER_SLOT, slot);
}

@@ -50,19 +51,19 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Basic) {
    client_cache_t id;
    id.token = binder;
    id.id = 0;
    uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
    uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 1, slot);

    client_cache_t idB;
    idB.token = binder;
    idB.id = 1;
    slot = mHwcSlotGenerator.getHwcCacheSlot(idB);
    slot = mHwcSlotGenerator->getHwcCacheSlot(idB);
    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 2, slot);

    slot = mHwcSlotGenerator.getHwcCacheSlot(idB);
    slot = mHwcSlotGenerator->getHwcCacheSlot(idB);
    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 2, slot);

    slot = mHwcSlotGenerator.getHwcCacheSlot(id);
    slot = mHwcSlotGenerator->getHwcCacheSlot(id);
    EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 1, slot);
}

@@ -77,12 +78,12 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Reuse) {
        id.id = cacheId;
        ids.push_back(id);

        uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
        uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
        EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
        cacheId++;
    }
    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(ids[i]);
        uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(ids[i]);
        EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
    }

@@ -90,7 +91,7 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Reuse) {
        client_cache_t id;
        id.token = binder;
        id.id = cacheId;
        uint32_t slot = mHwcSlotGenerator.getHwcCacheSlot(id);
        uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
        EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
        cacheId++;
    }
+31 −30
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ protected:
        }
    } mExpectDisableVsync{mSchedulerCallback};

    TestableScheduler mScheduler{mConfigs, mSchedulerCallback};
    TestableScheduler* mScheduler = new TestableScheduler{mConfigs, mSchedulerCallback};

    Scheduler::ConnectionHandle mConnectionHandle;
    mock::EventThread* mEventThread;
@@ -85,8 +85,10 @@ SchedulerTest::SchedulerTest() {
    EXPECT_CALL(*mEventThread, createEventConnection(_, _))
            .WillRepeatedly(Return(mEventThreadConnection));

    mConnectionHandle = mScheduler.createConnection(std::move(eventThread));
    mConnectionHandle = mScheduler->createConnection(std::move(eventThread));
    EXPECT_TRUE(mConnectionHandle);

    mFlinger.resetScheduler(mScheduler);
}

} // namespace
@@ -94,85 +96,84 @@ SchedulerTest::SchedulerTest() {
TEST_F(SchedulerTest, invalidConnectionHandle) {
    Scheduler::ConnectionHandle handle;

    const sp<IDisplayEventConnection> connection = mScheduler.createDisplayEventConnection(handle);
    const sp<IDisplayEventConnection> connection = mScheduler->createDisplayEventConnection(handle);

    EXPECT_FALSE(connection);
    EXPECT_FALSE(mScheduler.getEventConnection(handle));
    EXPECT_FALSE(mScheduler->getEventConnection(handle));

    // The EXPECT_CALLS make sure we don't call the functions on the subsequent event threads.
    EXPECT_CALL(*mEventThread, onHotplugReceived(_, _)).Times(0);
    mScheduler.onHotplugReceived(handle, PHYSICAL_DISPLAY_ID, false);
    mScheduler->onHotplugReceived(handle, PHYSICAL_DISPLAY_ID, false);

    EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(0);
    mScheduler.onScreenAcquired(handle);
    mScheduler->onScreenAcquired(handle);

    EXPECT_CALL(*mEventThread, onScreenReleased()).Times(0);
    mScheduler.onScreenReleased(handle);
    mScheduler->onScreenReleased(handle);

    std::string output;
    EXPECT_CALL(*mEventThread, dump(_)).Times(0);
    mScheduler.dump(handle, output);
    mScheduler->dump(handle, output);
    EXPECT_TRUE(output.empty());

    EXPECT_CALL(*mEventThread, setDuration(10ns, 20ns)).Times(0);
    mScheduler.setDuration(handle, 10ns, 20ns);
    mScheduler->setDuration(handle, 10ns, 20ns);
}

TEST_F(SchedulerTest, validConnectionHandle) {
    const sp<IDisplayEventConnection> connection =
            mScheduler.createDisplayEventConnection(mConnectionHandle);
            mScheduler->createDisplayEventConnection(mConnectionHandle);

    ASSERT_EQ(mEventThreadConnection, connection);
    EXPECT_TRUE(mScheduler.getEventConnection(mConnectionHandle));
    EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle));

    EXPECT_CALL(*mEventThread, onHotplugReceived(PHYSICAL_DISPLAY_ID, false)).Times(1);
    mScheduler.onHotplugReceived(mConnectionHandle, PHYSICAL_DISPLAY_ID, false);
    mScheduler->onHotplugReceived(mConnectionHandle, PHYSICAL_DISPLAY_ID, false);

    EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(1);
    mScheduler.onScreenAcquired(mConnectionHandle);
    mScheduler->onScreenAcquired(mConnectionHandle);

    EXPECT_CALL(*mEventThread, onScreenReleased()).Times(1);
    mScheduler.onScreenReleased(mConnectionHandle);
    mScheduler->onScreenReleased(mConnectionHandle);

    std::string output("dump");
    EXPECT_CALL(*mEventThread, dump(output)).Times(1);
    mScheduler.dump(mConnectionHandle, output);
    mScheduler->dump(mConnectionHandle, output);
    EXPECT_FALSE(output.empty());

    EXPECT_CALL(*mEventThread, setDuration(10ns, 20ns)).Times(1);
    mScheduler.setDuration(mConnectionHandle, 10ns, 20ns);
    mScheduler->setDuration(mConnectionHandle, 10ns, 20ns);

    static constexpr size_t kEventConnections = 5;
    EXPECT_CALL(*mEventThread, getEventThreadConnectionCount()).WillOnce(Return(kEventConnections));
    EXPECT_EQ(kEventConnections, mScheduler.getEventThreadConnectionCount(mConnectionHandle));
    EXPECT_EQ(kEventConnections, mScheduler->getEventThreadConnectionCount(mConnectionHandle));
}

TEST_F(SchedulerTest, noLayerHistory) {
    // Layer history should not be created if there is a single config.
    ASSERT_FALSE(mScheduler.hasLayerHistory());
    ASSERT_FALSE(mScheduler->hasLayerHistory());

    TestableSurfaceFlinger flinger;
    mock::MockLayer layer(flinger.flinger());
    sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());

    // Content detection should be no-op.
    mScheduler.registerLayer(&layer);
    mScheduler.recordLayerHistory(&layer, 0, LayerHistory::LayerUpdateType::Buffer);
    mScheduler->registerLayer(layer.get());
    mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer);

    constexpr bool kPowerStateNormal = true;
    mScheduler.setDisplayPowerState(kPowerStateNormal);
    mScheduler->setDisplayPowerState(kPowerStateNormal);

    constexpr uint32_t kDisplayArea = 999'999;
    mScheduler.onPrimaryDisplayAreaChanged(kDisplayArea);
    mScheduler->onPrimaryDisplayAreaChanged(kDisplayArea);

    EXPECT_CALL(mSchedulerCallback, changeRefreshRate(_, _)).Times(0);
    mScheduler.chooseRefreshRateForContent();
    mScheduler->chooseRefreshRateForContent();
}

TEST_F(SchedulerTest, testDispatchCachedReportedMode) {
    // If the optional fields are cleared, the function should return before
    // onModeChange is called.
    mScheduler.clearOptionalFieldsInFeatures();
    EXPECT_NO_FATAL_FAILURE(mScheduler.dispatchCachedReportedMode());
    mScheduler->clearOptionalFieldsInFeatures();
    EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
    EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0);
}

@@ -183,7 +184,7 @@ TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) {
    // If the handle is incorrect, the function should return before
    // onModeChange is called.
    Scheduler::ConnectionHandle invalidHandle = {.id = 123};
    EXPECT_NO_FATAL_FAILURE(mScheduler.onNonPrimaryDisplayModeChanged(invalidHandle,
    EXPECT_NO_FATAL_FAILURE(mScheduler->onNonPrimaryDisplayModeChanged(invalidHandle,
                                                                       PHYSICAL_DISPLAY_ID, modeId,
                                                                       vsyncPeriod));
    EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0);