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

Commit 43a68c3f authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: Do not trace FrameTimeline before start

Filter FrameTimeline events for frames started before the trace started.

Bug: 364194637
Test: manual
Flag: com.android.graphics.surfaceflinger.flags.filter_frames_before_trace_starts
Change-Id: I9185f384f306eddab1afc2ea9d7901dd70d2f1a2
parent 9a4c026c
Loading
Loading
Loading
Loading
+166 −92
Original line number Original line Diff line number Diff line
@@ -38,6 +38,8 @@ using base::StringAppendF;
using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;


namespace {

void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
               const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
               const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
    StringAppendF(&result, "%s", indent.c_str());
    StringAppendF(&result, "%s", indent.c_str());
@@ -319,6 +321,16 @@ nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
    return minTime;
    return minTime;
}
}


bool shouldTraceForDataSource(const FrameTimelineDataSource::TraceContext& ctx, nsecs_t timestamp) {
    if (auto ds = ctx.GetDataSourceLocked(); ds && ds->getStartTime() > timestamp) {
        return false;
    }

    return true;
}

} // namespace

int64_t TraceCookieCounter::getCookieForTracing() {
int64_t TraceCookieCounter::getCookieForTracing() {
    return ++mTraceCookie;
    return ++mTraceCookie;
}
}
@@ -726,15 +738,24 @@ void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRender
    classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
    classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
}
}


void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset,
                                    bool filterFramesBeforeTraceStarts) const {
    int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    bool traced = false;


    // Expected timeline start
    // Expected timeline start
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        const auto timestamp = mPredictions.startTime;
        if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
            // Do not trace packets started before tracing starts.
            return;
        }
        traced = true;

        std::scoped_lock lock(mMutex);
        std::scoped_lock lock(mMutex);
        auto packet = ctx.NewTracePacket();
        auto packet = ctx.NewTracePacket();
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
        packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));


        auto* event = packet->set_frame_timeline_event();
        auto* event = packet->set_frame_timeline_event();
        auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
        auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
@@ -748,6 +769,7 @@ void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootO
        expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
        expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
    });
    });


    if (traced) {
        // Expected timeline end
        // Expected timeline end
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
            std::scoped_lock lock(mMutex);
            std::scoped_lock lock(mMutex);
@@ -761,30 +783,41 @@ void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootO
            expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
            expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
        });
        });
    }
    }
}


void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset,
                                bool filterFramesBeforeTraceStarts) const {
    int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    bool traced = false;


    // Actual timeline start
    // Actual timeline start
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        const auto timestamp = [&]() {
            std::scoped_lock lock(mMutex);
            std::scoped_lock lock(mMutex);
        auto packet = ctx.NewTracePacket();
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
            // Actual start time is not yet available, so use expected start instead
            // Actual start time is not yet available, so use expected start instead
            if (mPredictionState == PredictionState::Expired) {
            if (mPredictionState == PredictionState::Expired) {
            // If prediction is expired, we can't use the predicted start time. Instead, just use a
                // If prediction is expired, we can't use the predicted start time. Instead, just
            // start time a little earlier than the end time so that we have some info about this
                // use a start time a little earlier than the end time so that we have some info
            // frame in the trace.
                // about this frame in the trace.
                nsecs_t endTime =
                nsecs_t endTime =
                        (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
                        (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
            const auto timestamp = endTime - kPredictionExpiredStartTimeDelta;
                return endTime - kPredictionExpiredStartTimeDelta;
            packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
        } else {
            const auto timestamp =
                    mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
            packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
            }
            }


            return mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
        }();

        if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
            // Do not trace packets started before tracing starts.
            return;
        }
        traced = true;

        std::scoped_lock lock(mMutex);
        auto packet = ctx.NewTracePacket();
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));

        auto* event = packet->set_frame_timeline_event();
        auto* event = packet->set_frame_timeline_event();
        auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
        auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();


@@ -812,6 +845,7 @@ void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffse
        actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
        actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
    });
    });


    if (traced) {
        // Actual timeline end
        // Actual timeline end
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
            std::scoped_lock lock(mMutex);
            std::scoped_lock lock(mMutex);
@@ -829,11 +863,13 @@ void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffse
            actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
            actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
        });
        });
    }
    }
}


/**
/**
 * TODO(b/178637512): add inputEventId to the perfetto trace.
 * TODO(b/178637512): add inputEventId to the perfetto trace.
 */
 */
void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset,
                         bool filterFramesBeforeTraceStarts) const {
    if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
    if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
        displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
        displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
        // No packets can be traced with a missing token.
        // No packets can be traced with a missing token.
@@ -842,9 +878,9 @@ void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) cons
    if (getPredictionState() != PredictionState::Expired) {
    if (getPredictionState() != PredictionState::Expired) {
        // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
        // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
        // a trace.
        // a trace.
        tracePredictions(displayFrameToken, monoBootOffset);
        tracePredictions(displayFrameToken, monoBootOffset, filterFramesBeforeTraceStarts);
    }
    }
    traceActuals(displayFrameToken, monoBootOffset);
    traceActuals(displayFrameToken, monoBootOffset, filterFramesBeforeTraceStarts);
}
}


namespace impl {
namespace impl {
@@ -870,8 +906,12 @@ std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token)
}
}


FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
                             JankClassificationThresholds thresholds, bool useBootTimeClock)
                             JankClassificationThresholds thresholds, bool useBootTimeClock,
                             bool filterFramesBeforeTraceStarts)
      : mUseBootTimeClock(useBootTimeClock),
      : mUseBootTimeClock(useBootTimeClock),
        mFilterFramesBeforeTraceStarts(
                FlagManager::getInstance().filter_frames_before_trace_starts() &&
                filterFramesBeforeTraceStarts),
        mMaxDisplayFrames(kDefaultMaxDisplayFrames),
        mMaxDisplayFrames(kDefaultMaxDisplayFrames),
        mTimeStats(std::move(timeStats)),
        mTimeStats(std::move(timeStats)),
        mSurfaceFlingerPid(surfaceFlingerPid),
        mSurfaceFlingerPid(surfaceFlingerPid),
@@ -1154,16 +1194,23 @@ void FrameTimeline::DisplayFrame::onCommitNotComposited() {
    }
    }
}
}


void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                                   nsecs_t monoBootOffset) const {
                                                   bool filterFramesBeforeTraceStarts) const {
    int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    bool traced = false;


    // Expected timeline start
    // Expected timeline start
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        const auto timestamp = mSurfaceFlingerPredictions.startTime;
        if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
            // Do not trace packets started before tracing starts.
            return;
        }
        traced = true;

        auto packet = ctx.NewTracePacket();
        auto packet = ctx.NewTracePacket();
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp(
        packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
                static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));


        auto* event = packet->set_frame_timeline_event();
        auto* event = packet->set_frame_timeline_event();
        auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
        auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
@@ -1174,6 +1221,7 @@ void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
        expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
        expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
    });
    });


    if (traced) {
        // Expected timeline end
        // Expected timeline end
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
            auto packet = ctx.NewTracePacket();
            auto packet = ctx.NewTracePacket();
@@ -1187,9 +1235,11 @@ void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
            expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
            expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
        });
        });
    }
    }
}


void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                                  nsecs_t previousPredictionPresentTime) const {
                                                  nsecs_t previousPredictionPresentTime,
                                                  bool filterFramesBeforeTraceStarts) const {
    nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
    nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
    const constexpr float kThresh = 0.5f;
    const constexpr float kThresh = 0.5f;
    const constexpr float kRange = 1.5f;
    const constexpr float kRange = 1.5f;
@@ -1215,9 +1265,17 @@ void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs
    // add slice
    // add slice
    if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
    if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
        int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
        int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
        bool traced = false;


        // Actual timeline start
        // Actual timeline start
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
            if (filterFramesBeforeTraceStarts &&
                !shouldTraceForDataSource(ctx, skippedFrameStartTime)) {
                // Do not trace packets started before tracing starts.
                return;
            }
            traced = true;

            auto packet = ctx.NewTracePacket();
            auto packet = ctx.NewTracePacket();
            packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
            packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
            packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
            packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
@@ -1238,11 +1296,13 @@ void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs
            actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None));
            actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None));
        });
        });


        if (traced) {
            // Actual timeline end
            // Actual timeline end
            FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
            FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
                auto packet = ctx.NewTracePacket();
                auto packet = ctx.NewTracePacket();
                packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
                packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
            packet->set_timestamp(static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
                packet->set_timestamp(
                        static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));


                auto* event = packet->set_frame_timeline_event();
                auto* event = packet->set_frame_timeline_event();
                auto* actualDisplayFrameEndEvent = event->set_frame_end();
                auto* actualDisplayFrameEndEvent = event->set_frame_end();
@@ -1251,17 +1311,25 @@ void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs
            });
            });
        }
        }
    }
    }
}


void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                               nsecs_t monoBootOffset) const {
                                               bool filterFramesBeforeTraceStarts) const {
    int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
    bool traced = false;


    // Actual timeline start
    // Actual timeline start
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
    FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        const auto timestamp = mSurfaceFlingerActuals.startTime;
        if (filterFramesBeforeTraceStarts && !shouldTraceForDataSource(ctx, timestamp)) {
            // Do not trace packets started before tracing starts.
            return;
        }
        traced = true;

        auto packet = ctx.NewTracePacket();
        auto packet = ctx.NewTracePacket();
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
        packet->set_timestamp(
        packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
                static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));


        auto* event = packet->set_frame_timeline_event();
        auto* event = packet->set_frame_timeline_event();
        auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
        auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
@@ -1280,6 +1348,7 @@ void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
        actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
        actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
    });
    });


    if (traced) {
        // Actual timeline end
        // Actual timeline end
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
        FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
            auto packet = ctx.NewTracePacket();
            auto packet = ctx.NewTracePacket();
@@ -1293,9 +1362,11 @@ void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
            actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
            actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
        });
        });
    }
    }
}


nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                                           nsecs_t previousPredictionPresentTime) const {
                                           nsecs_t previousPredictionPresentTime,
                                           bool filterFramesBeforeTraceStarts) const {
    if (mSurfaceFrames.empty()) {
    if (mSurfaceFrames.empty()) {
        // We don't want to trace display frames without any surface frames updates as this cannot
        // We don't want to trace display frames without any surface frames updates as this cannot
        // be janky
        // be janky
@@ -1311,16 +1382,17 @@ nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t mono
    if (mPredictionState == PredictionState::Valid) {
    if (mPredictionState == PredictionState::Valid) {
        // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
        // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
        // meaningful way in a trace.
        // meaningful way in a trace.
        tracePredictions(surfaceFlingerPid, monoBootOffset);
        tracePredictions(surfaceFlingerPid, monoBootOffset, filterFramesBeforeTraceStarts);
    }
    }
    traceActuals(surfaceFlingerPid, monoBootOffset);
    traceActuals(surfaceFlingerPid, monoBootOffset, filterFramesBeforeTraceStarts);


    for (auto& surfaceFrame : mSurfaceFrames) {
    for (auto& surfaceFrame : mSurfaceFrames) {
        surfaceFrame->trace(mToken, monoBootOffset);
        surfaceFrame->trace(mToken, monoBootOffset, filterFramesBeforeTraceStarts);
    }
    }


    if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
    if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
        addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime);
        addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime,
                        filterFramesBeforeTraceStarts);
    }
    }
    return mSurfaceFlingerPredictions.presentTime;
    return mSurfaceFlingerPredictions.presentTime;
}
}
@@ -1414,8 +1486,9 @@ void FrameTimeline::flushPendingPresentFences() {
        const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
        const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
        auto& displayFrame = pendingPresentFence.second;
        auto& displayFrame = pendingPresentFence.second;
        displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
        displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
        mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
        mPreviousPredictionPresentTime =
                                                             mPreviousPredictionPresentTime);
                displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
                                    mPreviousPredictionPresentTime, mFilterFramesBeforeTraceStarts);
        mPendingPresentFences.erase(mPendingPresentFences.begin());
        mPendingPresentFences.erase(mPendingPresentFences.begin());
    }
    }


@@ -1431,8 +1504,9 @@ void FrameTimeline::flushPendingPresentFences() {


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


        mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
        mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
+26 −11
Original line number Original line Diff line number Diff line
@@ -214,7 +214,8 @@ public:
    // enabled. The displayFrameToken is needed to link the SurfaceFrame to the corresponding
    // enabled. The displayFrameToken is needed to link the SurfaceFrame to the corresponding
    // DisplayFrame at the trace processor side. monoBootOffset is the difference
    // DisplayFrame at the trace processor side. monoBootOffset is the difference
    // between SYSTEM_TIME_BOOTTIME and SYSTEM_TIME_MONOTONIC.
    // between SYSTEM_TIME_BOOTTIME and SYSTEM_TIME_MONOTONIC.
    void trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
    void trace(int64_t displayFrameToken, nsecs_t monoBootOffset,
               bool filterFramesBeforeTraceStarts) const;


    // Getter functions used only by FrameTimelineTests and SurfaceFrame internally
    // Getter functions used only by FrameTimelineTests and SurfaceFrame internally
    TimelineItem getActuals() const;
    TimelineItem getActuals() const;
@@ -234,8 +235,10 @@ public:
            std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
            std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();


private:
private:
    void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
    void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset,
    void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
                          bool filterFramesBeforeTraceStarts) const;
    void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset,
                      bool filterFramesBeforeTraceStarts) const;
    void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
    void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
                            Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) REQUIRES(mMutex);
                            Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) REQUIRES(mMutex);


@@ -367,9 +370,15 @@ private:
class FrameTimeline : public android::frametimeline::FrameTimeline {
class FrameTimeline : public android::frametimeline::FrameTimeline {
public:
public:
    class FrameTimelineDataSource : public perfetto::DataSource<FrameTimelineDataSource> {
    class FrameTimelineDataSource : public perfetto::DataSource<FrameTimelineDataSource> {
    public:
        nsecs_t getStartTime() const { return mTraceStartTime; }

    private:
        void OnSetup(const SetupArgs&) override {};
        void OnSetup(const SetupArgs&) override {};
        void OnStart(const StartArgs&) override{};
        void OnStart(const StartArgs&) override { mTraceStartTime = systemTime(); };
        void OnStop(const StopArgs&) override {};
        void OnStop(const StopArgs&) override {};

        nsecs_t mTraceStartTime = 0;
    };
    };


    /*
    /*
@@ -390,7 +399,8 @@ public:
        // is enabled. monoBootOffset is the difference between SYSTEM_TIME_BOOTTIME
        // is enabled. monoBootOffset is the difference between SYSTEM_TIME_BOOTTIME
        // and SYSTEM_TIME_MONOTONIC.
        // and SYSTEM_TIME_MONOTONIC.
        nsecs_t trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
        nsecs_t trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                      nsecs_t previousPredictionPresentTime) const;
                      nsecs_t previousPredictionPresentTime,
                      bool filterFramesBeforeTraceStarts) const;
        // Sets the token, vsyncPeriod, predictions and SF start time.
        // Sets the token, vsyncPeriod, predictions and SF start time.
        void onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
        void onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
                        std::optional<TimelineItem> predictions, nsecs_t wakeUpTime);
                        std::optional<TimelineItem> predictions, nsecs_t wakeUpTime);
@@ -424,10 +434,13 @@ public:


    private:
    private:
        void dump(std::string& result, nsecs_t baseTime) const;
        void dump(std::string& result, nsecs_t baseTime) const;
        void tracePredictions(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
        void tracePredictions(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
        void traceActuals(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
                              bool filterFramesBeforeTraceStarts) const;
        void traceActuals(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                          bool filterFramesBeforeTraceStarts) const;
        void addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
        void addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
                             nsecs_t previousActualPresentTime) const;
                             nsecs_t previousActualPresentTime,
                             bool filterFramesBeforeTraceStarts) const;
        void classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
        void classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
                          nsecs_t previousPresentTime);
                          nsecs_t previousPresentTime);


@@ -471,7 +484,8 @@ public:
    };
    };


    FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
    FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
                  JankClassificationThresholds thresholds = {}, bool useBootTimeClock = true);
                  JankClassificationThresholds thresholds = {}, bool useBootTimeClock = true,
                  bool filterFramesBeforeTraceStarts = true);
    ~FrameTimeline() = default;
    ~FrameTimeline() = default;


    frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
    frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
@@ -516,6 +530,7 @@ private:
    TraceCookieCounter mTraceCookieCounter;
    TraceCookieCounter mTraceCookieCounter;
    mutable std::mutex mMutex;
    mutable std::mutex mMutex;
    const bool mUseBootTimeClock;
    const bool mUseBootTimeClock;
    const bool mFilterFramesBeforeTraceStarts;
    uint32_t mMaxDisplayFrames;
    uint32_t mMaxDisplayFrames;
    std::shared_ptr<TimeStats> mTimeStats;
    std::shared_ptr<TimeStats> mTimeStats;
    const pid_t mSurfaceFlingerPid;
    const pid_t mSurfaceFlingerPid;
+2 −0
Original line number Original line Diff line number Diff line
@@ -143,6 +143,7 @@ void FlagManager::dump(std::string& result) const {
    DUMP_READ_ONLY_FLAG(ce_fence_promise);
    DUMP_READ_ONLY_FLAG(ce_fence_promise);
    DUMP_READ_ONLY_FLAG(idle_screen_refresh_rate_timeout);
    DUMP_READ_ONLY_FLAG(idle_screen_refresh_rate_timeout);
    DUMP_READ_ONLY_FLAG(graphite_renderengine);
    DUMP_READ_ONLY_FLAG(graphite_renderengine);
    DUMP_READ_ONLY_FLAG(filter_frames_before_trace_starts);
    DUMP_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed);
    DUMP_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed);
    DUMP_READ_ONLY_FLAG(deprecate_vsync_sf);
    DUMP_READ_ONLY_FLAG(deprecate_vsync_sf);
    DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter);
    DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter);
@@ -248,6 +249,7 @@ FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, "");
FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "")
FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "")
FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
FLAG_MANAGER_READ_ONLY_FLAG(filter_frames_before_trace_starts, "")
FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, "");
FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, "");
FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, "");
FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, "");
+1 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ public:
    bool ce_fence_promise() const;
    bool ce_fence_promise() const;
    bool idle_screen_refresh_rate_timeout() const;
    bool idle_screen_refresh_rate_timeout() const;
    bool graphite_renderengine() const;
    bool graphite_renderengine() const;
    bool filter_frames_before_trace_starts() const;
    bool latch_unsignaled_with_auto_refresh_changed() const;
    bool latch_unsignaled_with_auto_refresh_changed() const;
    bool deprecate_vsync_sf() const;
    bool deprecate_vsync_sf() const;
    bool allow_n_vsyncs_in_targeter() const;
    bool allow_n_vsyncs_in_targeter() const;
+11 −0
Original line number Original line Diff line number Diff line
@@ -65,6 +65,17 @@ flag {
  }
  }
} # detached_mirror
} # detached_mirror


flag {
  name: "filter_frames_before_trace_starts"
  namespace: "core_graphics"
  description: "Do not trace FrameTimeline events for frames started before the trace started"
  bug: "364194637"
  is_fixed_read_only: true
  metadata {
    purpose: PURPOSE_BUGFIX
  }
} # filter_frames_before_trace_starts

flag {
flag {
  name: "flush_buffer_slots_to_uncache"
  name: "flush_buffer_slots_to_uncache"
  namespace: "core_graphics"
  namespace: "core_graphics"
Loading