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

Commit 438eb7d7 authored by Sally Qi's avatar Sally Qi
Browse files

[FrameTimeline] Refactor the logic of addSkippedFrame

Bug: 273701290
Test: https://screenshot.googleplex.com/3uyqAWi6bXgNbw2
Change-Id: I7dea4f9378e804d60af3ff849793fdc09b97166d
parent d28755ab
Loading
Loading
Loading
Loading
+38 −16
Original line number Diff line number Diff line
@@ -390,6 +390,22 @@ void SurfaceFrame::setGpuComposition() {
    mGpuComposition = true;
}

// TODO(b/316171339): migrate from perfetto side
bool SurfaceFrame::isSelfJanky() const {
    int32_t jankType = getJankType().value_or(JankType::None);

    if (jankType == JankType::None) {
        return false;
    }

    int32_t jankBitmask = JankType::AppDeadlineMissed | JankType::Unknown;
    if (jankType & jankBitmask) {
        return true;
    }

    return false;
}

std::optional<int32_t> SurfaceFrame::getJankType() const {
    std::scoped_lock lock(mMutex);
    if (mPresentState == PresentState::Dropped) {
@@ -1113,20 +1129,23 @@ void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
}

void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                                  nsecs_t previousActualPresentTime) const {
                                                  nsecs_t previousPredictionPresentTime) const {
    nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
    const constexpr float kThresh = 0.5f;
    const constexpr float kRange = 1.5f;
    for (auto& surfaceFrame : mSurfaceFrames) {
        if (previousActualPresentTime != 0 &&
            static_cast<float>(mSurfaceFlingerActuals.presentTime - previousActualPresentTime) >=
        if (previousPredictionPresentTime != 0 &&
            static_cast<float>(mSurfaceFlingerPredictions.presentTime -
                               previousPredictionPresentTime) >=
                    static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
            static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
                    (static_cast<float>(mSurfaceFlingerActuals.presentTime) -
                    (static_cast<float>(mSurfaceFlingerPredictions.presentTime) -
                     kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
            static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
                    (static_cast<float>(previousActualPresentTime) -
                     kThresh * static_cast<float>(mRenderRate.getPeriodNsecs()))) {
                    (static_cast<float>(previousPredictionPresentTime) -
                     kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
            // sf skipped frame is not considered if app is self janked
            !surfaceFrame->isSelfJanky()) {
            skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
            skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
            break;
@@ -1215,18 +1234,18 @@ void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
    });
}

void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                        nsecs_t previousActualPresentTime) const {
nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                           nsecs_t previousPredictionPresentTime) const {
    if (mSurfaceFrames.empty()) {
        // We don't want to trace display frames without any surface frames updates as this cannot
        // be janky
        return;
        return previousPredictionPresentTime;
    }

    if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
        // DisplayFrame should not have an invalid token.
        ALOGE("Cannot trace DisplayFrame with invalid token");
        return;
        return previousPredictionPresentTime;
    }

    if (mPredictionState == PredictionState::Valid) {
@@ -1241,8 +1260,9 @@ void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBoo
    }

    if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
        addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousActualPresentTime);
        addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime);
    }
    return mSurfaceFlingerPredictions.presentTime;
}

float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
@@ -1333,8 +1353,9 @@ void FrameTimeline::flushPendingPresentFences() {
        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, mPreviousPresentTime);
        displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
        mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
                                                             mPreviousPredictionPresentTime);
        mPendingPresentFences.erase(mPendingPresentFences.begin());
    }

@@ -1349,9 +1370,10 @@ void FrameTimeline::flushPendingPresentFences() {
        }

        auto& displayFrame = pendingPresentFence.second;
        displayFrame->onPresent(signalTime, mPreviousPresentTime);
        displayFrame->trace(mSurfaceFlingerPid, monoBootOffset, mPreviousPresentTime);
        mPreviousPresentTime = signalTime;
        displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
        mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
                                                             mPreviousPredictionPresentTime);
        mPreviousActualPresentTime = signalTime;

        mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
        --i;
+6 −3
Original line number Diff line number Diff line
@@ -165,6 +165,8 @@ public:
                 TraceCookieCounter* traceCookieCounter, bool isBuffer, GameMode);
    ~SurfaceFrame() = default;

    bool isSelfJanky() const;

    // Returns std::nullopt if the frame hasn't been classified yet.
    // Used by both SF and FrameTimeline.
    std::optional<int32_t> getJankType() const;
@@ -381,8 +383,8 @@ public:
        // Emits a packet for perfetto tracing. The function body will be executed only if tracing
        // is enabled. monoBootOffset is the difference between SYSTEM_TIME_BOOTTIME
        // and SYSTEM_TIME_MONOTONIC.
        void trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                   nsecs_t previousActualPresentTime) const;
        nsecs_t trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                      nsecs_t previousPredictionPresentTime) const;
        // Sets the token, vsyncPeriod, predictions and SF start time.
        void onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
                        std::optional<TimelineItem> predictions, nsecs_t wakeUpTime);
@@ -508,7 +510,8 @@ private:
    uint32_t mMaxDisplayFrames;
    std::shared_ptr<TimeStats> mTimeStats;
    const pid_t mSurfaceFlingerPid;
    nsecs_t mPreviousPresentTime = 0;
    nsecs_t mPreviousActualPresentTime = 0;
    nsecs_t mPreviousPredictionPresentTime = 0;
    const JankClassificationThresholds mJankClassificationThresholds;
    static constexpr uint32_t kDefaultMaxDisplayFrames = 64;
    // The initial container size for the vector<SurfaceFrames> inside display frame. Although