blob: e9f26b04c77fcb409c295426f2bd047ce6e0f42b [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
Ying Wei96eb5352023-11-21 17:37:21 +0000283FrameTimelineEvent::JankSeverityType toProto(JankSeverityType jankSeverityType) {
284 switch (jankSeverityType) {
285 case JankSeverityType::Unknown:
286 return FrameTimelineEvent::SEVERITY_UNKNOWN;
287 case JankSeverityType::None:
288 return FrameTimelineEvent::SEVERITY_NONE;
289 case JankSeverityType::Partial:
290 return FrameTimelineEvent::SEVERITY_PARTIAL;
291 case JankSeverityType::Full:
292 return FrameTimelineEvent::SEVERITY_FULL;
293 }
294}
295
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800296// Returns the smallest timestamp from the set of predictions and actuals.
297nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
298 TimelineItem actuals) {
299 nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
300 if (predictionState == PredictionState::Valid) {
301 // Checking start time for predictions is enough because start time is always lesser than
302 // endTime and presentTime.
303 minTime = std::min(minTime, predictions.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700304 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700305
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800306 // Need to check startTime, endTime and presentTime for actuals because some frames might not
307 // have them set.
308 if (actuals.startTime != 0) {
309 minTime = std::min(minTime, actuals.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700310 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800311 if (actuals.endTime != 0) {
312 minTime = std::min(minTime, actuals.endTime);
313 }
314 if (actuals.presentTime != 0) {
ramindaniea2bb822022-06-27 19:52:10 +0000315 minTime = std::min(minTime, actuals.presentTime);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800316 }
317 return minTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700318}
319
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000320int64_t TraceCookieCounter::getCookieForTracing() {
321 return ++mTraceCookie;
322}
323
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000324SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
Alec Mouriadebf5c2021-01-05 12:57:36 -0800325 uid_t ownerUid, int32_t layerId, std::string layerName,
326 std::string debugName, PredictionState predictionState,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800327 frametimeline::TimelineItem&& predictions,
328 std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000329 JankClassificationThresholds thresholds,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700330 TraceCookieCounter* traceCookieCounter, bool isBuffer, GameMode gameMode)
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000331 : mToken(frameTimelineInfo.vsyncId),
332 mInputEventId(frameTimelineInfo.inputEventId),
Adithya Srinivasan01189672020-10-20 14:23:05 -0700333 mOwnerPid(ownerPid),
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700334 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700335 mLayerName(std::move(layerName)),
336 mDebugName(std::move(debugName)),
Alec Mouriadebf5c2021-01-05 12:57:36 -0800337 mLayerId(layerId),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700338 mPresentState(PresentState::Unknown),
339 mPredictionState(predictionState),
340 mPredictions(predictions),
341 mActuals({0, 0, 0}),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800342 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000343 mJankClassificationThresholds(thresholds),
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000344 mTraceCookieCounter(*traceCookieCounter),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000345 mIsBuffer(isBuffer),
346 mGameMode(gameMode) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700347
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700348void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000349 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700350 mActuals.startTime = actualStartTime;
351}
352
353void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000354 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700355 mActualQueueTime = actualQueueTime;
356}
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000357
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700358void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000359 std::scoped_lock lock(mMutex);
Vishnu Nairbd7d07e2024-07-08 13:37:11 -0700360 if (CC_UNLIKELY(acquireFenceTime == Fence::SIGNAL_TIME_PENDING)) {
361 mActuals.endTime = mActualQueueTime;
362 } else {
363 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
364 }
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700365}
366
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000367void SurfaceFrame::setDropTime(nsecs_t dropTime) {
368 std::scoped_lock lock(mMutex);
369 mDropTime = dropTime;
370}
371
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800372void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000373 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000374 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
375 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
376 "PresentState - %s set already.",
377 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800378 mPresentState = presentState;
379 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700380}
381
Alec Mouri7d436ec2021-01-27 20:40:50 -0800382void SurfaceFrame::setRenderRate(Fps renderRate) {
383 std::lock_guard<std::mutex> lock(mMutex);
384 mRenderRate = renderRate;
385}
386
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200387Fps SurfaceFrame::getRenderRate() const {
388 std::lock_guard<std::mutex> lock(mMutex);
389 return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate;
390}
391
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000392void SurfaceFrame::setGpuComposition() {
393 std::scoped_lock lock(mMutex);
394 mGpuComposition = true;
395}
396
Sally Qi438eb7d2023-12-05 18:59:32 -0800397// TODO(b/316171339): migrate from perfetto side
398bool SurfaceFrame::isSelfJanky() const {
399 int32_t jankType = getJankType().value_or(JankType::None);
400
401 if (jankType == JankType::None) {
402 return false;
403 }
404
405 int32_t jankBitmask = JankType::AppDeadlineMissed | JankType::Unknown;
406 if (jankType & jankBitmask) {
407 return true;
408 }
409
410 return false;
411}
412
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800413std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000414 std::scoped_lock lock(mMutex);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000415 if (mPresentState == PresentState::Dropped) {
Edgar Arriaga631e4252023-03-02 02:11:24 +0000416 return JankType::Dropped;
Adithya Srinivasan95619432021-02-08 21:52:51 +0000417 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100418 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000419 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100420 return std::nullopt;
421 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700422 return mJankType;
423}
424
Ying Wei96eb5352023-11-21 17:37:21 +0000425std::optional<JankSeverityType> SurfaceFrame::getJankSeverityType() const {
426 std::scoped_lock lock(mMutex);
427 if (mActuals.presentTime == 0) {
428 // Frame hasn't been presented yet.
429 return std::nullopt;
430 }
431 return mJankSeverityType;
432}
433
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700434nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000435 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800436 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700437}
438
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800439TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000440 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800441 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700442}
443
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000444PredictionState SurfaceFrame::getPredictionState() const {
445 std::scoped_lock lock(mMutex);
446 return mPredictionState;
447}
448
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800449SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000450 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800451 return mPresentState;
452}
453
454FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000455 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800456 return mFramePresentMetadata;
457}
458
459FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000460 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800461 return mFrameReadyMetadata;
462}
463
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000464nsecs_t SurfaceFrame::getDropTime() const {
465 std::scoped_lock lock(mMutex);
466 return mDropTime;
467}
468
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000469void SurfaceFrame::promoteToBuffer() {
470 std::scoped_lock lock(mMutex);
471 LOG_ALWAYS_FATAL_IF(mIsBuffer == true,
472 "Trying to promote an already promoted BufferSurfaceFrame from layer %s "
473 "with token %" PRId64 "",
474 mDebugName.c_str(), mToken);
475 mIsBuffer = true;
476}
477
478bool SurfaceFrame::getIsBuffer() const {
479 std::scoped_lock lock(mMutex);
480 return mIsBuffer;
481}
482
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800483void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000484 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700485 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700486 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100487 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700488 // Easily identify a janky Surface Frame in the dump
489 StringAppendF(&result, " [*] ");
490 }
491 StringAppendF(&result, "\n");
492 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800493 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
494 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000495 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
496 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700497 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
498 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800499 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
500 mRenderRate ? mRenderRate->getIntValue() : 0);
501 StringAppendF(&result, "%s", indent.c_str());
Alec Mouriadebf5c2021-01-05 12:57:36 -0800502 StringAppendF(&result, "Layer ID : %d\n", mLayerId);
503 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800504 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700505 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000506 if (mPresentState == PresentState::Dropped) {
507 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
508 StringAppendF(&result, "Drop time : %10f\n",
509 std::chrono::duration<double, std::milli>(dropTime).count());
510 StringAppendF(&result, "%s", indent.c_str());
511 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700512 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
513 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800514 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700515 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800516 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
517 StringAppendF(&result, "%s", indent.c_str());
518 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
519 std::chrono::nanoseconds latchTime(
520 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
521 StringAppendF(&result, "%s", indent.c_str());
522 StringAppendF(&result, "Last latch time: %10f\n",
523 std::chrono::duration<double, std::milli>(latchTime).count());
524 if (mPredictionState == PredictionState::Valid) {
525 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
526 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
527 StringAppendF(&result, "%s", indent.c_str());
528 StringAppendF(&result, "Present delta: %10f\n",
529 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
530 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700531 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700532}
533
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000534std::string SurfaceFrame::miniDump() const {
535 std::scoped_lock lock(mMutex);
536 std::string result;
537 StringAppendF(&result, "Layer - %s\n", mDebugName.c_str());
538 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
539 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
540 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
541 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
542 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
543 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
544 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
545 StringAppendF(&result, "Present time: %" PRId64 "", mActuals.presentTime);
546 return result;
547}
548
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000549void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
Ady Abrahame96e79f2024-05-20 18:00:39 +0000550 Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) {
Ady Abrahame43ff722022-02-15 14:44:25 -0800551 if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000552 // Cannot do any classification for invalid present time.
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000553 mJankType = JankType::Unknown;
Ying Wei96eb5352023-11-21 17:37:21 +0000554 mJankSeverityType = JankSeverityType::Unknown;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000555 if (outDeadlineDelta) {
556 *outDeadlineDelta = -1;
557 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800558 return;
559 }
560
Ady Abrahame43ff722022-02-15 14:44:25 -0800561 if (mPredictionState == PredictionState::Expired) {
562 // We classify prediction expired as AppDeadlineMissed as the
563 // TokenManager::kMaxTokens we store is large enough to account for a
564 // reasonable app, so prediction expire would mean a huge scheduling delay.
Edgar Arriaga631e4252023-03-02 02:11:24 +0000565 mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
566 : JankType::AppDeadlineMissed;
Ying Wei96eb5352023-11-21 17:37:21 +0000567 mJankSeverityType = JankSeverityType::Unknown;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000568 if (outDeadlineDelta) {
569 *outDeadlineDelta = -1;
570 }
Ady Abrahame43ff722022-02-15 14:44:25 -0800571 return;
572 }
573
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800574 if (mPredictionState == PredictionState::None) {
575 // Cannot do jank classification on frames that don't have a token.
576 return;
577 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800578
579 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
Alec Mouriadebf5c2021-01-05 12:57:36 -0800580 const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
581 ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
582 : 0;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000583 const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
584 if (outDeadlineDelta) {
585 *outDeadlineDelta = deadlineDelta;
586 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800587
588 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
589 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
590 } else {
591 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
592 }
593
594 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
595 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
596 : FramePresentMetadata::EarlyPresent;
Ying Wei96eb5352023-11-21 17:37:21 +0000597 // Jank that is missing by less than the render rate period is classified as partial jank,
598 // otherwise it is a full jank.
599 mJankSeverityType = std::abs(presentDelta) < displayFrameRenderRate.getPeriodNsecs()
600 ? JankSeverityType::Partial
601 : JankSeverityType::Full;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800602 } else {
603 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
604 }
605
606 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
607 // Frames presented on time are not janky.
608 mJankType = JankType::None;
609 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
610 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
611 // Finish on time, Present early
612 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800613 deltaToVsync >= refreshRate.getPeriodNsecs() -
614 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800615 // Delta factor of vsync
616 mJankType = JankType::SurfaceFlingerScheduling;
617 } else {
618 // Delta not a factor of vsync
619 mJankType = JankType::PredictionError;
620 }
621 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
622 // Finish late, Present early
623 mJankType = JankType::Unknown;
624 }
625 } else {
626 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
627 // Buffer Stuffing.
628 mJankType |= JankType::BufferStuffing;
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000629 // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
630 // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
631 // We try to do this by moving the deadline. Since the queue could be stuffed by more
632 // than one buffer, we take the last latch time as reference and give one vsync
633 // worth of time for the frame to be ready.
634 nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
635 if (adjustedDeadline > mActuals.endTime) {
636 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
637 } else {
638 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
639 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800640 }
641 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
642 // Finish on time, Present late
643 if (displayFrameJankType != JankType::None) {
644 // Propagate displayFrame's jank if it exists
645 mJankType |= displayFrameJankType;
646 } else {
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000647 if (!(mJankType & JankType::BufferStuffing)) {
648 // In a stuffed state, if the app finishes on time and there is no display frame
649 // jank, only buffer stuffing is the root cause of the jank.
650 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
651 deltaToVsync >= refreshRate.getPeriodNsecs() -
652 mJankClassificationThresholds.presentThreshold) {
653 // Delta factor of vsync
654 mJankType |= JankType::SurfaceFlingerScheduling;
655 } else {
656 // Delta not a factor of vsync
657 mJankType |= JankType::PredictionError;
658 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800659 }
660 }
661 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
662 // Finish late, Present late
Adithya Srinivasan8a945502021-03-19 19:12:32 +0000663 mJankType |= JankType::AppDeadlineMissed;
664 // Propagate DisplayFrame's jankType if it is janky
665 mJankType |= displayFrameJankType;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800666 }
667 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000668 if (mPresentState != PresentState::Presented) {
669 mJankType = JankType::Dropped;
670 // Since frame was not presented, lets drop any present value
671 mActuals.presentTime = 0;
Ying Wei96eb5352023-11-21 17:37:21 +0000672 mJankSeverityType = JankSeverityType::Unknown;
Edgar Arriaga631e4252023-03-02 02:11:24 +0000673 }
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000674}
675
676void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200677 Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
678 nsecs_t displayPresentDelta) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000679 std::scoped_lock lock(mMutex);
680
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200681 mDisplayFrameRenderRate = displayFrameRenderRate;
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000682 mActuals.presentTime = presentTime;
683 nsecs_t deadlineDelta = 0;
684
Ady Abrahame96e79f2024-05-20 18:00:39 +0000685 classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, &deadlineDelta);
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000686
687 if (mPredictionState != PredictionState::None) {
688 // Only update janky frames if the app used vsync predictions
689 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000690 mGameMode, mJankType, displayDeadlineDelta,
691 displayPresentDelta, deadlineDelta});
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000692 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800693}
694
Ady Abraham14beed72024-05-15 17:16:45 -0700695void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate) {
696 std::scoped_lock lock(mMutex);
697
698 mDisplayFrameRenderRate = displayFrameRenderRate;
699 mActuals.presentTime = mPredictions.presentTime;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000700 classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
Ady Abraham14beed72024-05-15 17:16:45 -0700701}
702
Ady Abraham57f8e182022-03-08 15:54:33 -0800703void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000704 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000705
Adithya Srinivasan86678502021-01-19 21:50:38 +0000706 // Expected timeline start
707 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000708 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700709 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800710 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
711 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700712
713 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000714 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700715
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000716 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
717
718 expectedSurfaceFrameStartEvent->set_token(mToken);
719 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
720
721 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
722 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
723 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000724
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000725 // Expected timeline end
726 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000727 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000728 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800729 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
730 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000731
732 auto* event = packet->set_frame_timeline_event();
733 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
734
735 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
736 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000737}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000738
Ady Abraham57f8e182022-03-08 15:54:33 -0800739void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000740 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000741
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000742 // Actual timeline start
743 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000744 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000745 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800746 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000747 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000748 if (mPredictionState == PredictionState::Expired) {
749 // If prediction is expired, we can't use the predicted start time. Instead, just use a
750 // start time a little earlier than the end time so that we have some info about this
751 // frame in the trace.
Adithya Srinivasanb2283c32021-04-21 21:31:56 +0000752 nsecs_t endTime =
753 (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
Ady Abrahamdee22322022-03-18 10:58:39 -0700754 const auto timestamp = endTime - kPredictionExpiredStartTimeDelta;
755 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000756 } else {
Ady Abrahamdee22322022-03-18 10:58:39 -0700757 const auto timestamp =
758 mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
759 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000760 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000761
762 auto* event = packet->set_frame_timeline_event();
763 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
764
765 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
766
767 actualSurfaceFrameStartEvent->set_token(mToken);
768 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
769
770 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
771 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700772
773 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000774 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700775 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000776 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700777 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000778 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700779 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000780 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
781 FrameReadyMetadata::OnTimeFinish);
782 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
783 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000784 actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan1f9450c2021-06-10 22:39:19 +0000785 actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer);
Ying Wei96eb5352023-11-21 17:37:21 +0000786 actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000787 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000788
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000789 // Actual timeline end
790 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000791 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000792 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800793 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000794 if (mPresentState == PresentState::Dropped) {
Ady Abraham57f8e182022-03-08 15:54:33 -0800795 packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000796 } else {
Ady Abraham57f8e182022-03-08 15:54:33 -0800797 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000798 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700799
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000800 auto* event = packet->set_frame_timeline_event();
801 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700802
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000803 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700804 });
805}
806
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000807/**
808 * TODO(b/178637512): add inputEventId to the perfetto trace.
809 */
Ady Abraham57f8e182022-03-08 15:54:33 -0800810void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000811 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
812 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
813 // No packets can be traced with a missing token.
814 return;
815 }
816 if (getPredictionState() != PredictionState::Expired) {
817 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
818 // a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -0800819 tracePredictions(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000820 }
Ady Abraham57f8e182022-03-08 15:54:33 -0800821 traceActuals(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000822}
823
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800824namespace impl {
825
826int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
827 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000828 std::scoped_lock lock(mMutex);
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000829 while (mPredictions.size() >= kMaxTokens) {
830 mPredictions.erase(mPredictions.begin());
831 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800832 const int64_t assignedToken = mCurrentToken++;
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000833 mPredictions[assignedToken] = predictions;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800834 return assignedToken;
835}
836
837std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000838 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800839 auto predictionsIterator = mPredictions.find(token);
840 if (predictionsIterator != mPredictions.end()) {
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000841 return predictionsIterator->second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800842 }
843 return {};
844}
845
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800846FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
Ady Abraham57f8e182022-03-08 15:54:33 -0800847 JankClassificationThresholds thresholds, bool useBootTimeClock)
848 : mUseBootTimeClock(useBootTimeClock),
849 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800850 mTimeStats(std::move(timeStats)),
851 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan82eef322021-04-10 00:06:04 +0000852 mJankClassificationThresholds(thresholds) {
853 mCurrentDisplayFrame =
854 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000855}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700856
Adithya Srinivasan01189672020-10-20 14:23:05 -0700857void FrameTimeline::onBootFinished() {
858 perfetto::TracingInitArgs args;
859 args.backends = perfetto::kSystemBackend;
860 perfetto::Tracing::Initialize(args);
861 registerDataSource();
862}
863
864void FrameTimeline::registerDataSource() {
865 perfetto::DataSourceDescriptor dsd;
866 dsd.set_name(kFrameTimelineDataSource);
867 FrameTimelineDataSource::Register(dsd);
868}
869
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800870std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Alec Mouriadebf5c2021-01-05 12:57:36 -0800871 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700872 std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700873 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000874 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800875 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000876 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800877 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000878 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000879 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700880 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000881 std::optional<TimelineItem> predictions =
882 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700883 if (predictions) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800884 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000885 std::move(layerName), std::move(debugName),
886 PredictionState::Valid, std::move(*predictions),
887 mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000888 &mTraceCookieCounter, isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700889 }
Alec Mouriadebf5c2021-01-05 12:57:36 -0800890 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000891 std::move(layerName), std::move(debugName),
892 PredictionState::Expired, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000893 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000894 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700895}
896
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800897FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000898 JankClassificationThresholds thresholds,
899 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800900 : mSurfaceFlingerPredictions(TimelineItem()),
901 mSurfaceFlingerActuals(TimelineItem()),
902 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000903 mJankClassificationThresholds(thresholds),
904 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800905 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700906}
907
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800908void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700909 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000910 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800911 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
912}
913
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200914void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
915 Fps renderRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800916 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000917 std::scoped_lock lock(mMutex);
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200918 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800919 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700920}
921
922void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000923 const std::shared_ptr<FenceTime>& presentFence,
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000924 const std::shared_ptr<FenceTime>& gpuFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700925 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000926 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800927 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000928 mCurrentDisplayFrame->setGpuFence(gpuFence);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700929 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
930 flushPendingPresentFences();
931 finalizeCurrentDisplayFrame();
932}
933
Ady Abraham14beed72024-05-15 17:16:45 -0700934void FrameTimeline::onCommitNotComposited() {
935 ATRACE_CALL();
936 std::scoped_lock lock(mMutex);
937 mCurrentDisplayFrame->onCommitNotComposited();
938 mCurrentDisplayFrame.reset();
939 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
940 &mTraceCookieCounter);
941}
942
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800943void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
944 mSurfaceFrames.push_back(surfaceFrame);
945}
946
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200947void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800948 std::optional<TimelineItem> predictions,
949 nsecs_t wakeUpTime) {
950 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800951 mRefreshRate = refreshRate;
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200952 mRenderRate = renderRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800953 if (!predictions) {
954 mPredictionState = PredictionState::Expired;
955 } else {
956 mPredictionState = PredictionState::Valid;
957 mSurfaceFlingerPredictions = *predictions;
958 }
959 mSurfaceFlingerActuals.startTime = wakeUpTime;
960}
961
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800962void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
963 TimelineItem predictions) {
964 mPredictionState = predictionState;
965 mSurfaceFlingerPredictions = predictions;
966}
967
968void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
969 mSurfaceFlingerActuals.startTime = actualStartTime;
970}
971
972void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
973 mSurfaceFlingerActuals.endTime = actualEndTime;
974}
975
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000976void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
977 mGpuFence = gpuFence;
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000978}
979
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000980void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
981 nsecs_t previousPresentTime) {
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700982 const bool presentTimeValid =
983 mSurfaceFlingerActuals.presentTime >= mSurfaceFlingerActuals.startTime;
984 if (mPredictionState == PredictionState::Expired || !presentTimeValid) {
Adithya Srinivasande272452021-04-10 00:21:00 +0000985 // Cannot do jank classification with expired predictions or invalid signal times. Set the
986 // deltas to 0 as both negative and positive deltas are used as real values.
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000987 mJankType = JankType::Unknown;
Ying Wei96eb5352023-11-21 17:37:21 +0000988 mJankSeverityType = JankSeverityType::Unknown;
Adithya Srinivasande272452021-04-10 00:21:00 +0000989 deadlineDelta = 0;
990 deltaToVsync = 0;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700991 if (!presentTimeValid) {
Ady Abrahamfcb16862022-10-10 14:35:21 -0700992 mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700993 mJankType |= JankType::DisplayHAL;
Ady Abrahamfcb16862022-10-10 14:35:21 -0700994 }
995
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000996 return;
997 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800998
999 // Delta between the expected present and the actual present
1000 const nsecs_t presentDelta =
1001 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001002 // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
1003 // included the time for composition. However, for GPU composition, the final end time is max(sf
1004 // end time, gpu fence time).
1005 nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
1006 if (mGpuFence != FenceTime::NO_FENCE) {
1007 combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
1008 }
1009 deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
Alec Mouri363faf02021-01-29 16:34:55 -08001010
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001011 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
1012 // was a prediction error or not.
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001013 deltaToVsync = mRefreshRate.getPeriodNsecs() > 0
Alec Mouriadebf5c2021-01-05 12:57:36 -08001014 ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
1015 : 0;
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001016
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001017 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
1018 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
1019 : FramePresentMetadata::EarlyPresent;
Ying Wei96eb5352023-11-21 17:37:21 +00001020 // Jank that is missing by less than the render rate period is classified as partial jank,
1021 // otherwise it is a full jank.
1022 mJankSeverityType = std::abs(presentDelta) < mRenderRate.getPeriodNsecs()
1023 ? JankSeverityType::Partial
1024 : JankSeverityType::Full;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001025 } else {
1026 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
1027 }
1028
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001029 if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001030 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
1031 } else {
1032 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
1033 }
1034
1035 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
1036 mJankClassificationThresholds.startThreshold) {
1037 mFrameStartMetadata =
1038 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
1039 ? FrameStartMetadata::LateStart
1040 : FrameStartMetadata::EarlyStart;
1041 }
1042
1043 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
1044 // Do jank classification only if present is not on time
1045 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
1046 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
1047 // Finish on time, Present early
1048 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -08001049 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1050 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001051 // Delta is a factor of vsync if its within the presentTheshold on either side
1052 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1053 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1054 mJankType = JankType::SurfaceFlingerScheduling;
1055 } else {
1056 // Delta is not a factor of vsync,
1057 mJankType = JankType::PredictionError;
1058 }
1059 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
1060 // Finish late, Present early
1061 mJankType = JankType::SurfaceFlingerScheduling;
1062 } else {
1063 // Finish time unknown
1064 mJankType = JankType::Unknown;
1065 }
1066 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001067 if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
1068 mJankClassificationThresholds.presentThreshold ||
1069 previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
1070 // The previous frame was either presented in the current frame's expected vsync or
1071 // it was presented even later than the current frame's expected vsync.
1072 mJankType = JankType::SurfaceFlingerStuffing;
1073 }
1074 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
1075 !(mJankType & JankType::SurfaceFlingerStuffing)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001076 // Finish on time, Present late
1077 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -08001078 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1079 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001080 // Delta is a factor of vsync if its within the presentTheshold on either side
1081 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1082 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1083 mJankType = JankType::DisplayHAL;
1084 } else {
1085 // Delta is not a factor of vsync
1086 mJankType = JankType::PredictionError;
1087 }
1088 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001089 if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
1090 mSurfaceFlingerActuals.presentTime - previousPresentTime >
1091 mRefreshRate.getPeriodNsecs() +
1092 mJankClassificationThresholds.presentThreshold) {
1093 // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
1094 // was presented more than a vsync late.
Rachel Lee94917b32022-03-18 17:52:09 -07001095 if (mGpuFence != FenceTime::NO_FENCE) {
1096 // If SF was in GPU composition, classify it as GPU deadline missed.
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001097 mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
1098 } else {
1099 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
1100 }
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +00001101 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001102 } else {
1103 // Finish time unknown
1104 mJankType = JankType::Unknown;
1105 }
1106 } else {
1107 // Present unknown
1108 mJankType = JankType::Unknown;
1109 }
1110 }
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001111}
1112
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001113void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001114 mSurfaceFlingerActuals.presentTime = signalTime;
1115 nsecs_t deadlineDelta = 0;
1116 nsecs_t deltaToVsync = 0;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001117 classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001118
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001119 for (auto& surfaceFrame : mSurfaceFrames) {
Pascal Muetschardac7bcd92023-10-03 15:05:36 +02001120 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta,
1121 deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001122 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001123}
1124
Ady Abraham14beed72024-05-15 17:16:45 -07001125void FrameTimeline::DisplayFrame::onCommitNotComposited() {
1126 for (auto& surfaceFrame : mSurfaceFrames) {
1127 surfaceFrame->onCommitNotComposited(mRefreshRate, mRenderRate);
1128 }
1129}
1130
Ady Abraham57f8e182022-03-08 15:54:33 -08001131void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
1132 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001133 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001134
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001135 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001136 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001137 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001138 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1139 packet->set_timestamp(
1140 static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001141
1142 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001143 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001144
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001145 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001146
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001147 expectedDisplayFrameStartEvent->set_token(mToken);
1148 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1149 });
Adithya Srinivasan86678502021-01-19 21:50:38 +00001150
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001151 // Expected timeline end
1152 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1153 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001154 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1155 packet->set_timestamp(
1156 static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001157
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001158 auto* event = packet->set_frame_timeline_event();
1159 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001160
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001161 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
1162 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001163}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001164
Sally Qiaa107742023-09-29 14:53:14 -07001165void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
Sally Qi438eb7d2023-12-05 18:59:32 -08001166 nsecs_t previousPredictionPresentTime) const {
Sally Qiaa107742023-09-29 14:53:14 -07001167 nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
1168 const constexpr float kThresh = 0.5f;
1169 const constexpr float kRange = 1.5f;
1170 for (auto& surfaceFrame : mSurfaceFrames) {
Sally Qi438eb7d2023-12-05 18:59:32 -08001171 if (previousPredictionPresentTime != 0 &&
1172 static_cast<float>(mSurfaceFlingerPredictions.presentTime -
1173 previousPredictionPresentTime) >=
Sally Qiaa107742023-09-29 14:53:14 -07001174 static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
1175 static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
Sally Qi438eb7d2023-12-05 18:59:32 -08001176 (static_cast<float>(mSurfaceFlingerPredictions.presentTime) -
Sally Qiaa107742023-09-29 14:53:14 -07001177 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1178 static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
Sally Qi2269a692024-05-17 18:02:28 -07001179 (static_cast<float>(previousPredictionPresentTime) +
Sally Qi438eb7d2023-12-05 18:59:32 -08001180 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1181 // sf skipped frame is not considered if app is self janked
1182 !surfaceFrame->isSelfJanky()) {
Sally Qiaa107742023-09-29 14:53:14 -07001183 skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
1184 skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
1185 break;
1186 }
1187 }
1188
1189 // add slice
1190 if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
1191 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1192
1193 // Actual timeline start
1194 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1195 auto packet = ctx.NewTracePacket();
1196 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1197 packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
1198
1199 auto* event = packet->set_frame_timeline_event();
1200 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1201
1202 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1203
1204 actualDisplayFrameStartEvent->set_token(0);
1205 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1206 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1207 FrameReadyMetadata::OnTimeFinish);
1208 actualDisplayFrameStartEvent->set_gpu_composition(false);
1209 actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid));
1210 actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
1211 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped));
Ying Wei96eb5352023-11-21 17:37:21 +00001212 actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None));
Sally Qiaa107742023-09-29 14:53:14 -07001213 });
1214
1215 // Actual timeline end
1216 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1217 auto packet = ctx.NewTracePacket();
1218 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1219 packet->set_timestamp(static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
1220
1221 auto* event = packet->set_frame_timeline_event();
1222 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1223
1224 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1225 });
1226 }
1227}
1228
Ady Abraham57f8e182022-03-08 15:54:33 -08001229void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
1230 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001231 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001232
1233 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001234 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1235 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001236 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1237 packet->set_timestamp(
1238 static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001239
1240 auto* event = packet->set_frame_timeline_event();
1241 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1242
1243 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1244
1245 actualDisplayFrameStartEvent->set_token(mToken);
1246 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1247
1248 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
1249 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1250 FrameReadyMetadata::OnTimeFinish);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001251 actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001252 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +00001253 actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Ying Wei96eb5352023-11-21 17:37:21 +00001254 actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001255 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001256
1257 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001258 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1259 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001260 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1261 packet->set_timestamp(
1262 static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001263
1264 auto* event = packet->set_frame_timeline_event();
1265 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1266
1267 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001268 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001269}
1270
Sally Qi438eb7d2023-12-05 18:59:32 -08001271nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1272 nsecs_t previousPredictionPresentTime) const {
Ady Abraham57a8ab42023-01-26 15:28:19 -08001273 if (mSurfaceFrames.empty()) {
1274 // We don't want to trace display frames without any surface frames updates as this cannot
1275 // be janky
Sally Qi438eb7d2023-12-05 18:59:32 -08001276 return previousPredictionPresentTime;
Ady Abraham57a8ab42023-01-26 15:28:19 -08001277 }
1278
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001279 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
1280 // DisplayFrame should not have an invalid token.
1281 ALOGE("Cannot trace DisplayFrame with invalid token");
Sally Qi438eb7d2023-12-05 18:59:32 -08001282 return previousPredictionPresentTime;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001283 }
1284
1285 if (mPredictionState == PredictionState::Valid) {
1286 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
1287 // meaningful way in a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -08001288 tracePredictions(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001289 }
Ady Abraham57f8e182022-03-08 15:54:33 -08001290 traceActuals(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001291
1292 for (auto& surfaceFrame : mSurfaceFrames) {
Ady Abraham57f8e182022-03-08 15:54:33 -08001293 surfaceFrame->trace(mToken, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001294 }
Sally Qiaa107742023-09-29 14:53:14 -07001295
Sally Qif5721252023-11-17 11:14:53 -08001296 if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
Sally Qi438eb7d2023-12-05 18:59:32 -08001297 addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime);
Sally Qif5721252023-11-17 11:14:53 -08001298 }
Sally Qi438eb7d2023-12-05 18:59:32 -08001299 return mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001300}
1301
Alec Mouriadebf5c2021-01-05 12:57:36 -08001302float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
1303 if (layerIds.empty()) {
1304 return 0.0f;
1305 }
1306
1307 std::vector<nsecs_t> presentTimes;
1308 {
1309 std::scoped_lock lock(mMutex);
1310 presentTimes.reserve(mDisplayFrames.size());
1311 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1312 const auto& displayFrame = mDisplayFrames[i];
1313 if (displayFrame->getActuals().presentTime <= 0) {
1314 continue;
1315 }
1316 for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1317 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
1318 layerIds.count(surfaceFrame->getLayerId()) > 0) {
1319 // We're looking for DisplayFrames that presents at least one layer from
1320 // layerIds, so push the present time and skip looking through the rest of the
1321 // SurfaceFrames.
1322 presentTimes.push_back(displayFrame->getActuals().presentTime);
1323 break;
1324 }
1325 }
1326 }
1327 }
1328
1329 // FPS can't be computed when there's fewer than 2 presented frames.
1330 if (presentTimes.size() <= 1) {
1331 return 0.0f;
1332 }
1333
1334 nsecs_t priorPresentTime = -1;
1335 nsecs_t totalPresentToPresentWalls = 0;
1336
1337 for (const nsecs_t presentTime : presentTimes) {
1338 if (priorPresentTime == -1) {
1339 priorPresentTime = presentTime;
1340 continue;
1341 }
1342
1343 totalPresentToPresentWalls += (presentTime - priorPresentTime);
1344 priorPresentTime = presentTime;
1345 }
1346
1347 if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) {
1348 ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64,
1349 totalPresentToPresentWalls);
1350 return 0.0f;
1351 }
1352
1353 const constexpr nsecs_t kOneSecond =
1354 std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
1355 // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
1356 // M frames / second
1357 return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
1358 static_cast<float>(totalPresentToPresentWalls);
1359}
1360
Ady Abrahamfcb16862022-10-10 14:35:21 -07001361std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
1362 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1363 const auto& [fence, _] = mPendingPresentFences[i];
Theodore Dubois205c6dd2022-11-23 15:06:33 -08001364 if (fence && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001365 return i;
1366 }
1367 }
1368
1369 return {};
1370}
1371
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001372void FrameTimeline::flushPendingPresentFences() {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001373 const auto firstSignaledFence = getFirstSignalFenceIndex();
1374 if (!firstSignaledFence.has_value()) {
1375 return;
1376 }
1377
Ady Abraham57f8e182022-03-08 15:54:33 -08001378 // Perfetto is using boottime clock to void drifts when the device goes
1379 // to suspend.
1380 const auto monoBootOffset = mUseBootTimeClock
1381 ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
1382 : 0;
1383
Ady Abrahamfcb16862022-10-10 14:35:21 -07001384 // Present fences are expected to be signaled in order. Mark all the previous
1385 // pending fences as errors.
1386 for (size_t i = 0; i < firstSignaledFence.value(); i++) {
1387 const auto& pendingPresentFence = *mPendingPresentFences.begin();
1388 const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1389 auto& displayFrame = pendingPresentFence.second;
Sally Qi438eb7d2023-12-05 18:59:32 -08001390 displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1391 mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1392 mPreviousPredictionPresentTime);
Ady Abrahamfcb16862022-10-10 14:35:21 -07001393 mPendingPresentFences.erase(mPendingPresentFences.begin());
1394 }
1395
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001396 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1397 const auto& pendingPresentFence = mPendingPresentFences[i];
1398 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1399 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
1400 signalTime = pendingPresentFence.first->getSignalTime();
1401 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001402 break;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001403 }
1404 }
Ady Abrahamfcb16862022-10-10 14:35:21 -07001405
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +00001406 auto& displayFrame = pendingPresentFence.second;
Sally Qi438eb7d2023-12-05 18:59:32 -08001407 displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1408 mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1409 mPreviousPredictionPresentTime);
1410 mPreviousActualPresentTime = signalTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001411
1412 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
1413 --i;
1414 }
1415}
1416
1417void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001418 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001419 // We maintain only a fixed number of frames' data. Pop older frames
1420 mDisplayFrames.pop_front();
1421 }
1422 mDisplayFrames.push_back(mCurrentDisplayFrame);
1423 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001424 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan82eef322021-04-10 00:06:04 +00001425 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001426}
1427
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001428nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1429 nsecs_t baseTime =
1430 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1431 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001432 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1433 if (surfaceFrameBaseTime != 0) {
1434 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1435 }
1436 }
1437 return baseTime;
1438}
1439
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001440void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1441 int displayFrameCount) const {
1442 if (mJankType == JankType::None) {
1443 // Check if any Surface Frame has been janky
1444 bool isJanky = false;
1445 for (const auto& surfaceFrame : mSurfaceFrames) {
1446 if (surfaceFrame->getJankType() != JankType::None) {
1447 isJanky = true;
1448 break;
1449 }
1450 }
1451 if (!isJanky) {
1452 return;
1453 }
1454 }
1455 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1456 dump(result, baseTime);
1457}
1458
1459void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1460 dump(result, baseTime);
1461}
1462
1463void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1464 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001465 // Easily identify a janky Display Frame in the dump
1466 StringAppendF(&result, " [*] ");
1467 }
1468 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001469 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1470 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1471 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1472 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1473 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001474 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001475 StringAppendF(&result, "Vsync Period: %10f\n",
1476 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1477 nsecs_t presentDelta =
1478 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1479 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1480 StringAppendF(&result, "Present delta: %10f\n",
1481 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001482 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001483 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1484 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1485 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1486 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001487 StringAppendF(&result, "\n");
1488 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001489 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001490 surfaceFrame->dump(result, indent, baseTime);
1491 }
1492 StringAppendF(&result, "\n");
1493}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001494
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001495void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001496 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001497 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001498 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001499 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1500 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001501 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001502 }
1503}
1504
1505void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001506 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001507 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001508 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001509 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001510 }
1511}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001512
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001513void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1514 ATRACE_CALL();
1515 std::unordered_map<std::string, bool> argsMap;
1516 for (size_t i = 0; i < args.size(); i++) {
1517 argsMap[std::string(String8(args[i]).c_str())] = true;
1518 }
1519 if (argsMap.count("-jank")) {
1520 dumpJank(result);
1521 }
1522 if (argsMap.count("-all")) {
1523 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001524 }
1525}
1526
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001527void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001528 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001529
1530 // The size can either increase or decrease, clear everything, to be consistent
1531 mDisplayFrames.clear();
1532 mPendingPresentFences.clear();
1533 mMaxDisplayFrames = size;
1534}
1535
1536void FrameTimeline::reset() {
1537 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1538}
1539
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001540} // namespace impl
1541} // namespace android::frametimeline