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

Commit 9a29e67a authored by Alec Mouri's avatar Alec Mouri
Browse files

Expose shared timeline counters into telemetry:

* Add UID into both shared timeline and timestats tracking: due to BLAST
APIs, layer name is insufficient for identifying applications
* Plumb through jank counters from shared timeline into timestats and WW
* Fixed bug where SurfaceflingerDeadlineMissed was not being tracked.

One caveat is that transactions are tracked in shared timeline, so as
a consequence timestats will start tracking them as well.

Bug: 171309796
Test: builds, boots
Test: statsd_testdrive
Test: libsurfacefinger_unittest
Test: dumpsys SurfaceFlinger --timestats -dump

Change-Id: I71057c0976ce81bbb605e126cb30b9d6f06c5873
parent fac95177
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -442,7 +442,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
        }
        }


        auto surfaceFrame =
        auto surfaceFrame =
                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mName, mFrameTimelineVsyncId);
                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mOwnerUid, mName, mName,
                                                                     mFrameTimelineVsyncId);
        surfaceFrame->setActualQueueTime(systemTime());
        surfaceFrame->setActualQueueTime(systemTime());


        mQueueItems.push_back({item, std::move(surfaceFrame)});
        mQueueItems.push_back({item, std::move(surfaceFrame)});
@@ -480,7 +481,8 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
        }
        }


        auto surfaceFrame =
        auto surfaceFrame =
                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mName, mFrameTimelineVsyncId);
                mFlinger->mFrameTimeline->createSurfaceFrameForToken(mOwnerUid, mName, mName,
                                                                     mFrameTimelineVsyncId);
        surfaceFrame->setActualQueueTime(systemTime());
        surfaceFrame->setActualQueueTime(systemTime());
        mQueueItems[mQueueItems.size() - 1].item = item;
        mQueueItems[mQueueItems.size() - 1].item = item;
        mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame);
        mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame);
+1 −1
Original line number Original line Diff line number Diff line
@@ -276,7 +276,7 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence


    const int32_t layerId = getSequence();
    const int32_t layerId = getSequence();
    mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(),
    mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(),
                                      postTime);
                                      mOwnerUid, postTime);
    desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;
    desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;
    mCurrentState.desiredPresentTime = desiredPresentTime;
    mCurrentState.desiredPresentTime = desiredPresentTime;


+2 −0
Original line number Original line Diff line number Diff line
@@ -5,10 +5,12 @@ cc_library_static {
        "FrameTimeline.cpp",
        "FrameTimeline.cpp",
    ],
    ],
    shared_libs: [
    shared_libs: [
        "android.hardware.graphics.composer@2.4",
        "libbase",
        "libbase",
        "libcutils",
        "libcutils",
        "liblog",
        "liblog",
        "libgui",
        "libgui",
        "libtimestats",
        "libui",
        "libui",
        "libutils",
        "libutils",
    ],
    ],
+62 −36
Original line number Original line Diff line number Diff line
@@ -93,19 +93,19 @@ std::string toString(PredictionState predictionState) {
    }
    }
}
}


std::string toString(JankType jankType) {
std::string toString(TimeStats::JankType jankType) {
    switch (jankType) {
    switch (jankType) {
        case JankType::None:
        case TimeStats::JankType::None:
            return "None";
            return "None";
        case JankType::Display:
        case TimeStats::JankType::Display:
            return "Composer/Display - outside SF and App";
            return "Composer/Display - outside SF and App";
        case JankType::SurfaceFlingerDeadlineMissed:
        case TimeStats::JankType::SurfaceFlingerDeadlineMissed:
            return "SurfaceFlinger Deadline Missed";
            return "SurfaceFlinger Deadline Missed";
        case JankType::AppDeadlineMissed:
        case TimeStats::JankType::AppDeadlineMissed:
            return "App Deadline Missed";
            return "App Deadline Missed";
        case JankType::PredictionExpired:
        case TimeStats::JankType::PredictionExpired:
            return "Prediction Expired";
            return "Prediction Expired";
        case JankType::SurfaceFlingerEarlyLatch:
        case TimeStats::JankType::SurfaceFlingerEarlyLatch:
            return "SurfaceFlinger Early Latch";
            return "SurfaceFlinger Early Latch";
        default:
        default:
            return "Unclassified";
            return "Unclassified";
@@ -177,15 +177,18 @@ void TokenManager::flushTokens(nsecs_t flushTime) {
    }
    }
}
}


SurfaceFrame::SurfaceFrame(const std::string& layerName, PredictionState predictionState,
SurfaceFrame::SurfaceFrame(uid_t ownerUid, std::string layerName, std::string debugName,
                           PredictionState predictionState,
                           frametimeline::TimelineItem&& predictions)
                           frametimeline::TimelineItem&& predictions)
      : mLayerName(layerName),
      : mOwnerUid(ownerUid),
        mLayerName(std::move(layerName)),
        mDebugName(std::move(debugName)),
        mPresentState(PresentState::Unknown),
        mPresentState(PresentState::Unknown),
        mPredictionState(predictionState),
        mPredictionState(predictionState),
        mPredictions(predictions),
        mPredictions(predictions),
        mActuals({0, 0, 0}),
        mActuals({0, 0, 0}),
        mActualQueueTime(0),
        mActualQueueTime(0),
        mJankType(JankType::None),
        mJankType(TimeStats::JankType::None),
        mJankMetadata(0) {}
        mJankMetadata(0) {}


void SurfaceFrame::setPresentState(PresentState state) {
void SurfaceFrame::setPresentState(PresentState state) {
@@ -227,17 +230,25 @@ void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) {
    mActuals.presentTime = presentTime;
    mActuals.presentTime = presentTime;
}
}


void SurfaceFrame::setJankInfo(JankType jankType, int32_t jankMetadata) {
void SurfaceFrame::setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata) {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    mJankType = jankType;
    mJankType = jankType;
    mJankMetadata = jankMetadata;
    mJankMetadata = jankMetadata;
}
}


JankType SurfaceFrame::getJankType() const {
TimeStats::JankType SurfaceFrame::getJankType() const {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    return mJankType;
    return mJankType;
}
}


uid_t SurfaceFrame::getOwnerUid() const {
    return mOwnerUid;
}

const std::string& SurfaceFrame::getName() const {
    return mLayerName;
}

nsecs_t SurfaceFrame::getBaseTime() const {
nsecs_t SurfaceFrame::getBaseTime() const {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    nsecs_t baseTime = std::numeric_limits<nsecs_t>::max();
    nsecs_t baseTime = std::numeric_limits<nsecs_t>::max();
@@ -267,8 +278,8 @@ std::string presentStateToString(SurfaceFrame::PresentState presentState) {
void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) {
void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    StringAppendF(&result, "%s", indent.c_str());
    StringAppendF(&result, "%s", indent.c_str());
    StringAppendF(&result, "Layer - %s", mLayerName.c_str());
    StringAppendF(&result, "Layer - %s", mDebugName.c_str());
    if (mJankType != JankType::None) {
    if (mJankType != TimeStats::JankType::None) {
        // Easily identify a janky Surface Frame in the dump
        // Easily identify a janky Surface Frame in the dump
        StringAppendF(&result, " [*] ");
        StringAppendF(&result, " [*] ");
    }
    }
@@ -285,33 +296,35 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t
    dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
    dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
}
}


FrameTimeline::FrameTimeline()
FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats)
      : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()),
      : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()),
        mMaxDisplayFrames(kDefaultMaxDisplayFrames) {}
        mMaxDisplayFrames(kDefaultMaxDisplayFrames),
        mTimeStats(std::move(timeStats)) {}


FrameTimeline::DisplayFrame::DisplayFrame()
FrameTimeline::DisplayFrame::DisplayFrame()
      : surfaceFlingerPredictions(TimelineItem()),
      : surfaceFlingerPredictions(TimelineItem()),
        surfaceFlingerActuals(TimelineItem()),
        surfaceFlingerActuals(TimelineItem()),
        predictionState(PredictionState::None),
        predictionState(PredictionState::None),
        jankType(JankType::None),
        jankType(TimeStats::JankType::None),
        jankMetadata(0) {
        jankMetadata(0) {
    this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
    this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
}
}


std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
        const std::string& layerName, std::optional<int64_t> token) {
        uid_t uid, std::string layerName, std::string debugName, std::optional<int64_t> token) {
    ATRACE_CALL();
    ATRACE_CALL();
    if (!token) {
    if (!token) {
        return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::None,
        return std::make_unique<impl::SurfaceFrame>(uid, std::move(layerName), std::move(debugName),
                                                    TimelineItem());
                                                    PredictionState::None, TimelineItem());
    }
    }
    std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
    std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
    if (predictions) {
    if (predictions) {
        return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::Valid,
        return std::make_unique<impl::SurfaceFrame>(uid, std::move(layerName), std::move(debugName),
                                                    PredictionState::Valid,
                                                    std::move(*predictions));
                                                    std::move(*predictions));
    }
    }
    return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::Expired,
    return std::make_unique<impl::SurfaceFrame>(uid, std::move(layerName), std::move(debugName),
                                                TimelineItem());
                                                PredictionState::Expired, TimelineItem());
}
}


void FrameTimeline::addSurfaceFrame(
void FrameTimeline::addSurfaceFrame(
@@ -359,6 +372,7 @@ void FrameTimeline::flushPendingPresentFences() {
            }
            }
        }
        }
        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
            int32_t totalJankReasons = TimeStats::JankType::None;
            auto& displayFrame = pendingPresentFence.second;
            auto& displayFrame = pendingPresentFence.second;
            displayFrame->surfaceFlingerActuals.presentTime = signalTime;
            displayFrame->surfaceFlingerActuals.presentTime = signalTime;


@@ -377,21 +391,26 @@ void FrameTimeline::flushPendingPresentFences() {
                    displayFrame->jankMetadata |= EarlyFinish;
                    displayFrame->jankMetadata |= EarlyFinish;
                }
                }


                if (displayFrame->jankMetadata & EarlyFinish & EarlyPresent) {
                if ((displayFrame->jankMetadata & EarlyFinish) &&
                    displayFrame->jankType = JankType::SurfaceFlingerEarlyLatch;
                    (displayFrame->jankMetadata & EarlyPresent)) {
                } else if (displayFrame->jankMetadata & LateFinish & LatePresent) {
                    displayFrame->jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
                    displayFrame->jankType = JankType::SurfaceFlingerDeadlineMissed;
                } else if ((displayFrame->jankMetadata & LateFinish) &&
                           (displayFrame->jankMetadata & LatePresent)) {
                    displayFrame->jankType = TimeStats::JankType::SurfaceFlingerDeadlineMissed;
                } else if (displayFrame->jankMetadata & EarlyPresent ||
                } else if (displayFrame->jankMetadata & EarlyPresent ||
                           displayFrame->jankMetadata & LatePresent) {
                           displayFrame->jankMetadata & LatePresent) {
                    // Cases where SF finished early but frame was presented late and vice versa
                    // Cases where SF finished early but frame was presented late and vice versa
                    displayFrame->jankType = JankType::Display;
                    displayFrame->jankType = TimeStats::JankType::Display;
                }
                }
            }
            }

            if (std::abs(sfActuals.startTime - sfPredictions.startTime) > kSFStartThreshold) {
            if (std::abs(sfActuals.startTime - sfPredictions.startTime) > kSFStartThreshold) {
                displayFrame->jankMetadata |=
                displayFrame->jankMetadata |=
                        sfActuals.startTime > sfPredictions.startTime ? LateStart : EarlyStart;
                        sfActuals.startTime > sfPredictions.startTime ? LateStart : EarlyStart;
            }
            }


            totalJankReasons |= displayFrame->jankType;

            for (auto& surfaceFrame : displayFrame->surfaceFrames) {
            for (auto& surfaceFrame : displayFrame->surfaceFrames) {
                if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
                if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
                    // Only presented SurfaceFrames need to be updated
                    // Only presented SurfaceFrames need to be updated
@@ -401,13 +420,13 @@ void FrameTimeline::flushPendingPresentFences() {
                    const auto& predictionState = surfaceFrame->getPredictionState();
                    const auto& predictionState = surfaceFrame->getPredictionState();
                    if (predictionState == PredictionState::Expired) {
                    if (predictionState == PredictionState::Expired) {
                        // Jank analysis cannot be done on apps that don't use predictions
                        // Jank analysis cannot be done on apps that don't use predictions
                        surfaceFrame->setJankInfo(JankType::PredictionExpired, 0);
                        surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0);
                        continue;
                        continue;
                    } else if (predictionState == PredictionState::Valid) {
                    } else if (predictionState == PredictionState::Valid) {
                        const auto& actuals = surfaceFrame->getActuals();
                        const auto& actuals = surfaceFrame->getActuals();
                        const auto& predictions = surfaceFrame->getPredictions();
                        const auto& predictions = surfaceFrame->getPredictions();
                        int32_t jankMetadata = 0;
                        int32_t jankMetadata = 0;
                        JankType jankType = JankType::None;
                        TimeStats::JankType jankType = TimeStats::JankType::None;
                        if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) {
                        if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) {
                            jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish
                            jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish
                                                                                  : EarlyFinish;
                                                                                  : EarlyFinish;
@@ -419,19 +438,26 @@ void FrameTimeline::flushPendingPresentFences() {
                                    : EarlyPresent;
                                    : EarlyPresent;
                        }
                        }
                        if (jankMetadata & EarlyPresent) {
                        if (jankMetadata & EarlyPresent) {
                            jankType = JankType::SurfaceFlingerEarlyLatch;
                            jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
                        } else if (jankMetadata & LatePresent) {
                        } else if (jankMetadata & LatePresent) {
                            if (jankMetadata & EarlyFinish) {
                            if (jankMetadata & EarlyFinish) {
                                // TODO(b/169890654): Classify this properly
                                // TODO(b/169890654): Classify this properly
                                jankType = JankType::Display;
                                jankType = TimeStats::JankType::Display;
                            } else {
                            } else {
                                jankType = JankType::AppDeadlineMissed;
                                jankType = TimeStats::JankType::AppDeadlineMissed;
                            }
                            }
                        }
                        }

                        totalJankReasons |= jankType;
                        mTimeStats->incrementJankyFrames(surfaceFrame->getOwnerUid(),
                                                         surfaceFrame->getName(),
                                                         jankType | displayFrame->jankType);
                        surfaceFrame->setJankInfo(jankType, jankMetadata);
                        surfaceFrame->setJankInfo(jankType, jankMetadata);
                    }
                    }
                }
                }
            }
            }

            mTimeStats->incrementJankyFrames(totalJankReasons);
        }
        }


        mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
        mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
@@ -467,7 +493,7 @@ nsecs_t FrameTimeline::findBaseTime(const std::shared_ptr<DisplayFrame>& display
void FrameTimeline::dumpDisplayFrame(std::string& result,
void FrameTimeline::dumpDisplayFrame(std::string& result,
                                     const std::shared_ptr<DisplayFrame>& displayFrame,
                                     const std::shared_ptr<DisplayFrame>& displayFrame,
                                     nsecs_t baseTime) {
                                     nsecs_t baseTime) {
    if (displayFrame->jankType != JankType::None) {
    if (displayFrame->jankType != TimeStats::JankType::None) {
        // Easily identify a janky Display Frame in the dump
        // Easily identify a janky Display Frame in the dump
        StringAppendF(&result, " [*] ");
        StringAppendF(&result, " [*] ");
    }
    }
@@ -501,11 +527,11 @@ void FrameTimeline::dumpJank(std::string& result) {
    nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
    nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
    for (size_t i = 0; i < mDisplayFrames.size(); i++) {
    for (size_t i = 0; i < mDisplayFrames.size(); i++) {
        const auto& displayFrame = mDisplayFrames[i];
        const auto& displayFrame = mDisplayFrames[i];
        if (displayFrame->jankType == JankType::None) {
        if (displayFrame->jankType == TimeStats::JankType::None) {
            // Check if any Surface Frame has been janky
            // Check if any Surface Frame has been janky
            bool isJanky = false;
            bool isJanky = false;
            for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
            for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
                if (surfaceFrame->getJankType() != JankType::None) {
                if (surfaceFrame->getJankType() != TimeStats::JankType::None) {
                    isJanky = true;
                    isJanky = true;
                    break;
                    break;
                }
                }
+21 −31
Original line number Original line Diff line number Diff line
@@ -16,9 +16,7 @@


#pragma once
#pragma once


#include <deque>
#include <../TimeStats/TimeStats.h>
#include <mutex>

#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposer.h>
#include <ui/FenceTime.h>
#include <ui/FenceTime.h>
#include <utils/RefBase.h>
#include <utils/RefBase.h>
@@ -26,26 +24,10 @@
#include <utils/Timers.h>
#include <utils/Timers.h>
#include <utils/Vector.h>
#include <utils/Vector.h>


namespace android::frametimeline {
#include <deque>
#include <mutex>


/*
namespace android::frametimeline {
 * The type of jank that is associated with a Display/Surface frame
 */
enum class JankType {
    // No Jank
    None,
    // Jank not related to SurfaceFlinger or the App
    Display,
    // SF took too long on the CPU
    SurfaceFlingerDeadlineMissed,
    // Either App or GPU took too long on the frame
    AppDeadlineMissed,
    // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a jank
    // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame.
    PredictionExpired,
    // Latching a buffer early might cause an early present of the frame
    SurfaceFlingerEarlyLatch,
};


enum JankMetadata {
enum JankMetadata {
    // Frame was presented earlier than expected
    // Frame was presented earlier than expected
@@ -147,8 +129,10 @@ public:


    // Create a new surface frame, set the predictions based on a token and return it to the caller.
    // Create a new surface frame, set the predictions based on a token and return it to the caller.
    // Sets the PredictionState of SurfaceFrame.
    // Sets the PredictionState of SurfaceFrame.
    // Debug name is the human-readable debugging string for dumpsys.
    virtual std::unique_ptr<SurfaceFrame> createSurfaceFrameForToken(
    virtual std::unique_ptr<SurfaceFrame> createSurfaceFrameForToken(
            const std::string& layerName, std::optional<int64_t> token) = 0;
            uid_t uid, std::string layerName, std::string debugName,
            std::optional<int64_t> token) = 0;


    // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be
    // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be
    // composited into one display frame.
    // composited into one display frame.
@@ -206,8 +190,8 @@ private:


class SurfaceFrame : public android::frametimeline::SurfaceFrame {
class SurfaceFrame : public android::frametimeline::SurfaceFrame {
public:
public:
    SurfaceFrame(const std::string& layerName, PredictionState predictionState,
    SurfaceFrame(uid_t uid, std::string layerName, std::string debugName,
                 TimelineItem&& predictions);
                 PredictionState predictionState, TimelineItem&& predictions);
    ~SurfaceFrame() = default;
    ~SurfaceFrame() = default;


    TimelineItem getPredictions() const override { return mPredictions; };
    TimelineItem getPredictions() const override { return mPredictions; };
@@ -221,32 +205,37 @@ public:
    void setAcquireFenceTime(nsecs_t acquireFenceTime) override;
    void setAcquireFenceTime(nsecs_t acquireFenceTime) override;
    void setPresentState(PresentState state) override;
    void setPresentState(PresentState state) override;
    void setActualPresentTime(nsecs_t presentTime);
    void setActualPresentTime(nsecs_t presentTime);
    void setJankInfo(JankType jankType, int32_t jankMetadata);
    void setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata);
    JankType getJankType() const;
    TimeStats::JankType getJankType() const;
    nsecs_t getBaseTime() const;
    nsecs_t getBaseTime() const;
    uid_t getOwnerUid() const;
    const std::string& getName() const;
    // All the timestamps are dumped relative to the baseTime
    // All the timestamps are dumped relative to the baseTime
    void dump(std::string& result, const std::string& indent, nsecs_t baseTime);
    void dump(std::string& result, const std::string& indent, nsecs_t baseTime);


private:
private:
    const uid_t mOwnerUid;
    const std::string mLayerName;
    const std::string mLayerName;
    const std::string mDebugName;
    PresentState mPresentState GUARDED_BY(mMutex);
    PresentState mPresentState GUARDED_BY(mMutex);
    const PredictionState mPredictionState;
    const PredictionState mPredictionState;
    const TimelineItem mPredictions;
    const TimelineItem mPredictions;
    TimelineItem mActuals GUARDED_BY(mMutex);
    TimelineItem mActuals GUARDED_BY(mMutex);
    nsecs_t mActualQueueTime GUARDED_BY(mMutex);
    nsecs_t mActualQueueTime GUARDED_BY(mMutex);
    mutable std::mutex mMutex;
    mutable std::mutex mMutex;
    JankType mJankType GUARDED_BY(mMutex);    // Enum for the type of jank
    TimeStats::JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank
    int32_t mJankMetadata GUARDED_BY(mMutex); // Additional details about the jank
    int32_t mJankMetadata GUARDED_BY(mMutex); // Additional details about the jank
};
};


class FrameTimeline : public android::frametimeline::FrameTimeline {
class FrameTimeline : public android::frametimeline::FrameTimeline {
public:
public:
    FrameTimeline();
    FrameTimeline(std::shared_ptr<TimeStats> timeStats);
    ~FrameTimeline() = default;
    ~FrameTimeline() = default;


    frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
    frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
    std::unique_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken(
    std::unique_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForToken(
            const std::string& layerName, std::optional<int64_t> token) override;
            uid_t ownerUid, std::string layerName, std::string debugName,
            std::optional<int64_t> token) override;
    void addSurfaceFrame(std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame,
    void addSurfaceFrame(std::unique_ptr<frametimeline::SurfaceFrame> surfaceFrame,
                         SurfaceFrame::PresentState state) override;
                         SurfaceFrame::PresentState state) override;
    void setSfWakeUp(int64_t token, nsecs_t wakeupTime) override;
    void setSfWakeUp(int64_t token, nsecs_t wakeupTime) override;
@@ -278,7 +267,7 @@ private:
        std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames;
        std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames;


        PredictionState predictionState;
        PredictionState predictionState;
        JankType jankType = JankType::None; // Enum for the type of jank
        TimeStats::JankType jankType = TimeStats::JankType::None; // Enum for the type of jank
        int32_t jankMetadata = 0x0;         // Additional details about the jank
        int32_t jankMetadata = 0x0;         // Additional details about the jank
    };
    };


@@ -300,6 +289,7 @@ private:
    TokenManager mTokenManager;
    TokenManager mTokenManager;
    std::mutex mMutex;
    std::mutex mMutex;
    uint32_t mMaxDisplayFrames;
    uint32_t mMaxDisplayFrames;
    std::shared_ptr<TimeStats> mTimeStats;
    static constexpr uint32_t kDefaultMaxDisplayFrames = 64;
    static constexpr uint32_t kDefaultMaxDisplayFrames = 64;
    // The initial container size for the vector<SurfaceFrames> inside display frame. Although this
    // 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 display
    // number doesn't represent any bounds on the number of surface frames that can go in a display
Loading