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

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

Merge "Fix SF jank classification" into sc-dev

parents c4b9a8a9 939cd4d5
Loading
Loading
Loading
Loading
+42 −18
Original line number Diff line number Diff line
@@ -504,6 +504,17 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
        if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
            // Buffer Stuffing.
            mJankType |= JankType::BufferStuffing;
            // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
            // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
            // We try to do this by moving the deadline. Since the queue could be stuffed by more
            // than one buffer, we take the last latch time as reference and give one vsync
            // worth of time for the frame to be ready.
            nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
            if (adjustedDeadline > mActuals.endTime) {
                mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
            } else {
                mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
            }
        }
        if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
            // Finish on time, Present late
@@ -511,6 +522,9 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
                // Propagate displayFrame's jank if it exists
                mJankType |= displayFrameJankType;
            } else {
                if (!(mJankType & JankType::BufferStuffing)) {
                    // In a stuffed state, if the app finishes on time and there is no display frame
                    // jank, only buffer stuffing is the root cause of the jank.
                    if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
                        deltaToVsync >= refreshRate.getPeriodNsecs() -
                                        mJankClassificationThresholds.presentThreshold) {
@@ -521,6 +535,7 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
                        mJankType |= JankType::PredictionError;
                    }
                }
            }
        } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
            // Finish late, Present late
            if (displayFrameJankType == JankType::None) {
@@ -683,13 +698,14 @@ void TokenManager::flushTokens(nsecs_t flushTime) {
}

FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
                             JankClassificationThresholds thresholds)
                             JankClassificationThresholds thresholds, nsecs_t hwcDuration)
      : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
        mTimeStats(std::move(timeStats)),
        mSurfaceFlingerPid(surfaceFlingerPid),
        mJankClassificationThresholds(thresholds) {
    mCurrentDisplayFrame =
            std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
        mJankClassificationThresholds(thresholds),
        mHwcDuration(hwcDuration) {
    mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, thresholds, hwcDuration,
                                                          &mTraceCookieCounter);
}

void FrameTimeline::onBootFinished() {
@@ -732,11 +748,13 @@ std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(

FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
                                          JankClassificationThresholds thresholds,
                                          nsecs_t hwcDuration,
                                          TraceCookieCounter* traceCookieCounter)
      : mSurfaceFlingerPredictions(TimelineItem()),
        mSurfaceFlingerActuals(TimelineItem()),
        mTimeStats(timeStats),
        mJankClassificationThresholds(thresholds),
        mHwcDuration(hwcDuration),
        mTraceCookieCounter(*traceCookieCounter) {
    mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
}
@@ -808,7 +826,7 @@ void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
    const nsecs_t presentDelta =
            mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
    const nsecs_t deadlineDelta =
            mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime;
            mSurfaceFlingerActuals.endTime - (mSurfaceFlingerPredictions.endTime - mHwcDuration);

    // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
    // was a prediction error or not.
@@ -822,8 +840,9 @@ void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
        mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
    }

    if (mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime >
        mJankClassificationThresholds.deadlineThreshold) {
    if (mSurfaceFlingerActuals.endTime > mSurfaceFlingerPredictions.endTime - mHwcDuration) {
        // SF needs to have finished at least mHwcDuration ahead of the deadline for it to be
        // on time.
        mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
    } else {
        mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
@@ -875,8 +894,13 @@ void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
                    mJankType = JankType::PredictionError;
                }
            } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
                // Finish late, Present late
                if (mFrameStartMetadata == FrameStartMetadata::LateStart) {
                    // Late start, Late finish, Late Present
                    mJankType = JankType::SurfaceFlingerScheduling;
                } else {
                    // OnTime start, Finish late, Present late
                    mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
                }
            } else {
                // Finish time unknown
                mJankType = JankType::Unknown;
@@ -1066,7 +1090,7 @@ void FrameTimeline::finalizeCurrentDisplayFrame() {
    mDisplayFrames.push_back(mCurrentDisplayFrame);
    mCurrentDisplayFrame.reset();
    mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
                                                          &mTraceCookieCounter);
                                                          mHwcDuration, &mTraceCookieCounter);
}

nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
+10 −2
Original line number Diff line number Diff line
@@ -342,7 +342,7 @@ public:
    class DisplayFrame {
    public:
        DisplayFrame(std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds,
                     TraceCookieCounter* traceCookieCounter);
                     nsecs_t hwcDuration, TraceCookieCounter* traceCookieCounter);
        virtual ~DisplayFrame() = default;
        // Dumpsys interface - dumps only if the DisplayFrame itself is janky or is at least one
        // SurfaceFrame is janky.
@@ -371,6 +371,7 @@ public:
        // Functions to be used only in testing.
        TimelineItem getActuals() const { return mSurfaceFlingerActuals; };
        TimelineItem getPredictions() const { return mSurfaceFlingerPredictions; };
        FrameStartMetadata getFrameStartMetadata() const { return mFrameStartMetadata; };
        FramePresentMetadata getFramePresentMetadata() const { return mFramePresentMetadata; };
        FrameReadyMetadata getFrameReadyMetadata() const { return mFrameReadyMetadata; };
        int32_t getJankType() const { return mJankType; }
@@ -394,6 +395,7 @@ public:
        TimelineItem mSurfaceFlingerActuals;
        std::shared_ptr<TimeStats> mTimeStats;
        const JankClassificationThresholds mJankClassificationThresholds;
        const nsecs_t mHwcDuration;

        // Collection of predictions and actual values sent over by Layers
        std::vector<std::shared_ptr<SurfaceFrame>> mSurfaceFrames;
@@ -419,7 +421,8 @@ public:
    };

    FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
                  JankClassificationThresholds thresholds = {});
                  JankClassificationThresholds thresholds = {},
                  nsecs_t hwcDuration = kDefaultHwcDuration);
    ~FrameTimeline() = default;

    frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
@@ -464,6 +467,11 @@ private:
    std::shared_ptr<TimeStats> mTimeStats;
    const pid_t mSurfaceFlingerPid;
    const JankClassificationThresholds mJankClassificationThresholds;
    // In SF Predictions, both end & present are the same. The predictions consider the time used by
    // composer as well, but we have no way to estimate how much time the composer needs. We are
    // assuming an arbitrary time for the composer work.
    const nsecs_t mHwcDuration;
    static constexpr nsecs_t kDefaultHwcDuration = std::chrono::nanoseconds(3ms).count();
    static constexpr uint32_t kDefaultMaxDisplayFrames = 64;
    // The initial container size for the vector<SurfaceFrames> inside display frame. Although
    // this number doesn't represent any bounds on the number of surface frames that can go in a
+216 −162

File changed.

Preview size limit exceeded, changes collapsed.