diff options
Diffstat (limited to 'services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h')
-rw-r--r-- | services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h | 148 |
1 files changed, 133 insertions, 15 deletions
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h index 0c75f96e46..2afff8d313 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h @@ -40,37 +40,155 @@ public: std::string toString() const; }; + struct JankPayload { + // note that transactions are counted for these frames. + int32_t totalFrames = 0; + int32_t totalJankyFrames = 0; + int32_t totalSFLongCpu = 0; + int32_t totalSFLongGpu = 0; + int32_t totalSFUnattributed = 0; + int32_t totalAppUnattributed = 0; + int32_t totalSFScheduling = 0; + int32_t totalSFPredictionError = 0; + int32_t totalAppBufferStuffing = 0; + + 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; + }; + + /** + * GameMode of the layer. GameModes are set by SysUI through WMShell. + * Actual game mode definitions are managed by GameManager.java + * The values defined here should always be in sync with the ones in GameManager. + */ + enum GameMode { + GameModeUnsupported = 0, + GameModeStandard = 1, + GameModePerformance = 2, + GameModeBattery = 3, + }; + class TimeStatsLayer { public: + uid_t uid; std::string layerName; std::string packageName; + int32_t displayRefreshRateBucket = 0; + int32_t renderRateBucket = 0; + int32_t gameMode = 0; int32_t totalFrames = 0; int32_t droppedFrames = 0; int32_t lateAcquireFrames = 0; int32_t badDesiredPresentFrames = 0; + JankPayload jankPayload; + SetFrameRateVote setFrameRateVote; std::unordered_map<std::string, Histogram> deltas; std::string toString() const; + std::string toString(int32_t gameMode) const; SFTimeStatsLayerProto toProto() const; }; + // Lifted from SkiaGLRenderEngine's LinearEffect class. + // Which in turn was inspired by art/runtime/class_linker.cc + // Also this is what boost:hash_combine does so this is a pretty good hash. + static size_t HashCombine(size_t seed, size_t val) { + return seed ^ (val + 0x9e3779b9 + (seed << 6) + (seed >> 2)); + } + + struct TimelineStatsKey { + int32_t displayRefreshRateBucket = 0; + int32_t renderRateBucket = 0; + + struct Hasher { + size_t operator()(const TimelineStatsKey& key) const { + size_t result = std::hash<int32_t>{}(key.displayRefreshRateBucket); + return HashCombine(result, std::hash<int32_t>{}(key.renderRateBucket)); + } + }; + + bool operator==(const TimelineStatsKey& o) const { + return displayRefreshRateBucket == o.displayRefreshRateBucket && + renderRateBucket == o.renderRateBucket; + } + }; + + struct LayerStatsKey { + uid_t uid = 0; + std::string layerName; + int32_t gameMode = 0; + + struct Hasher { + size_t operator()(const LayerStatsKey& key) const { + size_t uidHash = std::hash<uid_t>{}(key.uid); + size_t layerNameHash = std::hash<std::string>{}(key.layerName); + size_t gameModeHash = std::hash<int32_t>{}(key.gameMode); + return HashCombine(uidHash, HashCombine(layerNameHash, gameModeHash)); + } + }; + + bool operator==(const LayerStatsKey& o) const { + return uid == o.uid && layerName == o.layerName && gameMode == o.gameMode; + } + }; + + struct TimelineStats { + TimelineStatsKey key; + JankPayload jankPayload; + Histogram displayDeadlineDeltas; + Histogram displayPresentDeltas; + std::unordered_map<LayerStatsKey, TimeStatsLayer, LayerStatsKey::Hasher> stats; + + void clearGlobals() { + jankPayload = {}; + displayDeadlineDeltas = {}; + displayPresentDeltas = {}; + } + }; + class TimeStatsGlobal { public: - int64_t statsStart = 0; - int64_t statsEnd = 0; - int32_t totalFrames = 0; - int32_t missedFrames = 0; - int32_t clientCompositionFrames = 0; - int32_t clientCompositionReusedFrames = 0; - int32_t refreshRateSwitches = 0; - int32_t compositionStrategyChanges = 0; - int32_t displayEventConnectionsCount = 0; - int64_t displayOnTime = 0; - Histogram presentToPresent; - Histogram frameDuration; - Histogram renderEngineTiming; - std::unordered_map<std::string, TimeStatsLayer> stats; - std::unordered_map<uint32_t, nsecs_t> refreshRateStats; + // Note: these are all legacy statistics, we're keeping these around because a variety of + // systems and form-factors find these useful when comparing with older releases. However, + // the current recommendation is that the new timeline-based metrics are used, and the old + // ones are deprecated. + int64_t statsStartLegacy = 0; + int64_t statsEndLegacy = 0; + int32_t totalFramesLegacy = 0; + int32_t missedFramesLegacy = 0; + int32_t clientCompositionFramesLegacy = 0; + int32_t clientCompositionReusedFramesLegacy = 0; + int32_t refreshRateSwitchesLegacy = 0; + int32_t compositionStrategyChangesLegacy = 0; + int32_t displayEventConnectionsCountLegacy = 0; + int64_t displayOnTimeLegacy = 0; + Histogram presentToPresentLegacy; + Histogram frameDurationLegacy; + Histogram renderEngineTimingLegacy; + std::unordered_map<uint32_t, nsecs_t> refreshRateStatsLegacy; + + std::unordered_map<TimelineStatsKey, TimelineStats, TimelineStatsKey::Hasher> stats; std::string toString(std::optional<uint32_t> maxLayers) const; SFTimeStatsGlobalProto toProto(std::optional<uint32_t> maxLayers) const; |