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

Commit f1f601e0 authored by Ady Abraham's avatar Ady Abraham Committed by Android (Google) Code Review
Browse files

Merge "SF: make FrameTimeline more robust for fence errors"

parents ae3bc147 fcb1686a
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -892,6 +892,10 @@ void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t&
        mJankType = JankType::Unknown;
        deadlineDelta = 0;
        deltaToVsync = 0;
        if (mSurfaceFlingerActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
            mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
        }

        return;
    }

@@ -1168,22 +1172,50 @@ float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
            static_cast<float>(totalPresentToPresentWalls);
}

std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
    for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
        const auto& [fence, _] = mPendingPresentFences[i];
        if (fence && fence->isValid() && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
            return i;
        }
    }

    return {};
}

void FrameTimeline::flushPendingPresentFences() {
    const auto firstSignaledFence = getFirstSignalFenceIndex();
    if (!firstSignaledFence.has_value()) {
        return;
    }

    // Perfetto is using boottime clock to void drifts when the device goes
    // to suspend.
    const auto monoBootOffset = mUseBootTimeClock
            ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
            : 0;

    // Present fences are expected to be signaled in order. Mark all the previous
    // pending fences as errors.
    for (size_t i = 0; i < firstSignaledFence.value(); i++) {
        const auto& pendingPresentFence = *mPendingPresentFences.begin();
        const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
        auto& displayFrame = pendingPresentFence.second;
        displayFrame->onPresent(signalTime, mPreviousPresentTime);
        displayFrame->trace(mSurfaceFlingerPid, monoBootOffset);
        mPendingPresentFences.erase(mPendingPresentFences.begin());
    }

    for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
        const auto& pendingPresentFence = mPendingPresentFences[i];
        nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
        if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
            signalTime = pendingPresentFence.first->getSignalTime();
            if (signalTime == Fence::SIGNAL_TIME_PENDING) {
                continue;
                break;
            }
        }

        auto& displayFrame = pendingPresentFence.second;
        displayFrame->onPresent(signalTime, mPreviousPresentTime);
        displayFrame->trace(mSurfaceFlingerPid, monoBootOffset);
+1 −0
Original line number Diff line number Diff line
@@ -474,6 +474,7 @@ private:
    friend class android::frametimeline::FrameTimelineTest;

    void flushPendingPresentFences() REQUIRES(mMutex);
    std::optional<size_t> getFirstSignalFenceIndex() const REQUIRES(mMutex);
    void finalizeCurrentDisplayFrame() REQUIRES(mMutex);
    void dumpAll(std::string& result);
    void dumpJank(std::string& result);
+45 −1
Original line number Diff line number Diff line
@@ -480,7 +480,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_invalidSignalTime) {
    addEmptyDisplayFrame();

    auto displayFrame0 = getDisplayFrame(0);
    EXPECT_EQ(displayFrame0->getActuals().presentTime, -1);
    EXPECT_EQ(displayFrame0->getActuals().presentTime, 59);
    EXPECT_EQ(displayFrame0->getJankType(), JankType::Unknown);
    EXPECT_EQ(surfaceFrame1->getActuals().presentTime, -1);
    EXPECT_EQ(surfaceFrame1->getJankType(), JankType::Unknown);
@@ -2228,6 +2228,50 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_G
    EXPECT_EQ(displayFrame2->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed);
}

TEST_F(FrameTimelineTest, jankClassification_presentFenceError) {
    auto erroneousPresentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    auto erroneousPresentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    auto validPresentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
    int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 60});
    int64_t sfToken3 = mTokenManager->generateTokenForPredictions({72, 80, 80});

    mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
    mFrameTimeline->setSfPresent(26, erroneousPresentFence1);

    mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
    mFrameTimeline->setSfPresent(60, erroneousPresentFence2);

    mFrameTimeline->setSfWakeUp(sfToken3, 72, Fps::fromPeriodNsecs(11));
    mFrameTimeline->setSfPresent(80, validPresentFence);

    validPresentFence->signalForTest(80);

    addEmptyDisplayFrame();

    {
        auto displayFrame = getDisplayFrame(0);
        EXPECT_EQ(displayFrame->getActuals().presentTime, 26);
        EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::UnknownPresent);
        EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::UnknownFinish);
        EXPECT_EQ(displayFrame->getJankType(), JankType::Unknown);
    }
    {
        auto displayFrame = getDisplayFrame(1);
        EXPECT_EQ(displayFrame->getActuals().presentTime, 60);
        EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::UnknownPresent);
        EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::UnknownFinish);
        EXPECT_EQ(displayFrame->getJankType(), JankType::Unknown);
    }
    {
        auto displayFrame = getDisplayFrame(2);
        EXPECT_EQ(displayFrame->getActuals().presentTime, 80);
        EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::OnTimePresent);
        EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish);
        EXPECT_EQ(displayFrame->getJankType(), JankType::None);
    }
}

TEST_F(FrameTimelineTest, computeFps_noLayerIds_returnsZero) {
    EXPECT_EQ(mFrameTimeline->computeFps({}), 0.0f);
}