blob: 2a0ee5a993eb6d3880141d7325bc896b55e5dfea [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>
Vishnu Nairbe0ad902024-06-27 23:38:43 +000025#include <common/trace.h>
Ady Abraham7f8a1e62020-09-28 16:09:35 -070026#include <utils/Log.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);
Vishnu Nairbd7d07e2024-07-08 13:37:11 -0700362 if (CC_UNLIKELY(acquireFenceTime == Fence::SIGNAL_TIME_PENDING)) {
363 mActuals.endTime = mActualQueueTime;
364 } else {
365 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
366 }
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700367}
368
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000369void SurfaceFrame::setDropTime(nsecs_t dropTime) {
370 std::scoped_lock lock(mMutex);
371 mDropTime = dropTime;
372}
373
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800374void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000375 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000376 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
377 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
378 "PresentState - %s set already.",
379 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800380 mPresentState = presentState;
381 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700382}
383
Alec Mouri7d436ec2021-01-27 20:40:50 -0800384void SurfaceFrame::setRenderRate(Fps renderRate) {
385 std::lock_guard<std::mutex> lock(mMutex);
386 mRenderRate = renderRate;
387}
388
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200389Fps SurfaceFrame::getRenderRate() const {
390 std::lock_guard<std::mutex> lock(mMutex);
391 return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate;
392}
393
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000394void SurfaceFrame::setGpuComposition() {
395 std::scoped_lock lock(mMutex);
396 mGpuComposition = true;
397}
398
Sally Qi438eb7d2023-12-05 18:59:32 -0800399// TODO(b/316171339): migrate from perfetto side
400bool SurfaceFrame::isSelfJanky() const {
401 int32_t jankType = getJankType().value_or(JankType::None);
402
403 if (jankType == JankType::None) {
404 return false;
405 }
406
407 int32_t jankBitmask = JankType::AppDeadlineMissed | JankType::Unknown;
408 if (jankType & jankBitmask) {
409 return true;
410 }
411
412 return false;
413}
414
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800415std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000416 std::scoped_lock lock(mMutex);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000417 if (mPresentState == PresentState::Dropped) {
Edgar Arriaga631e4252023-03-02 02:11:24 +0000418 return JankType::Dropped;
Adithya Srinivasan95619432021-02-08 21:52:51 +0000419 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100420 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000421 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100422 return std::nullopt;
423 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700424 return mJankType;
425}
426
Ying Wei96eb5352023-11-21 17:37:21 +0000427std::optional<JankSeverityType> SurfaceFrame::getJankSeverityType() const {
428 std::scoped_lock lock(mMutex);
429 if (mActuals.presentTime == 0) {
430 // Frame hasn't been presented yet.
431 return std::nullopt;
432 }
433 return mJankSeverityType;
434}
435
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700436nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000437 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800438 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700439}
440
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800441TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000442 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800443 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700444}
445
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000446PredictionState SurfaceFrame::getPredictionState() const {
447 std::scoped_lock lock(mMutex);
448 return mPredictionState;
449}
450
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800451SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000452 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800453 return mPresentState;
454}
455
456FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000457 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800458 return mFramePresentMetadata;
459}
460
461FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000462 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800463 return mFrameReadyMetadata;
464}
465
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000466nsecs_t SurfaceFrame::getDropTime() const {
467 std::scoped_lock lock(mMutex);
468 return mDropTime;
469}
470
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000471void SurfaceFrame::promoteToBuffer() {
472 std::scoped_lock lock(mMutex);
473 LOG_ALWAYS_FATAL_IF(mIsBuffer == true,
474 "Trying to promote an already promoted BufferSurfaceFrame from layer %s "
475 "with token %" PRId64 "",
476 mDebugName.c_str(), mToken);
477 mIsBuffer = true;
478}
479
480bool SurfaceFrame::getIsBuffer() const {
481 std::scoped_lock lock(mMutex);
482 return mIsBuffer;
483}
484
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800485void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000486 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700487 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700488 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100489 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700490 // Easily identify a janky Surface Frame in the dump
491 StringAppendF(&result, " [*] ");
492 }
493 StringAppendF(&result, "\n");
494 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800495 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
496 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000497 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
498 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700499 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
500 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800501 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
502 mRenderRate ? mRenderRate->getIntValue() : 0);
503 StringAppendF(&result, "%s", indent.c_str());
Alec Mouriadebf5c2021-01-05 12:57:36 -0800504 StringAppendF(&result, "Layer ID : %d\n", mLayerId);
505 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800506 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700507 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000508 if (mPresentState == PresentState::Dropped) {
509 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
510 StringAppendF(&result, "Drop time : %10f\n",
511 std::chrono::duration<double, std::milli>(dropTime).count());
512 StringAppendF(&result, "%s", indent.c_str());
513 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700514 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
515 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800516 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700517 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800518 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
519 StringAppendF(&result, "%s", indent.c_str());
520 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
521 std::chrono::nanoseconds latchTime(
522 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
523 StringAppendF(&result, "%s", indent.c_str());
524 StringAppendF(&result, "Last latch time: %10f\n",
525 std::chrono::duration<double, std::milli>(latchTime).count());
526 if (mPredictionState == PredictionState::Valid) {
527 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
528 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
529 StringAppendF(&result, "%s", indent.c_str());
530 StringAppendF(&result, "Present delta: %10f\n",
531 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
532 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700533 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700534}
535
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000536std::string SurfaceFrame::miniDump() const {
537 std::scoped_lock lock(mMutex);
538 std::string result;
539 StringAppendF(&result, "Layer - %s\n", mDebugName.c_str());
540 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
541 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
542 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
543 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
544 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
545 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
546 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
547 StringAppendF(&result, "Present time: %" PRId64 "", mActuals.presentTime);
548 return result;
549}
550
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000551void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
Ady Abrahame96e79f2024-05-20 18:00:39 +0000552 Fps displayFrameRenderRate, nsecs_t* outDeadlineDelta) {
Ady Abrahame43ff722022-02-15 14:44:25 -0800553 if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000554 // Cannot do any classification for invalid present time.
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000555 mJankType = JankType::Unknown;
Ying Wei96eb5352023-11-21 17:37:21 +0000556 mJankSeverityType = JankSeverityType::Unknown;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000557 if (outDeadlineDelta) {
558 *outDeadlineDelta = -1;
559 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800560 return;
561 }
562
Ady Abrahame43ff722022-02-15 14:44:25 -0800563 if (mPredictionState == PredictionState::Expired) {
564 // We classify prediction expired as AppDeadlineMissed as the
565 // TokenManager::kMaxTokens we store is large enough to account for a
566 // reasonable app, so prediction expire would mean a huge scheduling delay.
Edgar Arriaga631e4252023-03-02 02:11:24 +0000567 mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
568 : JankType::AppDeadlineMissed;
Ying Wei96eb5352023-11-21 17:37:21 +0000569 mJankSeverityType = JankSeverityType::Unknown;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000570 if (outDeadlineDelta) {
571 *outDeadlineDelta = -1;
572 }
Ady Abrahame43ff722022-02-15 14:44:25 -0800573 return;
574 }
575
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800576 if (mPredictionState == PredictionState::None) {
577 // Cannot do jank classification on frames that don't have a token.
578 return;
579 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800580
581 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
Alec Mouriadebf5c2021-01-05 12:57:36 -0800582 const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
583 ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
584 : 0;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000585 const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
586 if (outDeadlineDelta) {
587 *outDeadlineDelta = deadlineDelta;
588 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800589
590 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
591 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
592 } else {
593 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
594 }
595
596 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
597 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
598 : FramePresentMetadata::EarlyPresent;
Ying Wei96eb5352023-11-21 17:37:21 +0000599 // Jank that is missing by less than the render rate period is classified as partial jank,
600 // otherwise it is a full jank.
601 mJankSeverityType = std::abs(presentDelta) < displayFrameRenderRate.getPeriodNsecs()
602 ? JankSeverityType::Partial
603 : JankSeverityType::Full;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800604 } else {
605 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
606 }
607
608 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
609 // Frames presented on time are not janky.
610 mJankType = JankType::None;
611 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
612 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
613 // Finish on time, Present early
614 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800615 deltaToVsync >= refreshRate.getPeriodNsecs() -
616 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800617 // Delta factor of vsync
618 mJankType = JankType::SurfaceFlingerScheduling;
619 } else {
620 // Delta not a factor of vsync
621 mJankType = JankType::PredictionError;
622 }
623 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
624 // Finish late, Present early
625 mJankType = JankType::Unknown;
626 }
627 } else {
628 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
629 // Buffer Stuffing.
630 mJankType |= JankType::BufferStuffing;
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000631 // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
632 // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
633 // We try to do this by moving the deadline. Since the queue could be stuffed by more
634 // than one buffer, we take the last latch time as reference and give one vsync
635 // worth of time for the frame to be ready.
636 nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
637 if (adjustedDeadline > mActuals.endTime) {
638 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
639 } else {
640 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
641 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800642 }
643 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
644 // Finish on time, Present late
645 if (displayFrameJankType != JankType::None) {
646 // Propagate displayFrame's jank if it exists
647 mJankType |= displayFrameJankType;
648 } else {
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000649 if (!(mJankType & JankType::BufferStuffing)) {
650 // In a stuffed state, if the app finishes on time and there is no display frame
651 // jank, only buffer stuffing is the root cause of the jank.
652 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
653 deltaToVsync >= refreshRate.getPeriodNsecs() -
654 mJankClassificationThresholds.presentThreshold) {
655 // Delta factor of vsync
656 mJankType |= JankType::SurfaceFlingerScheduling;
657 } else {
658 // Delta not a factor of vsync
659 mJankType |= JankType::PredictionError;
660 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800661 }
662 }
663 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
664 // Finish late, Present late
Adithya Srinivasan8a945502021-03-19 19:12:32 +0000665 mJankType |= JankType::AppDeadlineMissed;
666 // Propagate DisplayFrame's jankType if it is janky
667 mJankType |= displayFrameJankType;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800668 }
669 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000670 if (mPresentState != PresentState::Presented) {
671 mJankType = JankType::Dropped;
672 // Since frame was not presented, lets drop any present value
673 mActuals.presentTime = 0;
Ying Wei96eb5352023-11-21 17:37:21 +0000674 mJankSeverityType = JankSeverityType::Unknown;
Edgar Arriaga631e4252023-03-02 02:11:24 +0000675 }
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000676}
677
678void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200679 Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
680 nsecs_t displayPresentDelta) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000681 std::scoped_lock lock(mMutex);
682
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200683 mDisplayFrameRenderRate = displayFrameRenderRate;
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000684 mActuals.presentTime = presentTime;
685 nsecs_t deadlineDelta = 0;
686
Ady Abrahame96e79f2024-05-20 18:00:39 +0000687 classifyJankLocked(displayFrameJankType, refreshRate, displayFrameRenderRate, &deadlineDelta);
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000688
689 if (mPredictionState != PredictionState::None) {
690 // Only update janky frames if the app used vsync predictions
691 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000692 mGameMode, mJankType, displayDeadlineDelta,
693 displayPresentDelta, deadlineDelta});
Pascal Mütschardd56514e2024-05-24 17:37:13 +0200694
695 gui::JankData jd;
696 jd.frameVsyncId = mToken;
697 jd.jankType = mJankType;
698 jd.frameIntervalNs =
699 (mRenderRate ? *mRenderRate : mDisplayFrameRenderRate).getPeriodNsecs();
700 JankTracker::onJankData(mLayerId, jd);
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000701 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800702}
703
Ady Abraham14beed72024-05-15 17:16:45 -0700704void SurfaceFrame::onCommitNotComposited(Fps refreshRate, Fps displayFrameRenderRate) {
705 std::scoped_lock lock(mMutex);
706
707 mDisplayFrameRenderRate = displayFrameRenderRate;
708 mActuals.presentTime = mPredictions.presentTime;
Ady Abrahame96e79f2024-05-20 18:00:39 +0000709 classifyJankLocked(JankType::None, refreshRate, displayFrameRenderRate, nullptr);
Ady Abraham14beed72024-05-15 17:16:45 -0700710}
711
Ady Abraham57f8e182022-03-08 15:54:33 -0800712void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000713 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000714
Adithya Srinivasan86678502021-01-19 21:50:38 +0000715 // Expected timeline start
716 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000717 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700718 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800719 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
720 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700721
722 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000723 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700724
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000725 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
726
727 expectedSurfaceFrameStartEvent->set_token(mToken);
728 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
729
730 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
731 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
732 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000733
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000734 // Expected timeline end
735 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000736 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000737 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800738 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
739 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000740
741 auto* event = packet->set_frame_timeline_event();
742 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
743
744 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
745 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000746}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000747
Ady Abraham57f8e182022-03-08 15:54:33 -0800748void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000749 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000750
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000751 // Actual timeline start
752 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000753 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000754 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800755 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000756 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000757 if (mPredictionState == PredictionState::Expired) {
758 // If prediction is expired, we can't use the predicted start time. Instead, just use a
759 // start time a little earlier than the end time so that we have some info about this
760 // frame in the trace.
Adithya Srinivasanb2283c32021-04-21 21:31:56 +0000761 nsecs_t endTime =
762 (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
Ady Abrahamdee22322022-03-18 10:58:39 -0700763 const auto timestamp = endTime - kPredictionExpiredStartTimeDelta;
764 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000765 } else {
Ady Abrahamdee22322022-03-18 10:58:39 -0700766 const auto timestamp =
767 mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
768 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000769 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000770
771 auto* event = packet->set_frame_timeline_event();
772 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
773
774 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
775
776 actualSurfaceFrameStartEvent->set_token(mToken);
777 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
778
779 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
780 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700781
782 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000783 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700784 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000785 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700786 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000787 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700788 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000789 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
790 FrameReadyMetadata::OnTimeFinish);
791 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
792 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000793 actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan1f9450c2021-06-10 22:39:19 +0000794 actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer);
Ying Wei96eb5352023-11-21 17:37:21 +0000795 actualSurfaceFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000796 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000797
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000798 // Actual timeline end
799 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000800 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000801 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800802 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000803 if (mPresentState == PresentState::Dropped) {
Ady Abraham57f8e182022-03-08 15:54:33 -0800804 packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000805 } else {
Ady Abraham57f8e182022-03-08 15:54:33 -0800806 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000807 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700808
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000809 auto* event = packet->set_frame_timeline_event();
810 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700811
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000812 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700813 });
814}
815
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000816/**
817 * TODO(b/178637512): add inputEventId to the perfetto trace.
818 */
Ady Abraham57f8e182022-03-08 15:54:33 -0800819void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000820 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
821 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
822 // No packets can be traced with a missing token.
823 return;
824 }
825 if (getPredictionState() != PredictionState::Expired) {
826 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
827 // a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -0800828 tracePredictions(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000829 }
Ady Abraham57f8e182022-03-08 15:54:33 -0800830 traceActuals(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000831}
832
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800833namespace impl {
834
835int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000836 SFTRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000837 std::scoped_lock lock(mMutex);
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000838 while (mPredictions.size() >= kMaxTokens) {
839 mPredictions.erase(mPredictions.begin());
840 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800841 const int64_t assignedToken = mCurrentToken++;
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000842 mPredictions[assignedToken] = predictions;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800843 return assignedToken;
844}
845
846std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000847 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800848 auto predictionsIterator = mPredictions.find(token);
849 if (predictionsIterator != mPredictions.end()) {
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000850 return predictionsIterator->second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800851 }
852 return {};
853}
854
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800855FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
Ady Abraham57f8e182022-03-08 15:54:33 -0800856 JankClassificationThresholds thresholds, bool useBootTimeClock)
857 : mUseBootTimeClock(useBootTimeClock),
858 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800859 mTimeStats(std::move(timeStats)),
860 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan82eef322021-04-10 00:06:04 +0000861 mJankClassificationThresholds(thresholds) {
862 mCurrentDisplayFrame =
863 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000864}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700865
Adithya Srinivasan01189672020-10-20 14:23:05 -0700866void FrameTimeline::onBootFinished() {
867 perfetto::TracingInitArgs args;
868 args.backends = perfetto::kSystemBackend;
869 perfetto::Tracing::Initialize(args);
870 registerDataSource();
871}
872
873void FrameTimeline::registerDataSource() {
874 perfetto::DataSourceDescriptor dsd;
875 dsd.set_name(kFrameTimelineDataSource);
876 FrameTimelineDataSource::Register(dsd);
877}
878
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800879std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Alec Mouriadebf5c2021-01-05 12:57:36 -0800880 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700881 std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000882 SFTRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000883 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
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),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800886 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000887 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000888 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700889 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000890 std::optional<TimelineItem> predictions =
891 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700892 if (predictions) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800893 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000894 std::move(layerName), std::move(debugName),
895 PredictionState::Valid, std::move(*predictions),
896 mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000897 &mTraceCookieCounter, isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700898 }
Alec Mouriadebf5c2021-01-05 12:57:36 -0800899 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000900 std::move(layerName), std::move(debugName),
901 PredictionState::Expired, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000902 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000903 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700904}
905
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800906FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000907 JankClassificationThresholds thresholds,
908 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800909 : mSurfaceFlingerPredictions(TimelineItem()),
910 mSurfaceFlingerActuals(TimelineItem()),
911 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000912 mJankClassificationThresholds(thresholds),
913 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800914 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700915}
916
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800917void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000918 SFTRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000919 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800920 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
921}
922
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200923void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
924 Fps renderRate) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000925 SFTRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000926 std::scoped_lock lock(mMutex);
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200927 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800928 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700929}
930
931void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000932 const std::shared_ptr<FenceTime>& presentFence,
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000933 const std::shared_ptr<FenceTime>& gpuFence) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000934 SFTRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000935 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800936 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000937 mCurrentDisplayFrame->setGpuFence(gpuFence);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700938 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
939 flushPendingPresentFences();
940 finalizeCurrentDisplayFrame();
941}
942
Ady Abraham14beed72024-05-15 17:16:45 -0700943void FrameTimeline::onCommitNotComposited() {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000944 SFTRACE_CALL();
Ady Abraham14beed72024-05-15 17:16:45 -0700945 std::scoped_lock lock(mMutex);
946 mCurrentDisplayFrame->onCommitNotComposited();
947 mCurrentDisplayFrame.reset();
948 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
949 &mTraceCookieCounter);
950}
951
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800952void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
953 mSurfaceFrames.push_back(surfaceFrame);
954}
955
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200956void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800957 std::optional<TimelineItem> predictions,
958 nsecs_t wakeUpTime) {
959 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800960 mRefreshRate = refreshRate;
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200961 mRenderRate = renderRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800962 if (!predictions) {
963 mPredictionState = PredictionState::Expired;
964 } else {
965 mPredictionState = PredictionState::Valid;
966 mSurfaceFlingerPredictions = *predictions;
967 }
968 mSurfaceFlingerActuals.startTime = wakeUpTime;
969}
970
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800971void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
972 TimelineItem predictions) {
973 mPredictionState = predictionState;
974 mSurfaceFlingerPredictions = predictions;
975}
976
977void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
978 mSurfaceFlingerActuals.startTime = actualStartTime;
979}
980
981void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
982 mSurfaceFlingerActuals.endTime = actualEndTime;
983}
984
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000985void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
986 mGpuFence = gpuFence;
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000987}
988
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000989void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
990 nsecs_t previousPresentTime) {
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700991 const bool presentTimeValid =
992 mSurfaceFlingerActuals.presentTime >= mSurfaceFlingerActuals.startTime;
993 if (mPredictionState == PredictionState::Expired || !presentTimeValid) {
Adithya Srinivasande272452021-04-10 00:21:00 +0000994 // Cannot do jank classification with expired predictions or invalid signal times. Set the
995 // deltas to 0 as both negative and positive deltas are used as real values.
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000996 mJankType = JankType::Unknown;
Ying Wei96eb5352023-11-21 17:37:21 +0000997 mJankSeverityType = JankSeverityType::Unknown;
Adithya Srinivasande272452021-04-10 00:21:00 +0000998 deadlineDelta = 0;
999 deltaToVsync = 0;
Ady Abrahamb1e10d12023-03-13 15:23:54 -07001000 if (!presentTimeValid) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001001 mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
Ady Abrahamb1e10d12023-03-13 15:23:54 -07001002 mJankType |= JankType::DisplayHAL;
Ady Abrahamfcb16862022-10-10 14:35:21 -07001003 }
1004
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001005 return;
1006 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001007
1008 // Delta between the expected present and the actual present
1009 const nsecs_t presentDelta =
1010 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001011 // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
1012 // included the time for composition. However, for GPU composition, the final end time is max(sf
1013 // end time, gpu fence time).
1014 nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
1015 if (mGpuFence != FenceTime::NO_FENCE) {
1016 combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
1017 }
1018 deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
Alec Mouri363faf02021-01-29 16:34:55 -08001019
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001020 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
1021 // was a prediction error or not.
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001022 deltaToVsync = mRefreshRate.getPeriodNsecs() > 0
Alec Mouriadebf5c2021-01-05 12:57:36 -08001023 ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
1024 : 0;
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001025
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001026 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
1027 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
1028 : FramePresentMetadata::EarlyPresent;
Ying Wei96eb5352023-11-21 17:37:21 +00001029 // Jank that is missing by less than the render rate period is classified as partial jank,
1030 // otherwise it is a full jank.
1031 mJankSeverityType = std::abs(presentDelta) < mRenderRate.getPeriodNsecs()
1032 ? JankSeverityType::Partial
1033 : JankSeverityType::Full;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001034 } else {
1035 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
1036 }
1037
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001038 if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001039 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
1040 } else {
1041 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
1042 }
1043
1044 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
1045 mJankClassificationThresholds.startThreshold) {
1046 mFrameStartMetadata =
1047 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
1048 ? FrameStartMetadata::LateStart
1049 : FrameStartMetadata::EarlyStart;
1050 }
1051
1052 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
1053 // Do jank classification only if present is not on time
1054 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
1055 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
1056 // Finish on time, Present early
1057 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -08001058 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1059 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001060 // Delta is a factor of vsync if its within the presentTheshold on either side
1061 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1062 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1063 mJankType = JankType::SurfaceFlingerScheduling;
1064 } else {
1065 // Delta is not a factor of vsync,
1066 mJankType = JankType::PredictionError;
1067 }
1068 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
1069 // Finish late, Present early
1070 mJankType = JankType::SurfaceFlingerScheduling;
1071 } else {
1072 // Finish time unknown
1073 mJankType = JankType::Unknown;
1074 }
1075 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001076 if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
1077 mJankClassificationThresholds.presentThreshold ||
1078 previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
1079 // The previous frame was either presented in the current frame's expected vsync or
1080 // it was presented even later than the current frame's expected vsync.
1081 mJankType = JankType::SurfaceFlingerStuffing;
1082 }
1083 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
1084 !(mJankType & JankType::SurfaceFlingerStuffing)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001085 // Finish on time, Present late
1086 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -08001087 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
1088 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001089 // Delta is a factor of vsync if its within the presentTheshold on either side
1090 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1091 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1092 mJankType = JankType::DisplayHAL;
1093 } else {
1094 // Delta is not a factor of vsync
1095 mJankType = JankType::PredictionError;
1096 }
1097 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001098 if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
1099 mSurfaceFlingerActuals.presentTime - previousPresentTime >
1100 mRefreshRate.getPeriodNsecs() +
1101 mJankClassificationThresholds.presentThreshold) {
1102 // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
1103 // was presented more than a vsync late.
Rachel Lee94917b32022-03-18 17:52:09 -07001104 if (mGpuFence != FenceTime::NO_FENCE) {
1105 // If SF was in GPU composition, classify it as GPU deadline missed.
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001106 mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
1107 } else {
1108 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
1109 }
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +00001110 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001111 } else {
1112 // Finish time unknown
1113 mJankType = JankType::Unknown;
1114 }
1115 } else {
1116 // Present unknown
1117 mJankType = JankType::Unknown;
1118 }
1119 }
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001120}
1121
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001122void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001123 mSurfaceFlingerActuals.presentTime = signalTime;
1124 nsecs_t deadlineDelta = 0;
1125 nsecs_t deltaToVsync = 0;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001126 classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001127
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001128 for (auto& surfaceFrame : mSurfaceFrames) {
Pascal Muetschardac7bcd92023-10-03 15:05:36 +02001129 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta,
1130 deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001131 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001132}
1133
Ady Abraham14beed72024-05-15 17:16:45 -07001134void FrameTimeline::DisplayFrame::onCommitNotComposited() {
1135 for (auto& surfaceFrame : mSurfaceFrames) {
1136 surfaceFrame->onCommitNotComposited(mRefreshRate, mRenderRate);
1137 }
1138}
1139
Ady Abraham57f8e182022-03-08 15:54:33 -08001140void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
1141 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001142 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001143
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001144 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001145 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001146 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001147 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1148 packet->set_timestamp(
1149 static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001150
1151 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001152 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001153
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001154 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001155
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001156 expectedDisplayFrameStartEvent->set_token(mToken);
1157 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1158 });
Adithya Srinivasan86678502021-01-19 21:50:38 +00001159
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001160 // Expected timeline end
1161 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1162 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001163 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1164 packet->set_timestamp(
1165 static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001166
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001167 auto* event = packet->set_frame_timeline_event();
1168 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001169
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001170 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
1171 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001172}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001173
Sally Qiaa107742023-09-29 14:53:14 -07001174void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
Sally Qi438eb7d2023-12-05 18:59:32 -08001175 nsecs_t previousPredictionPresentTime) const {
Sally Qiaa107742023-09-29 14:53:14 -07001176 nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
1177 const constexpr float kThresh = 0.5f;
1178 const constexpr float kRange = 1.5f;
1179 for (auto& surfaceFrame : mSurfaceFrames) {
Sally Qi438eb7d2023-12-05 18:59:32 -08001180 if (previousPredictionPresentTime != 0 &&
1181 static_cast<float>(mSurfaceFlingerPredictions.presentTime -
1182 previousPredictionPresentTime) >=
Sally Qiaa107742023-09-29 14:53:14 -07001183 static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
1184 static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
Sally Qi438eb7d2023-12-05 18:59:32 -08001185 (static_cast<float>(mSurfaceFlingerPredictions.presentTime) -
Sally Qiaa107742023-09-29 14:53:14 -07001186 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1187 static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
Sally Qi2269a692024-05-17 18:02:28 -07001188 (static_cast<float>(previousPredictionPresentTime) +
Sally Qi438eb7d2023-12-05 18:59:32 -08001189 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1190 // sf skipped frame is not considered if app is self janked
1191 !surfaceFrame->isSelfJanky()) {
Sally Qiaa107742023-09-29 14:53:14 -07001192 skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
1193 skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
1194 break;
1195 }
1196 }
1197
1198 // add slice
1199 if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
1200 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1201
1202 // Actual timeline start
1203 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1204 auto packet = ctx.NewTracePacket();
1205 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1206 packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
1207
1208 auto* event = packet->set_frame_timeline_event();
1209 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1210
1211 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1212
1213 actualDisplayFrameStartEvent->set_token(0);
1214 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1215 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1216 FrameReadyMetadata::OnTimeFinish);
1217 actualDisplayFrameStartEvent->set_gpu_composition(false);
1218 actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid));
1219 actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
1220 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped));
Ying Wei96eb5352023-11-21 17:37:21 +00001221 actualDisplayFrameStartEvent->set_jank_severity_type(toProto(JankSeverityType::None));
Sally Qiaa107742023-09-29 14:53:14 -07001222 });
1223
1224 // Actual timeline end
1225 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1226 auto packet = ctx.NewTracePacket();
1227 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1228 packet->set_timestamp(static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
1229
1230 auto* event = packet->set_frame_timeline_event();
1231 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1232
1233 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1234 });
1235 }
1236}
1237
Ady Abraham57f8e182022-03-08 15:54:33 -08001238void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
1239 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001240 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001241
1242 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001243 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1244 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001245 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1246 packet->set_timestamp(
1247 static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001248
1249 auto* event = packet->set_frame_timeline_event();
1250 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1251
1252 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1253
1254 actualDisplayFrameStartEvent->set_token(mToken);
1255 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1256
1257 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
1258 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1259 FrameReadyMetadata::OnTimeFinish);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001260 actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001261 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +00001262 actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Ying Wei96eb5352023-11-21 17:37:21 +00001263 actualDisplayFrameStartEvent->set_jank_severity_type(toProto(mJankSeverityType));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001264 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001265
1266 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001267 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1268 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001269 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1270 packet->set_timestamp(
1271 static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001272
1273 auto* event = packet->set_frame_timeline_event();
1274 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1275
1276 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001277 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001278}
1279
Sally Qi438eb7d2023-12-05 18:59:32 -08001280nsecs_t FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1281 nsecs_t previousPredictionPresentTime) const {
Ady Abraham57a8ab42023-01-26 15:28:19 -08001282 if (mSurfaceFrames.empty()) {
1283 // We don't want to trace display frames without any surface frames updates as this cannot
1284 // be janky
Sally Qi438eb7d2023-12-05 18:59:32 -08001285 return previousPredictionPresentTime;
Ady Abraham57a8ab42023-01-26 15:28:19 -08001286 }
1287
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001288 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
1289 // DisplayFrame should not have an invalid token.
1290 ALOGE("Cannot trace DisplayFrame with invalid token");
Sally Qi438eb7d2023-12-05 18:59:32 -08001291 return previousPredictionPresentTime;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001292 }
1293
1294 if (mPredictionState == PredictionState::Valid) {
1295 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
1296 // meaningful way in a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -08001297 tracePredictions(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001298 }
Ady Abraham57f8e182022-03-08 15:54:33 -08001299 traceActuals(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001300
1301 for (auto& surfaceFrame : mSurfaceFrames) {
Ady Abraham57f8e182022-03-08 15:54:33 -08001302 surfaceFrame->trace(mToken, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001303 }
Sally Qiaa107742023-09-29 14:53:14 -07001304
Sally Qif5721252023-11-17 11:14:53 -08001305 if (FlagManager::getInstance().add_sf_skipped_frames_to_trace()) {
Sally Qi438eb7d2023-12-05 18:59:32 -08001306 addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousPredictionPresentTime);
Sally Qif5721252023-11-17 11:14:53 -08001307 }
Sally Qi438eb7d2023-12-05 18:59:32 -08001308 return mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001309}
1310
Alec Mouriadebf5c2021-01-05 12:57:36 -08001311float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
1312 if (layerIds.empty()) {
1313 return 0.0f;
1314 }
1315
1316 std::vector<nsecs_t> presentTimes;
1317 {
1318 std::scoped_lock lock(mMutex);
1319 presentTimes.reserve(mDisplayFrames.size());
1320 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1321 const auto& displayFrame = mDisplayFrames[i];
1322 if (displayFrame->getActuals().presentTime <= 0) {
1323 continue;
1324 }
1325 for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1326 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
1327 layerIds.count(surfaceFrame->getLayerId()) > 0) {
1328 // We're looking for DisplayFrames that presents at least one layer from
1329 // layerIds, so push the present time and skip looking through the rest of the
1330 // SurfaceFrames.
1331 presentTimes.push_back(displayFrame->getActuals().presentTime);
1332 break;
1333 }
1334 }
1335 }
1336 }
1337
1338 // FPS can't be computed when there's fewer than 2 presented frames.
1339 if (presentTimes.size() <= 1) {
1340 return 0.0f;
1341 }
1342
1343 nsecs_t priorPresentTime = -1;
1344 nsecs_t totalPresentToPresentWalls = 0;
1345
1346 for (const nsecs_t presentTime : presentTimes) {
1347 if (priorPresentTime == -1) {
1348 priorPresentTime = presentTime;
1349 continue;
1350 }
1351
1352 totalPresentToPresentWalls += (presentTime - priorPresentTime);
1353 priorPresentTime = presentTime;
1354 }
1355
1356 if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) {
1357 ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64,
1358 totalPresentToPresentWalls);
1359 return 0.0f;
1360 }
1361
1362 const constexpr nsecs_t kOneSecond =
1363 std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
1364 // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
1365 // M frames / second
1366 return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
1367 static_cast<float>(totalPresentToPresentWalls);
1368}
1369
Ady Abrahamfcb16862022-10-10 14:35:21 -07001370std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
1371 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1372 const auto& [fence, _] = mPendingPresentFences[i];
Theodore Dubois205c6dd2022-11-23 15:06:33 -08001373 if (fence && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001374 return i;
1375 }
1376 }
1377
1378 return {};
1379}
1380
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001381void FrameTimeline::flushPendingPresentFences() {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001382 const auto firstSignaledFence = getFirstSignalFenceIndex();
1383 if (!firstSignaledFence.has_value()) {
1384 return;
1385 }
1386
Ady Abraham57f8e182022-03-08 15:54:33 -08001387 // Perfetto is using boottime clock to void drifts when the device goes
1388 // to suspend.
1389 const auto monoBootOffset = mUseBootTimeClock
1390 ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
1391 : 0;
1392
Ady Abrahamfcb16862022-10-10 14:35:21 -07001393 // Present fences are expected to be signaled in order. Mark all the previous
1394 // pending fences as errors.
1395 for (size_t i = 0; i < firstSignaledFence.value(); i++) {
1396 const auto& pendingPresentFence = *mPendingPresentFences.begin();
1397 const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1398 auto& displayFrame = pendingPresentFence.second;
Sally Qi438eb7d2023-12-05 18:59:32 -08001399 displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1400 mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1401 mPreviousPredictionPresentTime);
Ady Abrahamfcb16862022-10-10 14:35:21 -07001402 mPendingPresentFences.erase(mPendingPresentFences.begin());
1403 }
1404
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001405 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1406 const auto& pendingPresentFence = mPendingPresentFences[i];
1407 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1408 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
1409 signalTime = pendingPresentFence.first->getSignalTime();
1410 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001411 break;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001412 }
1413 }
Ady Abrahamfcb16862022-10-10 14:35:21 -07001414
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +00001415 auto& displayFrame = pendingPresentFence.second;
Sally Qi438eb7d2023-12-05 18:59:32 -08001416 displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
1417 mPreviousPredictionPresentTime = displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
1418 mPreviousPredictionPresentTime);
1419 mPreviousActualPresentTime = signalTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001420
1421 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
1422 --i;
1423 }
1424}
1425
1426void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001427 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001428 // We maintain only a fixed number of frames' data. Pop older frames
1429 mDisplayFrames.pop_front();
1430 }
1431 mDisplayFrames.push_back(mCurrentDisplayFrame);
1432 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001433 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan82eef322021-04-10 00:06:04 +00001434 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001435}
1436
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001437nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1438 nsecs_t baseTime =
1439 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1440 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001441 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1442 if (surfaceFrameBaseTime != 0) {
1443 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1444 }
1445 }
1446 return baseTime;
1447}
1448
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001449void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1450 int displayFrameCount) const {
1451 if (mJankType == JankType::None) {
1452 // Check if any Surface Frame has been janky
1453 bool isJanky = false;
1454 for (const auto& surfaceFrame : mSurfaceFrames) {
1455 if (surfaceFrame->getJankType() != JankType::None) {
1456 isJanky = true;
1457 break;
1458 }
1459 }
1460 if (!isJanky) {
1461 return;
1462 }
1463 }
1464 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1465 dump(result, baseTime);
1466}
1467
1468void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1469 dump(result, baseTime);
1470}
1471
1472void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1473 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001474 // Easily identify a janky Display Frame in the dump
1475 StringAppendF(&result, " [*] ");
1476 }
1477 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001478 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1479 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1480 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1481 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1482 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001483 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001484 StringAppendF(&result, "Vsync Period: %10f\n",
1485 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1486 nsecs_t presentDelta =
1487 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1488 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1489 StringAppendF(&result, "Present delta: %10f\n",
1490 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001491 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001492 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1493 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1494 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1495 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001496 StringAppendF(&result, "\n");
1497 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001498 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001499 surfaceFrame->dump(result, indent, baseTime);
1500 }
1501 StringAppendF(&result, "\n");
1502}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001503
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001504void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001505 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001506 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
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++) {
1509 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001510 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001511 }
1512}
1513
1514void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001515 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001516 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001517 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001518 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001519 }
1520}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001521
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001522void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +00001523 SFTRACE_CALL();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001524 std::unordered_map<std::string, bool> argsMap;
1525 for (size_t i = 0; i < args.size(); i++) {
1526 argsMap[std::string(String8(args[i]).c_str())] = true;
1527 }
1528 if (argsMap.count("-jank")) {
1529 dumpJank(result);
1530 }
1531 if (argsMap.count("-all")) {
1532 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001533 }
1534}
1535
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001536void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001537 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001538
1539 // The size can either increase or decrease, clear everything, to be consistent
1540 mDisplayFrames.clear();
1541 mPendingPresentFences.clear();
1542 mMaxDisplayFrames = size;
1543}
1544
1545void FrameTimeline::reset() {
1546 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1547}
1548
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001549} // namespace impl
1550} // namespace android::frametimeline