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

Commit 8b9e612e authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: Add setFrameRate vote to TimeStats

Test: SF unit tests
Bug: 172939060
Change-Id: I60ea90c6f31b4bb22f39dea654de14e6c354974c
parent 4fd10d8d
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -325,6 +325,37 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
    mRefreshPending = false;
    return hasReadyFrame();
}
namespace {
TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) {
    using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility;
    using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness;
    const auto frameRateCompatibility = [frameRate] {
        switch (frameRate.type) {
            case Layer::FrameRateCompatibility::Default:
                return FrameRateCompatibility::Default;
            case Layer::FrameRateCompatibility::ExactOrMultiple:
                return FrameRateCompatibility::ExactOrMultiple;
            default:
                return FrameRateCompatibility::Undefined;
        }
    }();

    const auto seamlessness = [frameRate] {
        switch (frameRate.seamlessness) {
            case scheduler::Seamlessness::OnlySeamless:
                return Seamlessness::ShouldBeSeamless;
            case scheduler::Seamlessness::SeamedAndSeamless:
                return Seamlessness::NotRequired;
            default:
                return Seamlessness::Undefined;
        }
    }();

    return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(),
                                       .frameRateCompatibility = frameRateCompatibility,
                                       .seamlessness = seamlessness};
}
} // namespace

bool BufferLayer::onPostComposition(const DisplayDevice* display,
                                    const std::shared_ptr<FenceTime>& glDoneFence,
@@ -377,7 +408,9 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display,
    const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
    if (presentFence->isValid()) {
        mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
                                              refreshRate, renderRate);
                                              refreshRate, renderRate,
                                              frameRateToSetFrameRateVotePayload(
                                                      mDrawingState.frameRate));
        mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
                                           presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
        mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
@@ -389,7 +422,9 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display,
        // timestamp instead.
        const nsecs_t actualPresentTime = display->getRefreshTimestamp();
        mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
                                             refreshRate, renderRate);
                                             refreshRate, renderRate,
                                             frameRateToSetFrameRateVotePayload(
                                                     mDrawingState.frameRate));
        mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
                                               actualPresentTime,
                                               FrameTracer::FrameEvent::PRESENT_FENCE);
+23 −10
Original line number Diff line number Diff line
@@ -89,12 +89,15 @@ std::string histogramToProtoByteString(const std::unordered_map<int32_t, int32_t
    return byteString;
}

std::string frameRateVoteToProtoByteString(float refreshRate, int frameRateCompatibility,
                                           int seamlessness) {
std::string frameRateVoteToProtoByteString(
        float refreshRate,
        TimeStats::SetFrameRateVote::FrameRateCompatibility frameRateCompatibility,
        TimeStats::SetFrameRateVote::Seamlessness seamlessness) {
    util::ProtoOutputStream proto;
    proto.write(android::util::FIELD_TYPE_FLOAT | 1 /* field id */, refreshRate);
    proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */, frameRateCompatibility);
    proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, seamlessness);
    proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */,
                static_cast<int>(frameRateCompatibility));
    proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, static_cast<int>(seamlessness));

    std::string byteString;
    proto.serializeToString(&byteString);
@@ -229,7 +232,10 @@ AStatsManager_PullAtomCallbackReturn TimeStats::populateLayerAtom(AStatsEventLis
        mStatsDelegate->statsEventWriteInt32(
                event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket
        mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket
        std::string frameRateVoteBytes = frameRateVoteToProtoByteString(0.0, 0, 0);
        std::string frameRateVoteBytes =
                frameRateVoteToProtoByteString(layer->setFrameRateVote.frameRate,
                                               layer->setFrameRateVote.frameRateCompatibility,
                                               layer->setFrameRateVote.seamlessness);
        mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameRateVoteBytes.c_str(),
                                                 frameRateVoteBytes.size()); // set_frame_rate_vote
        std::string appDeadlineMissedBytes =
@@ -468,8 +474,10 @@ static int32_t clampToSmallestBucket(Fps fps, size_t bucketWidth) {
}

void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate,
                                                   std::optional<Fps> renderRate) {
                                                   std::optional<Fps> renderRate,
                                                   SetFrameRateVote frameRateVote) {
    ATRACE_CALL();
    ALOGV("[%d]-flushAvailableRecordsToStatsLocked", layerId);

    LayerRecord& layerRecord = mTimeStatsTracker[layerId];
    TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord;
@@ -501,6 +509,9 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayR
                displayStats.stats[layerKey].uid = uid;
                displayStats.stats[layerKey].layerName = layerName;
            }
            if (frameRateVote.frameRate > 0.0f) {
                displayStats.stats[layerKey].setFrameRateVote = frameRateVote;
            }
            TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey];
            timeStatsLayer.totalFrames++;
            timeStatsLayer.droppedFrames += layerRecord.droppedFrames;
@@ -724,7 +735,8 @@ void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber,
}

void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime,
                               Fps displayRefreshRate, std::optional<Fps> renderRate) {
                               Fps displayRefreshRate, std::optional<Fps> renderRate,
                               SetFrameRateVote frameRateVote) {
    if (!mEnabled.load()) return;

    ATRACE_CALL();
@@ -743,12 +755,13 @@ void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t pr
        layerRecord.waitData++;
    }

    flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
    flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote);
}

void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber,
                                const std::shared_ptr<FenceTime>& presentFence,
                                Fps displayRefreshRate, std::optional<Fps> renderRate) {
                                Fps displayRefreshRate, std::optional<Fps> renderRate,
                                SetFrameRateVote frameRateVote) {
    if (!mEnabled.load()) return;

    ATRACE_CALL();
@@ -768,7 +781,7 @@ void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber,
        layerRecord.waitData++;
    }

    flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
    flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote);
}

static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL |
+11 −5
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ namespace android {

class TimeStats {
public:
    using SetFrameRateVote = TimeStatsHelper::SetFrameRateVote;

    virtual ~TimeStats() = default;

    // Called once boot has been finished to perform additional capabilities,
@@ -110,10 +112,12 @@ public:
    // SetPresent{Time, Fence} are not expected to be called in the critical
    // rendering path, as they flush prior fences if those fences have fired.
    virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime,
                                Fps displayRefreshRate, std::optional<Fps> renderRate) = 0;
                                Fps displayRefreshRate, std::optional<Fps> renderRate,
                                SetFrameRateVote frameRateVote) = 0;
    virtual void setPresentFence(int32_t layerId, uint64_t frameNumber,
                                 const std::shared_ptr<FenceTime>& presentFence,
                                 Fps displayRefreshRate, std::optional<Fps> renderRate) = 0;
                                 Fps displayRefreshRate, std::optional<Fps> renderRate,
                                 SetFrameRateVote frameRateVote) = 0;

    // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName}
    // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the
@@ -307,10 +311,11 @@ public:
    void setAcquireFence(int32_t layerId, uint64_t frameNumber,
                         const std::shared_ptr<FenceTime>& acquireFence) override;
    void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime,
                        Fps displayRefreshRate, std::optional<Fps> renderRate) override;
                        Fps displayRefreshRate, std::optional<Fps> renderRate,
                        SetFrameRateVote frameRateVote) override;
    void setPresentFence(int32_t layerId, uint64_t frameNumber,
                         const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate,
                         std::optional<Fps> renderRate) override;
                         std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) override;

    void incrementJankyFrames(const JankyFramesInfo& info) override;
    // Clean up the layer record
@@ -334,7 +339,8 @@ private:
    AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data);
    bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord);
    void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate,
                                            std::optional<Fps> renderRate);
                                            std::optional<Fps> renderRate,
                                            SetFrameRateVote frameRateVote);
    void flushPowerTimeLocked();
    void flushAvailableGlobalRecordsToStatsLocked();
    bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName);
+33 −0
Original line number Diff line number Diff line
@@ -91,6 +91,37 @@ std::string TimeStatsHelper::JankPayload::toString() const {
    return result;
}

std::string TimeStatsHelper::SetFrameRateVote::toString(FrameRateCompatibility compatibility) {
    switch (compatibility) {
        case FrameRateCompatibility::Undefined:
            return "Undefined";
        case FrameRateCompatibility::Default:
            return "Default";
        case FrameRateCompatibility::ExactOrMultiple:
            return "ExactOrMultiple";
    }
}

std::string TimeStatsHelper::SetFrameRateVote::toString(Seamlessness seamlessness) {
    switch (seamlessness) {
        case Seamlessness::Undefined:
            return "Undefined";
        case Seamlessness::ShouldBeSeamless:
            return "ShouldBeSeamless";
        case Seamlessness::NotRequired:
            return "NotRequired";
    }
}

std::string TimeStatsHelper::SetFrameRateVote::toString() const {
    std::string result;
    StringAppendF(&result, "frameRate = %.2f\n", frameRate);
    StringAppendF(&result, "frameRateCompatibility = %s\n",
                  toString(frameRateCompatibility).c_str());
    StringAppendF(&result, "seamlessness = %s\n", toString(seamlessness).c_str());
    return result;
}

std::string TimeStatsHelper::TimeStatsLayer::toString() const {
    std::string result = "\n";
    StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket);
@@ -104,6 +135,8 @@ std::string TimeStatsHelper::TimeStatsLayer::toString() const {
    StringAppendF(&result, "badDesiredPresentFrames = %d\n", badDesiredPresentFrames);
    result.append("Jank payload for this layer:\n");
    result.append(jankPayload.toString());
    result.append("SetFrateRate vote for this layer:\n");
    result.append(setFrameRateVote.toString());
    const auto iter = deltas.find("present2present");
    if (iter != deltas.end()) {
        const float averageTime = iter->second.averageTime();
+23 −0
Original line number Diff line number Diff line
@@ -55,6 +55,28 @@ public:
        std::string toString() const;
    };

    struct SetFrameRateVote {
        float frameRate = 0;

        // Needs to be in sync with atoms.proto
        enum class FrameRateCompatibility {
            Undefined = 0,
            Default = 1,
            ExactOrMultiple = 2,
        } frameRateCompatibility = FrameRateCompatibility::Undefined;

        // Needs to be in sync with atoms.proto
        enum class Seamlessness {
            Undefined = 0,
            ShouldBeSeamless = 1,
            NotRequired = 2,
        } seamlessness = Seamlessness::Undefined;

        static std::string toString(FrameRateCompatibility);
        static std::string toString(Seamlessness);
        std::string toString() const;
    };

    class TimeStatsLayer {
    public:
        uid_t uid;
@@ -67,6 +89,7 @@ public:
        int32_t lateAcquireFrames = 0;
        int32_t badDesiredPresentFrames = 0;
        JankPayload jankPayload;
        SetFrameRateVote setFrameRateVote;
        std::unordered_map<std::string, Histogram> deltas;

        std::string toString() const;
Loading