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

Commit cef0bca7 authored by Matt Buckley's avatar Matt Buckley
Browse files

Optimize HWUI ADPF for sysui and ensure correct closure

This patch prevents the HintSessionWrapper from setting the
timestamp on load_up hints, to avoid edge cases in systemui
where load_up hints were being sent before reset had a chance
to be checked, making ADPF think work was still ongoing.

This patch also ensures the session closes when a
CanvasContext is destructed, as previously it would wait until
the delayed destroy was evaluated before closing the session.

Bug: 302620048
Test: hwuiunit
Change-Id: I15172382665934acc28c80ff06937475481ba62b
parent 2a0f9e11
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ CanvasContext::~CanvasContext() {
    mRenderNodes.clear();
    mRenderThread.cacheManager().unregisterCanvasContext(this);
    mRenderThread.renderState().removeContextCallback(this);
    mHintSessionWrapper->destroy();
}

void CanvasContext::addRenderNode(RenderNode* node, bool placeFront) {
+0 −1
Original line number Diff line number Diff line
@@ -158,7 +158,6 @@ void HintSessionWrapper::sendLoadResetHint() {
void HintSessionWrapper::sendLoadIncreaseHint() {
    if (!init()) return;
    mBinding->sendHint(mHintSession, static_cast<int32_t>(SessionHint::CPU_LOAD_UP));
    mLastFrameNotification = systemTime();
}

bool HintSessionWrapper::alive() {
+57 −2
Original line number Diff line number Diff line
@@ -259,6 +259,31 @@ TEST_F(HintSessionWrapperTests, delayedDeletionResolvesAfterAsyncCreationFinishe

TEST_F(HintSessionWrapperTests, delayedDeletionDoesNotKillReusedSession) {
    EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(0);
    EXPECT_CALL(*sMockBinding, fakeReportActualWorkDuration(sessionPtr, 5_ms)).Times(1);

    mWrapper->init();
    waitForWrapperReady();
    // Init a second time just to grab the wrapper from the promise
    mWrapper->init();
    EXPECT_EQ(mWrapper->alive(), true);

    // First schedule the deletion
    scheduleDelayedDestroyManaged();

    // Then, report an actual duration
    mWrapper->reportActualWorkDuration(5_ms);

    // Then, run the delayed deletion after sending the update
    allowDelayedDestructionToStart();
    waitForDelayedDestructionToFinish();

    // Ensure it didn't close within the timeframe of the test
    Mock::VerifyAndClearExpectations(sMockBinding.get());
    EXPECT_EQ(mWrapper->alive(), true);
}

TEST_F(HintSessionWrapperTests, loadUpDoesNotResetDeletionTimer) {
    EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
    EXPECT_CALL(*sMockBinding,
                fakeSendHint(sessionPtr, static_cast<int32_t>(SessionHint::CPU_LOAD_UP)))
            .Times(1);
@@ -272,16 +297,46 @@ TEST_F(HintSessionWrapperTests, delayedDeletionDoesNotKillReusedSession) {
    // First schedule the deletion
    scheduleDelayedDestroyManaged();

    // Then, send a hint to update the timestamp
    // Then, send a load_up hint
    mWrapper->sendLoadIncreaseHint();

    // Then, run the delayed deletion after sending the update
    allowDelayedDestructionToStart();
    waitForDelayedDestructionToFinish();

    // Ensure it didn't close within the timeframe of the test
    // Ensure it closed within the timeframe of the test
    Mock::VerifyAndClearExpectations(sMockBinding.get());
    EXPECT_EQ(mWrapper->alive(), false);
}

TEST_F(HintSessionWrapperTests, manualSessionDestroyPlaysNiceWithDelayedDestruct) {
    EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);

    mWrapper->init();
    waitForWrapperReady();
    // Init a second time just to grab the wrapper from the promise
    mWrapper->init();
    EXPECT_EQ(mWrapper->alive(), true);

    // First schedule the deletion
    scheduleDelayedDestroyManaged();

    // Then, kill the session
    mWrapper->destroy();

    // Verify it died
    Mock::VerifyAndClearExpectations(sMockBinding.get());
    EXPECT_EQ(mWrapper->alive(), false);

    EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(0);

    // Then, run the delayed deletion after manually killing the session
    allowDelayedDestructionToStart();
    waitForDelayedDestructionToFinish();

    // Ensure it didn't close again and is still dead
    Mock::VerifyAndClearExpectations(sMockBinding.get());
    EXPECT_EQ(mWrapper->alive(), false);
}

}  // namespace android::uirenderer::renderthread
 No newline at end of file