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