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

Commit 064d5c76 authored by Adithya Srinivasan's avatar Adithya Srinivasan Committed by Android (Google) Code Review
Browse files

Merge "Update jank reasons in timestats" into sc-dev

parents 331822d6 ead17161
Loading
Loading
Loading
Loading
+22 −13
Original line number Diff line number Diff line
@@ -140,11 +140,12 @@ AStatsManager_PullAtomCallbackReturn TimeStats::populateGlobalAtom(AStatsEventLi
                                             globalSlice.second.jankPayload.totalSFUnattributed);
        mStatsDelegate->statsEventWriteInt32(event,
                                             globalSlice.second.jankPayload.totalAppUnattributed);

        // TODO: populate these with real values
        mStatsDelegate->statsEventWriteInt32(event, 0); // total_janky_frames_sf_scheduling
        mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_sf_prediction_error
        mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_app_buffer_stuffing
        mStatsDelegate->statsEventWriteInt32(event,
                                             globalSlice.second.jankPayload.totalSFScheduling);
        mStatsDelegate->statsEventWriteInt32(event,
                                             globalSlice.second.jankPayload.totalSFPredictionError);
        mStatsDelegate->statsEventWriteInt32(event,
                                             globalSlice.second.jankPayload.totalAppBufferStuffing);
        mStatsDelegate->statsEventWriteInt32(event, globalSlice.first.displayRefreshRateBucket);
        std::string sfDeadlineMissedBytes =
                histogramToProtoByteString(globalSlice.second.displayDeadlineDeltas.hist,
@@ -222,11 +223,9 @@ AStatsManager_PullAtomCallbackReturn TimeStats::populateLayerAtom(AStatsEventLis
        mStatsDelegate->statsEventWriteInt32(event, layer->jankPayload.totalSFLongGpu);
        mStatsDelegate->statsEventWriteInt32(event, layer->jankPayload.totalSFUnattributed);
        mStatsDelegate->statsEventWriteInt32(event, layer->jankPayload.totalAppUnattributed);

        // TODO: populate these with real values
        mStatsDelegate->statsEventWriteInt32(event, 0); // total_janky_frames_sf_scheduling
        mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_sf_prediction_error
        mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_app_buffer_stuffing
        mStatsDelegate->statsEventWriteInt32(event, layer->jankPayload.totalSFScheduling);
        mStatsDelegate->statsEventWriteInt32(event, layer->jankPayload.totalSFPredictionError);
        mStatsDelegate->statsEventWriteInt32(event, layer->jankPayload.totalAppBufferStuffing);
        mStatsDelegate->statsEventWriteInt32(
                event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket
        mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket
@@ -772,9 +771,10 @@ void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber,
    flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
}

static const constexpr int32_t kValidJankyReason = JankType::SurfaceFlingerCpuDeadlineMissed |
        JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed |
        JankType::DisplayHAL;
static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL |
        JankType::SurfaceFlingerCpuDeadlineMissed | JankType::SurfaceFlingerGpuDeadlineMissed |
        JankType::AppDeadlineMissed | JankType::PredictionError |
        JankType::SurfaceFlingerScheduling | JankType::BufferStuffing;

template <class T>
static void updateJankPayload(T& t, int32_t reasons) {
@@ -794,6 +794,15 @@ static void updateJankPayload(T& t, int32_t reasons) {
        if ((reasons & JankType::AppDeadlineMissed) != 0) {
            t.jankPayload.totalAppUnattributed++;
        }
        if ((reasons & JankType::PredictionError) != 0) {
            t.jankPayload.totalSFPredictionError++;
        }
        if ((reasons & JankType::SurfaceFlingerScheduling) != 0) {
            t.jankPayload.totalSFScheduling++;
        }
        if ((reasons & JankType::BufferStuffing) != 0) {
            t.jankPayload.totalAppBufferStuffing++;
        }
    }
}

+5 −2
Original line number Diff line number Diff line
@@ -83,8 +83,11 @@ std::string TimeStatsHelper::JankPayload::toString() const {
    StringAppendF(&result, "jankyFrames = %d\n", totalJankyFrames);
    StringAppendF(&result, "sfLongCpuJankyFrames = %d\n", totalSFLongCpu);
    StringAppendF(&result, "sfLongGpuJankyFrames = %d\n", totalSFLongGpu);
    StringAppendF(&result, "sfUnattributedJankyFrame = %d\n", totalSFUnattributed);
    StringAppendF(&result, "appUnattributedJankyFrame = %d\n", totalAppUnattributed);
    StringAppendF(&result, "sfUnattributedJankyFrames = %d\n", totalSFUnattributed);
    StringAppendF(&result, "appUnattributedJankyFrames = %d\n", totalAppUnattributed);
    StringAppendF(&result, "sfSchedulingJankyFrames = %d\n", totalSFScheduling);
    StringAppendF(&result, "sfPredictionErrorJankyFrames = %d\n", totalSFPredictionError);
    StringAppendF(&result, "appBufferStuffingJankyFrames = %d\n", totalAppBufferStuffing);
    return result;
}

+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ public:
        int32_t totalSFLongGpu = 0;
        int32_t totalSFUnattributed = 0;
        int32_t totalAppUnattributed = 0;
        int32_t totalSFScheduling = 0;
        int32_t totalSFPredictionError = 0;
        int32_t totalAppBufferStuffing = 0;

        std::string toString() const;
    };
+130 −66
Original line number Diff line number Diff line
@@ -156,12 +156,9 @@ public:
    uint32_t* maxDisplayFrames;
    nsecs_t maxTokenRetentionTime;
    static constexpr pid_t kSurfaceFlingerPid = 666;
    static constexpr nsecs_t kPresentThreshold =
            std::chrono::duration_cast<std::chrono::nanoseconds>(2ns).count();
    static constexpr nsecs_t kDeadlineThreshold =
            std::chrono::duration_cast<std::chrono::nanoseconds>(2ns).count();
    static constexpr nsecs_t kStartThreshold =
            std::chrono::duration_cast<std::chrono::nanoseconds>(2ns).count();
    static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
    static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(2ns).count();
    static constexpr nsecs_t kStartThreshold = std::chrono::nanoseconds(2ns).count();
    static constexpr JankClassificationThresholds kTestThresholds{kPresentThreshold,
                                                                  kDeadlineThreshold,
                                                                  kStartThreshold};
@@ -430,28 +427,21 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) {
                                                   0}));
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
            {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
            {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    mFrameTimeline->setSfWakeUp(sfToken1,
                                std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
                                refreshRate);
    surfaceFrame1->setAcquireFenceTime(
            std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(20ms).count());
    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(
            std::chrono::duration_cast<std::chrono::nanoseconds>(70ms).count());
    presentFence1->signalForTest(std::chrono::nanoseconds(70ms).count());

    mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(),
                                 presentFence1);
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(59ms).count(), presentFence1);
}

TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) {
@@ -463,27 +453,20 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) {

    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
            {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
            {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    mFrameTimeline->setSfWakeUp(sfToken1,
                                std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
                                refreshRate);
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);
    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    surfaceFrame1->setAcquireFenceTime(
            std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count());
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(20ms).count());
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(
            std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
                                 presentFence1);
    presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(56ms).count(), presentFence1);
    EXPECT_EQ(surfaceFrame1->getJankType(), JankType::DisplayHAL);
}

@@ -498,32 +481,120 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) {
                                                           .count()}));
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
            {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(82ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
            {std::chrono::nanoseconds(82ms).count(), std::chrono::nanoseconds(86ms).count(),
             std::chrono::nanoseconds(90ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    surfaceFrame1->setAcquireFenceTime(
            std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1,
                                std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
                                refreshRate);
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(45ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);

    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(
            std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
                                 presentFence1);
    presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(86ms).count(), presentFence1);

    EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed);
}

TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) {
    Fps refreshRate = Fps::fromPeriodNsecs(std::chrono::nanoseconds(32ms).count());
    EXPECT_CALL(*mTimeStats,
                incrementJankyFrames(
                        TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                   sLayerNameOne,
                                                   JankType::SurfaceFlingerScheduling, 0, 0,
                                                   std::chrono::duration_cast<
                                                           std::chrono::nanoseconds>(-10ms)
                                                           .count()}));
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::nanoseconds(40ms).count(), std::chrono::nanoseconds(60ms).count(),
             std::chrono::nanoseconds(92ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(50ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);

    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(std::chrono::nanoseconds(60ms).count());
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(56ms).count(), presentFence1);

    EXPECT_EQ(surfaceFrame1->getJankType(), JankType::SurfaceFlingerScheduling);
}

TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) {
    Fps refreshRate = Fps(16.66f);
    EXPECT_CALL(*mTimeStats,
                incrementJankyFrames(
                        TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                   sLayerNameOne, JankType::PredictionError, 0,
                                                   std::chrono::duration_cast<
                                                           std::chrono::nanoseconds>(5ms)
                                                           .count(),
                                                   0}));
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::nanoseconds(30ms).count(), std::chrono::nanoseconds(40ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::nanoseconds(52ms).count(), std::chrono::nanoseconds(56ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(40ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);

    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(std::chrono::nanoseconds(65ms).count());
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(56ms).count(), presentFence1);

    EXPECT_EQ(surfaceFrame1->getJankType(), JankType::PredictionError);
}

TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) {
    Fps refreshRate = Fps::fromPeriodNsecs(std::chrono::nanoseconds(32ms).count());
    EXPECT_CALL(*mTimeStats,
                incrementJankyFrames(
                        TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
                                                   sLayerNameOne,
                                                   JankType::BufferStuffing |
                                                           JankType::SurfaceFlingerScheduling,
                                                   0, 0, 0}));
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::nanoseconds(30ms).count(), std::chrono::nanoseconds(40ms).count(),
             std::chrono::nanoseconds(58ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::nanoseconds(82ms).count(), std::chrono::nanoseconds(86ms).count(),
             std::chrono::nanoseconds(90ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(40ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(82ms).count(), refreshRate);

    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented,
                                   /*previousLatchTime*/
                                   std::chrono::nanoseconds(56ms).count());
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(86ms).count(), presentFence1);

    EXPECT_EQ(surfaceFrame1->getJankType(),
              JankType::BufferStuffing | JankType::SurfaceFlingerScheduling);
}

TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) {
    Fps refreshRate = Fps(11.0);
    Fps renderRate = Fps(30.0);
@@ -536,29 +607,22 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) {
                                                           .count()}));
    auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
    int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
            {std::chrono::nanoseconds(10ms).count(), std::chrono::nanoseconds(20ms).count(),
             std::chrono::nanoseconds(60ms).count()});
    int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
            {std::chrono::duration_cast<std::chrono::nanoseconds>(82ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
             std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
            {std::chrono::nanoseconds(82ms).count(), std::chrono::nanoseconds(86ms).count(),
             std::chrono::nanoseconds(90ms).count()});
    auto surfaceFrame1 =
            mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
                                                       sUidOne, sLayerNameOne, sLayerNameOne);
    surfaceFrame1->setAcquireFenceTime(
            std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1,
                                std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
                                refreshRate);
    surfaceFrame1->setAcquireFenceTime(std::chrono::nanoseconds(45ms).count());
    mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::nanoseconds(52ms).count(), refreshRate);

    surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
    surfaceFrame1->setRenderRate(renderRate);
    mFrameTimeline->addSurfaceFrame(surfaceFrame1);
    presentFence1->signalForTest(
            std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
                                 presentFence1);
    presentFence1->signalForTest(std::chrono::nanoseconds(90ms).count());
    mFrameTimeline->setSfPresent(std::chrono::nanoseconds(86ms).count(), presentFence1);

    EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed);
}
+79 −67

File changed.

Preview size limit exceeded, changes collapsed.