blob: 444f756f3e7d53bfcd5890bb39989018ddfde469 [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"
22#include <android-base/stringprintf.h>
Ady Abraham7f8a1e62020-09-28 16:09:35 -070023#include <utils/Log.h>
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070024#include <utils/Trace.h>
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070025#include <chrono>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070026#include <cinttypes>
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070027#include <numeric>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070028
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080029namespace android::frametimeline {
Adithya Srinivasanf279e042020-08-17 14:56:27 -070030
31using base::StringAppendF;
Adithya Srinivasan01189672020-10-20 14:23:05 -070032using FrameTimelineEvent = perfetto::protos::pbzero::FrameTimelineEvent;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +000033using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070034
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070035void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
36 const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
37 StringAppendF(&result, "%s", indent.c_str());
38 StringAppendF(&result, "\t\t");
39 StringAppendF(&result, " Start time\t\t|");
40 StringAppendF(&result, " End time\t\t|");
41 StringAppendF(&result, " Present time\n");
42 if (predictionState == PredictionState::Valid) {
43 // Dump the Predictions only if they are valid
44 StringAppendF(&result, "%s", indent.c_str());
45 StringAppendF(&result, "Expected\t|");
46 std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
47 std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
48 std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
49 StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
50 std::chrono::duration<double, std::milli>(startTime).count(),
51 std::chrono::duration<double, std::milli>(endTime).count(),
52 std::chrono::duration<double, std::milli>(presentTime).count());
53 }
54 StringAppendF(&result, "%s", indent.c_str());
55 StringAppendF(&result, "Actual \t|");
56
57 if (actuals.startTime == 0) {
58 StringAppendF(&result, "\t\tN/A\t|");
59 } else {
60 std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
61 StringAppendF(&result, "\t%10.2f\t|",
62 std::chrono::duration<double, std::milli>(startTime).count());
63 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080064 if (actuals.endTime <= 0) {
65 // Animation leashes can send the endTime as -1
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070066 StringAppendF(&result, "\t\tN/A\t|");
67 } else {
68 std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
69 StringAppendF(&result, "\t%10.2f\t|",
70 std::chrono::duration<double, std::milli>(endTime).count());
71 }
72 if (actuals.presentTime == 0) {
73 StringAppendF(&result, "\t\tN/A\n");
74 } else {
75 std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
76 StringAppendF(&result, "\t%10.2f\n",
77 std::chrono::duration<double, std::milli>(presentTime).count());
78 }
79
80 StringAppendF(&result, "%s", indent.c_str());
81 StringAppendF(&result, "----------------------");
82 StringAppendF(&result, "----------------------");
83 StringAppendF(&result, "----------------------");
84 StringAppendF(&result, "----------------------\n");
85}
86
87std::string toString(PredictionState predictionState) {
88 switch (predictionState) {
89 case PredictionState::Valid:
90 return "Valid";
91 case PredictionState::Expired:
92 return "Expired";
93 case PredictionState::None:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070094 return "None";
95 }
96}
97
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080098std::string jankTypeBitmaskToString(int32_t jankType) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080099 if (jankType == JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700100 return "None";
101 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000102
103 std::vector<std::string> janks;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800104 if (jankType & JankType::DisplayHAL) {
105 janks.emplace_back("Display HAL");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000106 jankType &= ~JankType::DisplayHAL;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800107 }
108 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
109 janks.emplace_back("SurfaceFlinger CPU Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000110 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800111 }
112 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
113 janks.emplace_back("SurfaceFlinger GPU Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000114 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800115 }
116 if (jankType & JankType::AppDeadlineMissed) {
117 janks.emplace_back("App Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000118 jankType &= ~JankType::AppDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800119 }
120 if (jankType & JankType::PredictionError) {
121 janks.emplace_back("Prediction Error");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000122 jankType &= ~JankType::PredictionError;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800123 }
124 if (jankType & JankType::SurfaceFlingerScheduling) {
125 janks.emplace_back("SurfaceFlinger Scheduling");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000126 jankType &= ~JankType::SurfaceFlingerScheduling;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800127 }
128 if (jankType & JankType::BufferStuffing) {
129 janks.emplace_back("Buffer Stuffing");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000130 jankType &= ~JankType::BufferStuffing;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800131 }
132 if (jankType & JankType::Unknown) {
133 janks.emplace_back("Unknown jank");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000134 jankType &= ~JankType::Unknown;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800135 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000136
137 // jankType should be 0 if all types of jank were checked for.
138 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800139 return std::accumulate(janks.begin(), janks.end(), std::string(),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700140 [](const std::string& l, const std::string& r) {
141 return l.empty() ? r : l + ", " + r;
142 });
143}
144
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800145std::string toString(FramePresentMetadata presentMetadata) {
146 switch (presentMetadata) {
147 case FramePresentMetadata::OnTimePresent:
148 return "On Time Present";
149 case FramePresentMetadata::LatePresent:
150 return "Late Present";
151 case FramePresentMetadata::EarlyPresent:
152 return "Early Present";
153 case FramePresentMetadata::UnknownPresent:
154 return "Unknown Present";
Adithya Srinivasan01189672020-10-20 14:23:05 -0700155 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700156}
157
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800158std::string toString(FrameReadyMetadata finishMetadata) {
159 switch (finishMetadata) {
160 case FrameReadyMetadata::OnTimeFinish:
161 return "On Time Finish";
162 case FrameReadyMetadata::LateFinish:
163 return "Late Finish";
164 case FrameReadyMetadata::UnknownFinish:
165 return "Unknown Finish";
166 }
167}
168
169std::string toString(FrameStartMetadata startMetadata) {
170 switch (startMetadata) {
171 case FrameStartMetadata::OnTimeStart:
172 return "On Time Start";
173 case FrameStartMetadata::LateStart:
174 return "Late Start";
175 case FrameStartMetadata::EarlyStart:
176 return "Early Start";
177 case FrameStartMetadata::UnknownStart:
178 return "Unknown Start";
179 }
180}
181
182std::string toString(SurfaceFrame::PresentState presentState) {
183 using PresentState = SurfaceFrame::PresentState;
184 switch (presentState) {
185 case PresentState::Presented:
186 return "Presented";
187 case PresentState::Dropped:
188 return "Dropped";
189 case PresentState::Unknown:
190 return "Unknown";
191 }
192}
193
194FrameTimelineEvent::PresentType toProto(FramePresentMetadata presentMetadata) {
195 switch (presentMetadata) {
196 case FramePresentMetadata::EarlyPresent:
197 return FrameTimelineEvent::PRESENT_EARLY;
198 case FramePresentMetadata::LatePresent:
199 return FrameTimelineEvent::PRESENT_LATE;
200 case FramePresentMetadata::OnTimePresent:
201 return FrameTimelineEvent::PRESENT_ON_TIME;
202 case FramePresentMetadata::UnknownPresent:
203 return FrameTimelineEvent::PRESENT_UNSPECIFIED;
204 }
205}
206
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000207int32_t jankTypeBitmaskToProto(int32_t jankType) {
208 if (jankType == JankType::None) {
209 return FrameTimelineEvent::JANK_NONE;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700210 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000211
212 int32_t protoJank = 0;
213 if (jankType & JankType::DisplayHAL) {
214 protoJank |= FrameTimelineEvent::JANK_DISPLAY_HAL;
215 jankType &= ~JankType::DisplayHAL;
216 }
217 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
218 protoJank |= FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED;
219 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
220 }
221 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
222 protoJank |= FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
223 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
224 }
225 if (jankType & JankType::AppDeadlineMissed) {
226 protoJank |= FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
227 jankType &= ~JankType::AppDeadlineMissed;
228 }
229 if (jankType & JankType::PredictionError) {
230 protoJank |= FrameTimelineEvent::JANK_PREDICTION_ERROR;
231 jankType &= ~JankType::PredictionError;
232 }
233 if (jankType & JankType::SurfaceFlingerScheduling) {
234 protoJank |= FrameTimelineEvent::JANK_SF_SCHEDULING;
235 jankType &= ~JankType::SurfaceFlingerScheduling;
236 }
237 if (jankType & JankType::BufferStuffing) {
238 protoJank |= FrameTimelineEvent::JANK_BUFFER_STUFFING;
239 jankType &= ~JankType::BufferStuffing;
240 }
241 if (jankType & JankType::Unknown) {
242 protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
243 jankType &= ~JankType::Unknown;
244 }
245
246 // jankType should be 0 if all types of jank were checked for.
247 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
248 return protoJank;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700249}
250
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800251// Returns the smallest timestamp from the set of predictions and actuals.
252nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
253 TimelineItem actuals) {
254 nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
255 if (predictionState == PredictionState::Valid) {
256 // Checking start time for predictions is enough because start time is always lesser than
257 // endTime and presentTime.
258 minTime = std::min(minTime, predictions.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700259 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700260
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800261 // Need to check startTime, endTime and presentTime for actuals because some frames might not
262 // have them set.
263 if (actuals.startTime != 0) {
264 minTime = std::min(minTime, actuals.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700265 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800266 if (actuals.endTime != 0) {
267 minTime = std::min(minTime, actuals.endTime);
268 }
269 if (actuals.presentTime != 0) {
270 minTime = std::min(minTime, actuals.endTime);
271 }
272 return minTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700273}
274
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000275int64_t TraceCookieCounter::getCookieForTracing() {
276 return ++mTraceCookie;
277}
278
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000279SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
280 uid_t ownerUid, std::string layerName, std::string debugName,
281 PredictionState predictionState,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800282 frametimeline::TimelineItem&& predictions,
283 std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000284 JankClassificationThresholds thresholds,
285 TraceCookieCounter* traceCookieCounter)
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000286 : mToken(frameTimelineInfo.vsyncId),
287 mInputEventId(frameTimelineInfo.inputEventId),
Adithya Srinivasan01189672020-10-20 14:23:05 -0700288 mOwnerPid(ownerPid),
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700289 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700290 mLayerName(std::move(layerName)),
291 mDebugName(std::move(debugName)),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700292 mPresentState(PresentState::Unknown),
293 mPredictionState(predictionState),
294 mPredictions(predictions),
295 mActuals({0, 0, 0}),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800296 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000297 mJankClassificationThresholds(thresholds),
298 mTraceCookieCounter(*traceCookieCounter) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700299
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700300void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000301 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700302 mActuals.startTime = actualStartTime;
303}
304
305void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000306 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700307 mActualQueueTime = actualQueueTime;
308}
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000309
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700310void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000311 std::scoped_lock lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700312 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700313}
314
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000315void SurfaceFrame::setDropTime(nsecs_t dropTime) {
316 std::scoped_lock lock(mMutex);
317 mDropTime = dropTime;
318}
319
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800320void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000321 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000322 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
323 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
324 "PresentState - %s set already.",
325 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800326 mPresentState = presentState;
327 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700328}
329
Alec Mouri7d436ec2021-01-27 20:40:50 -0800330void SurfaceFrame::setRenderRate(Fps renderRate) {
331 std::lock_guard<std::mutex> lock(mMutex);
332 mRenderRate = renderRate;
333}
334
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800335std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000336 std::scoped_lock lock(mMutex);
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100337 if (mActuals.presentTime == 0) {
338 return std::nullopt;
339 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700340 return mJankType;
341}
342
343nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000344 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800345 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700346}
347
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800348TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000349 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800350 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700351}
352
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000353PredictionState SurfaceFrame::getPredictionState() const {
354 std::scoped_lock lock(mMutex);
355 return mPredictionState;
356}
357
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800358SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000359 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800360 return mPresentState;
361}
362
363FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000364 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800365 return mFramePresentMetadata;
366}
367
368FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000369 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800370 return mFrameReadyMetadata;
371}
372
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000373nsecs_t SurfaceFrame::getDropTime() const {
374 std::scoped_lock lock(mMutex);
375 return mDropTime;
376}
377
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800378void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000379 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700380 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700381 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100382 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700383 // Easily identify a janky Surface Frame in the dump
384 StringAppendF(&result, " [*] ");
385 }
386 StringAppendF(&result, "\n");
387 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800388 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
389 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700390 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
391 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800392 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
393 mRenderRate ? mRenderRate->getIntValue() : 0);
394 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800395 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700396 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000397 if (mPresentState == PresentState::Dropped) {
398 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
399 StringAppendF(&result, "Drop time : %10f\n",
400 std::chrono::duration<double, std::milli>(dropTime).count());
401 StringAppendF(&result, "%s", indent.c_str());
402 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700403 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
404 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800405 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700406 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800407 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
408 StringAppendF(&result, "%s", indent.c_str());
409 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
410 std::chrono::nanoseconds latchTime(
411 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
412 StringAppendF(&result, "%s", indent.c_str());
413 StringAppendF(&result, "Last latch time: %10f\n",
414 std::chrono::duration<double, std::milli>(latchTime).count());
415 if (mPredictionState == PredictionState::Valid) {
416 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
417 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
418 StringAppendF(&result, "%s", indent.c_str());
419 StringAppendF(&result, "Present delta: %10f\n",
420 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
421 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700422 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700423}
424
Alec Mouri363faf02021-01-29 16:34:55 -0800425void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
426 nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000427 std::scoped_lock lock(mMutex);
Alec Mouri7d436ec2021-01-27 20:40:50 -0800428
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800429 if (mPresentState != PresentState::Presented) {
430 // No need to update dropped buffers
431 return;
432 }
433
434 mActuals.presentTime = presentTime;
435 // Jank Analysis for SurfaceFrame
436 if (mPredictionState == PredictionState::None) {
437 // Cannot do jank classification on frames that don't have a token.
438 return;
439 }
440 if (mPredictionState == PredictionState::Expired) {
441 // We do not know what happened here to classify this correctly. This could
442 // potentially be AppDeadlineMissed but that's assuming no app will request frames
443 // 120ms apart.
444 mJankType = JankType::Unknown;
445 mFramePresentMetadata = FramePresentMetadata::UnknownPresent;
446 mFrameReadyMetadata = FrameReadyMetadata::UnknownFinish;
Alec Mouri363faf02021-01-29 16:34:55 -0800447 const constexpr nsecs_t kAppDeadlineDelta = -1;
448 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
449 mJankType, displayDeadlineDelta, displayPresentDelta,
450 kAppDeadlineDelta});
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800451 return;
452 }
453
454 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
455 const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800456 const nsecs_t deltaToVsync = std::abs(presentDelta) % refreshRate.getPeriodNsecs();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800457
458 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
459 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
460 } else {
461 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
462 }
463
464 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
465 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
466 : FramePresentMetadata::EarlyPresent;
467 } else {
468 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
469 }
470
471 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
472 // Frames presented on time are not janky.
473 mJankType = JankType::None;
474 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
475 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
476 // Finish on time, Present early
477 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800478 deltaToVsync >= refreshRate.getPeriodNsecs() -
479 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800480 // Delta factor of vsync
481 mJankType = JankType::SurfaceFlingerScheduling;
482 } else {
483 // Delta not a factor of vsync
484 mJankType = JankType::PredictionError;
485 }
486 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
487 // Finish late, Present early
488 mJankType = JankType::Unknown;
489 }
490 } else {
491 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
492 // Buffer Stuffing.
493 mJankType |= JankType::BufferStuffing;
494 }
495 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
496 // Finish on time, Present late
497 if (displayFrameJankType != JankType::None) {
498 // Propagate displayFrame's jank if it exists
499 mJankType |= displayFrameJankType;
500 } else {
501 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800502 deltaToVsync >= refreshRate.getPeriodNsecs() -
503 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800504 // Delta factor of vsync
505 mJankType |= JankType::SurfaceFlingerScheduling;
506 } else {
507 // Delta not a factor of vsync
508 mJankType |= JankType::PredictionError;
509 }
510 }
511 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
512 // Finish late, Present late
513 if (displayFrameJankType == JankType::None) {
514 // Display frame is not janky, so purely app's fault
515 mJankType |= JankType::AppDeadlineMissed;
516 } else {
517 // Propagate DisplayFrame's jankType if it is janky
518 mJankType |= displayFrameJankType;
519 }
520 }
521 }
Alec Mouri363faf02021-01-29 16:34:55 -0800522 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName, mJankType,
523 displayDeadlineDelta, displayPresentDelta, deadlineDelta});
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800524}
525
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000526void SurfaceFrame::tracePredictions(int64_t displayFrameToken) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000527 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000528
Adithya Srinivasan86678502021-01-19 21:50:38 +0000529 // Expected timeline start
530 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000531 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700532 auto packet = ctx.NewTracePacket();
533 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000534 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700535
536 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000537 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700538
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000539 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
540
541 expectedSurfaceFrameStartEvent->set_token(mToken);
542 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
543
544 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
545 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
546 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000547
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000548 // Expected timeline end
549 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000550 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000551 auto packet = ctx.NewTracePacket();
552 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
553 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
554
555 auto* event = packet->set_frame_timeline_event();
556 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
557
558 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
559 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000560}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000561
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000562void SurfaceFrame::traceActuals(int64_t displayFrameToken) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000563 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000564
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000565 // Actual timeline start
566 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000567 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000568 auto packet = ctx.NewTracePacket();
569 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
570 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000571 if (mPredictionState == PredictionState::Expired) {
572 // If prediction is expired, we can't use the predicted start time. Instead, just use a
573 // start time a little earlier than the end time so that we have some info about this
574 // frame in the trace.
575 packet->set_timestamp(
576 static_cast<uint64_t>(mActuals.endTime - kPredictionExpiredStartTimeDelta));
577 } else {
578 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
579 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000580
581 auto* event = packet->set_frame_timeline_event();
582 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
583
584 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
585
586 actualSurfaceFrameStartEvent->set_token(mToken);
587 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
588
589 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
590 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700591
592 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000593 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700594 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000595 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700596 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000597 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700598 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000599 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
600 FrameReadyMetadata::OnTimeFinish);
601 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
602 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
603 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000604
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000605 // Actual timeline end
606 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000607 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000608 auto packet = ctx.NewTracePacket();
609 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000610 if (mPresentState == PresentState::Dropped) {
611 packet->set_timestamp(static_cast<uint64_t>(mDropTime));
612 } else {
613 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
614 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700615
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000616 auto* event = packet->set_frame_timeline_event();
617 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700618
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000619 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700620 });
621}
622
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000623/**
624 * TODO(b/178637512): add inputEventId to the perfetto trace.
625 */
626void SurfaceFrame::trace(int64_t displayFrameToken) const {
627 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
628 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
629 // No packets can be traced with a missing token.
630 return;
631 }
632 if (getPredictionState() != PredictionState::Expired) {
633 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
634 // a trace.
635 tracePredictions(displayFrameToken);
636 }
637 traceActuals(displayFrameToken);
638}
639
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800640namespace impl {
641
642int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
643 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000644 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800645 const int64_t assignedToken = mCurrentToken++;
646 mPredictions[assignedToken] = {systemTime(), predictions};
647 flushTokens(systemTime());
648 return assignedToken;
649}
650
651std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000652 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800653 auto predictionsIterator = mPredictions.find(token);
654 if (predictionsIterator != mPredictions.end()) {
655 return predictionsIterator->second.predictions;
656 }
657 return {};
658}
659
660void TokenManager::flushTokens(nsecs_t flushTime) {
661 for (auto it = mPredictions.begin(); it != mPredictions.end();) {
662 if (flushTime - it->second.timestamp >= kMaxRetentionTime) {
663 it = mPredictions.erase(it);
664 } else {
665 // Tokens are ordered by time. If i'th token is within the retention time, then the
666 // i+1'th token will also be within retention time.
667 break;
668 }
669 }
670}
671
672FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
673 JankClassificationThresholds thresholds)
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000674 : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800675 mTimeStats(std::move(timeStats)),
676 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000677 mJankClassificationThresholds(thresholds) {
678 mCurrentDisplayFrame =
679 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
680}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700681
Adithya Srinivasan01189672020-10-20 14:23:05 -0700682void FrameTimeline::onBootFinished() {
683 perfetto::TracingInitArgs args;
684 args.backends = perfetto::kSystemBackend;
685 perfetto::Tracing::Initialize(args);
686 registerDataSource();
687}
688
689void FrameTimeline::registerDataSource() {
690 perfetto::DataSourceDescriptor dsd;
691 dsd.set_name(kFrameTimelineDataSource);
692 FrameTimelineDataSource::Register(dsd);
693}
694
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800695std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000696 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
697 std::string layerName, std::string debugName) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700698 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000699 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
700 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
701 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800702 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000703 mJankClassificationThresholds, &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700704 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000705 std::optional<TimelineItem> predictions =
706 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700707 if (predictions) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000708 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
709 std::move(layerName), std::move(debugName),
710 PredictionState::Valid, std::move(*predictions),
711 mTimeStats, mJankClassificationThresholds,
712 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700713 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000714 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
715 std::move(layerName), std::move(debugName),
716 PredictionState::Expired, TimelineItem(), mTimeStats,
717 mJankClassificationThresholds, &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700718}
719
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800720FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000721 JankClassificationThresholds thresholds,
722 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800723 : mSurfaceFlingerPredictions(TimelineItem()),
724 mSurfaceFlingerActuals(TimelineItem()),
725 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000726 mJankClassificationThresholds(thresholds),
727 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800728 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700729}
730
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800731void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700732 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000733 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800734 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
735}
736
Alec Mouri7d436ec2021-01-27 20:40:50 -0800737void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800738 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000739 std::scoped_lock lock(mMutex);
Alec Mouri7d436ec2021-01-27 20:40:50 -0800740 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800741 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700742}
743
744void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
745 const std::shared_ptr<FenceTime>& presentFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700746 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000747 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800748 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700749 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
750 flushPendingPresentFences();
751 finalizeCurrentDisplayFrame();
752}
753
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800754void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
755 mSurfaceFrames.push_back(surfaceFrame);
756}
757
Alec Mouri7d436ec2021-01-27 20:40:50 -0800758void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800759 std::optional<TimelineItem> predictions,
760 nsecs_t wakeUpTime) {
761 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800762 mRefreshRate = refreshRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800763 if (!predictions) {
764 mPredictionState = PredictionState::Expired;
765 } else {
766 mPredictionState = PredictionState::Valid;
767 mSurfaceFlingerPredictions = *predictions;
768 }
769 mSurfaceFlingerActuals.startTime = wakeUpTime;
770}
771
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800772void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
773 TimelineItem predictions) {
774 mPredictionState = predictionState;
775 mSurfaceFlingerPredictions = predictions;
776}
777
778void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
779 mSurfaceFlingerActuals.startTime = actualStartTime;
780}
781
782void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
783 mSurfaceFlingerActuals.endTime = actualEndTime;
784}
785
786void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
787 mSurfaceFlingerActuals.presentTime = signalTime;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000788 if (mPredictionState == PredictionState::Expired) {
789 // Cannot do jank classification with expired predictions
790 mJankType = JankType::Unknown;
791 return;
792 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800793
794 // Delta between the expected present and the actual present
795 const nsecs_t presentDelta =
796 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Alec Mouri363faf02021-01-29 16:34:55 -0800797 const nsecs_t deadlineDelta =
798 mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime;
799
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800800 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
801 // was a prediction error or not.
Alec Mouri7d436ec2021-01-27 20:40:50 -0800802 nsecs_t deltaToVsync = std::abs(presentDelta) % mRefreshRate.getPeriodNsecs();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800803 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
804 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
805 : FramePresentMetadata::EarlyPresent;
806 } else {
807 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
808 }
809
810 if (mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime >
811 mJankClassificationThresholds.deadlineThreshold) {
812 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
813 } else {
814 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
815 }
816
817 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
818 mJankClassificationThresholds.startThreshold) {
819 mFrameStartMetadata =
820 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
821 ? FrameStartMetadata::LateStart
822 : FrameStartMetadata::EarlyStart;
823 }
824
825 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
826 // Do jank classification only if present is not on time
827 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
828 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
829 // Finish on time, Present early
830 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800831 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
832 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800833 // Delta is a factor of vsync if its within the presentTheshold on either side
834 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
835 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
836 mJankType = JankType::SurfaceFlingerScheduling;
837 } else {
838 // Delta is not a factor of vsync,
839 mJankType = JankType::PredictionError;
840 }
841 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
842 // Finish late, Present early
843 mJankType = JankType::SurfaceFlingerScheduling;
844 } else {
845 // Finish time unknown
846 mJankType = JankType::Unknown;
847 }
848 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
849 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
850 // Finish on time, Present late
851 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800852 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
853 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800854 // Delta is a factor of vsync if its within the presentTheshold on either side
855 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
856 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
857 mJankType = JankType::DisplayHAL;
858 } else {
859 // Delta is not a factor of vsync
860 mJankType = JankType::PredictionError;
861 }
862 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
863 // Finish late, Present late
864 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
865 } else {
866 // Finish time unknown
867 mJankType = JankType::Unknown;
868 }
869 } else {
870 // Present unknown
871 mJankType = JankType::Unknown;
872 }
873 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800874 for (auto& surfaceFrame : mSurfaceFrames) {
Alec Mouri363faf02021-01-29 16:34:55 -0800875 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, deadlineDelta, deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800876 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800877}
878
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000879void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000880 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000881
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000882 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800883 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800884 auto packet = ctx.NewTracePacket();
885 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000886 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800887
888 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000889 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800890
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000891 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800892
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000893 expectedDisplayFrameStartEvent->set_token(mToken);
894 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
895 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000896
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000897 // Expected timeline end
898 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
899 auto packet = ctx.NewTracePacket();
900 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
901 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800902
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000903 auto* event = packet->set_frame_timeline_event();
904 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800905
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000906 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
907 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000908}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000909
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000910void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000911 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000912
913 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000914 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
915 auto packet = ctx.NewTracePacket();
916 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
917 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.startTime));
918
919 auto* event = packet->set_frame_timeline_event();
920 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
921
922 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
923
924 actualDisplayFrameStartEvent->set_token(mToken);
925 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
926
927 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
928 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
929 FrameReadyMetadata::OnTimeFinish);
930 actualDisplayFrameStartEvent->set_gpu_composition(mGpuComposition);
931 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
932 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000933
934 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000935 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
936 auto packet = ctx.NewTracePacket();
937 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
938 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.endTime));
939
940 auto* event = packet->set_frame_timeline_event();
941 auto* actualDisplayFrameEndEvent = event->set_frame_end();
942
943 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800944 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000945}
946
947void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const {
948 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
949 // DisplayFrame should not have an invalid token.
950 ALOGE("Cannot trace DisplayFrame with invalid token");
951 return;
952 }
953
954 if (mPredictionState == PredictionState::Valid) {
955 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
956 // meaningful way in a trace.
957 tracePredictions(surfaceFlingerPid);
958 }
959 traceActuals(surfaceFlingerPid);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800960
961 for (auto& surfaceFrame : mSurfaceFrames) {
962 surfaceFrame->trace(mToken);
963 }
964}
965
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700966void FrameTimeline::flushPendingPresentFences() {
967 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
968 const auto& pendingPresentFence = mPendingPresentFences[i];
969 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
970 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
971 signalTime = pendingPresentFence.first->getSignalTime();
972 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
973 continue;
974 }
975 }
976 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
977 auto& displayFrame = pendingPresentFence.second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800978 displayFrame->onPresent(signalTime);
979 displayFrame->trace(mSurfaceFlingerPid);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700980 }
981
982 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
983 --i;
984 }
985}
986
987void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700988 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700989 // We maintain only a fixed number of frames' data. Pop older frames
990 mDisplayFrames.pop_front();
991 }
992 mDisplayFrames.push_back(mCurrentDisplayFrame);
993 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000994 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
995 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700996}
997
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800998nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
999 nsecs_t baseTime =
1000 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1001 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001002 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1003 if (surfaceFrameBaseTime != 0) {
1004 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1005 }
1006 }
1007 return baseTime;
1008}
1009
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001010void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1011 int displayFrameCount) const {
1012 if (mJankType == JankType::None) {
1013 // Check if any Surface Frame has been janky
1014 bool isJanky = false;
1015 for (const auto& surfaceFrame : mSurfaceFrames) {
1016 if (surfaceFrame->getJankType() != JankType::None) {
1017 isJanky = true;
1018 break;
1019 }
1020 }
1021 if (!isJanky) {
1022 return;
1023 }
1024 }
1025 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1026 dump(result, baseTime);
1027}
1028
1029void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1030 dump(result, baseTime);
1031}
1032
1033void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1034 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001035 // Easily identify a janky Display Frame in the dump
1036 StringAppendF(&result, " [*] ");
1037 }
1038 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001039 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1040 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1041 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1042 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1043 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001044 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001045 StringAppendF(&result, "Vsync Period: %10f\n",
1046 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1047 nsecs_t presentDelta =
1048 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1049 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1050 StringAppendF(&result, "Present delta: %10f\n",
1051 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001052 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001053 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1054 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1055 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1056 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001057 StringAppendF(&result, "\n");
1058 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001059 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001060 surfaceFrame->dump(result, indent, baseTime);
1061 }
1062 StringAppendF(&result, "\n");
1063}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001064
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001065void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001066 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001067 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001068 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001069 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1070 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001071 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001072 }
1073}
1074
1075void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001076 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001077 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001078 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001079 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001080 }
1081}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001082
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001083void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1084 ATRACE_CALL();
1085 std::unordered_map<std::string, bool> argsMap;
1086 for (size_t i = 0; i < args.size(); i++) {
1087 argsMap[std::string(String8(args[i]).c_str())] = true;
1088 }
1089 if (argsMap.count("-jank")) {
1090 dumpJank(result);
1091 }
1092 if (argsMap.count("-all")) {
1093 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001094 }
1095}
1096
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001097void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001098 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001099
1100 // The size can either increase or decrease, clear everything, to be consistent
1101 mDisplayFrames.clear();
1102 mPendingPresentFences.clear();
1103 mMaxDisplayFrames = size;
1104}
1105
1106void FrameTimeline::reset() {
1107 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1108}
1109
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001110} // namespace impl
1111} // namespace android::frametimeline