blob: da04202ef279f0f1b9cdaa3baf88aaaf08a2448d [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);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000337 if (mPresentState == PresentState::Dropped) {
338 // Return no jank if it's a dropped frame since we cannot attribute a jank to a it.
339 return JankType::None;
340 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100341 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000342 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100343 return std::nullopt;
344 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700345 return mJankType;
346}
347
348nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000349 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800350 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700351}
352
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800353TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000354 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800355 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700356}
357
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000358PredictionState SurfaceFrame::getPredictionState() const {
359 std::scoped_lock lock(mMutex);
360 return mPredictionState;
361}
362
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800363SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000364 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800365 return mPresentState;
366}
367
368FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000369 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800370 return mFramePresentMetadata;
371}
372
373FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000374 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800375 return mFrameReadyMetadata;
376}
377
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000378nsecs_t SurfaceFrame::getDropTime() const {
379 std::scoped_lock lock(mMutex);
380 return mDropTime;
381}
382
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800383void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000384 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700385 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700386 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100387 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700388 // Easily identify a janky Surface Frame in the dump
389 StringAppendF(&result, " [*] ");
390 }
391 StringAppendF(&result, "\n");
392 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800393 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
394 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700395 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
396 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800397 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
398 mRenderRate ? mRenderRate->getIntValue() : 0);
399 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800400 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700401 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000402 if (mPresentState == PresentState::Dropped) {
403 std::chrono::nanoseconds dropTime(mDropTime - baseTime);
404 StringAppendF(&result, "Drop time : %10f\n",
405 std::chrono::duration<double, std::milli>(dropTime).count());
406 StringAppendF(&result, "%s", indent.c_str());
407 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700408 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
409 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800410 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700411 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800412 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
413 StringAppendF(&result, "%s", indent.c_str());
414 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
415 std::chrono::nanoseconds latchTime(
416 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
417 StringAppendF(&result, "%s", indent.c_str());
418 StringAppendF(&result, "Last latch time: %10f\n",
419 std::chrono::duration<double, std::milli>(latchTime).count());
420 if (mPredictionState == PredictionState::Valid) {
421 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
422 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
423 StringAppendF(&result, "%s", indent.c_str());
424 StringAppendF(&result, "Present delta: %10f\n",
425 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
426 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700427 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700428}
429
Alec Mouri363faf02021-01-29 16:34:55 -0800430void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
431 nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000432 std::scoped_lock lock(mMutex);
Alec Mouri7d436ec2021-01-27 20:40:50 -0800433
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800434 if (mPresentState != PresentState::Presented) {
435 // No need to update dropped buffers
436 return;
437 }
438
439 mActuals.presentTime = presentTime;
440 // Jank Analysis for SurfaceFrame
441 if (mPredictionState == PredictionState::None) {
442 // Cannot do jank classification on frames that don't have a token.
443 return;
444 }
445 if (mPredictionState == PredictionState::Expired) {
446 // We do not know what happened here to classify this correctly. This could
447 // potentially be AppDeadlineMissed but that's assuming no app will request frames
448 // 120ms apart.
449 mJankType = JankType::Unknown;
450 mFramePresentMetadata = FramePresentMetadata::UnknownPresent;
451 mFrameReadyMetadata = FrameReadyMetadata::UnknownFinish;
Alec Mouri363faf02021-01-29 16:34:55 -0800452 const constexpr nsecs_t kAppDeadlineDelta = -1;
453 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
454 mJankType, displayDeadlineDelta, displayPresentDelta,
455 kAppDeadlineDelta});
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800456 return;
457 }
458
459 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
460 const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800461 const nsecs_t deltaToVsync = std::abs(presentDelta) % refreshRate.getPeriodNsecs();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800462
463 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
464 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
465 } else {
466 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
467 }
468
469 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
470 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
471 : FramePresentMetadata::EarlyPresent;
472 } else {
473 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
474 }
475
476 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
477 // Frames presented on time are not janky.
478 mJankType = JankType::None;
479 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
480 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
481 // Finish on time, Present early
482 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800483 deltaToVsync >= refreshRate.getPeriodNsecs() -
484 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800485 // Delta factor of vsync
486 mJankType = JankType::SurfaceFlingerScheduling;
487 } else {
488 // Delta not a factor of vsync
489 mJankType = JankType::PredictionError;
490 }
491 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
492 // Finish late, Present early
493 mJankType = JankType::Unknown;
494 }
495 } else {
496 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
497 // Buffer Stuffing.
498 mJankType |= JankType::BufferStuffing;
499 }
500 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
501 // Finish on time, Present late
502 if (displayFrameJankType != JankType::None) {
503 // Propagate displayFrame's jank if it exists
504 mJankType |= displayFrameJankType;
505 } else {
506 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800507 deltaToVsync >= refreshRate.getPeriodNsecs() -
508 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800509 // Delta factor of vsync
510 mJankType |= JankType::SurfaceFlingerScheduling;
511 } else {
512 // Delta not a factor of vsync
513 mJankType |= JankType::PredictionError;
514 }
515 }
516 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
517 // Finish late, Present late
518 if (displayFrameJankType == JankType::None) {
519 // Display frame is not janky, so purely app's fault
520 mJankType |= JankType::AppDeadlineMissed;
521 } else {
522 // Propagate DisplayFrame's jankType if it is janky
523 mJankType |= displayFrameJankType;
524 }
525 }
526 }
Alec Mouri363faf02021-01-29 16:34:55 -0800527 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName, mJankType,
528 displayDeadlineDelta, displayPresentDelta, deadlineDelta});
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800529}
530
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000531void SurfaceFrame::tracePredictions(int64_t displayFrameToken) const {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000532 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000533
Adithya Srinivasan86678502021-01-19 21:50:38 +0000534 // Expected timeline start
535 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000536 std::scoped_lock lock(mMutex);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700537 auto packet = ctx.NewTracePacket();
538 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000539 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700540
541 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000542 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700543
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000544 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
545
546 expectedSurfaceFrameStartEvent->set_token(mToken);
547 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
548
549 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
550 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
551 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000552
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000553 // Expected timeline end
554 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000555 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000556 auto packet = ctx.NewTracePacket();
557 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
558 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
559
560 auto* event = packet->set_frame_timeline_event();
561 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
562
563 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
564 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000565}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000566
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000567void SurfaceFrame::traceActuals(int64_t displayFrameToken) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000568 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000569
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000570 // Actual timeline start
571 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000572 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000573 auto packet = ctx.NewTracePacket();
574 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
575 // Actual start time is not yet available, so use expected start instead
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000576 if (mPredictionState == PredictionState::Expired) {
577 // If prediction is expired, we can't use the predicted start time. Instead, just use a
578 // start time a little earlier than the end time so that we have some info about this
579 // frame in the trace.
580 packet->set_timestamp(
581 static_cast<uint64_t>(mActuals.endTime - kPredictionExpiredStartTimeDelta));
582 } else {
583 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
584 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000585
586 auto* event = packet->set_frame_timeline_event();
587 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
588
589 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
590
591 actualSurfaceFrameStartEvent->set_token(mToken);
592 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
593
594 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
595 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700596
597 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000598 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700599 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000600 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700601 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000602 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700603 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000604 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
605 FrameReadyMetadata::OnTimeFinish);
606 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
607 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
608 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000609
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000610 // Actual timeline end
611 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000612 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000613 auto packet = ctx.NewTracePacket();
614 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000615 if (mPresentState == PresentState::Dropped) {
616 packet->set_timestamp(static_cast<uint64_t>(mDropTime));
617 } else {
618 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
619 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700620
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000621 auto* event = packet->set_frame_timeline_event();
622 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700623
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000624 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700625 });
626}
627
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000628/**
629 * TODO(b/178637512): add inputEventId to the perfetto trace.
630 */
631void SurfaceFrame::trace(int64_t displayFrameToken) const {
632 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
633 displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
634 // No packets can be traced with a missing token.
635 return;
636 }
637 if (getPredictionState() != PredictionState::Expired) {
638 // Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
639 // a trace.
640 tracePredictions(displayFrameToken);
641 }
642 traceActuals(displayFrameToken);
643}
644
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800645namespace impl {
646
647int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
648 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000649 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800650 const int64_t assignedToken = mCurrentToken++;
651 mPredictions[assignedToken] = {systemTime(), predictions};
652 flushTokens(systemTime());
653 return assignedToken;
654}
655
656std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000657 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800658 auto predictionsIterator = mPredictions.find(token);
659 if (predictionsIterator != mPredictions.end()) {
660 return predictionsIterator->second.predictions;
661 }
662 return {};
663}
664
665void TokenManager::flushTokens(nsecs_t flushTime) {
666 for (auto it = mPredictions.begin(); it != mPredictions.end();) {
667 if (flushTime - it->second.timestamp >= kMaxRetentionTime) {
668 it = mPredictions.erase(it);
669 } else {
670 // Tokens are ordered by time. If i'th token is within the retention time, then the
671 // i+1'th token will also be within retention time.
672 break;
673 }
674 }
675}
676
677FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
678 JankClassificationThresholds thresholds)
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000679 : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800680 mTimeStats(std::move(timeStats)),
681 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000682 mJankClassificationThresholds(thresholds) {
683 mCurrentDisplayFrame =
684 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
685}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700686
Adithya Srinivasan01189672020-10-20 14:23:05 -0700687void FrameTimeline::onBootFinished() {
688 perfetto::TracingInitArgs args;
689 args.backends = perfetto::kSystemBackend;
690 perfetto::Tracing::Initialize(args);
691 registerDataSource();
692}
693
694void FrameTimeline::registerDataSource() {
695 perfetto::DataSourceDescriptor dsd;
696 dsd.set_name(kFrameTimelineDataSource);
697 FrameTimelineDataSource::Register(dsd);
698}
699
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800700std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000701 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
702 std::string layerName, std::string debugName) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700703 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000704 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
705 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
706 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800707 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000708 mJankClassificationThresholds, &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700709 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000710 std::optional<TimelineItem> predictions =
711 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700712 if (predictions) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000713 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
714 std::move(layerName), std::move(debugName),
715 PredictionState::Valid, std::move(*predictions),
716 mTimeStats, mJankClassificationThresholds,
717 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700718 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000719 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
720 std::move(layerName), std::move(debugName),
721 PredictionState::Expired, TimelineItem(), mTimeStats,
722 mJankClassificationThresholds, &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700723}
724
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800725FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000726 JankClassificationThresholds thresholds,
727 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800728 : mSurfaceFlingerPredictions(TimelineItem()),
729 mSurfaceFlingerActuals(TimelineItem()),
730 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000731 mJankClassificationThresholds(thresholds),
732 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800733 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700734}
735
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800736void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700737 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000738 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800739 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
740}
741
Alec Mouri7d436ec2021-01-27 20:40:50 -0800742void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800743 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000744 std::scoped_lock lock(mMutex);
Alec Mouri7d436ec2021-01-27 20:40:50 -0800745 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800746 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700747}
748
749void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
750 const std::shared_ptr<FenceTime>& presentFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700751 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000752 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800753 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700754 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
755 flushPendingPresentFences();
756 finalizeCurrentDisplayFrame();
757}
758
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800759void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
760 mSurfaceFrames.push_back(surfaceFrame);
761}
762
Alec Mouri7d436ec2021-01-27 20:40:50 -0800763void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800764 std::optional<TimelineItem> predictions,
765 nsecs_t wakeUpTime) {
766 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800767 mRefreshRate = refreshRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800768 if (!predictions) {
769 mPredictionState = PredictionState::Expired;
770 } else {
771 mPredictionState = PredictionState::Valid;
772 mSurfaceFlingerPredictions = *predictions;
773 }
774 mSurfaceFlingerActuals.startTime = wakeUpTime;
775}
776
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800777void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
778 TimelineItem predictions) {
779 mPredictionState = predictionState;
780 mSurfaceFlingerPredictions = predictions;
781}
782
783void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
784 mSurfaceFlingerActuals.startTime = actualStartTime;
785}
786
787void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
788 mSurfaceFlingerActuals.endTime = actualEndTime;
789}
790
791void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
792 mSurfaceFlingerActuals.presentTime = signalTime;
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000793 if (mPredictionState == PredictionState::Expired) {
794 // Cannot do jank classification with expired predictions
795 mJankType = JankType::Unknown;
796 return;
797 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800798
799 // Delta between the expected present and the actual present
800 const nsecs_t presentDelta =
801 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Alec Mouri363faf02021-01-29 16:34:55 -0800802 const nsecs_t deadlineDelta =
803 mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime;
804
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800805 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
806 // was a prediction error or not.
Alec Mouri7d436ec2021-01-27 20:40:50 -0800807 nsecs_t deltaToVsync = std::abs(presentDelta) % mRefreshRate.getPeriodNsecs();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800808 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
809 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
810 : FramePresentMetadata::EarlyPresent;
811 } else {
812 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
813 }
814
815 if (mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime >
816 mJankClassificationThresholds.deadlineThreshold) {
817 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
818 } else {
819 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
820 }
821
822 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
823 mJankClassificationThresholds.startThreshold) {
824 mFrameStartMetadata =
825 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
826 ? FrameStartMetadata::LateStart
827 : FrameStartMetadata::EarlyStart;
828 }
829
830 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
831 // Do jank classification only if present is not on time
832 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
833 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
834 // Finish on time, Present early
835 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800836 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
837 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800838 // Delta is a factor of vsync if its within the presentTheshold on either side
839 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
840 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
841 mJankType = JankType::SurfaceFlingerScheduling;
842 } else {
843 // Delta is not a factor of vsync,
844 mJankType = JankType::PredictionError;
845 }
846 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
847 // Finish late, Present early
848 mJankType = JankType::SurfaceFlingerScheduling;
849 } else {
850 // Finish time unknown
851 mJankType = JankType::Unknown;
852 }
853 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
854 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
855 // Finish on time, Present late
856 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800857 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
858 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800859 // Delta is a factor of vsync if its within the presentTheshold on either side
860 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
861 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
862 mJankType = JankType::DisplayHAL;
863 } else {
864 // Delta is not a factor of vsync
865 mJankType = JankType::PredictionError;
866 }
867 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
868 // Finish late, Present late
869 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
870 } else {
871 // Finish time unknown
872 mJankType = JankType::Unknown;
873 }
874 } else {
875 // Present unknown
876 mJankType = JankType::Unknown;
877 }
878 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800879 for (auto& surfaceFrame : mSurfaceFrames) {
Alec Mouri363faf02021-01-29 16:34:55 -0800880 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, deadlineDelta, deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800881 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800882}
883
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000884void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000885 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000886
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000887 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800888 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800889 auto packet = ctx.NewTracePacket();
890 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000891 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800892
893 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000894 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800895
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000896 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800897
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000898 expectedDisplayFrameStartEvent->set_token(mToken);
899 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
900 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000901
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000902 // Expected timeline end
903 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
904 auto packet = ctx.NewTracePacket();
905 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
906 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800907
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000908 auto* event = packet->set_frame_timeline_event();
909 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800910
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000911 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
912 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000913}
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000914
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000915void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000916 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000917
918 // Actual timeline start
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000919 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
920 auto packet = ctx.NewTracePacket();
921 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
922 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.startTime));
923
924 auto* event = packet->set_frame_timeline_event();
925 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
926
927 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
928
929 actualDisplayFrameStartEvent->set_token(mToken);
930 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
931
932 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
933 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
934 FrameReadyMetadata::OnTimeFinish);
935 actualDisplayFrameStartEvent->set_gpu_composition(mGpuComposition);
936 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
937 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000938
939 // Actual timeline end
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000940 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
941 auto packet = ctx.NewTracePacket();
942 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
943 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.endTime));
944
945 auto* event = packet->set_frame_timeline_event();
946 auto* actualDisplayFrameEndEvent = event->set_frame_end();
947
948 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800949 });
Adithya Srinivasan061c14c2021-02-11 01:19:47 +0000950}
951
952void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const {
953 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
954 // DisplayFrame should not have an invalid token.
955 ALOGE("Cannot trace DisplayFrame with invalid token");
956 return;
957 }
958
959 if (mPredictionState == PredictionState::Valid) {
960 // Expired and unknown predictions have zeroed timestamps. This cannot be used in any
961 // meaningful way in a trace.
962 tracePredictions(surfaceFlingerPid);
963 }
964 traceActuals(surfaceFlingerPid);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800965
966 for (auto& surfaceFrame : mSurfaceFrames) {
967 surfaceFrame->trace(mToken);
968 }
969}
970
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700971void FrameTimeline::flushPendingPresentFences() {
972 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
973 const auto& pendingPresentFence = mPendingPresentFences[i];
974 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
975 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
976 signalTime = pendingPresentFence.first->getSignalTime();
977 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
978 continue;
979 }
980 }
981 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
982 auto& displayFrame = pendingPresentFence.second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800983 displayFrame->onPresent(signalTime);
984 displayFrame->trace(mSurfaceFlingerPid);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700985 }
986
987 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
988 --i;
989 }
990}
991
992void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700993 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700994 // We maintain only a fixed number of frames' data. Pop older frames
995 mDisplayFrames.pop_front();
996 }
997 mDisplayFrames.push_back(mCurrentDisplayFrame);
998 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000999 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
1000 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001001}
1002
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001003nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
1004 nsecs_t baseTime =
1005 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
1006 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001007 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
1008 if (surfaceFrameBaseTime != 0) {
1009 baseTime = std::min(baseTime, surfaceFrameBaseTime);
1010 }
1011 }
1012 return baseTime;
1013}
1014
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001015void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
1016 int displayFrameCount) const {
1017 if (mJankType == JankType::None) {
1018 // Check if any Surface Frame has been janky
1019 bool isJanky = false;
1020 for (const auto& surfaceFrame : mSurfaceFrames) {
1021 if (surfaceFrame->getJankType() != JankType::None) {
1022 isJanky = true;
1023 break;
1024 }
1025 }
1026 if (!isJanky) {
1027 return;
1028 }
1029 }
1030 StringAppendF(&result, "Display Frame %d", displayFrameCount);
1031 dump(result, baseTime);
1032}
1033
1034void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
1035 dump(result, baseTime);
1036}
1037
1038void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
1039 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001040 // Easily identify a janky Display Frame in the dump
1041 StringAppendF(&result, " [*] ");
1042 }
1043 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001044 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
1045 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
1046 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
1047 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1048 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001049 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001050 StringAppendF(&result, "Vsync Period: %10f\n",
1051 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1052 nsecs_t presentDelta =
1053 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1054 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1055 StringAppendF(&result, "Present delta: %10f\n",
1056 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001057 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001058 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1059 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1060 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1061 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001062 StringAppendF(&result, "\n");
1063 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001064 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001065 surfaceFrame->dump(result, indent, baseTime);
1066 }
1067 StringAppendF(&result, "\n");
1068}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001069
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001070void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001071 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001072 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001073 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001074 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1075 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001076 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001077 }
1078}
1079
1080void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001081 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001082 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001083 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001084 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001085 }
1086}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001087
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001088void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1089 ATRACE_CALL();
1090 std::unordered_map<std::string, bool> argsMap;
1091 for (size_t i = 0; i < args.size(); i++) {
1092 argsMap[std::string(String8(args[i]).c_str())] = true;
1093 }
1094 if (argsMap.count("-jank")) {
1095 dumpJank(result);
1096 }
1097 if (argsMap.count("-all")) {
1098 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001099 }
1100}
1101
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001102void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001103 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001104
1105 // The size can either increase or decrease, clear everything, to be consistent
1106 mDisplayFrames.clear();
1107 mPendingPresentFences.clear();
1108 mMaxDisplayFrames = size;
1109}
1110
1111void FrameTimeline::reset() {
1112 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1113}
1114
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001115} // namespace impl
1116} // namespace android::frametimeline