• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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