blob: 9dc39383229e17b9c1afbe2a27bae1fa639d2266 [file] [log] [blame]
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001/*
2 * Copyright 2020 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#undef LOG_TAG
18#define LOG_TAG "FrameTimeline"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include "FrameTimeline.h"
Alec Mouriadebf5c2021-01-05 12:57:36 -080022
Adithya Srinivasanf279e042020-08-17 14:56:27 -070023#include <android-base/stringprintf.h>
Sally Qif5721252023-11-17 11:14:53 -080024#include <common/FlagManager.h>
Ady Abraham7f8a1e62020-09-28 16:09:35 -070025#include <utils/Log.h>
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070026#include <utils/Trace.h>
Alec Mouriadebf5c2021-01-05 12:57:36 -080027
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070028#include <chrono>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070029#include <cinttypes>
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070030#include <numeric>
Alec Mouriadebf5c2021-01-05 12:57:36 -080031#include <unordered_set>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070032
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080033namespace android::frametimeline {
Adithya Srinivasanf279e042020-08-17 14:56:27 -070034
35using base::StringAppendF;
Adithya Srinivasan01189672020-10-20 14:23:05 -070036using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +000037using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070038
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070039void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
40 const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
41 StringAppendF(&result, "%s", indent.c_str());
42 StringAppendF(&result, "\t\t");
43 StringAppendF(&result, " Start time\t\t|");
44 StringAppendF(&result, " End time\t\t|");
45 StringAppendF(&result, " Present time\n");
46 if (predictionState == PredictionState::Valid) {
47 // Dump the Predictions only if they are valid
48 StringAppendF(&result, "%s", indent.c_str());
49 StringAppendF(&result, "Expected\t|");
50 std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
51 std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
52 std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
53 StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
54 std::chrono::duration<double, std::milli>(startTime).count(),
55 std::chrono::duration<double, std::milli>(endTime).count(),
56 std::chrono::duration<double, std::milli>(presentTime).count());
57 }
58 StringAppendF(&result, "%s", indent.c_str());
59 StringAppendF(&result, "Actual \t|");
60
61 if (actuals.startTime == 0) {
62 StringAppendF(&result, "\t\tN/A\t|");
63 } else {
64 std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
65 StringAppendF(&result, "\t%10.2f\t|",
66 std::chrono::duration<double, std::milli>(startTime).count());
67 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080068 if (actuals.endTime <= 0) {
69 // Animation leashes can send the endTime as -1
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070070 StringAppendF(&result, "\t\tN/A\t|");
71 } else {
72 std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
73 StringAppendF(&result, "\t%10.2f\t|",
74 std::chrono::duration<double, std::milli>(endTime).count());
75 }
76 if (actuals.presentTime == 0) {
77 StringAppendF(&result, "\t\tN/A\n");
78 } else {
79 std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
80 StringAppendF(&result, "\t%10.2f\n",
81 std::chrono::duration<double, std::milli>(presentTime).count());
82 }
83
84 StringAppendF(&result, "%s", indent.c_str());
85 StringAppendF(&result, "----------------------");
86 StringAppendF(&result, "----------------------");
87 StringAppendF(&result, "----------------------");
88 StringAppendF(&result, "----------------------\n");
89}
90
91std::string toString(PredictionState predictionState) {
92 switch (predictionState) {
93 case PredictionState::Valid:
94 return "Valid";
95 case PredictionState::Expired:
96 return "Expired";
97 case PredictionState::None:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070098 return "None";
99 }
100}
101
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800102std::string jankTypeBitmaskToString(int32_t jankType) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800103 if (jankType == JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700104 return "None";
105 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000106
107 std::vector<std::string> janks;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800108 if (jankType & JankType::DisplayHAL) {
109 janks.emplace_back("Display HAL");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000110 jankType &= ~JankType::DisplayHAL;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800111 }
112 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
Rachel Lee94917b32022-03-18 17:52:09 -0700113 janks.emplace_back("SurfaceFlinger deadline missed (while in HWC)");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000114 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800115 }
116 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
Rachel Lee94917b32022-03-18 17:52:09 -0700117 janks.emplace_back("SurfaceFlinger deadline missed (while in GPU comp)");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000118 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800119 }
120 if (jankType & JankType::AppDeadlineMissed) {
121 janks.emplace_back("App Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000122 jankType &= ~JankType::AppDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800123 }
124 if (jankType & JankType::PredictionError) {
125 janks.emplace_back("Prediction Error");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000126 jankType &= ~JankType::PredictionError;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800127 }
128 if (jankType & JankType::SurfaceFlingerScheduling) {
129 janks.emplace_back("SurfaceFlinger Scheduling");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000130 jankType &= ~JankType::SurfaceFlingerScheduling;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800131 }
132 if (jankType & JankType::BufferStuffing) {
133 janks.emplace_back("Buffer Stuffing");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000134 jankType &= ~JankType::BufferStuffing;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800135 }
136 if (jankType & JankType::Unknown) {
137 janks.emplace_back("Unknown jank");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000138 jankType &= ~JankType::Unknown;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800139 }
Adithya Srinivasan2045ddf2021-05-27 17:38:10 +0000140 if (jankType & JankType::SurfaceFlingerStuffing) {
141 janks.emplace_back("SurfaceFlinger Stuffing");
142 jankType &= ~JankType::SurfaceFlingerStuffing;
143 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000144 if (jankType & JankType::Dropped) {
145 janks.emplace_back("Dropped Frame");
146 jankType &= ~JankType::Dropped;
147 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000148
149 // jankType should be 0 if all types of jank were checked for.
150 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800151 return std::accumulate(janks.begin(), janks.end(), std::string(),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700152 [](const std::string& l, const std::string& r) {
153 return l.empty() ? r : l + ", " + r;
154 });
155}
156
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800157std::string toString(FramePresentMetadata presentMetadata) {
158 switch (presentMetadata) {
159 case FramePresentMetadata::OnTimePresent:
160 return "On Time Present";
161 case FramePresentMetadata::LatePresent:
162 return "Late Present";
163 case FramePresentMetadata::EarlyPresent:
164 return "Early Present";
165 case FramePresentMetadata::UnknownPresent:
166 return "Unknown Present";
Adithya Srinivasan01189672020-10-20 14:23:05 -0700167 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700168}
169
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800170std::string toString(FrameReadyMetadata finishMetadata) {
171 switch (finishMetadata) {
172 case FrameReadyMetadata::OnTimeFinish:
173 return "On Time Finish";
174 case FrameReadyMetadata::LateFinish:
175 return "Late Finish";
176 case FrameReadyMetadata::UnknownFinish:
177 return "Unknown Finish";
178 }
179}
180
181std::string toString(FrameStartMetadata startMetadata) {
182 switch (startMetadata) {
183 case FrameStartMetadata::OnTimeStart:
184 return "On Time Start";
185 case FrameStartMetadata::LateStart:
186 return "Late Start";
187 case FrameStartMetadata::EarlyStart:
188 return "Early Start";
189 case FrameStartMetadata::UnknownStart:
190 return "Unknown Start";
191 }
192}
193
194std::string toString(SurfaceFrame::PresentState presentState) {
195 using PresentState = SurfaceFrame::PresentState;
196 switch (presentState) {
197 case PresentState::Presented:
198 return "Presented";
199 case PresentState::Dropped:
200 return "Dropped";
201 case PresentState::Unknown:
202 return "Unknown";
203 }
204}
205
206FrameTimelineEvent::PresentType toProto(FramePresentMetadata presentMetadata) {
207 switch (presentMetadata) {
208 case FramePresentMetadata::EarlyPresent:
209 return FrameTimelineEvent::PRESENT_EARLY;
210 case FramePresentMetadata::LatePresent:
211 return FrameTimelineEvent::PRESENT_LATE;
212 case FramePresentMetadata::OnTimePresent:
213 return FrameTimelineEvent::PRESENT_ON_TIME;
214 case FramePresentMetadata::UnknownPresent:
215 return FrameTimelineEvent::PRESENT_UNSPECIFIED;
216 }
217}
218
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000219FrameTimelineEvent::PredictionType toProto(PredictionState predictionState) {
220 switch (predictionState) {
221 case PredictionState::Valid:
222 return FrameTimelineEvent::PREDICTION_VALID;
223 case PredictionState::Expired:
224 return FrameTimelineEvent::PREDICTION_EXPIRED;
225 case PredictionState::None:
226 return FrameTimelineEvent::PREDICTION_UNKNOWN;
227 }
228}
229
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000230int32_t jankTypeBitmaskToProto(int32_t jankType) {
231 if (jankType == JankType::None) {
232 return FrameTimelineEvent::JANK_NONE;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700233 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000234
235 int32_t protoJank = 0;
236 if (jankType & JankType::DisplayHAL) {
237 protoJank |= FrameTimelineEvent::JANK_DISPLAY_HAL;
238 jankType &= ~JankType::DisplayHAL;
239 }
240 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
241 protoJank |= FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED;
242 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
243 }
244 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
245 protoJank |= FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
246 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
247 }
248 if (jankType & JankType::AppDeadlineMissed) {
249 protoJank |= FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
250 jankType &= ~JankType::AppDeadlineMissed;
251 }
252 if (jankType & JankType::PredictionError) {
253 protoJank |= FrameTimelineEvent::JANK_PREDICTION_ERROR;
254 jankType &= ~JankType::PredictionError;
255 }
256 if (jankType & JankType::SurfaceFlingerScheduling) {
257 protoJank |= FrameTimelineEvent::JANK_SF_SCHEDULING;
258 jankType &= ~JankType::SurfaceFlingerScheduling;
259 }
260 if (jankType & JankType::BufferStuffing) {
261 protoJank |= FrameTimelineEvent::JANK_BUFFER_STUFFING;
262 jankType &= ~JankType::BufferStuffing;
263 }
264 if (jankType & JankType::Unknown) {
265 protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
266 jankType &= ~JankType::Unknown;
267 }
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000268 if (jankType & JankType::SurfaceFlingerStuffing) {
269 protoJank |= FrameTimelineEvent::JANK_SF_STUFFING;
270 jankType &= ~JankType::SurfaceFlingerStuffing;
271 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000272 if (jankType & JankType::Dropped) {
273 // Jank dropped does not append to other janks, it fully overrides.
274 protoJank |= FrameTimelineEvent::JANK_DROPPED;
275 jankType &= ~JankType::Dropped;
276 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000277
278 // jankType should be 0 if all types of jank were checked for.
279 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
280 return protoJank;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700281}
282
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800283// Returns the smallest timestamp from the set of predictions and actuals.
284nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
285 TimelineItem actuals) {
286 nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
287 if (predictionState == PredictionState::Valid) {
288 // Checking start time for predictions is enough because start time is always lesser than
289 // endTime and presentTime.
290 minTime = std::min(minTime, predictions.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700291 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700292
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800293 // Need to check startTime, endTime and presentTime for actuals because some frames might not
294 // have them set.
295 if (actuals.startTime != 0) {
296 minTime = std::min(minTime, actuals.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700297 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800298 if (actuals.endTime != 0) {
299 minTime = std::min(minTime, actuals.endTime);
300 }
301 if (actuals.presentTime != 0) {
ramindaniea2bb822022-06-27 19:52:10 +0000302 minTime = std::min(minTime, actuals.presentTime);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800303 }
304 return minTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700305}
306
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000307int64_t TraceCookieCounter::getCookieForTracing() {
308 return ++mTraceCookie;
309}
310
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000311SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
Alec Mouriadebf5c2021-01-05 12:57:36 -0800312 uid_t ownerUid, int32_t layerId, std::string layerName,
313 std::string debugName, PredictionState predictionState,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800314 frametimeline::TimelineItem&& predictions,
315 std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000316 JankClassificationThresholds thresholds,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700317 TraceCookieCounter* traceCookieCounter, bool isBuffer, GameMode gameMode)
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000318 : mToken(frameTimelineInfo.vsyncId),
319 mInputEventId(frameTimelineInfo.inputEventId),
Adithya Srinivasan01189672020-10-20 14:23:05 -0700320 mOwnerPid(ownerPid),
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700321 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700322 mLayerName(std::move(layerName)),
323 mDebugName(std::move(debugName)),
Alec Mouriadebf5c2021-01-05 12:57:36 -0800324 mLayerId(layerId),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700325 mPresentState(PresentState::Unknown),
326 mPredictionState(predictionState),
327 mPredictions(predictions),
328 mActuals({0, 0, 0}),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800329 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000330 mJankClassificationThresholds(thresholds),
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000331 mTraceCookieCounter(*traceCookieCounter),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000332 mIsBuffer(isBuffer),
333 mGameMode(gameMode) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700334
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700335void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000336 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700337 mActuals.startTime = actualStartTime;
338}
339
340void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000341 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700342 mActualQueueTime = actualQueueTime;
343}
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000344
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700345void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000346 std::scoped_lock lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700347 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700348}
349
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000350void SurfaceFrame::setDropTime(nsecs_t dropTime) {
351 std::scoped_lock lock(mMutex);
352 mDropTime = dropTime;
353}
354
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800355void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000356 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000357 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
358 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
359 "PresentState - %s set already.",
360 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800361 mPresentState = presentState;
362 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700363}
364
Alec Mouri7d436ec2021-01-27 20:40:50 -0800365void SurfaceFrame::setRenderRate(Fps renderRate) {
366 std::lock_guard<std::mutex> lock(mMutex);
367 mRenderRate = renderRate;
368}
369
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200370Fps SurfaceFrame::getRenderRate() const {
371 std::lock_guard<std::mutex> lock(mMutex);
372 return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate;
373}
374
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000375void SurfaceFrame::setGpuComposition() {
376 std::scoped_lock lock(mMutex);
377 mGpuComposition = true;
378}
379
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800380std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000381 std::scoped_lock lock(mMutex);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000382 if (mPresentState == PresentState::Dropped) {
Edgar Arriaga631e4252023-03-02 02:11:24 +0000383 return JankType::Dropped;
Adithya Srinivasan95619432021-02-08 21:52:51 +0000384 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100385 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000386 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100387 return std::nullopt;
388 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700389 return mJankType;
390}
391
392nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000393 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800394 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700395}
396
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800397TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000398 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800399 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700400}
401
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000402PredictionState SurfaceFrame::getPredictionState() const {
403 std::scoped_lock lock(mMutex);
404 return mPredictionState;
405}
406
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800407SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000408 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800409 return mPresentState;
410}
411
412FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000413 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800414 return mFramePresentMetadata;
415}
416
417FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000418 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800419 return mFrameReadyMetadata;
420}
421
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000422nsecs_t SurfaceFrame::getDropTime() const {
423 std::scoped_lock lock(mMutex);
424 return mDropTime;
425}
426
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000427void SurfaceFrame::promoteToBuffer() {
428 std::scoped_lock lock(mMutex);
429 LOG_ALWAYS_FATAL_IF(mIsBuffer == true,
430 "Trying to promote an already promoted BufferSurfaceFrame from layer %s "
431 "with token %" PRId64 "",
432 mDebugName.c_str(), mToken);
433 mIsBuffer = true;
434}
435
436bool SurfaceFrame::getIsBuffer() const {
437 std::scoped_lock lock(mMutex);
438 return mIsBuffer;
439}
440
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800441void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000442 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700443 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700444 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100445 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700446 // Easily identify a janky Surface Frame in the dump
447 StringAppendF(&result, " [*] ");
448 }
449 StringAppendF(&result, "\n");
450 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800451 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
452 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000453 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
454 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700455 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
456 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800457 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
458 mRenderRate ? mRenderRate->getIntValue() : 0);
459 StringAppendF(&result, "%s", indent.c_str());
Alec Mouriadebf5c2021-01-05 12:57:36 -0800460 StringAppendF(&result, "Layer ID : %d\n", mLayerId);
461 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800462 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700463 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000464 if (mPresentState == PresentState::Dropped) {
465 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
466 StringAppendF(&result, "Drop time : %10f\n",
467 std::chrono::duration<double, std::milli>(dropTime).count());
468 StringAppendF(&result, "%s", indent.c_str());
469 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700470 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
471 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800472 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700473 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800474 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
475 StringAppendF(&result, "%s", indent.c_str());
476 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
477 std::chrono::nanoseconds latchTime(
478 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
479 StringAppendF(&result, "%s", indent.c_str());
480 StringAppendF(&result, "Last latch time: %10f\n",
481 std::chrono::duration<double, std::milli>(latchTime).count());
482 if (mPredictionState == PredictionState::Valid) {
483 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
484 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
485 StringAppendF(&result, "%s", indent.c_str());
486 StringAppendF(&result, "Present delta: %10f\n",
487 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
488 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700489 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700490}
491
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000492std::string SurfaceFrame::miniDump() const {
493 std::scoped_lock lock(mMutex);
494 std::string result;
495 StringAppendF(&result, "Layer - %s\n", mDebugName.c_str());
496 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
497 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
498 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
499 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
500 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
501 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
502 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
503 StringAppendF(&result, "Present time: %" PRId64 "", mActuals.presentTime);
504 return result;
505}
506
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000507void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
508 nsecs_t& deadlineDelta) {
Ady Abrahame43ff722022-02-15 14:44:25 -0800509 if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000510 // Cannot do any classification for invalid present time.
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000511 mJankType = JankType::Unknown;
512 deadlineDelta = -1;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800513 return;
514 }
515
Ady Abrahame43ff722022-02-15 14:44:25 -0800516 if (mPredictionState == PredictionState::Expired) {
517 // We classify prediction expired as AppDeadlineMissed as the
518 // TokenManager::kMaxTokens we store is large enough to account for a
519 // reasonable app, so prediction expire would mean a huge scheduling delay.
Edgar Arriaga631e4252023-03-02 02:11:24 +0000520 mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
521 : JankType::AppDeadlineMissed;
Ady Abrahame43ff722022-02-15 14:44:25 -0800522 deadlineDelta = -1;
523 return;
524 }
525
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800526 if (mPredictionState == PredictionState::None) {
527 // Cannot do jank classification on frames that don't have a token.
528 return;
529 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800530
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000531 deadlineDelta = mActuals.endTime - mPredictions.endTime;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800532 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
Alec Mouriadebf5c2021-01-05 12:57:36 -0800533 const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
534 ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
535 : 0;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800536
537 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
538 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
539 } else {
540 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
541 }
542
543 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
544 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
545 : FramePresentMetadata::EarlyPresent;
546 } else {
547 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
548 }
549
550 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
551 // Frames presented on time are not janky.
552 mJankType = JankType::None;
553 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
554 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
555 // Finish on time, Present early
556 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800557 deltaToVsync >= refreshRate.getPeriodNsecs() -
558 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800559 // Delta factor of vsync
560 mJankType = JankType::SurfaceFlingerScheduling;
561 } else {
562 // Delta not a factor of vsync
563 mJankType = JankType::PredictionError;
564 }
565 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
566 // Finish late, Present early
567 mJankType = JankType::Unknown;
568 }
569 } else {
570 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
571 // Buffer Stuffing.
572 mJankType |= JankType::BufferStuffing;
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000573 // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
574 // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
575 // We try to do this by moving the deadline. Since the queue could be stuffed by more
576 // than one buffer, we take the last latch time as reference and give one vsync
577 // worth of time for the frame to be ready.
578 nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
579 if (adjustedDeadline > mActuals.endTime) {
580 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
581 } else {
582 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
583 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800584 }
585 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
586 // Finish on time, Present late
587 if (displayFrameJankType != JankType::None) {
588 // Propagate displayFrame's jank if it exists
589 mJankType |= displayFrameJankType;
590 } else {
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000591 if (!(mJankType & JankType::BufferStuffing)) {
592 // In a stuffed state, if the app finishes on time and there is no display frame
593 // jank, only buffer stuffing is the root cause of the jank.
594 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
595 deltaToVsync >= refreshRate.getPeriodNsecs() -
596 mJankClassificationThresholds.presentThreshold) {
597 // Delta factor of vsync
598 mJankType |= JankType::SurfaceFlingerScheduling;
599 } else {
600 // Delta not a factor of vsync
601 mJankType |= JankType::PredictionError;
602 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800603 }
604 }
605 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
606 // Finish late, Present late
Adithya Srinivasan8a945502021-03-19 19:12:32 +0000607 mJankType |= JankType::AppDeadlineMissed;
608 // Propagate DisplayFrame's jankType if it is janky
609 mJankType |= displayFrameJankType;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800610 }
611 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000612 if (mPresentState != PresentState::Presented) {
613 mJankType = JankType::Dropped;
614 // Since frame was not presented, lets drop any present value
615 mActuals.presentTime = 0;
616 }
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000617}
618
619void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200620 Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
621 nsecs_t displayPresentDelta) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000622 std::scoped_lock lock(mMutex);
623
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200624 mDisplayFrameRenderRate = displayFrameRenderRate;
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000625 mActuals.presentTime = presentTime;
626 nsecs_t deadlineDelta = 0;
627
628 classifyJankLocked(displayFrameJankType, refreshRate, deadlineDelta);
629
630 if (mPredictionState != PredictionState::None) {
631 // Only update janky frames if the app used vsync predictions
632 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000633 mGameMode, mJankType, displayDeadlineDelta,
634 displayPresentDelta, deadlineDelta});
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000635 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800636}
637
Ady Abraham57f8e182022-03-08 15:54:33 -0800638void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000639 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000640
Adithya Srinivasan86678502021-01-19 21:50:38 +0000641 // Expected timeline start
642 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000643 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700644 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800645 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
646 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700647
648 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000649 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700650
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000651 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
652
653 expectedSurfaceFrameStartEvent->set_token(mToken);
654 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
655
656 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
657 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
658 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000659
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000660 // Expected timeline end
661 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000662 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000663 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800664 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
665 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000666
667 auto* event = packet->set_frame_timeline_event();
668 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
669
670 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
671 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000672}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000673
Ady Abraham57f8e182022-03-08 15:54:33 -0800674void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000675 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000676
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000677 // Actual timeline start
678 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000679 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000680 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800681 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000682 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000683 if (mPredictionState == PredictionState::Expired) {
684 // If prediction is expired, we can't use the predicted start time. Instead, just use a
685 // start time a little earlier than the end time so that we have some info about this
686 // frame in the trace.
Adithya Srinivasanb2283c32021-04-21 21:31:56 +0000687 nsecs_t endTime =
688 (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
Ady Abrahamdee22322022-03-18 10:58:39 -0700689 const auto timestamp = endTime - kPredictionExpiredStartTimeDelta;
690 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000691 } else {
Ady Abrahamdee22322022-03-18 10:58:39 -0700692 const auto timestamp =
693 mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
694 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000695 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000696
697 auto* event = packet->set_frame_timeline_event();
698 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
699
700 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
701
702 actualSurfaceFrameStartEvent->set_token(mToken);
703 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
704
705 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
706 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700707
708 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000709 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700710 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000711 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700712 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000713 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700714 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000715 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
716 FrameReadyMetadata::OnTimeFinish);
717 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
718 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000719 actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan1f9450c2021-06-10 22:39:19 +0000720 actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000721 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000722
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000723 // Actual timeline end
724 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000725 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000726 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800727 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000728 if (mPresentState == PresentState::Dropped) {
Ady Abraham57f8e182022-03-08 15:54:33 -0800729 packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000730 } else {
Ady Abraham57f8e182022-03-08 15:54:33 -0800731 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000732 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700733
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000734 auto* event = packet->set_frame_timeline_event();
735 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700736
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000737 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700738 });
739}
740
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000741/**
742 * TODO(b/178637512): add inputEventId to the perfetto trace.
743 */
Ady Abraham57f8e182022-03-08 15:54:33 -0800744void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000745 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
746 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
747 // No packets can be traced with a missing token.
748 return;
749 }
750 if (getPredictionState() != PredictionState::Expired) {
751 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
752 // a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -0800753 tracePredictions(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000754 }
Ady Abraham57f8e182022-03-08 15:54:33 -0800755 traceActuals(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000756}
757
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800758namespace impl {
759
760int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
761 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000762 std::scoped_lock lock(mMutex);
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000763 while (mPredictions.size() >= kMaxTokens) {
764 mPredictions.erase(mPredictions.begin());
765 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800766 const int64_t assignedToken = mCurrentToken++;
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000767 mPredictions[assignedToken] = predictions;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800768 return assignedToken;
769}
770
771std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000772 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800773 auto predictionsIterator = mPredictions.find(token);
774 if (predictionsIterator != mPredictions.end()) {
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000775 return predictionsIterator->second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800776 }
777 return {};
778}
779
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800780FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
Ady Abraham57f8e182022-03-08 15:54:33 -0800781 JankClassificationThresholds thresholds, bool useBootTimeClock)
782 : mUseBootTimeClock(useBootTimeClock),
783 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800784 mTimeStats(std::move(timeStats)),
785 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan82eef322021-04-10 00:06:04 +0000786 mJankClassificationThresholds(thresholds) {
787 mCurrentDisplayFrame =
788 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000789}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700790
Adithya Srinivasan01189672020-10-20 14:23:05 -0700791void FrameTimeline::onBootFinished() {
792 perfetto::TracingInitArgs args;
793 args.backends = perfetto::kSystemBackend;
794 perfetto::Tracing::Initialize(args);
795 registerDataSource();
796}
797
798void FrameTimeline::registerDataSource() {
799 perfetto::DataSourceDescriptor dsd;
800 dsd.set_name(kFrameTimelineDataSource);
801 FrameTimelineDataSource::Register(dsd);
802}
803
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800804std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Alec Mouriadebf5c2021-01-05 12:57:36 -0800805 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700806 std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700807 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000808 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800809 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000810 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800811 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000812 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000813 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700814 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000815 std::optional<TimelineItem> predictions =
816 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700817 if (predictions) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800818 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000819 std::move(layerName), std::move(debugName),
820 PredictionState::Valid, std::move(*predictions),
821 mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000822 &mTraceCookieCounter, isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700823 }
Alec Mouriadebf5c2021-01-05 12:57:36 -0800824 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000825 std::move(layerName), std::move(debugName),
826 PredictionState::Expired, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000827 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000828 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700829}
830
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800831FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000832 JankClassificationThresholds thresholds,
833 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800834 : mSurfaceFlingerPredictions(TimelineItem()),
835 mSurfaceFlingerActuals(TimelineItem()),
836 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000837 mJankClassificationThresholds(thresholds),
838 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800839 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700840}
841
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800842void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700843 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000844 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800845 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
846}
847
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200848void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
849 Fps renderRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800850 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000851 std::scoped_lock lock(mMutex);
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200852 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800853 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700854}
855
856void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000857 const std::shared_ptr<FenceTime>& presentFence,
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000858 const std::shared_ptr<FenceTime>& gpuFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700859 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000860 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800861 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000862 mCurrentDisplayFrame->setGpuFence(gpuFence);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700863 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
864 flushPendingPresentFences();
865 finalizeCurrentDisplayFrame();
866}
867
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800868void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
869 mSurfaceFrames.push_back(surfaceFrame);
870}
871
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200872void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800873 std::optional<TimelineItem> predictions,
874 nsecs_t wakeUpTime) {
875 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800876 mRefreshRate = refreshRate;
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200877 mRenderRate = renderRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800878 if (!predictions) {
879 mPredictionState = PredictionState::Expired;
880 } else {
881 mPredictionState = PredictionState::Valid;
882 mSurfaceFlingerPredictions = *predictions;
883 }
884 mSurfaceFlingerActuals.startTime = wakeUpTime;
885}
886
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800887void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
888 TimelineItem predictions) {
889 mPredictionState = predictionState;
890 mSurfaceFlingerPredictions = predictions;
891}
892
893void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
894 mSurfaceFlingerActuals.startTime = actualStartTime;
895}
896
897void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
898 mSurfaceFlingerActuals.endTime = actualEndTime;
899}
900
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000901void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
902 mGpuFence = gpuFence;
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000903}
904
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000905void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
906 nsecs_t previousPresentTime) {
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700907 const bool presentTimeValid =
908 mSurfaceFlingerActuals.presentTime >= mSurfaceFlingerActuals.startTime;
909 if (mPredictionState == PredictionState::Expired || !presentTimeValid) {
Adithya Srinivasande272452021-04-10 00:21:00 +0000910 // Cannot do jank classification with expired predictions or invalid signal times. Set the
911 // deltas to 0 as both negative and positive deltas are used as real values.
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000912 mJankType = JankType::Unknown;
Adithya Srinivasande272452021-04-10 00:21:00 +0000913 deadlineDelta = 0;
914 deltaToVsync = 0;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700915 if (!presentTimeValid) {
Ady Abrahamfcb16862022-10-10 14:35:21 -0700916 mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700917 mJankType |= JankType::DisplayHAL;
Ady Abrahamfcb16862022-10-10 14:35:21 -0700918 }
919
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000920 return;
921 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800922
923 // Delta between the expected present and the actual present
924 const nsecs_t presentDelta =
925 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000926 // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
927 // included the time for composition. However, for GPU composition, the final end time is max(sf
928 // end time, gpu fence time).
929 nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
930 if (mGpuFence != FenceTime::NO_FENCE) {
931 combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
932 }
933 deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
Alec Mouri363faf02021-01-29 16:34:55 -0800934
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800935 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
936 // was a prediction error or not.
Adithya Srinivasan115ac692021-03-06 01:21:30 +0000937 deltaToVsync = mRefreshRate.getPeriodNsecs() > 0
Alec Mouriadebf5c2021-01-05 12:57:36 -0800938 ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
939 : 0;
Adithya Srinivasan115ac692021-03-06 01:21:30 +0000940
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800941 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
942 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
943 : FramePresentMetadata::EarlyPresent;
944 } else {
945 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
946 }
947
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000948 if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800949 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
950 } else {
951 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
952 }
953
954 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
955 mJankClassificationThresholds.startThreshold) {
956 mFrameStartMetadata =
957 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
958 ? FrameStartMetadata::LateStart
959 : FrameStartMetadata::EarlyStart;
960 }
961
962 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
963 // Do jank classification only if present is not on time
964 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
965 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
966 // Finish on time, Present early
967 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800968 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
969 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800970 // Delta is a factor of vsync if its within the presentTheshold on either side
971 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
972 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
973 mJankType = JankType::SurfaceFlingerScheduling;
974 } else {
975 // Delta is not a factor of vsync,
976 mJankType = JankType::PredictionError;
977 }
978 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
979 // Finish late, Present early
980 mJankType = JankType::SurfaceFlingerScheduling;
981 } else {
982 // Finish time unknown
983 mJankType = JankType::Unknown;
984 }
985 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000986 if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
987 mJankClassificationThresholds.presentThreshold ||
988 previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
989 // The previous frame was either presented in the current frame's expected vsync or
990 // it was presented even later than the current frame's expected vsync.
991 mJankType = JankType::SurfaceFlingerStuffing;
992 }
993 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
994 !(mJankType & JankType::SurfaceFlingerStuffing)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800995 // Finish on time, Present late
996 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800997 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
998 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800999 // Delta is a factor of vsync if its within the presentTheshold on either side
1000 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1001 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1002 mJankType = JankType::DisplayHAL;
1003 } else {
1004 // Delta is not a factor of vsync
1005 mJankType = JankType::PredictionError;
1006 }
1007 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001008 if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
1009 mSurfaceFlingerActuals.presentTime - previousPresentTime >
1010 mRefreshRate.getPeriodNsecs() +
1011 mJankClassificationThresholds.presentThreshold) {
1012 // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
1013 // was presented more than a vsync late.
Rachel Lee94917b32022-03-18 17:52:09 -07001014 if (mGpuFence != FenceTime::NO_FENCE) {
1015 // If SF was in GPU composition, classify it as GPU deadline missed.
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001016 mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
1017 } else {
1018 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
1019 }
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +00001020 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001021 } else {
1022 // Finish time unknown
1023 mJankType = JankType::Unknown;
1024 }
1025 } else {
1026 // Present unknown
1027 mJankType = JankType::Unknown;
1028 }
1029 }
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001030}
1031
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001032void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001033 mSurfaceFlingerActuals.presentTime = signalTime;
1034 nsecs_t deadlineDelta = 0;
1035 nsecs_t deltaToVsync = 0;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001036 classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001037
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001038 for (auto& surfaceFrame : mSurfaceFrames) {
Pascal Muetschardac7bcd92023-10-03 15:05:36 +02001039 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta,
1040 deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001041 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001042}
1043
Ady Abraham57f8e182022-03-08 15:54:33 -08001044void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
1045 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001046 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001047
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001048 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001049 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001050 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001051 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1052 packet->set_timestamp(
1053 static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001054
1055 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001056 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001057
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001058 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001059
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001060 expectedDisplayFrameStartEvent->set_token(mToken);
1061 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1062 });
Adithya Srinivasan86678502021-01-19 21:50:38 +00001063
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001064 // Expected timeline end
1065 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1066 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001067 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1068 packet->set_timestamp(
1069 static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001070
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001071 auto* event = packet->set_frame_timeline_event();
1072 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001073
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001074 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
1075 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001076}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001077
Sally Qiaa107742023-09-29 14:53:14 -07001078void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1079 nsecs_t previousActualPresentTime) const {
1080 nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
1081 const constexpr float kThresh = 0.5f;
1082 const constexpr float kRange = 1.5f;
1083 for (auto& surfaceFrame : mSurfaceFrames) {
1084 if (previousActualPresentTime != 0 &&
1085 static_cast<float>(mSurfaceFlingerActuals.presentTime - previousActualPresentTime) >=
1086 static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
1087 static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
1088 (static_cast<float>(mSurfaceFlingerActuals.presentTime) -
1089 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1090 static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
1091 (static_cast<float>(previousActualPresentTime) -
1092 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs()))) {
1093 skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
1094 skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
1095 break;
1096 }
1097 }
1098
1099 // add slice
1100 if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
1101 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1102
1103 // Actual timeline start
1104 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1105 auto packet = ctx.NewTracePacket();
1106 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1107 packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
1108
1109 auto* event = packet->set_frame_timeline_event();
1110 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1111
1112 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1113
1114 actualDisplayFrameStartEvent->set_token(0);
1115 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1116 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1117 FrameReadyMetadata::OnTimeFinish);
1118 actualDisplayFrameStartEvent->set_gpu_composition(false);
1119 actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid));
1120 actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
1121 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped));
1122 });
1123
1124 // Actual timeline end
1125 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1126 auto packet = ctx.NewTracePacket();
1127 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1128 packet->set_timestamp(static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
1129
1130 auto* event = packet->set_frame_timeline_event();
1131 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1132
1133 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1134 });
1135 }
1136}
1137
Ady Abraham57f8e182022-03-08 15:54:33 -08001138void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
1139 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001140 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001141
1142 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001143 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1144 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001145 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1146 packet->set_timestamp(
1147 static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001148
1149 auto* event = packet->set_frame_timeline_event();
1150 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1151
1152 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1153
1154 actualDisplayFrameStartEvent->set_token(mToken);
1155 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1156
1157 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
1158 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1159 FrameReadyMetadata::OnTimeFinish);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001160 actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001161 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +00001162 actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001163 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001164
1165 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001166 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1167 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001168 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1169 packet->set_timestamp(
1170 static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001171
1172 auto* event = packet->set_frame_timeline_event();
1173 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1174
1175 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001176 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001177}
1178
Sally Qiaa107742023-09-29 14:53:14 -07001179void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1180 nsecs_t previousActualPresentTime) const {
Ady Abraham57a8ab42023-01-26 15:28:19 -08001181 if (mSurfaceFrames.empty()) {
1182 // We don't want to trace display frames without any surface frames updates as this cannot
1183 // be janky
1184 return;
1185 }
1186
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001187 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
1188 // DisplayFrame should not have an invalid token.
1189 ALOGE("Cannot trace DisplayFrame with invalid token");
1190 return;
1191 }
1192
1193 if (mPredictionState == PredictionState::Valid) {
1194 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
1195 // meaningful way in a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -08001196 tracePredictions(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001197 }
Ady Abraham57f8e182022-03-08 15:54:33 -08001198 traceActuals(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001199
1200 for (auto& surfaceFrame : mSurfaceFrames) {
Ady Abraham57f8e182022-03-08 15:54:33 -08001201 surfaceFrame->trace(mToken, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001202 }
Sally Qiaa107742023-09-29 14:53:14 -07001203
Sally Qif5721252023-11-17 11:14:53 -08001204 if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
1205 addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousActualPresentTime);
1206 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001207}
1208
Alec Mouriadebf5c2021-01-05 12:57:36 -08001209float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
1210 if (layerIds.empty()) {
1211 return 0.0f;
1212 }
1213
1214 std::vector<nsecs_t> presentTimes;
1215 {
1216 std::scoped_lock lock(mMutex);
1217 presentTimes.reserve(mDisplayFrames.size());
1218 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1219 const auto& displayFrame = mDisplayFrames[i];
1220 if (displayFrame->getActuals().presentTime <= 0) {
1221 continue;
1222 }
1223 for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1224 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
1225 layerIds.count(surfaceFrame->getLayerId()) > 0) {
1226 // We're looking for DisplayFrames that presents at least one layer from
1227 // layerIds, so push the present time and skip looking through the rest of the
1228 // SurfaceFrames.
1229 presentTimes.push_back(displayFrame->getActuals().presentTime);
1230 break;
1231 }
1232 }
1233 }
1234 }
1235
1236 // FPS can't be computed when there's fewer than 2 presented frames.
1237 if (presentTimes.size() <= 1) {
1238 return 0.0f;
1239 }
1240
1241 nsecs_t priorPresentTime = -1;
1242 nsecs_t totalPresentToPresentWalls = 0;
1243
1244 for (const nsecs_t presentTime : presentTimes) {
1245 if (priorPresentTime == -1) {
1246 priorPresentTime = presentTime;
1247 continue;
1248 }
1249
1250 totalPresentToPresentWalls += (presentTime - priorPresentTime);
1251 priorPresentTime = presentTime;
1252 }
1253
1254 if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) {
1255 ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64,
1256 totalPresentToPresentWalls);
1257 return 0.0f;
1258 }
1259
1260 const constexpr nsecs_t kOneSecond =
1261 std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
1262 // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
1263 // M frames / second
1264 return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
1265 static_cast<float>(totalPresentToPresentWalls);
1266}
1267
Ady Abrahamfcb16862022-10-10 14:35:21 -07001268std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
1269 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1270 const auto& [fence, _] = mPendingPresentFences[i];
Theodore Dubois205c6dd2022-11-23 15:06:33 -08001271 if (fence && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001272 return i;
1273 }
1274 }
1275
1276 return {};
1277}
1278
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001279void FrameTimeline::flushPendingPresentFences() {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001280 const auto firstSignaledFence = getFirstSignalFenceIndex();
1281 if (!firstSignaledFence.has_value()) {
1282 return;
1283 }
1284
Ady Abraham57f8e182022-03-08 15:54:33 -08001285 // Perfetto is using boottime clock to void drifts when the device goes
1286 // to suspend.
1287 const auto monoBootOffset = mUseBootTimeClock
1288 ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
1289 : 0;
1290
Ady Abrahamfcb16862022-10-10 14:35:21 -07001291 // Present fences are expected to be signaled in order. Mark all the previous
1292 // pending fences as errors.
1293 for (size_t i = 0; i < firstSignaledFence.value(); i++) {
1294 const auto& pendingPresentFence = *mPendingPresentFences.begin();
1295 const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1296 auto& displayFrame = pendingPresentFence.second;
1297 displayFrame->onPresent(signalTime, mPreviousPresentTime);
Sally Qiaa107742023-09-29 14:53:14 -07001298 displayFrame->trace(mSurfaceFlingerPid, monoBootOffset, mPreviousPresentTime);
Ady Abrahamfcb16862022-10-10 14:35:21 -07001299 mPendingPresentFences.erase(mPendingPresentFences.begin());
1300 }
1301
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001302 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1303 const auto& pendingPresentFence = mPendingPresentFences[i];
1304 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1305 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
1306 signalTime = pendingPresentFence.first->getSignalTime();
1307 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001308 break;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001309 }
1310 }
Ady Abrahamfcb16862022-10-10 14:35:21 -07001311
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +00001312 auto& displayFrame = pendingPresentFence.second;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001313 displayFrame->onPresent(signalTime, mPreviousPresentTime);
Sally Qiaa107742023-09-29 14:53:14 -07001314 displayFrame->trace(mSurfaceFlingerPid, monoBootOffset, mPreviousPresentTime);
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001315 mPreviousPresentTime = signalTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001316
1317 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
1318 --i;
1319 }
1320}
1321
1322void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001323 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001324 // We maintain only a fixed number of frames' data. Pop older frames
1325 mDisplayFrames.pop_front();
1326 }
1327 mDisplayFrames.push_back(mCurrentDisplayFrame);
1328 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001329 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan82eef322021-04-10 00:06:04 +00001330 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001331}
1332
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001333nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1334 nsecs_t baseTime =
1335 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1336 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001337 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1338 if (surfaceFrameBaseTime != 0) {
1339 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1340 }
1341 }
1342 return baseTime;
1343}
1344
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001345void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1346 int displayFrameCount) const {
1347 if (mJankType == JankType::None) {
1348 // Check if any Surface Frame has been janky
1349 bool isJanky = false;
1350 for (const auto& surfaceFrame : mSurfaceFrames) {
1351 if (surfaceFrame->getJankType() != JankType::None) {
1352 isJanky = true;
1353 break;
1354 }
1355 }
1356 if (!isJanky) {
1357 return;
1358 }
1359 }
1360 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1361 dump(result, baseTime);
1362}
1363
1364void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1365 dump(result, baseTime);
1366}
1367
1368void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1369 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001370 // Easily identify a janky Display Frame in the dump
1371 StringAppendF(&result, " [*] ");
1372 }
1373 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001374 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1375 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1376 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1377 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1378 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001379 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001380 StringAppendF(&result, "Vsync Period: %10f\n",
1381 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1382 nsecs_t presentDelta =
1383 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1384 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1385 StringAppendF(&result, "Present delta: %10f\n",
1386 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001387 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001388 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1389 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1390 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1391 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001392 StringAppendF(&result, "\n");
1393 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001394 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001395 surfaceFrame->dump(result, indent, baseTime);
1396 }
1397 StringAppendF(&result, "\n");
1398}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001399
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001400void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001401 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001402 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001403 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001404 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1405 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001406 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001407 }
1408}
1409
1410void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001411 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001412 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001413 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001414 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001415 }
1416}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001417
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001418void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1419 ATRACE_CALL();
1420 std::unordered_map<std::string, bool> argsMap;
1421 for (size_t i = 0; i < args.size(); i++) {
1422 argsMap[std::string(String8(args[i]).c_str())] = true;
1423 }
1424 if (argsMap.count("-jank")) {
1425 dumpJank(result);
1426 }
1427 if (argsMap.count("-all")) {
1428 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001429 }
1430}
1431
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001432void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001433 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001434
1435 // The size can either increase or decrease, clear everything, to be consistent
1436 mDisplayFrames.clear();
1437 mPendingPresentFences.clear();
1438 mMaxDisplayFrames = size;
1439}
1440
1441void FrameTimeline::reset() {
1442 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1443}
1444
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001445} // namespace impl
1446} // namespace android::frametimeline