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

Commit 3a226d2a authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

SF TimeStats: add primary display on time metrics

Bug: b/79872109
Test: dumpsys SurfaceFlinger --timestats <options>
Change-Id: Iae949ce4648f2f6f4d38164d8e620d62970c0af1
parent dc224041
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -4135,6 +4135,10 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int
        getHwComposer().setPowerMode(type, mode);
        getHwComposer().setPowerMode(type, mode);
    }
    }


    if (display->isPrimary()) {
        mTimeStats.setPowerMode(mode);
    }

    ALOGD("Finished setting power mode %d on display %d", mode, displayId);
    ALOGD("Finished setting power mode %d on display %d", mode, displayId);
}
}


+39 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
#include <log/log.h>
#include <log/log.h>


#include <utils/String8.h>
#include <utils/String8.h>
#include <utils/Timers.h>
#include <utils/Trace.h>
#include <utils/Trace.h>


#include <algorithm>
#include <algorithm>
@@ -445,6 +446,39 @@ void TimeStats::removeTimeRecord(const std::string& layerName, uint64_t frameNum
    layerRecord.droppedFrames++;
    layerRecord.droppedFrames++;
}
}


void TimeStats::flushPowerTimeLocked() {
    nsecs_t curTime = systemTime();
    // elapsedTime is in milliseconds.
    int64_t elapsedTime = (curTime - mPowerTime.prevTime) / 1000000;

    switch (mPowerTime.powerMode) {
        case HWC_POWER_MODE_NORMAL:
            mTimeStats.displayOnTime += elapsedTime;
            break;
        case HWC_POWER_MODE_OFF:
        case HWC_POWER_MODE_DOZE:
        case HWC_POWER_MODE_DOZE_SUSPEND:
        default:
            break;
    }

    mPowerTime.prevTime = curTime;
}

void TimeStats::setPowerMode(int32_t powerMode) {
    if (!mEnabled.load()) {
        std::lock_guard<std::mutex> lock(mMutex);
        mPowerTime.powerMode = powerMode;
        return;
    }

    std::lock_guard<std::mutex> lock(mMutex);
    if (powerMode == mPowerTime.powerMode) return;

    flushPowerTimeLocked();
    mPowerTime.powerMode = powerMode;
}

void TimeStats::enable() {
void TimeStats::enable() {
    if (mEnabled.load()) return;
    if (mEnabled.load()) return;


@@ -454,6 +488,7 @@ void TimeStats::enable() {
    ALOGD("Enabled");
    ALOGD("Enabled");
    mEnabled.store(true);
    mEnabled.store(true);
    mTimeStats.statsStart = static_cast<int64_t>(std::time(0));
    mTimeStats.statsStart = static_cast<int64_t>(std::time(0));
    mPowerTime.prevTime = systemTime();
}
}


void TimeStats::disable() {
void TimeStats::disable() {
@@ -478,6 +513,8 @@ void TimeStats::clear() {
    mTimeStats.totalFrames = 0;
    mTimeStats.totalFrames = 0;
    mTimeStats.missedFrames = 0;
    mTimeStats.missedFrames = 0;
    mTimeStats.clientCompositionFrames = 0;
    mTimeStats.clientCompositionFrames = 0;
    mTimeStats.displayOnTime = 0;
    mPowerTime.prevTime = systemTime();
}
}


bool TimeStats::isEnabled() {
bool TimeStats::isEnabled() {
@@ -494,6 +531,8 @@ void TimeStats::dump(bool asProto, std::optional<uint32_t> maxLayers, String8& r


    mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
    mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));


    flushPowerTimeLocked();

    if (asProto) {
    if (asProto) {
        ALOGD("Dumping TimeStats as proto");
        ALOGD("Dumping TimeStats as proto");
        SFTimeStatsGlobalProto timeStatsProto = mTimeStats.toProto(maxLayers);
        SFTimeStatsGlobalProto timeStatsProto = mTimeStats.toProto(maxLayers);
+11 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,8 @@
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsProtoHeader.h>
#include <timestatsproto/TimeStatsProtoHeader.h>


#include <hardware/hwcomposer_defs.h>

#include <ui/FenceTime.h>
#include <ui/FenceTime.h>


#include <utils/String16.h>
#include <utils/String16.h>
@@ -66,6 +68,11 @@ class TimeStats {
        std::deque<TimeRecord> timeRecords;
        std::deque<TimeRecord> timeRecords;
    };
    };


    struct PowerTime {
        int32_t powerMode = HWC_POWER_MODE_OFF;
        nsecs_t prevTime = 0;
    };

public:
public:
    static TimeStats& getInstance();
    static TimeStats& getInstance();
    void parseArgs(bool asProto, const Vector<String16>& args, size_t& index, String8& result);
    void parseArgs(bool asProto, const Vector<String16>& args, size_t& index, String8& result);
@@ -91,11 +98,14 @@ public:
    // If SF skips or rejects a buffer, remove the corresponding TimeRecord.
    // If SF skips or rejects a buffer, remove the corresponding TimeRecord.
    void removeTimeRecord(const std::string& layerName, uint64_t frameNumber);
    void removeTimeRecord(const std::string& layerName, uint64_t frameNumber);


    void setPowerMode(int32_t powerMode);

private:
private:
    TimeStats() = default;
    TimeStats() = default;


    bool recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord);
    bool recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord);
    void flushAvailableRecordsToStatsLocked(const std::string& layerName);
    void flushAvailableRecordsToStatsLocked(const std::string& layerName);
    void flushPowerTimeLocked();


    void enable();
    void enable();
    void disable();
    void disable();
@@ -107,6 +117,7 @@ private:
    std::mutex mMutex;
    std::mutex mMutex;
    TimeStatsHelper::TimeStatsGlobal mTimeStats;
    TimeStatsHelper::TimeStatsGlobal mTimeStats;
    std::unordered_map<std::string, LayerRecord> mTimeStatsTracker;
    std::unordered_map<std::string, LayerRecord> mTimeStatsTracker;
    PowerTime mPowerTime;
};
};


} // namespace android
} // namespace android
+12 −10
Original line number Original line Diff line number Diff line
@@ -49,7 +49,7 @@ void TimeStatsHelper::Histogram::insert(int32_t delta) {
float TimeStatsHelper::Histogram::averageTime() const {
float TimeStatsHelper::Histogram::averageTime() const {
    int64_t ret = 0;
    int64_t ret = 0;
    int64_t count = 0;
    int64_t count = 0;
    for (auto& ele : hist) {
    for (const auto& ele : hist) {
        count += ele.second;
        count += ele.second;
        ret += ele.first * ele.second;
        ret += ele.first * ele.second;
    }
    }
@@ -73,13 +73,13 @@ std::string TimeStatsHelper::TimeStatsLayer::toString() const {
    StringAppendF(&result, "packageName = %s\n", packageName.c_str());
    StringAppendF(&result, "packageName = %s\n", packageName.c_str());
    StringAppendF(&result, "totalFrames = %d\n", totalFrames);
    StringAppendF(&result, "totalFrames = %d\n", totalFrames);
    StringAppendF(&result, "droppedFrames = %d\n", droppedFrames);
    StringAppendF(&result, "droppedFrames = %d\n", droppedFrames);
    auto iter = deltas.find("present2present");
    const auto iter = deltas.find("present2present");
    if (iter != deltas.end()) {
    if (iter != deltas.end()) {
        StringAppendF(&result, "averageFPS = %.3f\n", 1000.0 / iter->second.averageTime());
        StringAppendF(&result, "averageFPS = %.3f\n", 1000.0 / iter->second.averageTime());
    }
    }
    for (auto& ele : deltas) {
    for (const auto& ele : deltas) {
        StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str());
        StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str());
        StringAppendF(&result, "%s", ele.second.toString().c_str());
        result.append(ele.second.toString());
    }
    }


    return result;
    return result;
@@ -92,9 +92,10 @@ std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> m
    StringAppendF(&result, "totalFrames = %d\n", totalFrames);
    StringAppendF(&result, "totalFrames = %d\n", totalFrames);
    StringAppendF(&result, "missedFrames = %d\n", missedFrames);
    StringAppendF(&result, "missedFrames = %d\n", missedFrames);
    StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
    StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
    StringAppendF(&result, "displayOnTime = %lld ms\n", static_cast<long long int>(displayOnTime));
    const auto dumpStats = generateDumpStats(maxLayers);
    const auto dumpStats = generateDumpStats(maxLayers);
    for (auto& ele : dumpStats) {
    for (const auto& ele : dumpStats) {
        StringAppendF(&result, "%s", ele->toString().c_str());
        result.append(ele->toString());
    }
    }


    return result;
    return result;
@@ -106,10 +107,10 @@ SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() const {
    layerProto.set_package_name(packageName);
    layerProto.set_package_name(packageName);
    layerProto.set_total_frames(totalFrames);
    layerProto.set_total_frames(totalFrames);
    layerProto.set_dropped_frames(droppedFrames);
    layerProto.set_dropped_frames(droppedFrames);
    for (auto& ele : deltas) {
    for (const auto& ele : deltas) {
        SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas();
        SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas();
        deltaProto->set_delta_name(ele.first);
        deltaProto->set_delta_name(ele.first);
        for (auto& histEle : ele.second.hist) {
        for (const auto& histEle : ele.second.hist) {
            SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms();
            SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms();
            histProto->set_time_millis(histEle.first);
            histProto->set_time_millis(histEle.first);
            histProto->set_frame_count(histEle.second);
            histProto->set_frame_count(histEle.second);
@@ -126,8 +127,9 @@ SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto(
    globalProto.set_total_frames(totalFrames);
    globalProto.set_total_frames(totalFrames);
    globalProto.set_missed_frames(missedFrames);
    globalProto.set_missed_frames(missedFrames);
    globalProto.set_client_composition_frames(clientCompositionFrames);
    globalProto.set_client_composition_frames(clientCompositionFrames);
    globalProto.set_display_on_time(displayOnTime);
    const auto dumpStats = generateDumpStats(maxLayers);
    const auto dumpStats = generateDumpStats(maxLayers);
    for (auto& ele : dumpStats) {
    for (const auto& ele : dumpStats) {
        SFTimeStatsLayerProto* layerProto = globalProto.add_stats();
        SFTimeStatsLayerProto* layerProto = globalProto.add_stats();
        layerProto->CopyFrom(ele->toProto());
        layerProto->CopyFrom(ele->toProto());
    }
    }
@@ -137,7 +139,7 @@ SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto(
std::vector<TimeStatsHelper::TimeStatsLayer const*>
std::vector<TimeStatsHelper::TimeStatsLayer const*>
TimeStatsHelper::TimeStatsGlobal::generateDumpStats(std::optional<uint32_t> maxLayers) const {
TimeStatsHelper::TimeStatsGlobal::generateDumpStats(std::optional<uint32_t> maxLayers) const {
    std::vector<TimeStatsLayer const*> dumpStats;
    std::vector<TimeStatsLayer const*> dumpStats;
    for (auto& ele : stats) {
    for (const auto& ele : stats) {
        dumpStats.push_back(&ele.second);
        dumpStats.push_back(&ele.second);
    }
    }


+1 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ public:
        int32_t totalFrames = 0;
        int32_t totalFrames = 0;
        int32_t missedFrames = 0;
        int32_t missedFrames = 0;
        int32_t clientCompositionFrames = 0;
        int32_t clientCompositionFrames = 0;
        int64_t displayOnTime = 0;
        std::unordered_map<std::string, TimeStatsLayer> stats;
        std::unordered_map<std::string, TimeStatsLayer> stats;


        std::string toString(std::optional<uint32_t> maxLayers) const;
        std::string toString(std::optional<uint32_t> maxLayers) const;
Loading