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 // TODO(b/129481165): remove the #pragma below and fix conversion issues 20 #pragma clang diagnostic push 21 #pragma clang diagnostic ignored "-Wconversion" 22 23 #include <android/hardware/graphics/composer/2.4/IComposerClient.h> 24 25 // TODO(b/129481165): remove the #pragma below and fix conversion issues 26 #pragma clang diagnostic pop // ignored "-Wconversion" 27 28 #include <stats_event.h> 29 #include <stats_pull_atom_callback.h> 30 #include <statslog.h> 31 #include <timestatsproto/TimeStatsHelper.h> 32 #include <timestatsproto/TimeStatsProtoHeader.h> 33 #include <ui/FenceTime.h> 34 #include <utils/String16.h> 35 #include <utils/Vector.h> 36 37 #include <deque> 38 #include <mutex> 39 #include <optional> 40 #include <unordered_map> 41 #include <variant> 42 43 using namespace android::surfaceflinger; 44 45 namespace android { 46 47 class TimeStats { 48 public: 49 virtual ~TimeStats() = default; 50 51 // Called once boot has been finished to perform additional capabilities, 52 // e.g. registration to statsd. 53 virtual void onBootFinished() = 0; 54 55 virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0; 56 virtual bool isEnabled() = 0; 57 virtual std::string miniDump() = 0; 58 59 virtual void incrementTotalFrames() = 0; 60 virtual void incrementMissedFrames() = 0; 61 virtual void incrementClientCompositionFrames() = 0; 62 virtual void incrementClientCompositionReusedFrames() = 0; 63 // Increments the number of times the display refresh rate changed. 64 virtual void incrementRefreshRateSwitches() = 0; 65 // Increments the number of changes in composition strategy 66 // The intention is to reflect the number of changes between hwc and gpu 67 // composition, where "gpu composition" may also include mixed composition. 68 virtual void incrementCompositionStrategyChanges() = 0; 69 // Records the most up-to-date count of display event connections. 70 // The stored count will be the maximum ever recoded. 71 virtual void recordDisplayEventConnectionCount(int32_t count) = 0; 72 73 // Records the start and end times for a frame. 74 // The start time is the same as the beginning of a SurfaceFlinger 75 // invalidate message. 76 // The end time corresponds to when SurfaceFlinger finishes submitting the 77 // request to HWC to present a frame. 78 virtual void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) = 0; 79 // Records the start time and end times for when RenderEngine begins work. 80 // The start time corresponds to the beginning of RenderEngine::drawLayers. 81 // The end time corresponds to when RenderEngine finishes rendering. 82 virtual void recordRenderEngineDuration(nsecs_t startTime, nsecs_t endTime) = 0; 83 // Same as above, but passes in a fence representing the end time. 84 virtual void recordRenderEngineDuration(nsecs_t startTime, 85 const std::shared_ptr<FenceTime>& readyFence) = 0; 86 87 virtual void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, 88 nsecs_t postTime) = 0; 89 virtual void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) = 0; 90 // Reasons why latching a particular buffer may be skipped 91 enum class LatchSkipReason { 92 // If the acquire fence did not fire on some devices we skip latching 93 // the buffer until the fence fires. 94 LateAcquire, 95 }; 96 // Increments the counter of skipped latch buffers. 97 virtual void incrementLatchSkipped(int32_t layerId, LatchSkipReason reason) = 0; 98 // Increments the counter of bad desired present times for this layer. 99 // Bad desired present times are "implausible" and cause SurfaceFlinger to 100 // latch a buffer immediately to avoid stalling. 101 virtual void incrementBadDesiredPresent(int32_t layerId) = 0; 102 virtual void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) = 0; 103 virtual void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) = 0; 104 virtual void setAcquireFence(int32_t layerId, uint64_t frameNumber, 105 const std::shared_ptr<FenceTime>& acquireFence) = 0; 106 // SetPresent{Time, Fence} are not expected to be called in the critical 107 // rendering path, as they flush prior fences if those fences have fired. 108 virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) = 0; 109 virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, 110 const std::shared_ptr<FenceTime>& presentFence) = 0; 111 // Clean up the layer record 112 virtual void onDestroy(int32_t layerId) = 0; 113 // If SF skips or rejects a buffer, remove the corresponding TimeRecord. 114 virtual void removeTimeRecord(int32_t layerId, uint64_t frameNumber) = 0; 115 116 virtual void setPowerMode( 117 hardware::graphics::composer::V2_4::IComposerClient::PowerMode powerMode) = 0; 118 // Source of truth is RefrehRateStats. 119 virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; 120 virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0; 121 }; 122 123 namespace impl { 124 125 class TimeStats : public android::TimeStats { 126 using PowerMode = android::hardware::graphics::composer::V2_4::IComposerClient::PowerMode; 127 128 struct FrameTime { 129 uint64_t frameNumber = 0; 130 nsecs_t postTime = 0; 131 nsecs_t latchTime = 0; 132 nsecs_t acquireTime = 0; 133 nsecs_t desiredTime = 0; 134 nsecs_t presentTime = 0; 135 }; 136 137 struct TimeRecord { 138 bool ready = false; 139 FrameTime frameTime; 140 std::shared_ptr<FenceTime> acquireFence; 141 std::shared_ptr<FenceTime> presentFence; 142 }; 143 144 struct LayerRecord { 145 std::string layerName; 146 // This is the index in timeRecords, at which the timestamps for that 147 // specific frame are still not fully received. This is not waiting for 148 // fences to signal, but rather waiting to receive those fences/timestamps. 149 int32_t waitData = -1; 150 uint32_t droppedFrames = 0; 151 uint32_t lateAcquireFrames = 0; 152 uint32_t badDesiredPresentFrames = 0; 153 TimeRecord prevTimeRecord; 154 std::deque<TimeRecord> timeRecords; 155 }; 156 157 struct PowerTime { 158 PowerMode powerMode = PowerMode::OFF; 159 nsecs_t prevTime = 0; 160 }; 161 162 struct RenderEngineDuration { 163 nsecs_t startTime; 164 std::variant<nsecs_t, std::shared_ptr<FenceTime>> endTime; 165 }; 166 167 struct GlobalRecord { 168 nsecs_t prevPresentTime = 0; 169 std::deque<std::shared_ptr<FenceTime>> presentFences; 170 std::deque<RenderEngineDuration> renderEngineDurations; 171 }; 172 173 public: 174 TimeStats(); 175 176 // Delegate to the statsd service and associated APIs. 177 // Production code may use this class directly, whereas unit test may define 178 // a subclass for ease of testing. 179 class StatsEventDelegate { 180 public: 181 virtual ~StatsEventDelegate() = default; addStatsEventToPullData(AStatsEventList * data)182 virtual AStatsEvent* addStatsEventToPullData(AStatsEventList* data) { 183 return AStatsEventList_addStatsEvent(data); 184 } setStatsPullAtomCallback(int32_t atom_tag,AStatsManager_PullAtomMetadata * metadata,AStatsManager_PullAtomCallback callback,void * cookie)185 virtual void setStatsPullAtomCallback(int32_t atom_tag, 186 AStatsManager_PullAtomMetadata* metadata, 187 AStatsManager_PullAtomCallback callback, 188 void* cookie) { 189 return AStatsManager_setPullAtomCallback(atom_tag, metadata, callback, cookie); 190 } 191 clearStatsPullAtomCallback(int32_t atom_tag)192 virtual void clearStatsPullAtomCallback(int32_t atom_tag) { 193 return AStatsManager_clearPullAtomCallback(atom_tag); 194 } 195 statsEventSetAtomId(AStatsEvent * event,uint32_t atom_id)196 virtual void statsEventSetAtomId(AStatsEvent* event, uint32_t atom_id) { 197 return AStatsEvent_setAtomId(event, atom_id); 198 } 199 statsEventWriteInt32(AStatsEvent * event,int32_t field)200 virtual void statsEventWriteInt32(AStatsEvent* event, int32_t field) { 201 return AStatsEvent_writeInt32(event, field); 202 } 203 statsEventWriteInt64(AStatsEvent * event,int64_t field)204 virtual void statsEventWriteInt64(AStatsEvent* event, int64_t field) { 205 return AStatsEvent_writeInt64(event, field); 206 } 207 statsEventWriteString8(AStatsEvent * event,const char * field)208 virtual void statsEventWriteString8(AStatsEvent* event, const char* field) { 209 return AStatsEvent_writeString(event, field); 210 } 211 statsEventWriteByteArray(AStatsEvent * event,const uint8_t * buf,size_t numBytes)212 virtual void statsEventWriteByteArray(AStatsEvent* event, const uint8_t* buf, 213 size_t numBytes) { 214 return AStatsEvent_writeByteArray(event, buf, numBytes); 215 } 216 statsEventBuild(AStatsEvent * event)217 virtual void statsEventBuild(AStatsEvent* event) { return AStatsEvent_build(event); } 218 }; 219 // For testing only for injecting custom dependencies. 220 TimeStats(std::unique_ptr<StatsEventDelegate> statsDelegate, 221 std::optional<size_t> maxPulledLayers, 222 std::optional<size_t> maxPulledHistogramBuckets); 223 224 ~TimeStats() override; 225 226 void onBootFinished() override; 227 void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override; 228 bool isEnabled() override; 229 std::string miniDump() override; 230 231 void incrementTotalFrames() override; 232 void incrementMissedFrames() override; 233 void incrementClientCompositionFrames() override; 234 void incrementClientCompositionReusedFrames() override; 235 void incrementRefreshRateSwitches() override; 236 void incrementCompositionStrategyChanges() override; 237 void recordDisplayEventConnectionCount(int32_t count) override; 238 239 void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) override; 240 void recordRenderEngineDuration(nsecs_t startTime, nsecs_t endTime) override; 241 void recordRenderEngineDuration(nsecs_t startTime, 242 const std::shared_ptr<FenceTime>& readyFence) override; 243 244 void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, 245 nsecs_t postTime) override; 246 void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) override; 247 void incrementLatchSkipped(int32_t layerId, LatchSkipReason reason) override; 248 void incrementBadDesiredPresent(int32_t layerId) override; 249 void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) override; 250 void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) override; 251 void setAcquireFence(int32_t layerId, uint64_t frameNumber, 252 const std::shared_ptr<FenceTime>& acquireFence) override; 253 void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) override; 254 void setPresentFence(int32_t layerId, uint64_t frameNumber, 255 const std::shared_ptr<FenceTime>& presentFence) override; 256 // Clean up the layer record 257 void onDestroy(int32_t layerId) override; 258 // If SF skips or rejects a buffer, remove the corresponding TimeRecord. 259 void removeTimeRecord(int32_t layerId, uint64_t frameNumber) override; 260 261 void setPowerMode( 262 hardware::graphics::composer::V2_4::IComposerClient::PowerMode powerMode) override; 263 // Source of truth is RefrehRateStats. 264 void recordRefreshRate(uint32_t fps, nsecs_t duration) override; 265 void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override; 266 267 static const size_t MAX_NUM_TIME_RECORDS = 64; 268 269 private: 270 static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atom_tag, 271 AStatsEventList* data, 272 void* cookie); 273 AStatsManager_PullAtomCallbackReturn populateGlobalAtom(AStatsEventList* data); 274 AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data); 275 bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); 276 void flushAvailableRecordsToStatsLocked(int32_t layerId); 277 void flushPowerTimeLocked(); 278 void flushAvailableGlobalRecordsToStatsLocked(); 279 280 void enable(); 281 void disable(); 282 void clearAll(); 283 void clearGlobalLocked(); 284 void clearLayersLocked(); 285 void dump(bool asProto, std::optional<uint32_t> maxLayers, std::string& result); 286 287 std::atomic<bool> mEnabled = false; 288 std::mutex mMutex; 289 TimeStatsHelper::TimeStatsGlobal mTimeStats; 290 // Hashmap for LayerRecord with layerId as the hash key 291 std::unordered_map<int32_t, LayerRecord> mTimeStatsTracker; 292 PowerTime mPowerTime; 293 GlobalRecord mGlobalRecord; 294 295 static const size_t MAX_NUM_LAYER_RECORDS = 200; 296 static const size_t MAX_NUM_LAYER_STATS = 200; 297 std::unique_ptr<StatsEventDelegate> mStatsDelegate = std::make_unique<StatsEventDelegate>(); 298 size_t mMaxPulledLayers = 8; 299 size_t mMaxPulledHistogramBuckets = 6; 300 }; 301 302 } // namespace impl 303 304 } // namespace android 305