blob: f6710061499283794cd605b7c3946fbdfcbade1f [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
Pascal Mütschardd56514e2024-05-24 17:37:13 +020033#include "../Jank/JankTracker.h"
34
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080035namespace android::frametimeline {
Adithya Srinivasanf279e042020-08-17 14:56:27 -070036
37using base::StringAppendF;
Adithya Srinivasan01189672020-10-20 14:23:05 -070038using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +000039using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070040
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070041void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
42 const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
43 StringAppendF(&result, "%s", indent.c_str());
44 StringAppendF(&result, "\t\t");
45 StringAppendF(&result, " Start time\t\t|");
46 StringAppendF(&result, " End time\t\t|");
47 StringAppendF(&result, " Present time\n");
48 if (predictionState == PredictionState::Valid) {
49 // Dump the Predictions only if they are valid
50 StringAppendF(&result, "%s", indent.c_str());
51 StringAppendF(&result, "Expected\t|");
52 std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
53 std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
54 std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
55 StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
56 std::chrono::duration<double, std::milli>(startTime).count(),
57 std::chrono::duration<double, std::milli>(endTime).count(),
58 std::chrono::duration<double, std::milli>(presentTime).count());
59 }
60 StringAppendF(&result, "%s", indent.c_str());
61 StringAppendF(&result, "Actual \t|");
62
63 if (actuals.startTime == 0) {
64 StringAppendF(&result, "\t\tN/A\t|");
65 } else {
66 std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
67 StringAppendF(&result, "\t%10.2f\t|",
68 std::chrono::duration<double, std::milli>(startTime).count());
69 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080070 if (actuals.endTime <= 0) {
71 // Animation leashes can send the endTime as -1
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070072 StringAppendF(&result, "\t\tN/A\t|");
73 } else {
74 std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
75 StringAppendF(&result, "\t%10.2f\t|",
76 std::chrono::duration<double, std::milli>(endTime).count());
77 }
78 if (actuals.presentTime == 0) {
79 StringAppendF(&result, "\t\tN/A\n");
80 } else {
81 std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
82 StringAppendF(&result, "\t%10.2f\n",
83 std::chrono::duration<double, std::milli>(presentTime).count());
84 }
85
86 StringAppendF(&result, "%s", indent.c_str());
87 StringAppendF(&result, "----------------------");
88 StringAppendF(&result, "----------------------");
89 StringAppendF(&result, "----------------------");
90 StringAppendF(&result, "----------------------\n");
91}
92
93std::string toString(PredictionState predictionState) {
94 switch (predictionState) {
95 case PredictionState::Valid:
96 return "Valid";
97 case PredictionState::Expired:
98 return "Expired";
99 case PredictionState::None:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700100 return "None";
101 }
102}
103
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800104std::string jankTypeBitmaskToString(int32_t jankType) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800105 if (jankType == JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700106 return "None";
107 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000108
109 std::vector<std::string> janks;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800110 if (jankType & JankType::DisplayHAL) {
111 janks.emplace_back("Display HAL");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000112 jankType &= ~JankType::DisplayHAL;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800113 }
114 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
Rachel Lee94917b32022-03-18 17:52:09 -0700115 janks.emplace_back("SurfaceFlinger deadline missed (while in HWC)");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000116 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800117 }
118 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
Rachel Lee94917b32022-03-18 17:52:09 -0700119 janks.emplace_back("SurfaceFlinger deadline missed (while in GPU comp)");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000120 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800121 }
122 if (jankType & JankType::AppDeadlineMissed) {
123 janks.emplace_back("App Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000124 jankType &= ~JankType::AppDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800125 }
126 if (jankType & JankType::PredictionError) {
127 janks.emplace_back("Prediction Error");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000128 jankType &= ~JankType::PredictionError;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800129 }
130 if (jankType & JankType::SurfaceFlingerScheduling) {
131 janks.emplace_back("SurfaceFlinger Scheduling");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000132 jankType &= ~JankType::SurfaceFlingerScheduling;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800133 }
134 if (jankType & JankType::BufferStuffing) {
135 janks.emplace_back("Buffer Stuffing");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000136 jankType &= ~JankType::BufferStuffing;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800137 }
138 if (jankType & JankType::Unknown) {
139 janks.emplace_back("Unknown jank");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000140 jankType &= ~JankType::Unknown;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800141 }
Adithya Srinivasan2045ddf2021-05-27 17:38:10 +0000142 if (jankType & JankType::SurfaceFlingerStuffing) {
143 janks.emplace_back("SurfaceFlinger Stuffing");
144 jankType &= ~JankType::SurfaceFlingerStuffing;
145 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000146 if (jankType & JankType::Dropped) {
147 janks.emplace_back("Dropped Frame");
148 jankType &= ~JankType::Dropped;
149 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000150
151 // jankType should be 0 if all types of jank were checked for.
152 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800153 return std::accumulate(janks.begin(), janks.end(), std::string(),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700154 [](const std::string& l, const std::string& r) {
155 return l.empty() ? r : l + ", " + r;
156 });
157}
158
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800159std::string toString(FramePresentMetadata presentMetadata) {
160 switch (presentMetadata) {
161 case FramePresentMetadata::OnTimePresent:
162 return "On Time Present";
163 case FramePresentMetadata::LatePresent:
164 return "Late Present";
165 case FramePresentMetadata::EarlyPresent:
166 return "Early Present";
167 case FramePresentMetadata::UnknownPresent:
168 return "Unknown Present";
Adithya Srinivasan01189672020-10-20 14:23:05 -0700169 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700170}
171
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800172std::string toString(FrameReadyMetadata finishMetadata) {
173 switch (finishMetadata) {
174 case FrameReadyMetadata::OnTimeFinish:
175 return "On Time Finish";
176 case FrameReadyMetadata::LateFinish:
177 return "Late Finish";
178 case FrameReadyMetadata::UnknownFinish:
179 return "Unknown Finish";
180 }
181}
182
183std::string toString(FrameStartMetadata startMetadata) {
184 switch (startMetadata) {
185 case FrameStartMetadata::OnTimeStart:
186 return "On Time Start";
187 case FrameStartMetadata::LateStart:
188 return "Late Start";
189 case FrameStartMetadata::EarlyStart:
190 return "Early Start";
191 case FrameStartMetadata::UnknownStart:
192 return "Unknown Start";
193 }
194}
195
196std::string toString(SurfaceFrame::PresentState presentState) {
197 using PresentState = SurfaceFrame::PresentState;
198 switch (presentState) {
199 case PresentState::Presented:
200 return "Presented";
201 case PresentState::Dropped:
202 return "Dropped";
203 case PresentState::Unknown:
204 return "Unknown";
205 }
206}
207
208FrameTimelineEvent::PresentType toProto(FramePresentMetadata presentMetadata) {
209 switch (presentMetadata) {
210 case FramePresentMetadata::EarlyPresent:
211 return FrameTimelineEvent::PRESENT_EARLY;
212 case FramePresentMetadata::LatePresent:
213 return FrameTimelineEvent::PRESENT_LATE;
214 case FramePresentMetadata::OnTimePresent:
215 return FrameTimelineEvent::PRESENT_ON_TIME;
216 case FramePresentMetadata::UnknownPresent:
217 return FrameTimelineEvent::PRESENT_UNSPECIFIED;
218 }
219}
220
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000221FrameTimelineEvent::PredictionType toProto(PredictionState predictionState) {
222 switch (predictionState) {
223 case PredictionState::Valid:
224 return FrameTimelineEvent::PREDICTION_VALID;
225 case PredictionState::Expired:
226 return FrameTimelineEvent::PREDICTION_EXPIRED;
227 case PredictionState::None:
228 return FrameTimelineEvent::PREDICTION_UNKNOWN;
229 }
230}
231
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000232int32_t jankTypeBitmaskToProto(int32_t jankType) {
233 if (jankType == JankType::None) {
234 return FrameTimelineEvent::JANK_NONE;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700235 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000236
237 int32_t protoJank = 0;
238 if (jankType & JankType::DisplayHAL) {
239 protoJank |= FrameTimelineEvent::JANK_DISPLAY_HAL;
240 jankType &= ~JankType::DisplayHAL;
241 }
242 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
243 protoJank |= FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED;
244 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
245 }
246 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
247 protoJank |= FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
248 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
249 }
250 if (jankType & JankType::AppDeadlineMissed) {
251 protoJank |= FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
252 jankType &= ~JankType::AppDeadlineMissed;
253 }
254 if (jankType & JankType::PredictionError) {
255 protoJank |= FrameTimelineEvent::JANK_PREDICTION_ERROR;
256 jankType &= ~JankType::PredictionError;
257 }
258 if (jankType & JankType::SurfaceFlingerScheduling) {
259 protoJank |= FrameTimelineEvent::JANK_SF_SCHEDULING;
260 jankType &= ~JankType::SurfaceFlingerScheduling;
261 }
262 if (jankType & JankType::BufferStuffing) {
263 protoJank |= FrameTimelineEvent::JANK_BUFFER_STUFFING;
264 jankType &= ~JankType::BufferStuffing;
265 }
266 if (jankType & JankType::Unknown) {
267 protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
268 jankType &= ~JankType::Unknown;
269 }
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000270 if (jankType & JankType::SurfaceFlingerStuffing) {
271 protoJank |= FrameTimelineEvent::JANK_SF_STUFFING;
272 jankType &= ~JankType::SurfaceFlingerStuffing;
273 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000274 if (jankType & JankType::Dropped) {
275 // Jank dropped does not append to other janks, it fully overrides.
276 protoJank |= FrameTimelineEvent::JANK_DROPPED;
277 jankType &= ~JankType::Dropped;
278 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000279
280 // jankType should be 0 if all types of jank were checked for.
281 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
282 return protoJank;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700283}
284
Ying Wei96eb5352023-11-21 17:37:21 +0000285FrameTimelineEvent::JankSeverityType toProto(JankSeverityType jankSeverityType) {
286 switch (jankSeverityType) {
287 case JankSeverityType::Unknown:
288 return FrameTimelineEvent::SEVERITY_UNKNOWN;
289 case JankSeverityType::None:
290 return FrameTimelineEvent::SEVERITY_NONE;
291 case JankSeverityType::Partial:
292 return FrameTimelineEvent::SEVERITY_PARTIAL;
293 case JankSeverityType::Full:
294 return FrameTimelineEvent::SEVERITY_FULL;
295 }
296}
297
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800298// Returns the smallest timestamp from the set of predictions and actuals.
299nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
300 TimelineItem actuals) {
301 nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
302 if (predictionState == PredictionState::Valid) {
303 // Checking start time for predictions is enough because start time is always lesser than
304 // endTime and presentTime.
305 minTime = std::min(minTime, predictions.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700306 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700307
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800308 // Need to check startTime, endTime and presentTime for actuals because some frames might not
309 // have them set.
310 if (actuals.startTime != 0) {
311 minTime = std::min(minTime, actuals.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700312 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800313 if (actuals.endTime != 0) {
314 minTime = std::min(minTime, actuals.endTime);
315 }
316 if (actuals.presentTime != 0) {
ramindaniea2bb822022-06-27 19:52:10 +0000317 minTime = std::min(minTime, actuals.presentTime);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800318 }
319 return minTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700320}
321
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000322int64_t TraceCookieCounter::getCookieForTracing() {
323 return ++mTraceCookie;
324}
325
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000326SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
Alec Mouriadebf5c2021-01-05 12:57:36 -0800327 uid_t ownerUid, int32_t layerId, std::string layerName,
328 std::string debugName, PredictionState predictionState,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800329 frametimeline::TimelineItem&& predictions,
330 std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000331 JankClassificationThresholds thresholds,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700332 TraceCookieCounter* traceCookieCounter, bool isBuffer, GameMode gameMode)
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000333 : mToken(frameTimelineInfo.vsyncId),
334 mInputEventId(frameTimelineInfo.inputEventId),
Adithya Srinivasan01189672020-10-20 14:23:05 -0700335 mOwnerPid(ownerPid),
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700336 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700337 mLayerName(std::move(layerName)),
338 mDebugName(std::move(debugName)),
Alec Mouriadebf5c2021-01-05 12:57:36 -0800339 mLayerId(layerId),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700340 mPresentState(PresentState::Unknown),
341 mPredictionState(predictionState),
342 mPredictions(predictions),
343 mActuals({0, 0, 0}),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800344 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000345 mJankClassificationThresholds(thresholds),
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000346 mTraceCookieCounter(*traceCookieCounter),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000347 mIsBuffer(isBuffer),
348 mGameMode(gameMode) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700349
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700350void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000351 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700352 mActuals.startTime = actualStartTime;
353}
354
355void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000356 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700357 mActualQueueTime = actualQueueTime;
358}
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000359
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700360void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000361 std::scoped_lock lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700362 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700363}
364
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000365void SurfaceFrame::setDropTime(nsecs_t dropTime) {
366 std::scoped_lock lock(mMutex);
367 mDropTime = dropTime;
368}
369
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800370void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000371 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000372 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
373 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
374 "PresentState - %s set already.",
375 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800376 mPresentState = presentState;
377 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700378}
379
Alec Mouri7d436ec2021-01-27 20:40:50 -0800380void SurfaceFrame::setRenderRate(Fps renderRate) {
381 std::lock_guard<std::mutex> lock(mMutex);
382 mRenderRate = renderRate;
383}
384
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200385Fps SurfaceFrame::getRenderRate() const {
386 std::lock_guard<std::mutex> lock(mMutex);
387 return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate;
388}
389
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000390void SurfaceFrame::setGpuComposition() {
391 std::scoped_lock lock(mMutex);
392 mGpuComposition = true;
393}
394
Sally Qi438eb7d2023-12-05 18:59:32 -0800395// TODO(b/316171339): migrate from perfetto side
396bool SurfaceFrame::isSelfJanky() const {
397 int32_t jankType = getJankType().value_or(JankType::None);
398
399 if (jankType == JankType::None) {
400 return false;
401 }
402
403 int32_t jankBitmask = JankType::AppDeadlineMissed | JankType::Unknown;
404 if (jankType & jankBitmask) {
405 return true;
406 }
407
408 return false;
409}
410
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800411std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000412 std::scoped_lock lock(mMutex);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000413 if (mPresentState == PresentState::Dropped) {
Edgar Arriaga631e4252023-03-02 02:11:24 +0000414 return JankType::Dropped;
Adithya Srinivasan95619432021-02-08 21:52:51 +0000415 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100416 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000417 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100418 return std::nullopt;
419 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700420 return mJankType;
421}
422
Ying Wei96eb5352023-11-21 17:37:21 +0000423std::optional<JankSeverityType> SurfaceFrame::getJankSeverityType() const {
424 std::scoped_lock lock(mMutex);
425 if (mActuals.presentTime == 0) {
426 // Frame hasn't been presented yet.
427 return std::nullopt;
428 }
429 return mJankSeverityType;
430}
431
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700432nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000433 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800434 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700435}
436
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800437TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000438 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800439 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700440}
441
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000442PredictionState SurfaceFrame::getPredictionState() const {
443 std::scoped_lock lock(mMutex);
444 return mPredictionState;
445}
446
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800447SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000448 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800449 return mPresentState;
450}
451
452FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000453 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800454 return mFramePresentMetadata;
455}
456
457FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000458 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800459 return mFrameReadyMetadata;
460}
461
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000462nsecs_t SurfaceFrame::getDropTime() const {
463 std::scoped_lock lock(mMutex);
464 return mDropTime;
465}
466
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000467void SurfaceFrame::promoteToBuffer() {
468 std::scoped_lock lock(mMutex);
469 LOG_ALWAYS_FATAL_IF(mIsBuffer == true,
470 "Trying to promote an already promoted BufferSurfaceFrame from layer %s "
471 "with token %" PRId64 "",
472 mDebugName.c_str(), mToken);
473 mIsBuffer = true;
474}
475
476bool SurfaceFrame::getIsBuffer() const {
477 std::scoped_lock lock(mMutex);
478 return mIsBuffer;
479}
480
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800481void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000482 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700483 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700484 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100485 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700486 // Easily identify a janky Surface Frame in the dump
487 StringAppendF(&result, " [*] ");
488 }
489 StringAppendF(&result, "\n");
490 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800491 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
492 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000493 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
494 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700495 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
496 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800497 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
498 mRenderRate ? mRenderRate->getIntValue() : 0);
499 StringAppendF(&result, "%s", indent.c_str());
Alec Mouriadebf5c2021-01-05 12:57:36 -0800500 StringAppendF(&result, "Layer ID : %d\n", mLayerId);
501 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800502 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700503 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000504 if (mPresentState == PresentState::Dropped) {
505 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
506 StringAppendF(&result, "Drop time : %10f\n",
507 std::chrono::duration<double, std::milli>(dropTime).count());
508 StringAppendF(&result, "%s", indent.c_str());
509 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700510 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
511 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800512 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700513 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800514 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
515 StringAppendF(&result, "%s", indent.c_str());
516 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
517 std::chrono::nanoseconds latchTime(
518 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
519 StringAppendF(&result, "%s", indent.c_str());
520 StringAppendF(&result, "Last latch time: %10f\n",
521 std::chrono::duration<double, std::milli>(latchTime).count());
522 if (mPredictionState == PredictionState::Valid) {
523 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
524 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
525 StringAppendF(&result, "%s", indent.c_str());
526 StringAppendF(&result, "Present delta: %10f\n",
527 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
528 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700529 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700530}
531
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000532std::string SurfaceFrame::miniDump() const {
533 std::scoped_lock lock(mMutex);
534 std::string result;
535 StringAppendF(&result, "Layer - %s\n", mDebugName.c_str());
536 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
537 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
538 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
539 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
540 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
541 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
542 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
543 StringAppendF(&result, "Present time: %" PRId64 "", mActuals.presentTime);
544 return result;
545}
546
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000547void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
Ady Abrahame96e79f2024-05-20 18:00:39 +0000548 Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) {
Ady Abrahame43ff722022-02-15 14:44:25 -0800549 if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000550 // Cannot do any classification for invalid present time.
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000551 mJankType = JankType::Unknown;
Ying Wei96eb5352023-11-21 17:37:21 +0000552 mJankSeverityType = JankSeverityType::Unknown;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000553 if (outDeadlineDelta) {
554 *outDeadlineDelta = -1;
555 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800556 return;
557 }
558
Ady Abrahame43ff722022-02-15 14:44:25 -0800559 if (mPredictionState == PredictionState::Expired) {
560 // We classify prediction expired as AppDeadlineMissed as the
561 // TokenManager::kMaxTokens we store is large enough to account for a
562 // reasonable app, so prediction expire would mean a huge scheduling delay.
Edgar Arriaga631e4252023-03-02 02:11:24 +0000563 mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
564 : JankType::AppDeadlineMissed;
Ying Wei96eb5352023-11-21 17:37:21 +0000565 mJankSeverityType = JankSeverityType::Unknown;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000566 if (outDeadlineDelta) {
567 *outDeadlineDelta = -1;
568 }
Ady Abrahame43ff722022-02-15 14:44:25 -0800569 return;
570 }
571
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800572 if (mPredictionState == PredictionState::None) {
573 // Cannot do jank classification on frames that don't have a token.
574 return;
575 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800576
577 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
Alec Mouriadebf5c2021-01-05 12:57:36 -0800578 const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
579 ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
580 : 0;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000581 const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
582 if (outDeadlineDelta) {
583 *outDeadlineDelta = deadlineDelta;
584 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800585
586 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
587 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
588 } else {
589 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
590 }
591
592 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
593 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
594 : FramePresentMetadata::EarlyPresent;
Ying Wei96eb5352023-11-21 17:37:21 +0000595 // Jank that is missing by less than the render rate period is classified as partial jank,
596 // otherwise it is a full jank.
597 mJankSeverityType = std::abs(presentDelta) < displayFrameRenderRate.getPeriodNsecs()
598 ? JankSeverityType::Partial
599 : JankSeverityType::Full;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800600 } else {
601 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
602 }
603
604 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
605 // Frames presented on time are not janky.
606 mJankType = JankType::None;
607 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
608 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
609 // Finish on time, Present early
610 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800611 deltaToVsync >= refreshRate.getPeriodNsecs() -
612 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800613 // Delta factor of vsync
614 mJankType = JankType::SurfaceFlingerScheduling;
615 } else {
616 // Delta not a factor of vsync
617 mJankType = JankType::PredictionError;
618 }
619 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
620 // Finish late, Present early
621 mJankType = JankType::Unknown;
622 }
623 } else {
624 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
625 // Buffer Stuffing.
626 mJankType |= JankType::BufferStuffing;
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000627 // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
628 // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
629 // We try to do this by moving the deadline. Since the queue could be stuffed by more
630 // than one buffer, we take the last latch time as reference and give one vsync
631 // worth of time for the frame to be ready.
632 nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
633 if (adjustedDeadline > mActuals.endTime) {
634 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
635 } else {
636 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
637 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800638 }
639 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
640 // Finish on time, Present late
641 if (displayFrameJankType != JankType::None) {
642 // Propagate displayFrame's jank if it exists
643 mJankType |= displayFrameJankType;
644 } else {
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000645 if (!(mJankType & JankType::BufferStuffing)) {
646 // In a stuffed state, if the app finishes on time and there is no display frame
647 // jank, only buffer stuffing is the root cause of the jank.
648 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
649 deltaToVsync >= refreshRate.getPeriodNsecs() -
650 mJankClassificationThresholds.presentThreshold) {
651 // Delta factor of vsync
652 mJankType |= JankType::SurfaceFlingerScheduling;
653 } else {
654 // Delta not a factor of vsync
655 mJankType |= JankType::PredictionError;
656 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800657 }
658 }
659 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
660 // Finish late, Present late
Adithya Srinivasan8a945502021-03-19 19:12:32 +0000661 mJankType |= JankType::AppDeadlineMissed;
662 // Propagate DisplayFrame's jankType if it is janky
663 mJankType |= displayFrameJankType;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800664 }
665 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000666 if (mPresentState != PresentState::Presented) {
667 mJankType = JankType::Dropped;
668 // Since frame was not presented, lets drop any present value
669 mActuals.presentTime = 0;
Ying Wei96eb5352023-11-21 17:37:21 +0000670 mJankSeverityType = JankSeverityType::Unknown;
Edgar Arriaga631e4252023-03-02 02:11:24 +0000671 }
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000672}
673
674void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200675 Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
676 nsecs_t displayPresentDelta) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000677 std::scoped_lock lock(mMutex);
678
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200679 mDisplayFrameRenderRate = displayFrameRenderRate;
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000680 mActuals.presentTime = presentTime;
681 nsecs_t deadlineDelta = 0;
682
Ady Abrahame96e79f2024-05-20 18:00:39 +0000683 classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, &deadlineDelta);
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000684
685 if (mPredictionState != PredictionState::None) {
686 // Only update janky frames if the app used vsync predictions
687 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000688 mGameMode, mJankType, displayDeadlineDelta,
689 displayPresentDelta, deadlineDelta});
Pascal Mütschardd56514e2024-05-24 17:37:13 +0200690
691 gui::JankData jd;
692 jd.frameVsyncId = mToken;
693 jd.jankType = mJankType;
694 jd.frameIntervalNs =
695 (mRenderRate ? *mRenderRate : mDisplayFrameRenderRate).getPeriodNsecs();
696 JankTracker::onJankData(mLayerId, jd);
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000697 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800698}
699
Ady Abraham14beed72024-05-15 17:16:45 -0700700void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate) {
701 std::scoped_lock lock(mMutex);
702
703 mDisplayFrameRenderRate = displayFrameRenderRate;
704 mActuals.presentTime = mPredictions.presentTime;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000705 classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
Ady Abraham14beed72024-05-15 17:16:45 -0700706}
707
Ady Abraham57f8e182022-03-08 15:54:33 -0800708void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000709 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000710
Adithya Srinivasan86678502021-01-19 21:50:38 +0000711 // Expected timeline start
712 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000713 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700714 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800715 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
716 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700717
718 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000719 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700720
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000721 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
722
723 expectedSurfaceFrameStartEvent->set_token(mToken);
724 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
725
726 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
727 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
728 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000729
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000730 // Expected timeline end
731 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000732 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000733 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800734 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
735 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000736
737 auto* event = packet->set_frame_timeline_event();
738 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
739
740 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
741 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000742}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000743
Ady Abraham57f8e182022-03-08 15:54:33 -0800744void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000745 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000746
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000747 // Actual timeline start
748 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000749 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000750 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800751 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000752 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000753 if (mPredictionState == PredictionState::Expired) {
754 // If prediction is expired, we can't use the predicted start time. Instead, just use a
755 // start time a little earlier than the end time so that we have some info about this
756 // frame in the trace.
Adithya Srinivasanb2283c32021-04-21 21:31:56 +0000757 nsecs_t endTime =
758 (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
Ady Abrahamdee22322022-03-18 10:58:39 -0700759 const auto timestamp = endTime - kPredictionExpiredStartTimeDelta;
760 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000761 } else {
Ady Abrahamdee22322022-03-18 10:58:39 -0700762 const auto timestamp =
763 mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
764 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000765 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000766
767 auto* event = packet->set_frame_timeline_event();
768 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
769
770 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
771
772 actualSurfaceFrameStartEvent->set_token(mToken);
773 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
774
775 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
776 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700777
778 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000779 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700780 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000781 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700782 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000783 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700784 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000785 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
786 FrameReadyMetadata::OnTimeFinish);
787 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
788 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000789 actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan1f9450c2021-06-10 22:39:19 +0000790 actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer);
Ying Wei96eb5352023-11-21 17:37:21 +0000791 actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000792 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000793
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000794 // Actual timeline end
795 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000796 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000797 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800798 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000799 if (mPresentState == PresentState::Dropped) {
Ady Abraham57f8e182022-03-08 15:54:33 -0800800 packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000801 } else {
Ady Abraham57f8e182022-03-08 15:54:33 -0800802 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000803 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700804
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000805 auto* event = packet->set_frame_timeline_event();
806 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700807
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000808 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700809 });
810}
811
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000812/**
813 * TODO(b/178637512): add inputEventId to the perfetto trace.
814 */
Ady Abraham57f8e182022-03-08 15:54:33 -0800815void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000816 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
817 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
818 // No packets can be traced with a missing token.
819 return;
820 }
821 if (getPredictionState() != PredictionState::Expired) {
822 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
823 // a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -0800824 tracePredictions(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000825 }
Ady Abraham57f8e182022-03-08 15:54:33 -0800826 traceActuals(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000827}
828
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800829namespace impl {
830
831int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
832 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000833 std::scoped_lock lock(mMutex);
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000834 while (mPredictions.size() >= kMaxTokens) {
835 mPredictions.erase(mPredictions.begin());
836 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800837 const int64_t assignedToken = mCurrentToken++;
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000838 mPredictions[assignedToken] = predictions;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800839 return assignedToken;
840}
841
842std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000843 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800844 auto predictionsIterator = mPredictions.find(token);
845 if (predictionsIterator != mPredictions.end()) {
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000846 return predictionsIterator->second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800847 }
848 return {};
849}
850
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800851FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
Ady Abraham57f8e182022-03-08 15:54:33 -0800852 JankClassificationThresholds thresholds, bool useBootTimeClock)
853 : mUseBootTimeClock(useBootTimeClock),
854 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800855 mTimeStats(std::move(timeStats)),
856 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan82eef322021-04-10 00:06:04 +0000857 mJankClassificationThresholds(thresholds) {
858 mCurrentDisplayFrame =
859 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000860}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700861
Adithya Srinivasan01189672020-10-20 14:23:05 -0700862void FrameTimeline::onBootFinished() {
863 perfetto::TracingInitArgs args;
864 args.backends = perfetto::kSystemBackend;
865 perfetto::Tracing::Initialize(args);
866 registerDataSource();
867}
868
869void FrameTimeline::registerDataSource() {
870 perfetto::DataSourceDescriptor dsd;
871 dsd.set_name(kFrameTimelineDataSource);
872 FrameTimelineDataSource::Register(dsd);
873}
874
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800875std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Alec Mouriadebf5c2021-01-05 12:57:36 -0800876 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700877 std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700878 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000879 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800880 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000881 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800882 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000883 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000884 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700885 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000886 std::optional<TimelineItem> predictions =
887 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700888 if (predictions) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800889 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000890 std::move(layerName), std::move(debugName),
891 PredictionState::Valid, std::move(*predictions),
892 mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000893 &mTraceCookieCounter, isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700894 }
Alec Mouriadebf5c2021-01-05 12:57:36 -0800895 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000896 std::move(layerName), std::move(debugName),
897 PredictionState::Expired, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000898 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000899 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700900}
901
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800902FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000903 JankClassificationThresholds thresholds,
904 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800905 : mSurfaceFlingerPredictions(TimelineItem()),
906 mSurfaceFlingerActuals(TimelineItem()),
907 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000908 mJankClassificationThresholds(thresholds),
909 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800910 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700911}
912
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800913void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700914 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000915 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800916 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
917}
918
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200919void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
920 Fps renderRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800921 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000922 std::scoped_lock lock(mMutex);
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200923 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800924 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700925}
926
927void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000928 const std::shared_ptr<FenceTime>& presentFence,
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000929 const std::shared_ptr<FenceTime>& gpuFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700930 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000931 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800932 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000933 mCurrentDisplayFrame->setGpuFence(gpuFence);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700934 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
935 flushPendingPresentFences();
936 finalizeCurrentDisplayFrame();
937}
938
Ady Abraham14beed72024-05-15 17:16:45 -0700939void FrameTimeline::onCommitNotComposited() {
940 ATRACE_CALL();
941 std::scoped_lock lock(mMutex);
942 mCurrentDisplayFrame->onCommitNotComposited();
943 mCurrentDisplayFrame.reset();
944 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
945 &mTraceCookieCounter);
946}
947
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800948void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
949 mSurfaceFrames.push_back(surfaceFrame);
950}
951
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200952void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800953 std::optional<TimelineItem> predictions,
954 nsecs_t wakeUpTime) {
955 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800956 mRefreshRate = refreshRate;
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200957 mRenderRate = renderRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800958 if (!predictions) {
959 mPredictionState = PredictionState::Expired;
960 } else {
961 mPredictionState = PredictionState::Valid;
962 mSurfaceFlingerPredictions = *predictions;
963 }
964 mSurfaceFlingerActuals.startTime = wakeUpTime;
965}
966
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800967void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
968 TimelineItem predictions) {
969 mPredictionState = predictionState;
970 mSurfaceFlingerPredictions = predictions;
971}
972
973void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
974 mSurfaceFlingerActuals.startTime = actualStartTime;
975}
976
977void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
978 mSurfaceFlingerActuals.endTime = actualEndTime;
979}
980
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000981void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
982 mGpuFence = gpuFence;
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000983}
984
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000985void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
986 nsecs_t previousPresentTime) {
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700987 const bool presentTimeValid =
988 mSurfaceFlingerActuals.presentTime >= mSurfaceFlingerActuals.startTime;
989 if (mPredictionState == PredictionState::Expired || !presentTimeValid) {
Adithya Srinivasande272452021-04-10 00:21:00 +0000990 // Cannot do jank classification with expired predictions or invalid signal times. Set the
991 // deltas to 0 as both negative and positive deltas are used as real values.
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000992 mJankType = JankType::Unknown;
Ying Wei96eb5352023-11-21 17:37:21 +0000993 mJankSeverityType = JankSeverityType::Unknown;
Adithya Srinivasande272452021-04-10 00:21:00 +0000994 deadlineDelta = 0;
995 deltaToVsync = 0;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700996 if (!presentTimeValid) {
Ady Abrahamfcb16862022-10-10 14:35:21 -0700997 mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700998 mJankType |= JankType::DisplayHAL;
Ady Abrahamfcb16862022-10-10 14:35:21 -0700999 }
1000
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001001 return;
1002 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001003
1004 // Delta between the expected present and the actual present
1005 const nsecs_t presentDelta =
1006 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001007 // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
1008 // included the time for composition. However, for GPU composition, the final end time is max(sf
1009 // end time, gpu fence time).
1010 nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
1011 if (mGpuFence != FenceTime::NO_FENCE) {
1012 combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
1013 }
1014 deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
Alec Mouri363faf02021-01-29 16:34:55 -08001015
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001016 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
1017 // was a prediction error or not.
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001018 deltaToVsync = mRefreshRate.getPeriodNsecs() > 0
Alec Mouriadebf5c2021-01-05 12:57:36 -08001019 ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
1020 : 0;
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001021
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001022 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
1023 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
1024 : FramePresentMetadata::EarlyPresent;
Ying Wei96eb5352023-11-21 17:37:21 +00001025 // Jank that is missing by less than the render rate period is classified as partial jank,
1026 // otherwise it is a full jank.
1027 mJankSeverityType = std::abs(presentDelta) < mRenderRate.getPeriodNsecs()
1028 ? JankSeverityType::Partial
1029 : JankSeverityType::Full;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001030 } else {
1031 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
1032 }
1033
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001034 if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001035 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
1036 } else {
1037 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
1038 }
1039
1040 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
1041 mJankClassificationThresholds.startThreshold) {
1042 mFrameStartMetadata =
1043 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
1044 ? FrameStartMetadata::LateStart
1045 : FrameStartMetadata::EarlyStart;
1046 }
1047
1048 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
1049 // Do jank classification only if present is not on time
1050 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
1051 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
1052 // Finish on time, Present early
1053 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -08001054 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1055 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001056 // Delta is a factor of vsync if its within the presentTheshold on either side
1057 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1058 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1059 mJankType = JankType::SurfaceFlingerScheduling;
1060 } else {
1061 // Delta is not a factor of vsync,
1062 mJankType = JankType::PredictionError;
1063 }
1064 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
1065 // Finish late, Present early
1066 mJankType = JankType::SurfaceFlingerScheduling;
1067 } else {
1068 // Finish time unknown
1069 mJankType = JankType::Unknown;
1070 }
1071 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001072 if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
1073 mJankClassificationThresholds.presentThreshold ||
1074 previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
1075 // The previous frame was either presented in the current frame's expected vsync or
1076 // it was presented even later than the current frame's expected vsync.
1077 mJankType = JankType::SurfaceFlingerStuffing;
1078 }
1079 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
1080 !(mJankType & JankType::SurfaceFlingerStuffing)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001081 // Finish on time, Present late
1082 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -08001083 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1084 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001085 // Delta is a factor of vsync if its within the presentTheshold on either side
1086 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1087 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1088 mJankType = JankType::DisplayHAL;
1089 } else {
1090 // Delta is not a factor of vsync
1091 mJankType = JankType::PredictionError;
1092 }
1093 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001094 if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
1095 mSurfaceFlingerActuals.presentTime - previousPresentTime >
1096 mRefreshRate.getPeriodNsecs() +
1097 mJankClassificationThresholds.presentThreshold) {
1098 // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
1099 // was presented more than a vsync late.
Rachel Lee94917b32022-03-18 17:52:09 -07001100 if (mGpuFence != FenceTime::NO_FENCE) {
1101 // If SF was in GPU composition, classify it as GPU deadline missed.
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001102 mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
1103 } else {
1104 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
1105 }
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +00001106 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001107 } else {
1108 // Finish time unknown
1109 mJankType = JankType::Unknown;
1110 }
1111 } else {
1112 // Present unknown
1113 mJankType = JankType::Unknown;
1114 }
1115 }
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001116}
1117
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001118void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001119 mSurfaceFlingerActuals.presentTime = signalTime;
1120 nsecs_t deadlineDelta = 0;
1121 nsecs_t deltaToVsync = 0;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001122 classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001123
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001124 for (auto& surfaceFrame : mSurfaceFrames) {
Pascal Muetschardac7bcd92023-10-03 15:05:36 +02001125 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta,
1126 deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001127 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001128}
1129
Ady Abraham14beed72024-05-15 17:16:45 -07001130void FrameTimeline::DisplayFrame::onCommitNotComposited() {
1131 for (auto& surfaceFrame : mSurfaceFrames) {
1132 surfaceFrame->onCommitNotComposited(mRefreshRate, mRenderRate);
1133 }
1134}
1135
Ady Abraham57f8e182022-03-08 15:54:33 -08001136void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
1137 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001138 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001139
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001140 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001141 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001142 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001143 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1144 packet->set_timestamp(
1145 static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001146
1147 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001148 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001149
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001150 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001151
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001152 expectedDisplayFrameStartEvent->set_token(mToken);
1153 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1154 });
Adithya Srinivasan86678502021-01-19 21:50:38 +00001155
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001156 // Expected timeline end
1157 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1158 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001159 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1160 packet->set_timestamp(
1161 static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001162
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001163 auto* event = packet->set_frame_timeline_event();
1164 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001165
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001166 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
1167 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001168}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001169
Sally Qiaa107742023-09-29 14:53:14 -07001170void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
Sally Qi438eb7d2023-12-05 18:59:32 -08001171 nsecs_t previousPredictionPresentTime) const {
Sally Qiaa107742023-09-29 14:53:14 -07001172 nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
1173 const constexpr float kThresh = 0.5f;
1174 const constexpr float kRange = 1.5f;
1175 for (auto& surfaceFrame : mSurfaceFrames) {
Sally Qi438eb7d2023-12-05 18:59:32 -08001176 if (previousPredictionPresentTime != 0 &&
1177 static_cast<float>(mSurfaceFlingerPredictions.presentTime -
1178 previousPredictionPresentTime) >=
Sally Qiaa107742023-09-29 14:53:14 -07001179 static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
1180 static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
Sally Qi438eb7d2023-12-05 18:59:32 -08001181 (static_cast<float>(mSurfaceFlingerPredictions.presentTime) -
Sally Qiaa107742023-09-29 14:53:14 -07001182 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1183 static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
Sally Qi2269a692024-05-17 18:02:28 -07001184 (static_cast<float>(previousPredictionPresentTime) +
Sally Qi438eb7d2023-12-05 18:59:32 -08001185 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1186 // sf skipped frame is not considered if app is self janked
1187 !surfaceFrame->isSelfJanky()) {
Sally Qiaa107742023-09-29 14:53:14 -07001188 skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
1189 skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
1190 break;
1191 }
1192 }
1193
1194 // add slice
1195 if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
1196 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1197
1198 // Actual timeline start
1199 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1200 auto packet = ctx.NewTracePacket();
1201 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1202 packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
1203
1204 auto* event = packet->set_frame_timeline_event();
1205 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1206
1207 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1208
1209 actualDisplayFrameStartEvent->set_token(0);
1210 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1211 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1212 FrameReadyMetadata::OnTimeFinish);
1213 actualDisplayFrameStartEvent->set_gpu_composition(false);
1214 actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid));
1215 actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
1216 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped));
Ying Wei96eb5352023-11-21 17:37:21 +00001217 actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None));
Sally Qiaa107742023-09-29 14:53:14 -07001218 });
1219
1220 // Actual timeline end
1221 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1222 auto packet = ctx.NewTracePacket();
1223 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1224 packet->set_timestamp(static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
1225
1226 auto* event = packet->set_frame_timeline_event();
1227 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1228
1229 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1230 });
1231 }
1232}
1233
Ady Abraham57f8e182022-03-08 15:54:33 -08001234void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
1235 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001236 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001237
1238 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001239 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1240 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001241 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1242 packet->set_timestamp(
1243 static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001244
1245 auto* event = packet->set_frame_timeline_event();
1246 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1247
1248 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1249
1250 actualDisplayFrameStartEvent->set_token(mToken);
1251 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1252
1253 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
1254 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1255 FrameReadyMetadata::OnTimeFinish);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001256 actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001257 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +00001258 actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Ying Wei96eb5352023-11-21 17:37:21 +00001259 actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001260 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001261
1262 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001263 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1264 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001265 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1266 packet->set_timestamp(
1267 static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001268
1269 auto* event = packet->set_frame_timeline_event();
1270 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1271
1272 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001273 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001274}
1275
Sally Qi438eb7d2023-12-05 18:59:32 -08001276nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1277 nsecs_t previousPredictionPresentTime) const {
Ady Abraham57a8ab42023-01-26 15:28:19 -08001278 if (mSurfaceFrames.empty()) {
1279 // We don't want to trace display frames without any surface frames updates as this cannot
1280 // be janky
Sally Qi438eb7d2023-12-05 18:59:32 -08001281 return previousPredictionPresentTime;
Ady Abraham57a8ab42023-01-26 15:28:19 -08001282 }
1283
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001284 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
1285 // DisplayFrame should not have an invalid token.
1286 ALOGE("Cannot trace DisplayFrame with invalid token");
Sally Qi438eb7d2023-12-05 18:59:32 -08001287 return previousPredictionPresentTime;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001288 }
1289
1290 if (mPredictionState == PredictionState::Valid) {
1291 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
1292 // meaningful way in a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -08001293 tracePredictions(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001294 }
Ady Abraham57f8e182022-03-08 15:54:33 -08001295 traceActuals(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001296
1297 for (auto& surfaceFrame : mSurfaceFrames) {
Ady Abraham57f8e182022-03-08 15:54:33 -08001298 surfaceFrame->trace(mToken, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001299 }
Sally Qiaa107742023-09-29 14:53:14 -07001300
Sally Qif5721252023-11-17 11:14:53 -08001301 if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
Sally Qi438eb7d2023-12-05 18:59:32 -08001302 addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime);
Sally Qif5721252023-11-17 11:14:53 -08001303 }
Sally Qi438eb7d2023-12-05 18:59:32 -08001304 return mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001305}
1306
Alec Mouriadebf5c2021-01-05 12:57:36 -08001307float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
1308 if (layerIds.empty()) {
1309 return 0.0f;
1310 }
1311
1312 std::vector<nsecs_t> presentTimes;
1313 {
1314 std::scoped_lock lock(mMutex);
1315 presentTimes.reserve(mDisplayFrames.size());
1316 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1317 const auto& displayFrame = mDisplayFrames[i];
1318 if (displayFrame->getActuals().presentTime <= 0) {
1319 continue;
1320 }
1321 for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1322 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
1323 layerIds.count(surfaceFrame->getLayerId()) > 0) {
1324 // We're looking for DisplayFrames that presents at least one layer from
1325 // layerIds, so push the present time and skip looking through the rest of the
1326 // SurfaceFrames.
1327 presentTimes.push_back(displayFrame->getActuals().presentTime);
1328 break;
1329 }
1330 }
1331 }
1332 }
1333
1334 // FPS can't be computed when there's fewer than 2 presented frames.
1335 if (presentTimes.size() <= 1) {
1336 return 0.0f;
1337 }
1338
1339 nsecs_t priorPresentTime = -1;
1340 nsecs_t totalPresentToPresentWalls = 0;
1341
1342 for (const nsecs_t presentTime : presentTimes) {
1343 if (priorPresentTime == -1) {
1344 priorPresentTime = presentTime;
1345 continue;
1346 }
1347
1348 totalPresentToPresentWalls += (presentTime - priorPresentTime);
1349 priorPresentTime = presentTime;
1350 }
1351
1352 if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) {
1353 ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64,
1354 totalPresentToPresentWalls);
1355 return 0.0f;
1356 }
1357
1358 const constexpr nsecs_t kOneSecond =
1359 std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
1360 // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
1361 // M frames / second
1362 return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
1363 static_cast<float>(totalPresentToPresentWalls);
1364}
1365
Ady Abrahamfcb16862022-10-10 14:35:21 -07001366std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
1367 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1368 const auto& [fence, _] = mPendingPresentFences[i];
Theodore Dubois205c6dd2022-11-23 15:06:33 -08001369 if (fence && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001370 return i;
1371 }
1372 }
1373
1374 return {};
1375}
1376
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001377void FrameTimeline::flushPendingPresentFences() {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001378 const auto firstSignaledFence = getFirstSignalFenceIndex();
1379 if (!firstSignaledFence.has_value()) {
1380 return;
1381 }
1382
Ady Abraham57f8e182022-03-08 15:54:33 -08001383 // Perfetto is using boottime clock to void drifts when the device goes
1384 // to suspend.
1385 const auto monoBootOffset = mUseBootTimeClock
1386 ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
1387 : 0;
1388
Ady Abrahamfcb16862022-10-10 14:35:21 -07001389 // Present fences are expected to be signaled in order. Mark all the previous
1390 // pending fences as errors.
1391 for (size_t i = 0; i < firstSignaledFence.value(); i++) {
1392 const auto& pendingPresentFence = *mPendingPresentFences.begin();
1393 const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1394 auto& displayFrame = pendingPresentFence.second;
Sally Qi438eb7d2023-12-05 18:59:32 -08001395 displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1396 mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1397 mPreviousPredictionPresentTime);
Ady Abrahamfcb16862022-10-10 14:35:21 -07001398 mPendingPresentFences.erase(mPendingPresentFences.begin());
1399 }
1400
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001401 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1402 const auto& pendingPresentFence = mPendingPresentFences[i];
1403 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1404 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
1405 signalTime = pendingPresentFence.first->getSignalTime();
1406 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001407 break;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001408 }
1409 }
Ady Abrahamfcb16862022-10-10 14:35:21 -07001410
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +00001411 auto& displayFrame = pendingPresentFence.second;
Sally Qi438eb7d2023-12-05 18:59:32 -08001412 displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1413 mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1414 mPreviousPredictionPresentTime);
1415 mPreviousActualPresentTime = signalTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001416
1417 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
1418 --i;
1419 }
1420}
1421
1422void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001423 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001424 // We maintain only a fixed number of frames' data. Pop older frames
1425 mDisplayFrames.pop_front();
1426 }
1427 mDisplayFrames.push_back(mCurrentDisplayFrame);
1428 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001429 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan82eef322021-04-10 00:06:04 +00001430 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001431}
1432
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001433nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1434 nsecs_t baseTime =
1435 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1436 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001437 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1438 if (surfaceFrameBaseTime != 0) {
1439 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1440 }
1441 }
1442 return baseTime;
1443}
1444
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001445void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1446 int displayFrameCount) const {
1447 if (mJankType == JankType::None) {
1448 // Check if any Surface Frame has been janky
1449 bool isJanky = false;
1450 for (const auto& surfaceFrame : mSurfaceFrames) {
1451 if (surfaceFrame->getJankType() != JankType::None) {
1452 isJanky = true;
1453 break;
1454 }
1455 }
1456 if (!isJanky) {
1457 return;
1458 }
1459 }
1460 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1461 dump(result, baseTime);
1462}
1463
1464void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1465 dump(result, baseTime);
1466}
1467
1468void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1469 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001470 // Easily identify a janky Display Frame in the dump
1471 StringAppendF(&result, " [*] ");
1472 }
1473 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001474 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1475 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1476 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1477 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1478 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001479 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001480 StringAppendF(&result, "Vsync Period: %10f\n",
1481 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1482 nsecs_t presentDelta =
1483 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1484 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1485 StringAppendF(&result, "Present delta: %10f\n",
1486 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001487 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001488 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1489 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1490 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1491 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001492 StringAppendF(&result, "\n");
1493 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001494 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001495 surfaceFrame->dump(result, indent, baseTime);
1496 }
1497 StringAppendF(&result, "\n");
1498}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001499
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001500void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001501 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001502 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001503 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001504 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1505 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001506 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001507 }
1508}
1509
1510void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001511 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001512 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001513 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001514 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001515 }
1516}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001517
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001518void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1519 ATRACE_CALL();
1520 std::unordered_map<std::string, bool> argsMap;
1521 for (size_t i = 0; i < args.size(); i++) {
1522 argsMap[std::string(String8(args[i]).c_str())] = true;
1523 }
1524 if (argsMap.count("-jank")) {
1525 dumpJank(result);
1526 }
1527 if (argsMap.count("-all")) {
1528 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001529 }
1530}
1531
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001532void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001533 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001534
1535 // The size can either increase or decrease, clear everything, to be consistent
1536 mDisplayFrames.clear();
1537 mPendingPresentFences.clear();
1538 mMaxDisplayFrames = size;
1539}
1540
1541void FrameTimeline::reset() {
1542 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1543}
1544
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001545} // namespace impl
1546} // namespace android::frametimeline