blob: dfbb55dacc0e866ecaf787d0c6e169193a0e7336 [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>
Ady Abraham7f8a1e62020-09-28 16:09:35 -070024#include <utils/Log.h>
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070025#include <utils/Trace.h>
Alec Mouriadebf5c2021-01-05 12:57:36 -080026
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070027#include <chrono>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070028#include <cinttypes>
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070029#include <numeric>
Alec Mouriadebf5c2021-01-05 12:57:36 -080030#include <unordered_set>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070031
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080032namespace android::frametimeline {
Adithya Srinivasanf279e042020-08-17 14:56:27 -070033
34using base::StringAppendF;
Adithya Srinivasan01189672020-10-20 14:23:05 -070035using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +000036using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070037
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070038void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
39 const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
40 StringAppendF(&result, "%s", indent.c_str());
41 StringAppendF(&result, "\t\t");
42 StringAppendF(&result, " Start time\t\t|");
43 StringAppendF(&result, " End time\t\t|");
44 StringAppendF(&result, " Present time\n");
45 if (predictionState == PredictionState::Valid) {
46 // Dump the Predictions only if they are valid
47 StringAppendF(&result, "%s", indent.c_str());
48 StringAppendF(&result, "Expected\t|");
49 std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
50 std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
51 std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
52 StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
53 std::chrono::duration<double, std::milli>(startTime).count(),
54 std::chrono::duration<double, std::milli>(endTime).count(),
55 std::chrono::duration<double, std::milli>(presentTime).count());
56 }
57 StringAppendF(&result, "%s", indent.c_str());
58 StringAppendF(&result, "Actual \t|");
59
60 if (actuals.startTime == 0) {
61 StringAppendF(&result, "\t\tN/A\t|");
62 } else {
63 std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
64 StringAppendF(&result, "\t%10.2f\t|",
65 std::chrono::duration<double, std::milli>(startTime).count());
66 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080067 if (actuals.endTime <= 0) {
68 // Animation leashes can send the endTime as -1
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070069 StringAppendF(&result, "\t\tN/A\t|");
70 } else {
71 std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
72 StringAppendF(&result, "\t%10.2f\t|",
73 std::chrono::duration<double, std::milli>(endTime).count());
74 }
75 if (actuals.presentTime == 0) {
76 StringAppendF(&result, "\t\tN/A\n");
77 } else {
78 std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
79 StringAppendF(&result, "\t%10.2f\n",
80 std::chrono::duration<double, std::milli>(presentTime).count());
81 }
82
83 StringAppendF(&result, "%s", indent.c_str());
84 StringAppendF(&result, "----------------------");
85 StringAppendF(&result, "----------------------");
86 StringAppendF(&result, "----------------------");
87 StringAppendF(&result, "----------------------\n");
88}
89
90std::string toString(PredictionState predictionState) {
91 switch (predictionState) {
92 case PredictionState::Valid:
93 return "Valid";
94 case PredictionState::Expired:
95 return "Expired";
96 case PredictionState::None:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070097 return "None";
98 }
99}
100
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800101std::string jankTypeBitmaskToString(int32_t jankType) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800102 if (jankType == JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700103 return "None";
104 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000105
106 std::vector<std::string> janks;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800107 if (jankType & JankType::DisplayHAL) {
108 janks.emplace_back("Display HAL");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000109 jankType &= ~JankType::DisplayHAL;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800110 }
111 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
Rachel Lee94917b32022-03-18 17:52:09 -0700112 janks.emplace_back("SurfaceFlinger deadline missed (while in HWC)");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000113 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800114 }
115 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
Rachel Lee94917b32022-03-18 17:52:09 -0700116 janks.emplace_back("SurfaceFlinger deadline missed (while in GPU comp)");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000117 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800118 }
119 if (jankType & JankType::AppDeadlineMissed) {
120 janks.emplace_back("App Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000121 jankType &= ~JankType::AppDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800122 }
123 if (jankType & JankType::PredictionError) {
124 janks.emplace_back("Prediction Error");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000125 jankType &= ~JankType::PredictionError;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800126 }
127 if (jankType & JankType::SurfaceFlingerScheduling) {
128 janks.emplace_back("SurfaceFlinger Scheduling");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000129 jankType &= ~JankType::SurfaceFlingerScheduling;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800130 }
131 if (jankType & JankType::BufferStuffing) {
132 janks.emplace_back("Buffer Stuffing");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000133 jankType &= ~JankType::BufferStuffing;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800134 }
135 if (jankType & JankType::Unknown) {
136 janks.emplace_back("Unknown jank");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000137 jankType &= ~JankType::Unknown;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800138 }
Adithya Srinivasan2045ddf2021-05-27 17:38:10 +0000139 if (jankType & JankType::SurfaceFlingerStuffing) {
140 janks.emplace_back("SurfaceFlinger Stuffing");
141 jankType &= ~JankType::SurfaceFlingerStuffing;
142 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000143 if (jankType & JankType::Dropped) {
144 janks.emplace_back("Dropped Frame");
145 jankType &= ~JankType::Dropped;
146 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000147
148 // jankType should be 0 if all types of jank were checked for.
149 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800150 return std::accumulate(janks.begin(), janks.end(), std::string(),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700151 [](const std::string& l, const std::string& r) {
152 return l.empty() ? r : l + ", " + r;
153 });
154}
155
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800156std::string toString(FramePresentMetadata presentMetadata) {
157 switch (presentMetadata) {
158 case FramePresentMetadata::OnTimePresent:
159 return "On Time Present";
160 case FramePresentMetadata::LatePresent:
161 return "Late Present";
162 case FramePresentMetadata::EarlyPresent:
163 return "Early Present";
164 case FramePresentMetadata::UnknownPresent:
165 return "Unknown Present";
Adithya Srinivasan01189672020-10-20 14:23:05 -0700166 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700167}
168
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800169std::string toString(FrameReadyMetadata finishMetadata) {
170 switch (finishMetadata) {
171 case FrameReadyMetadata::OnTimeFinish:
172 return "On Time Finish";
173 case FrameReadyMetadata::LateFinish:
174 return "Late Finish";
175 case FrameReadyMetadata::UnknownFinish:
176 return "Unknown Finish";
177 }
178}
179
180std::string toString(FrameStartMetadata startMetadata) {
181 switch (startMetadata) {
182 case FrameStartMetadata::OnTimeStart:
183 return "On Time Start";
184 case FrameStartMetadata::LateStart:
185 return "Late Start";
186 case FrameStartMetadata::EarlyStart:
187 return "Early Start";
188 case FrameStartMetadata::UnknownStart:
189 return "Unknown Start";
190 }
191}
192
193std::string toString(SurfaceFrame::PresentState presentState) {
194 using PresentState = SurfaceFrame::PresentState;
195 switch (presentState) {
196 case PresentState::Presented:
197 return "Presented";
198 case PresentState::Dropped:
199 return "Dropped";
200 case PresentState::Unknown:
201 return "Unknown";
202 }
203}
204
205FrameTimelineEvent::PresentType toProto(FramePresentMetadata presentMetadata) {
206 switch (presentMetadata) {
207 case FramePresentMetadata::EarlyPresent:
208 return FrameTimelineEvent::PRESENT_EARLY;
209 case FramePresentMetadata::LatePresent:
210 return FrameTimelineEvent::PRESENT_LATE;
211 case FramePresentMetadata::OnTimePresent:
212 return FrameTimelineEvent::PRESENT_ON_TIME;
213 case FramePresentMetadata::UnknownPresent:
214 return FrameTimelineEvent::PRESENT_UNSPECIFIED;
215 }
216}
217
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000218FrameTimelineEvent::PredictionType toProto(PredictionState predictionState) {
219 switch (predictionState) {
220 case PredictionState::Valid:
221 return FrameTimelineEvent::PREDICTION_VALID;
222 case PredictionState::Expired:
223 return FrameTimelineEvent::PREDICTION_EXPIRED;
224 case PredictionState::None:
225 return FrameTimelineEvent::PREDICTION_UNKNOWN;
226 }
227}
228
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000229int32_t jankTypeBitmaskToProto(int32_t jankType) {
230 if (jankType == JankType::None) {
231 return FrameTimelineEvent::JANK_NONE;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700232 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000233
234 int32_t protoJank = 0;
235 if (jankType & JankType::DisplayHAL) {
236 protoJank |= FrameTimelineEvent::JANK_DISPLAY_HAL;
237 jankType &= ~JankType::DisplayHAL;
238 }
239 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
240 protoJank |= FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED;
241 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
242 }
243 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
244 protoJank |= FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
245 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
246 }
247 if (jankType & JankType::AppDeadlineMissed) {
248 protoJank |= FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
249 jankType &= ~JankType::AppDeadlineMissed;
250 }
251 if (jankType & JankType::PredictionError) {
252 protoJank |= FrameTimelineEvent::JANK_PREDICTION_ERROR;
253 jankType &= ~JankType::PredictionError;
254 }
255 if (jankType & JankType::SurfaceFlingerScheduling) {
256 protoJank |= FrameTimelineEvent::JANK_SF_SCHEDULING;
257 jankType &= ~JankType::SurfaceFlingerScheduling;
258 }
259 if (jankType & JankType::BufferStuffing) {
260 protoJank |= FrameTimelineEvent::JANK_BUFFER_STUFFING;
261 jankType &= ~JankType::BufferStuffing;
262 }
263 if (jankType & JankType::Unknown) {
264 protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
265 jankType &= ~JankType::Unknown;
266 }
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000267 if (jankType & JankType::SurfaceFlingerStuffing) {
268 protoJank |= FrameTimelineEvent::JANK_SF_STUFFING;
269 jankType &= ~JankType::SurfaceFlingerStuffing;
270 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000271 if (jankType & JankType::Dropped) {
272 // Jank dropped does not append to other janks, it fully overrides.
273 protoJank |= FrameTimelineEvent::JANK_DROPPED;
274 jankType &= ~JankType::Dropped;
275 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000276
277 // jankType should be 0 if all types of jank were checked for.
278 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
279 return protoJank;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700280}
281
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800282// Returns the smallest timestamp from the set of predictions and actuals.
283nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
284 TimelineItem actuals) {
285 nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
286 if (predictionState == PredictionState::Valid) {
287 // Checking start time for predictions is enough because start time is always lesser than
288 // endTime and presentTime.
289 minTime = std::min(minTime, predictions.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700290 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700291
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800292 // Need to check startTime, endTime and presentTime for actuals because some frames might not
293 // have them set.
294 if (actuals.startTime != 0) {
295 minTime = std::min(minTime, actuals.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700296 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800297 if (actuals.endTime != 0) {
298 minTime = std::min(minTime, actuals.endTime);
299 }
300 if (actuals.presentTime != 0) {
ramindaniea2bb822022-06-27 19:52:10 +0000301 minTime = std::min(minTime, actuals.presentTime);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800302 }
303 return minTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700304}
305
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000306int64_t TraceCookieCounter::getCookieForTracing() {
307 return ++mTraceCookie;
308}
309
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000310SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
Alec Mouriadebf5c2021-01-05 12:57:36 -0800311 uid_t ownerUid, int32_t layerId, std::string layerName,
312 std::string debugName, PredictionState predictionState,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800313 frametimeline::TimelineItem&& predictions,
314 std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000315 JankClassificationThresholds thresholds,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700316 TraceCookieCounter* traceCookieCounter, bool isBuffer, GameMode gameMode)
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000317 : mToken(frameTimelineInfo.vsyncId),
318 mInputEventId(frameTimelineInfo.inputEventId),
Adithya Srinivasan01189672020-10-20 14:23:05 -0700319 mOwnerPid(ownerPid),
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700320 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700321 mLayerName(std::move(layerName)),
322 mDebugName(std::move(debugName)),
Alec Mouriadebf5c2021-01-05 12:57:36 -0800323 mLayerId(layerId),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700324 mPresentState(PresentState::Unknown),
325 mPredictionState(predictionState),
326 mPredictions(predictions),
327 mActuals({0, 0, 0}),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800328 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000329 mJankClassificationThresholds(thresholds),
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000330 mTraceCookieCounter(*traceCookieCounter),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000331 mIsBuffer(isBuffer),
332 mGameMode(gameMode) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700333
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700334void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000335 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700336 mActuals.startTime = actualStartTime;
337}
338
339void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000340 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700341 mActualQueueTime = actualQueueTime;
342}
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000343
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700344void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000345 std::scoped_lock lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700346 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700347}
348
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000349void SurfaceFrame::setDropTime(nsecs_t dropTime) {
350 std::scoped_lock lock(mMutex);
351 mDropTime = dropTime;
352}
353
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800354void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000355 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000356 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
357 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
358 "PresentState - %s set already.",
359 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800360 mPresentState = presentState;
361 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700362}
363
Alec Mouri7d436ec2021-01-27 20:40:50 -0800364void SurfaceFrame::setRenderRate(Fps renderRate) {
365 std::lock_guard<std::mutex> lock(mMutex);
366 mRenderRate = renderRate;
367}
368
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200369Fps SurfaceFrame::getRenderRate() const {
370 std::lock_guard<std::mutex> lock(mMutex);
371 return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate;
372}
373
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000374void SurfaceFrame::setGpuComposition() {
375 std::scoped_lock lock(mMutex);
376 mGpuComposition = true;
377}
378
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800379std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000380 std::scoped_lock lock(mMutex);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000381 if (mPresentState == PresentState::Dropped) {
Edgar Arriaga631e4252023-03-02 02:11:24 +0000382 return JankType::Dropped;
Adithya Srinivasan95619432021-02-08 21:52:51 +0000383 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100384 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000385 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100386 return std::nullopt;
387 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700388 return mJankType;
389}
390
391nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000392 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800393 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700394}
395
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800396TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000397 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800398 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700399}
400
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000401PredictionState SurfaceFrame::getPredictionState() const {
402 std::scoped_lock lock(mMutex);
403 return mPredictionState;
404}
405
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800406SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000407 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800408 return mPresentState;
409}
410
411FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000412 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800413 return mFramePresentMetadata;
414}
415
416FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000417 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800418 return mFrameReadyMetadata;
419}
420
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000421nsecs_t SurfaceFrame::getDropTime() const {
422 std::scoped_lock lock(mMutex);
423 return mDropTime;
424}
425
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000426void SurfaceFrame::promoteToBuffer() {
427 std::scoped_lock lock(mMutex);
428 LOG_ALWAYS_FATAL_IF(mIsBuffer == true,
429 "Trying to promote an already promoted BufferSurfaceFrame from layer %s "
430 "with token %" PRId64 "",
431 mDebugName.c_str(), mToken);
432 mIsBuffer = true;
433}
434
435bool SurfaceFrame::getIsBuffer() const {
436 std::scoped_lock lock(mMutex);
437 return mIsBuffer;
438}
439
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800440void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000441 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700442 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700443 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100444 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700445 // Easily identify a janky Surface Frame in the dump
446 StringAppendF(&result, " [*] ");
447 }
448 StringAppendF(&result, "\n");
449 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800450 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
451 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000452 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
453 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700454 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
455 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800456 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
457 mRenderRate ? mRenderRate->getIntValue() : 0);
458 StringAppendF(&result, "%s", indent.c_str());
Alec Mouriadebf5c2021-01-05 12:57:36 -0800459 StringAppendF(&result, "Layer ID : %d\n", mLayerId);
460 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800461 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700462 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000463 if (mPresentState == PresentState::Dropped) {
464 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
465 StringAppendF(&result, "Drop time : %10f\n",
466 std::chrono::duration<double, std::milli>(dropTime).count());
467 StringAppendF(&result, "%s", indent.c_str());
468 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700469 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
470 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800471 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700472 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800473 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
474 StringAppendF(&result, "%s", indent.c_str());
475 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
476 std::chrono::nanoseconds latchTime(
477 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
478 StringAppendF(&result, "%s", indent.c_str());
479 StringAppendF(&result, "Last latch time: %10f\n",
480 std::chrono::duration<double, std::milli>(latchTime).count());
481 if (mPredictionState == PredictionState::Valid) {
482 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
483 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
484 StringAppendF(&result, "%s", indent.c_str());
485 StringAppendF(&result, "Present delta: %10f\n",
486 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
487 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700488 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700489}
490
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000491std::string SurfaceFrame::miniDump() const {
492 std::scoped_lock lock(mMutex);
493 std::string result;
494 StringAppendF(&result, "Layer - %s\n", mDebugName.c_str());
495 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
496 StringAppendF(&result, "Is Buffer?: %d\n", mIsBuffer);
497 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
498 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
499 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
500 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
501 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
502 StringAppendF(&result, "Present time: %" PRId64 "", mActuals.presentTime);
503 return result;
504}
505
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000506void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
507 nsecs_t& deadlineDelta) {
Ady Abrahame43ff722022-02-15 14:44:25 -0800508 if (mActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000509 // Cannot do any classification for invalid present time.
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000510 mJankType = JankType::Unknown;
511 deadlineDelta = -1;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800512 return;
513 }
514
Ady Abrahame43ff722022-02-15 14:44:25 -0800515 if (mPredictionState == PredictionState::Expired) {
516 // We classify prediction expired as AppDeadlineMissed as the
517 // TokenManager::kMaxTokens we store is large enough to account for a
518 // reasonable app, so prediction expire would mean a huge scheduling delay.
Edgar Arriaga631e4252023-03-02 02:11:24 +0000519 mJankType = mPresentState != PresentState::Presented ? JankType::Dropped
520 : JankType::AppDeadlineMissed;
Ady Abrahame43ff722022-02-15 14:44:25 -0800521 deadlineDelta = -1;
522 return;
523 }
524
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800525 if (mPredictionState == PredictionState::None) {
526 // Cannot do jank classification on frames that don't have a token.
527 return;
528 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800529
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000530 deadlineDelta = mActuals.endTime - mPredictions.endTime;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800531 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
Alec Mouriadebf5c2021-01-05 12:57:36 -0800532 const nsecs_t deltaToVsync = refreshRate.getPeriodNsecs() > 0
533 ? std::abs(presentDelta) % refreshRate.getPeriodNsecs()
534 : 0;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800535
536 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
537 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
538 } else {
539 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
540 }
541
542 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
543 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
544 : FramePresentMetadata::EarlyPresent;
545 } else {
546 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
547 }
548
549 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
550 // Frames presented on time are not janky.
551 mJankType = JankType::None;
552 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
553 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
554 // Finish on time, Present early
555 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800556 deltaToVsync >= refreshRate.getPeriodNsecs() -
557 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800558 // Delta factor of vsync
559 mJankType = JankType::SurfaceFlingerScheduling;
560 } else {
561 // Delta not a factor of vsync
562 mJankType = JankType::PredictionError;
563 }
564 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
565 // Finish late, Present early
566 mJankType = JankType::Unknown;
567 }
568 } else {
569 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
570 // Buffer Stuffing.
571 mJankType |= JankType::BufferStuffing;
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000572 // In a stuffed state, the frame could be stuck on a dequeue wait for quite some time.
573 // Because of this dequeue wait, it can be hard to tell if a frame was genuinely late.
574 // We try to do this by moving the deadline. Since the queue could be stuffed by more
575 // than one buffer, we take the last latch time as reference and give one vsync
576 // worth of time for the frame to be ready.
577 nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
578 if (adjustedDeadline > mActuals.endTime) {
579 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
580 } else {
581 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
582 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800583 }
584 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
585 // Finish on time, Present late
586 if (displayFrameJankType != JankType::None) {
587 // Propagate displayFrame's jank if it exists
588 mJankType |= displayFrameJankType;
589 } else {
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +0000590 if (!(mJankType & JankType::BufferStuffing)) {
591 // In a stuffed state, if the app finishes on time and there is no display frame
592 // jank, only buffer stuffing is the root cause of the jank.
593 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
594 deltaToVsync >= refreshRate.getPeriodNsecs() -
595 mJankClassificationThresholds.presentThreshold) {
596 // Delta factor of vsync
597 mJankType |= JankType::SurfaceFlingerScheduling;
598 } else {
599 // Delta not a factor of vsync
600 mJankType |= JankType::PredictionError;
601 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800602 }
603 }
604 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
605 // Finish late, Present late
Adithya Srinivasan8a945502021-03-19 19:12:32 +0000606 mJankType |= JankType::AppDeadlineMissed;
607 // Propagate DisplayFrame's jankType if it is janky
608 mJankType |= displayFrameJankType;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800609 }
610 }
Edgar Arriaga631e4252023-03-02 02:11:24 +0000611 if (mPresentState != PresentState::Presented) {
612 mJankType = JankType::Dropped;
613 // Since frame was not presented, lets drop any present value
614 mActuals.presentTime = 0;
615 }
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000616}
617
618void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200619 Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta,
620 nsecs_t displayPresentDelta) {
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000621 std::scoped_lock lock(mMutex);
622
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200623 mDisplayFrameRenderRate = displayFrameRenderRate;
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000624 mActuals.presentTime = presentTime;
625 nsecs_t deadlineDelta = 0;
626
627 classifyJankLocked(displayFrameJankType, refreshRate, deadlineDelta);
628
629 if (mPredictionState != PredictionState::None) {
630 // Only update janky frames if the app used vsync predictions
631 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000632 mGameMode, mJankType, displayDeadlineDelta,
633 displayPresentDelta, deadlineDelta});
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +0000634 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800635}
636
Ady Abraham57f8e182022-03-08 15:54:33 -0800637void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000638 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000639
Adithya Srinivasan86678502021-01-19 21:50:38 +0000640 // Expected timeline start
641 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000642 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700643 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800644 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
645 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700646
647 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000648 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700649
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000650 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
651
652 expectedSurfaceFrameStartEvent->set_token(mToken);
653 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
654
655 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
656 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
657 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000658
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000659 // Expected timeline end
660 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000661 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000662 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800663 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
664 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000665
666 auto* event = packet->set_frame_timeline_event();
667 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
668
669 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
670 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000671}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000672
Ady Abraham57f8e182022-03-08 15:54:33 -0800673void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000674 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000675
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000676 // Actual timeline start
677 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000678 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000679 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800680 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000681 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000682 if (mPredictionState == PredictionState::Expired) {
683 // If prediction is expired, we can't use the predicted start time. Instead, just use a
684 // start time a little earlier than the end time so that we have some info about this
685 // frame in the trace.
Adithya Srinivasanb2283c32021-04-21 21:31:56 +0000686 nsecs_t endTime =
687 (mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
Ady Abrahamdee22322022-03-18 10:58:39 -0700688 const auto timestamp = endTime - kPredictionExpiredStartTimeDelta;
689 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000690 } else {
Ady Abrahamdee22322022-03-18 10:58:39 -0700691 const auto timestamp =
692 mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime;
693 packet->set_timestamp(static_cast<uint64_t>(timestamp + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000694 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000695
696 auto* event = packet->set_frame_timeline_event();
697 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
698
699 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
700
701 actualSurfaceFrameStartEvent->set_token(mToken);
702 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
703
704 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
705 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700706
707 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000708 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700709 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000710 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700711 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000712 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700713 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000714 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
715 FrameReadyMetadata::OnTimeFinish);
716 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
717 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +0000718 actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan1f9450c2021-06-10 22:39:19 +0000719 actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000720 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000721
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000722 // Actual timeline end
723 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000724 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000725 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -0800726 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000727 if (mPresentState == PresentState::Dropped) {
Ady Abraham57f8e182022-03-08 15:54:33 -0800728 packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000729 } else {
Ady Abraham57f8e182022-03-08 15:54:33 -0800730 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000731 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700732
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000733 auto* event = packet->set_frame_timeline_event();
734 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700735
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000736 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700737 });
738}
739
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000740/**
741 * TODO(b/178637512): add inputEventId to the perfetto trace.
742 */
Ady Abraham57f8e182022-03-08 15:54:33 -0800743void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000744 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
745 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
746 // No packets can be traced with a missing token.
747 return;
748 }
749 if (getPredictionState() != PredictionState::Expired) {
750 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
751 // a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -0800752 tracePredictions(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000753 }
Ady Abraham57f8e182022-03-08 15:54:33 -0800754 traceActuals(displayFrameToken, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000755}
756
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800757namespace impl {
758
759int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
760 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000761 std::scoped_lock lock(mMutex);
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000762 while (mPredictions.size() >= kMaxTokens) {
763 mPredictions.erase(mPredictions.begin());
764 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800765 const int64_t assignedToken = mCurrentToken++;
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000766 mPredictions[assignedToken] = predictions;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800767 return assignedToken;
768}
769
770std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000771 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800772 auto predictionsIterator = mPredictions.find(token);
773 if (predictionsIterator != mPredictions.end()) {
Adithya Srinivasanbed4c4f2021-05-03 20:24:46 +0000774 return predictionsIterator->second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800775 }
776 return {};
777}
778
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800779FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
Ady Abraham57f8e182022-03-08 15:54:33 -0800780 JankClassificationThresholds thresholds, bool useBootTimeClock)
781 : mUseBootTimeClock(useBootTimeClock),
782 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800783 mTimeStats(std::move(timeStats)),
784 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan82eef322021-04-10 00:06:04 +0000785 mJankClassificationThresholds(thresholds) {
786 mCurrentDisplayFrame =
787 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000788}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700789
Adithya Srinivasan01189672020-10-20 14:23:05 -0700790void FrameTimeline::onBootFinished() {
791 perfetto::TracingInitArgs args;
792 args.backends = perfetto::kSystemBackend;
793 perfetto::Tracing::Initialize(args);
794 registerDataSource();
795}
796
797void FrameTimeline::registerDataSource() {
798 perfetto::DataSourceDescriptor dsd;
799 dsd.set_name(kFrameTimelineDataSource);
800 FrameTimelineDataSource::Register(dsd);
801}
802
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800803std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Alec Mouriadebf5c2021-01-05 12:57:36 -0800804 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700805 std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700806 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000807 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800808 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000809 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800810 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000811 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000812 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700813 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000814 std::optional<TimelineItem> predictions =
815 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700816 if (predictions) {
Alec Mouriadebf5c2021-01-05 12:57:36 -0800817 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000818 std::move(layerName), std::move(debugName),
819 PredictionState::Valid, std::move(*predictions),
820 mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000821 &mTraceCookieCounter, isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700822 }
Alec Mouriadebf5c2021-01-05 12:57:36 -0800823 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid, layerId,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000824 std::move(layerName), std::move(debugName),
825 PredictionState::Expired, TimelineItem(), mTimeStats,
Adithya Srinivasan785addd2021-03-09 00:38:00 +0000826 mJankClassificationThresholds, &mTraceCookieCounter,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000827 isBuffer, gameMode);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700828}
829
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800830FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000831 JankClassificationThresholds thresholds,
832 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800833 : mSurfaceFlingerPredictions(TimelineItem()),
834 mSurfaceFlingerActuals(TimelineItem()),
835 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000836 mJankClassificationThresholds(thresholds),
837 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800838 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700839}
840
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800841void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700842 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000843 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800844 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
845}
846
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200847void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate,
848 Fps renderRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800849 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000850 std::scoped_lock lock(mMutex);
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200851 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800852 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700853}
854
855void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000856 const std::shared_ptr<FenceTime>& presentFence,
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000857 const std::shared_ptr<FenceTime>& gpuFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700858 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000859 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800860 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000861 mCurrentDisplayFrame->setGpuFence(gpuFence);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700862 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
863 flushPendingPresentFences();
864 finalizeCurrentDisplayFrame();
865}
866
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800867void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
868 mSurfaceFrames.push_back(surfaceFrame);
869}
870
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200871void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800872 std::optional<TimelineItem> predictions,
873 nsecs_t wakeUpTime) {
874 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800875 mRefreshRate = refreshRate;
Pascal Muetschardac7bcd92023-10-03 15:05:36 +0200876 mRenderRate = renderRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800877 if (!predictions) {
878 mPredictionState = PredictionState::Expired;
879 } else {
880 mPredictionState = PredictionState::Valid;
881 mSurfaceFlingerPredictions = *predictions;
882 }
883 mSurfaceFlingerActuals.startTime = wakeUpTime;
884}
885
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800886void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
887 TimelineItem predictions) {
888 mPredictionState = predictionState;
889 mSurfaceFlingerPredictions = predictions;
890}
891
892void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
893 mSurfaceFlingerActuals.startTime = actualStartTime;
894}
895
896void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
897 mSurfaceFlingerActuals.endTime = actualEndTime;
898}
899
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000900void FrameTimeline::DisplayFrame::setGpuFence(const std::shared_ptr<FenceTime>& gpuFence) {
901 mGpuFence = gpuFence;
Adithya Srinivasanb6a2fa12021-03-13 00:23:09 +0000902}
903
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000904void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
905 nsecs_t previousPresentTime) {
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700906 const bool presentTimeValid =
907 mSurfaceFlingerActuals.presentTime >= mSurfaceFlingerActuals.startTime;
908 if (mPredictionState == PredictionState::Expired || !presentTimeValid) {
Adithya Srinivasande272452021-04-10 00:21:00 +0000909 // Cannot do jank classification with expired predictions or invalid signal times. Set the
910 // deltas to 0 as both negative and positive deltas are used as real values.
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000911 mJankType = JankType::Unknown;
Adithya Srinivasande272452021-04-10 00:21:00 +0000912 deadlineDelta = 0;
913 deltaToVsync = 0;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700914 if (!presentTimeValid) {
Ady Abrahamfcb16862022-10-10 14:35:21 -0700915 mSurfaceFlingerActuals.presentTime = mSurfaceFlingerActuals.endTime;
Ady Abrahamb1e10d12023-03-13 15:23:54 -0700916 mJankType |= JankType::DisplayHAL;
Ady Abrahamfcb16862022-10-10 14:35:21 -0700917 }
918
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000919 return;
920 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800921
922 // Delta between the expected present and the actual present
923 const nsecs_t presentDelta =
924 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000925 // Sf actual end time represents the CPU end time. In case of HWC, SF's end time would have
926 // included the time for composition. However, for GPU composition, the final end time is max(sf
927 // end time, gpu fence time).
928 nsecs_t combinedEndTime = mSurfaceFlingerActuals.endTime;
929 if (mGpuFence != FenceTime::NO_FENCE) {
930 combinedEndTime = std::max(combinedEndTime, mGpuFence->getSignalTime());
931 }
932 deadlineDelta = combinedEndTime - mSurfaceFlingerPredictions.endTime;
Alec Mouri363faf02021-01-29 16:34:55 -0800933
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800934 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
935 // was a prediction error or not.
Adithya Srinivasan115ac692021-03-06 01:21:30 +0000936 deltaToVsync = mRefreshRate.getPeriodNsecs() > 0
Alec Mouriadebf5c2021-01-05 12:57:36 -0800937 ? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
938 : 0;
Adithya Srinivasan115ac692021-03-06 01:21:30 +0000939
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800940 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
941 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
942 : FramePresentMetadata::EarlyPresent;
943 } else {
944 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
945 }
946
Adithya Srinivasan36b01af2021-04-07 22:29:47 +0000947 if (combinedEndTime > mSurfaceFlingerPredictions.endTime) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800948 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
949 } else {
950 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
951 }
952
953 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
954 mJankClassificationThresholds.startThreshold) {
955 mFrameStartMetadata =
956 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
957 ? FrameStartMetadata::LateStart
958 : FrameStartMetadata::EarlyStart;
959 }
960
961 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
962 // Do jank classification only if present is not on time
963 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
964 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
965 // Finish on time, Present early
966 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800967 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
968 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800969 // Delta is a factor of vsync if its within the presentTheshold on either side
970 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
971 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
972 mJankType = JankType::SurfaceFlingerScheduling;
973 } else {
974 // Delta is not a factor of vsync,
975 mJankType = JankType::PredictionError;
976 }
977 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
978 // Finish late, Present early
979 mJankType = JankType::SurfaceFlingerScheduling;
980 } else {
981 // Finish time unknown
982 mJankType = JankType::Unknown;
983 }
984 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +0000985 if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
986 mJankClassificationThresholds.presentThreshold ||
987 previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
988 // The previous frame was either presented in the current frame's expected vsync or
989 // it was presented even later than the current frame's expected vsync.
990 mJankType = JankType::SurfaceFlingerStuffing;
991 }
992 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
993 !(mJankType & JankType::SurfaceFlingerStuffing)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800994 // Finish on time, Present late
995 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800996 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
997 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800998 // Delta is a factor of vsync if its within the presentTheshold on either side
999 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
1000 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
1001 mJankType = JankType::DisplayHAL;
1002 } else {
1003 // Delta is not a factor of vsync
1004 mJankType = JankType::PredictionError;
1005 }
1006 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001007 if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
1008 mSurfaceFlingerActuals.presentTime - previousPresentTime >
1009 mRefreshRate.getPeriodNsecs() +
1010 mJankClassificationThresholds.presentThreshold) {
1011 // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
1012 // was presented more than a vsync late.
Rachel Lee94917b32022-03-18 17:52:09 -07001013 if (mGpuFence != FenceTime::NO_FENCE) {
1014 // If SF was in GPU composition, classify it as GPU deadline missed.
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001015 mJankType = JankType::SurfaceFlingerGpuDeadlineMissed;
1016 } else {
1017 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
1018 }
Adithya Srinivasan939cd4d2021-02-23 06:18:13 +00001019 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001020 } else {
1021 // Finish time unknown
1022 mJankType = JankType::Unknown;
1023 }
1024 } else {
1025 // Present unknown
1026 mJankType = JankType::Unknown;
1027 }
1028 }
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001029}
1030
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001031void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001032 mSurfaceFlingerActuals.presentTime = signalTime;
1033 nsecs_t deadlineDelta = 0;
1034 nsecs_t deltaToVsync = 0;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001035 classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
Adithya Srinivasan115ac692021-03-06 01:21:30 +00001036
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001037 for (auto& surfaceFrame : mSurfaceFrames) {
Pascal Muetschardac7bcd92023-10-03 15:05:36 +02001038 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta,
1039 deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001040 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001041}
1042
Ady Abraham57f8e182022-03-08 15:54:33 -08001043void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
1044 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001045 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001046
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001047 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001048 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001049 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001050 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1051 packet->set_timestamp(
1052 static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001053
1054 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001055 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001056
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001057 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001058
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001059 expectedDisplayFrameStartEvent->set_token(mToken);
1060 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1061 });
Adithya Srinivasan86678502021-01-19 21:50:38 +00001062
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001063 // Expected timeline end
1064 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1065 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001066 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1067 packet->set_timestamp(
1068 static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001069
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001070 auto* event = packet->set_frame_timeline_event();
1071 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001072
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001073 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
1074 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001075}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001076
Sally Qiaa107742023-09-29 14:53:14 -07001077void FrameTimeline::DisplayFrame::addSkippedFrame(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1078 nsecs_t previousActualPresentTime) const {
1079 nsecs_t skippedFrameStartTime = 0, skippedFramePresentTime = 0;
1080 const constexpr float kThresh = 0.5f;
1081 const constexpr float kRange = 1.5f;
1082 for (auto& surfaceFrame : mSurfaceFrames) {
1083 if (previousActualPresentTime != 0 &&
1084 static_cast<float>(mSurfaceFlingerActuals.presentTime - previousActualPresentTime) >=
1085 static_cast<float>(mRenderRate.getPeriodNsecs()) * kRange &&
1086 static_cast<float>(surfaceFrame->getPredictions().presentTime) <=
1087 (static_cast<float>(mSurfaceFlingerActuals.presentTime) -
1088 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs())) &&
1089 static_cast<float>(surfaceFrame->getPredictions().presentTime) >=
1090 (static_cast<float>(previousActualPresentTime) -
1091 kThresh * static_cast<float>(mRenderRate.getPeriodNsecs()))) {
1092 skippedFrameStartTime = surfaceFrame->getPredictions().endTime;
1093 skippedFramePresentTime = surfaceFrame->getPredictions().presentTime;
1094 break;
1095 }
1096 }
1097
1098 // add slice
1099 if (skippedFrameStartTime != 0 && skippedFramePresentTime != 0) {
1100 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
1101
1102 // Actual timeline start
1103 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1104 auto packet = ctx.NewTracePacket();
1105 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1106 packet->set_timestamp(static_cast<uint64_t>(skippedFrameStartTime + monoBootOffset));
1107
1108 auto* event = packet->set_frame_timeline_event();
1109 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1110
1111 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1112
1113 actualDisplayFrameStartEvent->set_token(0);
1114 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1115 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1116 FrameReadyMetadata::OnTimeFinish);
1117 actualDisplayFrameStartEvent->set_gpu_composition(false);
1118 actualDisplayFrameStartEvent->set_prediction_type(toProto(PredictionState::Valid));
1119 actualDisplayFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
1120 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(JankType::Dropped));
1121 });
1122
1123 // Actual timeline end
1124 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1125 auto packet = ctx.NewTracePacket();
1126 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1127 packet->set_timestamp(static_cast<uint64_t>(skippedFramePresentTime + monoBootOffset));
1128
1129 auto* event = packet->set_frame_timeline_event();
1130 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1131
1132 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
1133 });
1134 }
1135}
1136
Ady Abraham57f8e182022-03-08 15:54:33 -08001137void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
1138 nsecs_t monoBootOffset) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001139 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001140
1141 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001142 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1143 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001144 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1145 packet->set_timestamp(
1146 static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001147
1148 auto* event = packet->set_frame_timeline_event();
1149 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
1150
1151 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
1152
1153 actualDisplayFrameStartEvent->set_token(mToken);
1154 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
1155
1156 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
1157 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
1158 FrameReadyMetadata::OnTimeFinish);
Adithya Srinivasan36b01af2021-04-07 22:29:47 +00001159 actualDisplayFrameStartEvent->set_gpu_composition(mGpuFence != FenceTime::NO_FENCE);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001160 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
Adithya Srinivasan78e58af2021-02-25 00:08:08 +00001161 actualDisplayFrameStartEvent->set_prediction_type(toProto(mPredictionState));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001162 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001163
1164 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001165 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
1166 auto packet = ctx.NewTracePacket();
Ady Abraham57f8e182022-03-08 15:54:33 -08001167 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
1168 packet->set_timestamp(
1169 static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001170
1171 auto* event = packet->set_frame_timeline_event();
1172 auto* actualDisplayFrameEndEvent = event->set_frame_end();
1173
1174 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001175 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001176}
1177
Sally Qiaa107742023-09-29 14:53:14 -07001178void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset,
1179 nsecs_t previousActualPresentTime) const {
Ady Abraham57a8ab42023-01-26 15:28:19 -08001180 if (mSurfaceFrames.empty()) {
1181 // We don't want to trace display frames without any surface frames updates as this cannot
1182 // be janky
1183 return;
1184 }
1185
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001186 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
1187 // DisplayFrame should not have an invalid token.
1188 ALOGE("Cannot trace DisplayFrame with invalid token");
1189 return;
1190 }
1191
1192 if (mPredictionState == PredictionState::Valid) {
1193 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
1194 // meaningful way in a trace.
Ady Abraham57f8e182022-03-08 15:54:33 -08001195 tracePredictions(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +00001196 }
Ady Abraham57f8e182022-03-08 15:54:33 -08001197 traceActuals(surfaceFlingerPid, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001198
1199 for (auto& surfaceFrame : mSurfaceFrames) {
Ady Abraham57f8e182022-03-08 15:54:33 -08001200 surfaceFrame->trace(mToken, monoBootOffset);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001201 }
Sally Qiaa107742023-09-29 14:53:14 -07001202
1203 addSkippedFrame(surfaceFlingerPid, monoBootOffset, previousActualPresentTime);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001204}
1205
Alec Mouriadebf5c2021-01-05 12:57:36 -08001206float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
1207 if (layerIds.empty()) {
1208 return 0.0f;
1209 }
1210
1211 std::vector<nsecs_t> presentTimes;
1212 {
1213 std::scoped_lock lock(mMutex);
1214 presentTimes.reserve(mDisplayFrames.size());
1215 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1216 const auto& displayFrame = mDisplayFrames[i];
1217 if (displayFrame->getActuals().presentTime <= 0) {
1218 continue;
1219 }
1220 for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1221 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented &&
1222 layerIds.count(surfaceFrame->getLayerId()) > 0) {
1223 // We're looking for DisplayFrames that presents at least one layer from
1224 // layerIds, so push the present time and skip looking through the rest of the
1225 // SurfaceFrames.
1226 presentTimes.push_back(displayFrame->getActuals().presentTime);
1227 break;
1228 }
1229 }
1230 }
1231 }
1232
1233 // FPS can't be computed when there's fewer than 2 presented frames.
1234 if (presentTimes.size() <= 1) {
1235 return 0.0f;
1236 }
1237
1238 nsecs_t priorPresentTime = -1;
1239 nsecs_t totalPresentToPresentWalls = 0;
1240
1241 for (const nsecs_t presentTime : presentTimes) {
1242 if (priorPresentTime == -1) {
1243 priorPresentTime = presentTime;
1244 continue;
1245 }
1246
1247 totalPresentToPresentWalls += (presentTime - priorPresentTime);
1248 priorPresentTime = presentTime;
1249 }
1250
1251 if (CC_UNLIKELY(totalPresentToPresentWalls <= 0)) {
1252 ALOGW("Invalid total present-to-present duration when computing fps: %" PRId64,
1253 totalPresentToPresentWalls);
1254 return 0.0f;
1255 }
1256
1257 const constexpr nsecs_t kOneSecond =
1258 std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
1259 // (10^9 nanoseconds / second) * (N present deltas) / (total nanoseconds in N present deltas) =
1260 // M frames / second
1261 return kOneSecond * static_cast<nsecs_t>((presentTimes.size() - 1)) /
1262 static_cast<float>(totalPresentToPresentWalls);
1263}
1264
Ady Abrahamfcb16862022-10-10 14:35:21 -07001265std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
1266 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1267 const auto& [fence, _] = mPendingPresentFences[i];
Theodore Dubois205c6dd2022-11-23 15:06:33 -08001268 if (fence && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001269 return i;
1270 }
1271 }
1272
1273 return {};
1274}
1275
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001276void FrameTimeline::flushPendingPresentFences() {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001277 const auto firstSignaledFence = getFirstSignalFenceIndex();
1278 if (!firstSignaledFence.has_value()) {
1279 return;
1280 }
1281
Ady Abraham57f8e182022-03-08 15:54:33 -08001282 // Perfetto is using boottime clock to void drifts when the device goes
1283 // to suspend.
1284 const auto monoBootOffset = mUseBootTimeClock
1285 ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
1286 : 0;
1287
Ady Abrahamfcb16862022-10-10 14:35:21 -07001288 // Present fences are expected to be signaled in order. Mark all the previous
1289 // pending fences as errors.
1290 for (size_t i = 0; i < firstSignaledFence.value(); i++) {
1291 const auto& pendingPresentFence = *mPendingPresentFences.begin();
1292 const nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1293 auto& displayFrame = pendingPresentFence.second;
1294 displayFrame->onPresent(signalTime, mPreviousPresentTime);
Sally Qiaa107742023-09-29 14:53:14 -07001295 displayFrame->trace(mSurfaceFlingerPid, monoBootOffset, mPreviousPresentTime);
Ady Abrahamfcb16862022-10-10 14:35:21 -07001296 mPendingPresentFences.erase(mPendingPresentFences.begin());
1297 }
1298
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001299 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
1300 const auto& pendingPresentFence = mPendingPresentFences[i];
1301 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
1302 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
1303 signalTime = pendingPresentFence.first->getSignalTime();
1304 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
Ady Abrahamfcb16862022-10-10 14:35:21 -07001305 break;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001306 }
1307 }
Ady Abrahamfcb16862022-10-10 14:35:21 -07001308
Adithya Srinivasan7c4ac7a2021-03-08 23:48:03 +00001309 auto& displayFrame = pendingPresentFence.second;
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001310 displayFrame->onPresent(signalTime, mPreviousPresentTime);
Sally Qiaa107742023-09-29 14:53:14 -07001311 displayFrame->trace(mSurfaceFlingerPid, monoBootOffset, mPreviousPresentTime);
Adithya Srinivasan57dc81d2021-04-14 17:31:41 +00001312 mPreviousPresentTime = signalTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001313
1314 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
1315 --i;
1316 }
1317}
1318
1319void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001320 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001321 // We maintain only a fixed number of frames' data. Pop older frames
1322 mDisplayFrames.pop_front();
1323 }
1324 mDisplayFrames.push_back(mCurrentDisplayFrame);
1325 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +00001326 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
Adithya Srinivasan82eef322021-04-10 00:06:04 +00001327 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001328}
1329
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001330nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1331 nsecs_t baseTime =
1332 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1333 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001334 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1335 if (surfaceFrameBaseTime != 0) {
1336 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1337 }
1338 }
1339 return baseTime;
1340}
1341
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001342void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1343 int displayFrameCount) const {
1344 if (mJankType == JankType::None) {
1345 // Check if any Surface Frame has been janky
1346 bool isJanky = false;
1347 for (const auto& surfaceFrame : mSurfaceFrames) {
1348 if (surfaceFrame->getJankType() != JankType::None) {
1349 isJanky = true;
1350 break;
1351 }
1352 }
1353 if (!isJanky) {
1354 return;
1355 }
1356 }
1357 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1358 dump(result, baseTime);
1359}
1360
1361void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1362 dump(result, baseTime);
1363}
1364
1365void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1366 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001367 // Easily identify a janky Display Frame in the dump
1368 StringAppendF(&result, " [*] ");
1369 }
1370 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001371 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1372 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1373 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1374 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1375 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001376 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001377 StringAppendF(&result, "Vsync Period: %10f\n",
1378 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1379 nsecs_t presentDelta =
1380 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1381 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1382 StringAppendF(&result, "Present delta: %10f\n",
1383 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001384 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001385 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1386 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1387 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1388 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001389 StringAppendF(&result, "\n");
1390 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001391 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001392 surfaceFrame->dump(result, indent, baseTime);
1393 }
1394 StringAppendF(&result, "\n");
1395}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001396
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001397void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001398 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001399 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001400 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001401 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1402 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001403 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001404 }
1405}
1406
1407void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001408 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001409 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001410 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001411 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001412 }
1413}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001414
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001415void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1416 ATRACE_CALL();
1417 std::unordered_map<std::string, bool> argsMap;
1418 for (size_t i = 0; i < args.size(); i++) {
1419 argsMap[std::string(String8(args[i]).c_str())] = true;
1420 }
1421 if (argsMap.count("-jank")) {
1422 dumpJank(result);
1423 }
1424 if (argsMap.count("-all")) {
1425 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001426 }
1427}
1428
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001429void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001430 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001431
1432 // The size can either increase or decrease, clear everything, to be consistent
1433 mDisplayFrames.clear();
1434 mPendingPresentFences.clear();
1435 mMaxDisplayFrames = size;
1436}
1437
1438void FrameTimeline::reset() {
1439 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1440}
1441
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001442} // namespace impl
1443} // namespace android::frametimeline