1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cstdint> 20 21 #include <../Fps.h> 22 #include <android/hardware/graphics/composer/2.4/IComposerClient.h> 23 #include <gui/JankInfo.h> 24 #include <timestatsproto/TimeStatsHelper.h> 25 #include <timestatsproto/TimeStatsProtoHeader.h> 26 #include <ui/FenceTime.h> 27 #include <utils/String16.h> 28 #include <utils/Vector.h> 29 30 #include <deque> 31 #include <mutex> 32 #include <optional> 33 #include <unordered_map> 34 #include <variant> 35 36 using namespace android::surfaceflinger; 37 38 namespace android { 39 40 class TimeStats { 41 public: 42 using SetFrameRateVote = TimeStatsHelper::SetFrameRateVote; 43 44 virtual ~TimeStats() = default; 45 46 // Process a pull request from statsd. 47 virtual bool onPullAtom(const int atomId, std::string* pulledData); 48 49 virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0; 50 virtual bool isEnabled() = 0; 51 virtual std::string miniDump() = 0; 52 53 virtual void incrementTotalFrames() = 0; 54 virtual void incrementMissedFrames() = 0; 55 virtual void incrementClientCompositionFrames() = 0; 56 virtual void incrementClientCompositionReusedFrames() = 0; 57 // Increments the number of times the display refresh rate changed. 58 virtual void incrementRefreshRateSwitches() = 0; 59 // Increments the number of changes in composition strategy 60 // The intention is to reflect the number of changes between hwc and gpu 61 // composition, where "gpu composition" may also include mixed composition. 62 virtual void incrementCompositionStrategyChanges() = 0; 63 // Records the most up-to-date count of display event connections. 64 // The stored count will be the maximum ever recoded. 65 virtual void recordDisplayEventConnectionCount(int32_t count) = 0; 66 67 // Records the start and end times for a frame. 68 // The start time is the same as the beginning of a SurfaceFlinger 69 // invalidate message. 70 // The end time corresponds to when SurfaceFlinger finishes submitting the 71 // request to HWC to present a frame. 72 virtual void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) = 0; 73 // Records the start time and end times for when RenderEngine begins work. 74 // The start time corresponds to the beginning of RenderEngine::drawLayers. 75 // The end time corresponds to when RenderEngine finishes rendering. 76 virtual void recordRenderEngineDuration(nsecs_t startTime, nsecs_t endTime) = 0; 77 // Same as above, but passes in a fence representing the end time. 78 virtual void recordRenderEngineDuration(nsecs_t startTime, 79 const std::shared_ptr<FenceTime>& readyFence) = 0; 80 81 virtual void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, 82 uid_t uid, nsecs_t postTime, int32_t gameMode) = 0; 83 virtual void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) = 0; 84 // Reasons why latching a particular buffer may be skipped 85 enum class LatchSkipReason { 86 // If the acquire fence did not fire on some devices we skip latching 87 // the buffer until the fence fires. 88 LateAcquire, 89 }; 90 // Increments the counter of skipped latch buffers. 91 virtual void incrementLatchSkipped(int32_t layerId, LatchSkipReason reason) = 0; 92 // Increments the counter of bad desired present times for this layer. 93 // Bad desired present times are "implausible" and cause SurfaceFlinger to 94 // latch a buffer immediately to avoid stalling. 95 virtual void incrementBadDesiredPresent(int32_t layerId) = 0; 96 virtual void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) = 0; 97 virtual void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) = 0; 98 virtual void setAcquireFence(int32_t layerId, uint64_t frameNumber, 99 const std::shared_ptr<FenceTime>& acquireFence) = 0; 100 // SetPresent{Time, Fence} are not expected to be called in the critical 101 // rendering path, as they flush prior fences if those fences have fired. 102 virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, 103 Fps displayRefreshRate, std::optional<Fps> renderRate, 104 SetFrameRateVote frameRateVote, int32_t gameMode) = 0; 105 virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, 106 const std::shared_ptr<FenceTime>& presentFence, 107 Fps displayRefreshRate, std::optional<Fps> renderRate, 108 SetFrameRateVote frameRateVote, int32_t gameMode) = 0; 109 110 // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName} 111 // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the 112 // infrastructure responsible for computing jank in the system, this is expected to be called 113 // from FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there 114 // are no jank reasons, then total frames are incremented but jank is not, for accurate 115 // accounting of janky frames. 116 // displayDeadlineDelta, displayPresentJitter, and appDeadlineDelta are also provided in order 117 // to provide contextual information about a janky frame. These values may only be uploaded if 118 // there was an associated valid jank reason, and they must be positive. When these frame counts 119 // are incremented, these are also aggregated into a global reporting packet to help with data 120 // validation and assessing of overall device health. 121 struct JankyFramesInfo { 122 Fps refreshRate; 123 std::optional<Fps> renderRate; 124 uid_t uid = 0; 125 std::string layerName; 126 int32_t gameMode = 0; 127 int32_t reasons = 0; 128 nsecs_t displayDeadlineDelta = 0; 129 nsecs_t displayPresentJitter = 0; 130 nsecs_t appDeadlineDelta = 0; 131 132 bool operator==(const JankyFramesInfo& o) const { 133 return Fps::EqualsInBuckets{}(refreshRate, o.refreshRate) && 134 ((renderRate == std::nullopt && o.renderRate == std::nullopt) || 135 (renderRate != std::nullopt && o.renderRate != std::nullopt && 136 Fps::EqualsInBuckets{}(*renderRate, *o.renderRate))) && 137 uid == o.uid && layerName == o.layerName && gameMode == o.gameMode && 138 reasons == o.reasons && displayDeadlineDelta == o.displayDeadlineDelta && 139 displayPresentJitter == o.displayPresentJitter && 140 appDeadlineDelta == o.appDeadlineDelta; 141 } 142 143 friend std::ostream& operator<<(std::ostream& os, const JankyFramesInfo& info) { 144 os << "JankyFramesInfo {"; 145 os << "\n .refreshRate = " << info.refreshRate; 146 os << "\n .renderRate = " 147 << (info.renderRate ? to_string(*info.renderRate) : "nullopt"); 148 os << "\n .uid = " << info.uid; 149 os << "\n .layerName = " << info.layerName; 150 os << "\n .reasons = " << info.reasons; 151 os << "\n .displayDeadlineDelta = " << info.displayDeadlineDelta; 152 os << "\n .displayPresentJitter = " << info.displayPresentJitter; 153 os << "\n .appDeadlineDelta = " << info.appDeadlineDelta; 154 return os << "\n}"; 155 } 156 }; 157 158 virtual void incrementJankyFrames(const JankyFramesInfo& info) = 0; 159 // Clean up the layer record 160 virtual void onDestroy(int32_t layerId) = 0; 161 // If SF skips or rejects a buffer, remove the corresponding TimeRecord. 162 virtual void removeTimeRecord(int32_t layerId, uint64_t frameNumber) = 0; 163 164 virtual void setPowerMode( 165 hardware::graphics::composer::V2_4::IComposerClient::PowerMode powerMode) = 0; 166 // Source of truth is RefrehRateStats. 167 virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; 168 virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0; 169 }; 170 171 namespace impl { 172 173 class TimeStats : public android::TimeStats { 174 using PowerMode = android::hardware::graphics::composer::V2_4::IComposerClient::PowerMode; 175 176 struct FrameTime { 177 uint64_t frameNumber = 0; 178 nsecs_t postTime = 0; 179 nsecs_t latchTime = 0; 180 nsecs_t acquireTime = 0; 181 nsecs_t desiredTime = 0; 182 nsecs_t presentTime = 0; 183 }; 184 185 struct TimeRecord { 186 bool ready = false; 187 FrameTime frameTime; 188 std::shared_ptr<FenceTime> acquireFence; 189 std::shared_ptr<FenceTime> presentFence; 190 }; 191 192 struct LayerRecord { 193 uid_t uid; 194 std::string layerName; 195 int32_t gameMode = 0; 196 // This is the index in timeRecords, at which the timestamps for that 197 // specific frame are still not fully received. This is not waiting for 198 // fences to signal, but rather waiting to receive those fences/timestamps. 199 int32_t waitData = -1; 200 uint32_t droppedFrames = 0; 201 uint32_t lateAcquireFrames = 0; 202 uint32_t badDesiredPresentFrames = 0; 203 TimeRecord prevTimeRecord; 204 std::deque<TimeRecord> timeRecords; 205 }; 206 207 struct PowerTime { 208 PowerMode powerMode = PowerMode::OFF; 209 nsecs_t prevTime = 0; 210 }; 211 212 struct RenderEngineDuration { 213 nsecs_t startTime; 214 std::variant<nsecs_t, std::shared_ptr<FenceTime>> endTime; 215 }; 216 217 struct GlobalRecord { 218 nsecs_t prevPresentTime = 0; 219 std::deque<std::shared_ptr<FenceTime>> presentFences; 220 std::deque<RenderEngineDuration> renderEngineDurations; 221 }; 222 223 public: 224 TimeStats(); 225 // For testing only for injecting custom dependencies. 226 TimeStats(std::optional<size_t> maxPulledLayers, 227 std::optional<size_t> maxPulledHistogramBuckets); 228 229 bool onPullAtom(const int atomId, std::string* pulledData) override; 230 void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override; 231 bool isEnabled() override; 232 std::string miniDump() override; 233 234 void incrementTotalFrames() override; 235 void incrementMissedFrames() override; 236 void incrementClientCompositionFrames() override; 237 void incrementClientCompositionReusedFrames() override; 238 void incrementRefreshRateSwitches() override; 239 void incrementCompositionStrategyChanges() override; 240 void recordDisplayEventConnectionCount(int32_t count) override; 241 242 void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) override; 243 void recordRenderEngineDuration(nsecs_t startTime, nsecs_t endTime) override; 244 void recordRenderEngineDuration(nsecs_t startTime, 245 const std::shared_ptr<FenceTime>& readyFence) override; 246 247 void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, uid_t uid, 248 nsecs_t postTime, int32_t gameMode) override; 249 void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) override; 250 void incrementLatchSkipped(int32_t layerId, LatchSkipReason reason) override; 251 void incrementBadDesiredPresent(int32_t layerId) override; 252 void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) override; 253 void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) override; 254 void setAcquireFence(int32_t layerId, uint64_t frameNumber, 255 const std::shared_ptr<FenceTime>& acquireFence) override; 256 void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, 257 Fps displayRefreshRate, std::optional<Fps> renderRate, 258 SetFrameRateVote frameRateVote, int32_t gameMode) override; 259 void setPresentFence(int32_t layerId, uint64_t frameNumber, 260 const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, 261 std::optional<Fps> renderRate, SetFrameRateVote frameRateVote, 262 int32_t gameMode) override; 263 264 void incrementJankyFrames(const JankyFramesInfo& info) override; 265 // Clean up the layer record 266 void onDestroy(int32_t layerId) override; 267 // If SF skips or rejects a buffer, remove the corresponding TimeRecord. 268 void removeTimeRecord(int32_t layerId, uint64_t frameNumber) override; 269 270 void setPowerMode( 271 hardware::graphics::composer::V2_4::IComposerClient::PowerMode powerMode) override; 272 // Source of truth is RefrehRateStats. 273 void recordRefreshRate(uint32_t fps, nsecs_t duration) override; 274 void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override; 275 276 static const size_t MAX_NUM_TIME_RECORDS = 64; 277 278 private: 279 bool populateGlobalAtom(std::string* pulledData); 280 bool populateLayerAtom(std::string* pulledData); 281 bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); 282 void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, 283 std::optional<Fps> renderRate, 284 SetFrameRateVote frameRateVote, int32_t gameMode); 285 void flushPowerTimeLocked(); 286 void flushAvailableGlobalRecordsToStatsLocked(); 287 bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName, int32_t gameMode); 288 289 void enable(); 290 void disable(); 291 void clearAll(); 292 void clearGlobalLocked(); 293 void clearLayersLocked(); 294 void dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result); 295 296 std::atomic<bool> mEnabled = false; 297 std::mutex mMutex; 298 TimeStatsHelper::TimeStatsGlobal mTimeStats; 299 // Hashmap for LayerRecord with layerId as the hash key 300 std::unordered_map<int32_t, LayerRecord> mTimeStatsTracker; 301 PowerTime mPowerTime; 302 GlobalRecord mGlobalRecord; 303 304 static const size_t MAX_NUM_LAYER_RECORDS = 200; 305 306 static const size_t REFRESH_RATE_BUCKET_WIDTH = 30; 307 static const size_t RENDER_RATE_BUCKET_WIDTH = REFRESH_RATE_BUCKET_WIDTH; 308 static const size_t MAX_NUM_LAYER_STATS = 200; 309 static const size_t MAX_NUM_PULLED_LAYERS = MAX_NUM_LAYER_STATS; 310 size_t mMaxPulledLayers = MAX_NUM_PULLED_LAYERS; 311 size_t mMaxPulledHistogramBuckets = 6; 312 }; 313 314 } // namespace impl 315 316 } // namespace android 317