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

Commit 94917b3c authored by Rachel Lee's avatar Rachel Lee
Browse files

Change jank for CPU/GPU deadline miss.

There are cases where there is composition in both cpu and gpu, so it is
better to track jank for when deadline miss occurred in HWC or GPU
composition instead.

Bug: 204463368
Test: atest FrameTimelineTest
Test: Perfetto trace
Change-Id: Ibfd87d5688e2ef6ff88a3b9f9276954de18beed2
parent 29bfcc33
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -24,9 +24,9 @@ enum JankType {
    None = 0x0,
    // Jank that occurs in the layers below SurfaceFlinger
    DisplayHAL = 0x1,
    // SF took too long on the CPU
    // SF took too long on the CPU; deadline missed during HWC
    SurfaceFlingerCpuDeadlineMissed = 0x2,
    // SF took too long on the GPU
    // SF took too long on the GPU; deadline missed during GPU composition
    SurfaceFlingerGpuDeadlineMissed = 0x4,
    // Either App or GPU took too long on the frame
    AppDeadlineMissed = 0x8,
+4 −7
Original line number Diff line number Diff line
@@ -109,11 +109,11 @@ std::string jankTypeBitmaskToString(int32_t jankType) {
        jankType &= ~JankType::DisplayHAL;
    }
    if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
        janks.emplace_back("SurfaceFlinger CPU Deadline Missed");
        janks.emplace_back("SurfaceFlinger deadline missed (while in HWC)");
        jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
    }
    if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
        janks.emplace_back("SurfaceFlinger GPU Deadline Missed");
        janks.emplace_back("SurfaceFlinger deadline missed (while in GPU comp)");
        jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
    }
    if (jankType & JankType::AppDeadlineMissed) {
@@ -986,11 +986,8 @@ void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t&
                                    mJankClassificationThresholds.presentThreshold) {
                    // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
                    // was presented more than a vsync late.
                    if (mGpuFence != FenceTime::NO_FENCE &&
                        mSurfaceFlingerActuals.endTime - mSurfaceFlingerActuals.startTime <
                                mRefreshRate.getPeriodNsecs()) {
                        // If SF was in GPU composition and the CPU work finished before the vsync
                        // period, classify it as GPU deadline missed.
                    if (mGpuFence != FenceTime::NO_FENCE) {
                        // If SF was in GPU composition, classify it as GPU deadline missed.
                        mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
                    } else {
                        mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
+45 −1
Original line number Diff line number Diff line
@@ -1680,7 +1680,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent)
    EXPECT_EQ(displayFrame0->getActuals().presentTime, 52);
    EXPECT_EQ(displayFrame0->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
    EXPECT_EQ(displayFrame0->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
    EXPECT_EQ(displayFrame0->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed);
    EXPECT_EQ(displayFrame0->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed);

    // case 3 - cpu time = 86 - 82 = 4, vsync period = 30
    mFrameTimeline->setSfWakeUp(sfToken3, 106, Fps::fromPeriodNsecs(30));
@@ -2184,6 +2184,50 @@ TEST_F(FrameTimelineTest, jankClassification_appDeadlineAdjustedForBufferStuffin
    EXPECT_EQ(presentedSurfaceFrame2.getJankType(), JankType::BufferStuffing);
}

TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_GpuAndCpuMiss) {
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    auto gpuFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
    int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 60});

    // Case 1: cpu time = 33 - 12 = 21, vsync period = 11
    mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11));
    mFrameTimeline->setSfPresent(33, presentFence1, gpuFence1);
    auto displayFrame = getDisplayFrame(0);
    gpuFence1->signalForTest(36);
    presentFence1->signalForTest(52);

    // Fences haven't been flushed yet, so it should be 0
    EXPECT_EQ(displayFrame->getActuals().presentTime, 0);

    addEmptyDisplayFrame();
    displayFrame = getDisplayFrame(0);

    // Fences have flushed, so the present timestamps should be updated
    EXPECT_EQ(displayFrame->getActuals().presentTime, 52);
    EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
    EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
    EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed);

    // Case 2: No GPU fence so it will not use GPU composition.
    mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(30));
    mFrameTimeline->setSfPresent(66, presentFence2);
    auto displayFrame2 = getDisplayFrame(2); // 2 because of previous empty frame
    presentFence2->signalForTest(90);

    // Fences for the frame haven't been flushed yet, so it should be 0
    EXPECT_EQ(displayFrame2->getActuals().presentTime, 0);

    addEmptyDisplayFrame();

    // Fences have flushed, so the present timestamps should be updated
    EXPECT_EQ(displayFrame2->getActuals().presentTime, 90);
    EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
    EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
    EXPECT_EQ(displayFrame2->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed);
}

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