blob: 0a40388fc66ad6bce086962412843590ae37c433 [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 Srinivasanf279e042020-08-17 14:56:27 -070033
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070034void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
35 const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
36 StringAppendF(&result, "%s", indent.c_str());
37 StringAppendF(&result, "\t\t");
38 StringAppendF(&result, " Start time\t\t|");
39 StringAppendF(&result, " End time\t\t|");
40 StringAppendF(&result, " Present time\n");
41 if (predictionState == PredictionState::Valid) {
42 // Dump the Predictions only if they are valid
43 StringAppendF(&result, "%s", indent.c_str());
44 StringAppendF(&result, "Expected\t|");
45 std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
46 std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
47 std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
48 StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
49 std::chrono::duration<double, std::milli>(startTime).count(),
50 std::chrono::duration<double, std::milli>(endTime).count(),
51 std::chrono::duration<double, std::milli>(presentTime).count());
52 }
53 StringAppendF(&result, "%s", indent.c_str());
54 StringAppendF(&result, "Actual \t|");
55
56 if (actuals.startTime == 0) {
57 StringAppendF(&result, "\t\tN/A\t|");
58 } else {
59 std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
60 StringAppendF(&result, "\t%10.2f\t|",
61 std::chrono::duration<double, std::milli>(startTime).count());
62 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080063 if (actuals.endTime <= 0) {
64 // Animation leashes can send the endTime as -1
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070065 StringAppendF(&result, "\t\tN/A\t|");
66 } else {
67 std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
68 StringAppendF(&result, "\t%10.2f\t|",
69 std::chrono::duration<double, std::milli>(endTime).count());
70 }
71 if (actuals.presentTime == 0) {
72 StringAppendF(&result, "\t\tN/A\n");
73 } else {
74 std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
75 StringAppendF(&result, "\t%10.2f\n",
76 std::chrono::duration<double, std::milli>(presentTime).count());
77 }
78
79 StringAppendF(&result, "%s", indent.c_str());
80 StringAppendF(&result, "----------------------");
81 StringAppendF(&result, "----------------------");
82 StringAppendF(&result, "----------------------");
83 StringAppendF(&result, "----------------------\n");
84}
85
86std::string toString(PredictionState predictionState) {
87 switch (predictionState) {
88 case PredictionState::Valid:
89 return "Valid";
90 case PredictionState::Expired:
91 return "Expired";
92 case PredictionState::None:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070093 return "None";
94 }
95}
96
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080097std::string jankTypeBitmaskToString(int32_t jankType) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -080098 if (jankType == JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070099 return "None";
100 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000101
102 std::vector<std::string> janks;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800103 if (jankType & JankType::DisplayHAL) {
104 janks.emplace_back("Display HAL");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000105 jankType &= ~JankType::DisplayHAL;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800106 }
107 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
108 janks.emplace_back("SurfaceFlinger CPU Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000109 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800110 }
111 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
112 janks.emplace_back("SurfaceFlinger GPU Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000113 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800114 }
115 if (jankType & JankType::AppDeadlineMissed) {
116 janks.emplace_back("App Deadline Missed");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000117 jankType &= ~JankType::AppDeadlineMissed;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800118 }
119 if (jankType & JankType::PredictionError) {
120 janks.emplace_back("Prediction Error");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000121 jankType &= ~JankType::PredictionError;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800122 }
123 if (jankType & JankType::SurfaceFlingerScheduling) {
124 janks.emplace_back("SurfaceFlinger Scheduling");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000125 jankType &= ~JankType::SurfaceFlingerScheduling;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800126 }
127 if (jankType & JankType::BufferStuffing) {
128 janks.emplace_back("Buffer Stuffing");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000129 jankType &= ~JankType::BufferStuffing;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800130 }
131 if (jankType & JankType::Unknown) {
132 janks.emplace_back("Unknown jank");
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000133 jankType &= ~JankType::Unknown;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800134 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000135
136 // jankType should be 0 if all types of jank were checked for.
137 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800138 return std::accumulate(janks.begin(), janks.end(), std::string(),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700139 [](const std::string& l, const std::string& r) {
140 return l.empty() ? r : l + ", " + r;
141 });
142}
143
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800144std::string toString(FramePresentMetadata presentMetadata) {
145 switch (presentMetadata) {
146 case FramePresentMetadata::OnTimePresent:
147 return "On Time Present";
148 case FramePresentMetadata::LatePresent:
149 return "Late Present";
150 case FramePresentMetadata::EarlyPresent:
151 return "Early Present";
152 case FramePresentMetadata::UnknownPresent:
153 return "Unknown Present";
Adithya Srinivasan01189672020-10-20 14:23:05 -0700154 }
Adithya Srinivasan01189672020-10-20 14:23:05 -0700155}
156
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800157std::string toString(FrameReadyMetadata finishMetadata) {
158 switch (finishMetadata) {
159 case FrameReadyMetadata::OnTimeFinish:
160 return "On Time Finish";
161 case FrameReadyMetadata::LateFinish:
162 return "Late Finish";
163 case FrameReadyMetadata::UnknownFinish:
164 return "Unknown Finish";
165 }
166}
167
168std::string toString(FrameStartMetadata startMetadata) {
169 switch (startMetadata) {
170 case FrameStartMetadata::OnTimeStart:
171 return "On Time Start";
172 case FrameStartMetadata::LateStart:
173 return "Late Start";
174 case FrameStartMetadata::EarlyStart:
175 return "Early Start";
176 case FrameStartMetadata::UnknownStart:
177 return "Unknown Start";
178 }
179}
180
181std::string toString(SurfaceFrame::PresentState presentState) {
182 using PresentState = SurfaceFrame::PresentState;
183 switch (presentState) {
184 case PresentState::Presented:
185 return "Presented";
186 case PresentState::Dropped:
187 return "Dropped";
188 case PresentState::Unknown:
189 return "Unknown";
190 }
191}
192
193FrameTimelineEvent::PresentType toProto(FramePresentMetadata presentMetadata) {
194 switch (presentMetadata) {
195 case FramePresentMetadata::EarlyPresent:
196 return FrameTimelineEvent::PRESENT_EARLY;
197 case FramePresentMetadata::LatePresent:
198 return FrameTimelineEvent::PRESENT_LATE;
199 case FramePresentMetadata::OnTimePresent:
200 return FrameTimelineEvent::PRESENT_ON_TIME;
201 case FramePresentMetadata::UnknownPresent:
202 return FrameTimelineEvent::PRESENT_UNSPECIFIED;
203 }
204}
205
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000206int32_t jankTypeBitmaskToProto(int32_t jankType) {
207 if (jankType == JankType::None) {
208 return FrameTimelineEvent::JANK_NONE;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700209 }
Adithya Srinivasan552e2a72021-01-15 03:21:53 +0000210
211 int32_t protoJank = 0;
212 if (jankType & JankType::DisplayHAL) {
213 protoJank |= FrameTimelineEvent::JANK_DISPLAY_HAL;
214 jankType &= ~JankType::DisplayHAL;
215 }
216 if (jankType & JankType::SurfaceFlingerCpuDeadlineMissed) {
217 protoJank |= FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED;
218 jankType &= ~JankType::SurfaceFlingerCpuDeadlineMissed;
219 }
220 if (jankType & JankType::SurfaceFlingerGpuDeadlineMissed) {
221 protoJank |= FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED;
222 jankType &= ~JankType::SurfaceFlingerGpuDeadlineMissed;
223 }
224 if (jankType & JankType::AppDeadlineMissed) {
225 protoJank |= FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
226 jankType &= ~JankType::AppDeadlineMissed;
227 }
228 if (jankType & JankType::PredictionError) {
229 protoJank |= FrameTimelineEvent::JANK_PREDICTION_ERROR;
230 jankType &= ~JankType::PredictionError;
231 }
232 if (jankType & JankType::SurfaceFlingerScheduling) {
233 protoJank |= FrameTimelineEvent::JANK_SF_SCHEDULING;
234 jankType &= ~JankType::SurfaceFlingerScheduling;
235 }
236 if (jankType & JankType::BufferStuffing) {
237 protoJank |= FrameTimelineEvent::JANK_BUFFER_STUFFING;
238 jankType &= ~JankType::BufferStuffing;
239 }
240 if (jankType & JankType::Unknown) {
241 protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
242 jankType &= ~JankType::Unknown;
243 }
244
245 // jankType should be 0 if all types of jank were checked for.
246 LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
247 return protoJank;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700248}
249
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800250// Returns the smallest timestamp from the set of predictions and actuals.
251nsecs_t getMinTime(PredictionState predictionState, TimelineItem predictions,
252 TimelineItem actuals) {
253 nsecs_t minTime = std::numeric_limits<nsecs_t>::max();
254 if (predictionState == PredictionState::Valid) {
255 // Checking start time for predictions is enough because start time is always lesser than
256 // endTime and presentTime.
257 minTime = std::min(minTime, predictions.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700258 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700259
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800260 // Need to check startTime, endTime and presentTime for actuals because some frames might not
261 // have them set.
262 if (actuals.startTime != 0) {
263 minTime = std::min(minTime, actuals.startTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700264 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800265 if (actuals.endTime != 0) {
266 minTime = std::min(minTime, actuals.endTime);
267 }
268 if (actuals.presentTime != 0) {
269 minTime = std::min(minTime, actuals.endTime);
270 }
271 return minTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700272}
273
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000274int64_t TraceCookieCounter::getCookieForTracing() {
275 return ++mTraceCookie;
276}
277
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000278SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
279 uid_t ownerUid, std::string layerName, std::string debugName,
280 PredictionState predictionState,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800281 frametimeline::TimelineItem&& predictions,
282 std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000283 JankClassificationThresholds thresholds,
284 TraceCookieCounter* traceCookieCounter)
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000285 : mToken(frameTimelineInfo.vsyncId),
286 mInputEventId(frameTimelineInfo.inputEventId),
Adithya Srinivasan01189672020-10-20 14:23:05 -0700287 mOwnerPid(ownerPid),
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700288 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700289 mLayerName(std::move(layerName)),
290 mDebugName(std::move(debugName)),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700291 mPresentState(PresentState::Unknown),
292 mPredictionState(predictionState),
293 mPredictions(predictions),
294 mActuals({0, 0, 0}),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800295 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000296 mJankClassificationThresholds(thresholds),
297 mTraceCookieCounter(*traceCookieCounter) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700298
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700299void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000300 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700301 mActuals.startTime = actualStartTime;
302}
303
304void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000305 std::scoped_lock lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700306 mActualQueueTime = actualQueueTime;
307}
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700308void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000309 std::scoped_lock lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700310 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700311}
312
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800313void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000314 std::scoped_lock lock(mMutex);
Adithya Srinivasanb9a7dab2021-01-14 23:49:46 +0000315 LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
316 "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
317 "PresentState - %s set already.",
318 mDebugName.c_str(), toString(mPresentState).c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800319 mPresentState = presentState;
320 mLastLatchTime = lastLatchTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700321}
322
Alec Mouri7d436ec2021-01-27 20:40:50 -0800323void SurfaceFrame::setRenderRate(Fps renderRate) {
324 std::lock_guard<std::mutex> lock(mMutex);
325 mRenderRate = renderRate;
326}
327
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800328std::optional<int32_t> SurfaceFrame::getJankType() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000329 std::scoped_lock lock(mMutex);
Adithya Srinivasan95619432021-02-08 21:52:51 +0000330 if (mPresentState == PresentState::Dropped) {
331 // Return no jank if it's a dropped frame since we cannot attribute a jank to a it.
332 return JankType::None;
333 }
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100334 if (mActuals.presentTime == 0) {
Adithya Srinivasan95619432021-02-08 21:52:51 +0000335 // Frame hasn't been presented yet.
Jorim Jaggi9c03b502020-11-24 23:51:31 +0100336 return std::nullopt;
337 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700338 return mJankType;
339}
340
341nsecs_t SurfaceFrame::getBaseTime() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000342 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800343 return getMinTime(mPredictionState, mPredictions, mActuals);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700344}
345
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800346TimelineItem SurfaceFrame::getActuals() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000347 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800348 return mActuals;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700349}
350
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800351SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000352 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800353 return mPresentState;
354}
355
356FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000357 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800358 return mFramePresentMetadata;
359}
360
361FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000362 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800363 return mFrameReadyMetadata;
364}
365
366void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000367 std::scoped_lock lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700368 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700369 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
Jorim Jaggi5814ab82020-12-03 20:45:58 +0100370 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700371 // Easily identify a janky Surface Frame in the dump
372 StringAppendF(&result, " [*] ");
373 }
374 StringAppendF(&result, "\n");
375 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800376 StringAppendF(&result, "Token: %" PRId64 "\n", mToken);
377 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700378 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
379 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -0800380 StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
381 mRenderRate ? mRenderRate->getIntValue() : 0);
382 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800383 StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700384 StringAppendF(&result, "%s", indent.c_str());
385 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
386 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800387 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700388 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800389 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
390 StringAppendF(&result, "%s", indent.c_str());
391 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
392 std::chrono::nanoseconds latchTime(
393 std::max(static_cast<int64_t>(0), mLastLatchTime - baseTime));
394 StringAppendF(&result, "%s", indent.c_str());
395 StringAppendF(&result, "Last latch time: %10f\n",
396 std::chrono::duration<double, std::milli>(latchTime).count());
397 if (mPredictionState == PredictionState::Valid) {
398 nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
399 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
400 StringAppendF(&result, "%s", indent.c_str());
401 StringAppendF(&result, "Present delta: %10f\n",
402 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
403 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700404 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700405}
406
Alec Mouri363faf02021-01-29 16:34:55 -0800407void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
408 nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000409 std::scoped_lock lock(mMutex);
Alec Mouri7d436ec2021-01-27 20:40:50 -0800410
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800411 if (mPresentState != PresentState::Presented) {
412 // No need to update dropped buffers
413 return;
414 }
415
416 mActuals.presentTime = presentTime;
417 // Jank Analysis for SurfaceFrame
418 if (mPredictionState == PredictionState::None) {
419 // Cannot do jank classification on frames that don't have a token.
420 return;
421 }
422 if (mPredictionState == PredictionState::Expired) {
423 // We do not know what happened here to classify this correctly. This could
424 // potentially be AppDeadlineMissed but that's assuming no app will request frames
425 // 120ms apart.
426 mJankType = JankType::Unknown;
427 mFramePresentMetadata = FramePresentMetadata::UnknownPresent;
428 mFrameReadyMetadata = FrameReadyMetadata::UnknownFinish;
Alec Mouri363faf02021-01-29 16:34:55 -0800429 const constexpr nsecs_t kAppDeadlineDelta = -1;
430 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
431 mJankType, displayDeadlineDelta, displayPresentDelta,
432 kAppDeadlineDelta});
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800433 return;
434 }
435
436 const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
437 const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800438 const nsecs_t deltaToVsync = std::abs(presentDelta) % refreshRate.getPeriodNsecs();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800439
440 if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
441 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
442 } else {
443 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
444 }
445
446 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
447 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
448 : FramePresentMetadata::EarlyPresent;
449 } else {
450 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
451 }
452
453 if (mFramePresentMetadata == FramePresentMetadata::OnTimePresent) {
454 // Frames presented on time are not janky.
455 mJankType = JankType::None;
456 } else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
457 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
458 // Finish on time, Present early
459 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800460 deltaToVsync >= refreshRate.getPeriodNsecs() -
461 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800462 // Delta factor of vsync
463 mJankType = JankType::SurfaceFlingerScheduling;
464 } else {
465 // Delta not a factor of vsync
466 mJankType = JankType::PredictionError;
467 }
468 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
469 // Finish late, Present early
470 mJankType = JankType::Unknown;
471 }
472 } else {
473 if (mLastLatchTime != 0 && mPredictions.endTime <= mLastLatchTime) {
474 // Buffer Stuffing.
475 mJankType |= JankType::BufferStuffing;
476 }
477 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
478 // Finish on time, Present late
479 if (displayFrameJankType != JankType::None) {
480 // Propagate displayFrame's jank if it exists
481 mJankType |= displayFrameJankType;
482 } else {
483 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800484 deltaToVsync >= refreshRate.getPeriodNsecs() -
485 mJankClassificationThresholds.presentThreshold) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800486 // Delta factor of vsync
487 mJankType |= JankType::SurfaceFlingerScheduling;
488 } else {
489 // Delta not a factor of vsync
490 mJankType |= JankType::PredictionError;
491 }
492 }
493 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
494 // Finish late, Present late
495 if (displayFrameJankType == JankType::None) {
496 // Display frame is not janky, so purely app's fault
497 mJankType |= JankType::AppDeadlineMissed;
498 } else {
499 // Propagate DisplayFrame's jankType if it is janky
500 mJankType |= displayFrameJankType;
501 }
502 }
503 }
Alec Mouri363faf02021-01-29 16:34:55 -0800504 mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName, mJankType,
505 displayDeadlineDelta, displayPresentDelta, deadlineDelta});
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800506}
507
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000508/**
509 * TODO(b/178637512): add inputEventId to the perfetto trace.
510 */
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800511void SurfaceFrame::trace(int64_t displayFrameToken) {
512 using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
Adithya Srinivasan86678502021-01-19 21:50:38 +0000513
514 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
515 bool missingToken = false;
516 // Expected timeline start
517 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000518 std::scoped_lock lock(mMutex);
519 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
Adithya Srinivasan01189672020-10-20 14:23:05 -0700520 ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str());
Adithya Srinivasan86678502021-01-19 21:50:38 +0000521 missingToken = true;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700522 return;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000523 } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
Adithya Srinivasan01189672020-10-20 14:23:05 -0700524 ALOGD("Cannot trace SurfaceFrame - %s with invalid displayFrameToken",
525 mLayerName.c_str());
Adithya Srinivasan86678502021-01-19 21:50:38 +0000526 missingToken = true;
Adithya Srinivasan01189672020-10-20 14:23:05 -0700527 return;
528 }
529 auto packet = ctx.NewTracePacket();
530 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000531 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700532
533 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000534 auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700535
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000536 expectedSurfaceFrameStartEvent->set_cookie(expectedTimelineCookie);
537
538 expectedSurfaceFrameStartEvent->set_token(mToken);
539 expectedSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
540
541 expectedSurfaceFrameStartEvent->set_pid(mOwnerPid);
542 expectedSurfaceFrameStartEvent->set_layer_name(mDebugName);
543 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000544
545 if (missingToken) {
546 // If one packet can't be traced because of missing token, then no packets can be traced.
547 // Exit early in this case.
548 return;
549 }
550
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000551 // Expected timeline end
552 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000553 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000554 auto packet = ctx.NewTracePacket();
555 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
556 packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
557
558 auto* event = packet->set_frame_timeline_event();
559 auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
560
561 expectedSurfaceFrameEndEvent->set_cookie(expectedTimelineCookie);
562 });
563
564 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
565 // 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
571 packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
572
573 auto* event = packet->set_frame_timeline_event();
574 auto* actualSurfaceFrameStartEvent = event->set_actual_surface_frame_start();
575
576 actualSurfaceFrameStartEvent->set_cookie(actualTimelineCookie);
577
578 actualSurfaceFrameStartEvent->set_token(mToken);
579 actualSurfaceFrameStartEvent->set_display_frame_token(displayFrameToken);
580
581 actualSurfaceFrameStartEvent->set_pid(mOwnerPid);
582 actualSurfaceFrameStartEvent->set_layer_name(mDebugName);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700583
584 if (mPresentState == PresentState::Dropped) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000585 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_DROPPED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700586 } else if (mPresentState == PresentState::Unknown) {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000587 actualSurfaceFrameStartEvent->set_present_type(FrameTimelineEvent::PRESENT_UNSPECIFIED);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700588 } else {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000589 actualSurfaceFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700590 }
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000591 actualSurfaceFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
592 FrameReadyMetadata::OnTimeFinish);
593 actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition);
594 actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
595 });
596 // Actual timeline end
597 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000598 std::scoped_lock lock(mMutex);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000599 auto packet = ctx.NewTracePacket();
600 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
601 packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
Adithya Srinivasan01189672020-10-20 14:23:05 -0700602
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000603 auto* event = packet->set_frame_timeline_event();
604 auto* actualSurfaceFrameEndEvent = event->set_frame_end();
Adithya Srinivasan01189672020-10-20 14:23:05 -0700605
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000606 actualSurfaceFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan01189672020-10-20 14:23:05 -0700607 });
608}
609
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800610namespace impl {
611
612int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
613 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000614 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800615 const int64_t assignedToken = mCurrentToken++;
616 mPredictions[assignedToken] = {systemTime(), predictions};
617 flushTokens(systemTime());
618 return assignedToken;
619}
620
621std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000622 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800623 auto predictionsIterator = mPredictions.find(token);
624 if (predictionsIterator != mPredictions.end()) {
625 return predictionsIterator->second.predictions;
626 }
627 return {};
628}
629
630void TokenManager::flushTokens(nsecs_t flushTime) {
631 for (auto it = mPredictions.begin(); it != mPredictions.end();) {
632 if (flushTime - it->second.timestamp >= kMaxRetentionTime) {
633 it = mPredictions.erase(it);
634 } else {
635 // Tokens are ordered by time. If i'th token is within the retention time, then the
636 // i+1'th token will also be within retention time.
637 break;
638 }
639 }
640}
641
642FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
643 JankClassificationThresholds thresholds)
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000644 : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800645 mTimeStats(std::move(timeStats)),
646 mSurfaceFlingerPid(surfaceFlingerPid),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000647 mJankClassificationThresholds(thresholds) {
648 mCurrentDisplayFrame =
649 std::make_shared<DisplayFrame>(mTimeStats, thresholds, &mTraceCookieCounter);
650}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700651
Adithya Srinivasan01189672020-10-20 14:23:05 -0700652void FrameTimeline::onBootFinished() {
653 perfetto::TracingInitArgs args;
654 args.backends = perfetto::kSystemBackend;
655 perfetto::Tracing::Initialize(args);
656 registerDataSource();
657}
658
659void FrameTimeline::registerDataSource() {
660 perfetto::DataSourceDescriptor dsd;
661 dsd.set_name(kFrameTimelineDataSource);
662 FrameTimelineDataSource::Register(dsd);
663}
664
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800665std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000666 const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
667 std::string layerName, std::string debugName) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700668 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000669 if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
670 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
671 std::move(layerName), std::move(debugName),
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800672 PredictionState::None, TimelineItem(), mTimeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000673 mJankClassificationThresholds, &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700674 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000675 std::optional<TimelineItem> predictions =
676 mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700677 if (predictions) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000678 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
679 std::move(layerName), std::move(debugName),
680 PredictionState::Valid, std::move(*predictions),
681 mTimeStats, mJankClassificationThresholds,
682 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700683 }
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000684 return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
685 std::move(layerName), std::move(debugName),
686 PredictionState::Expired, TimelineItem(), mTimeStats,
687 mJankClassificationThresholds, &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700688}
689
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800690FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000691 JankClassificationThresholds thresholds,
692 TraceCookieCounter* traceCookieCounter)
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800693 : mSurfaceFlingerPredictions(TimelineItem()),
694 mSurfaceFlingerActuals(TimelineItem()),
695 mTimeStats(timeStats),
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000696 mJankClassificationThresholds(thresholds),
697 mTraceCookieCounter(*traceCookieCounter) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800698 mSurfaceFrames.reserve(kNumSurfaceFramesInitial);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700699}
700
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800701void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700702 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000703 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800704 mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
705}
706
Alec Mouri7d436ec2021-01-27 20:40:50 -0800707void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800708 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000709 std::scoped_lock lock(mMutex);
Alec Mouri7d436ec2021-01-27 20:40:50 -0800710 mCurrentDisplayFrame->onSfWakeUp(token, refreshRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800711 mTokenManager.getPredictionsForToken(token), wakeUpTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700712}
713
714void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
715 const std::shared_ptr<FenceTime>& presentFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700716 ATRACE_CALL();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000717 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800718 mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700719 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
720 flushPendingPresentFences();
721 finalizeCurrentDisplayFrame();
722}
723
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800724void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
725 mSurfaceFrames.push_back(surfaceFrame);
726}
727
Alec Mouri7d436ec2021-01-27 20:40:50 -0800728void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate,
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800729 std::optional<TimelineItem> predictions,
730 nsecs_t wakeUpTime) {
731 mToken = token;
Alec Mouri7d436ec2021-01-27 20:40:50 -0800732 mRefreshRate = refreshRate;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800733 if (!predictions) {
734 mPredictionState = PredictionState::Expired;
735 } else {
736 mPredictionState = PredictionState::Valid;
737 mSurfaceFlingerPredictions = *predictions;
738 }
739 mSurfaceFlingerActuals.startTime = wakeUpTime;
740}
741
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800742void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
743 TimelineItem predictions) {
744 mPredictionState = predictionState;
745 mSurfaceFlingerPredictions = predictions;
746}
747
748void FrameTimeline::DisplayFrame::setActualStartTime(nsecs_t actualStartTime) {
749 mSurfaceFlingerActuals.startTime = actualStartTime;
750}
751
752void FrameTimeline::DisplayFrame::setActualEndTime(nsecs_t actualEndTime) {
753 mSurfaceFlingerActuals.endTime = actualEndTime;
754}
755
756void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
757 mSurfaceFlingerActuals.presentTime = signalTime;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800758
759 // Delta between the expected present and the actual present
760 const nsecs_t presentDelta =
761 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
Alec Mouri363faf02021-01-29 16:34:55 -0800762 const nsecs_t deadlineDelta =
763 mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime;
764
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800765 // How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
766 // was a prediction error or not.
Alec Mouri7d436ec2021-01-27 20:40:50 -0800767 nsecs_t deltaToVsync = std::abs(presentDelta) % mRefreshRate.getPeriodNsecs();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800768 if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
769 mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
770 : FramePresentMetadata::EarlyPresent;
771 } else {
772 mFramePresentMetadata = FramePresentMetadata::OnTimePresent;
773 }
774
775 if (mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime >
776 mJankClassificationThresholds.deadlineThreshold) {
777 mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
778 } else {
779 mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
780 }
781
782 if (std::abs(mSurfaceFlingerActuals.startTime - mSurfaceFlingerPredictions.startTime) >
783 mJankClassificationThresholds.startThreshold) {
784 mFrameStartMetadata =
785 mSurfaceFlingerActuals.startTime > mSurfaceFlingerPredictions.startTime
786 ? FrameStartMetadata::LateStart
787 : FrameStartMetadata::EarlyStart;
788 }
789
790 if (mFramePresentMetadata != FramePresentMetadata::OnTimePresent) {
791 // Do jank classification only if present is not on time
792 if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
793 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
794 // Finish on time, Present early
795 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800796 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
797 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800798 // Delta is a factor of vsync if its within the presentTheshold on either side
799 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
800 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
801 mJankType = JankType::SurfaceFlingerScheduling;
802 } else {
803 // Delta is not a factor of vsync,
804 mJankType = JankType::PredictionError;
805 }
806 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
807 // Finish late, Present early
808 mJankType = JankType::SurfaceFlingerScheduling;
809 } else {
810 // Finish time unknown
811 mJankType = JankType::Unknown;
812 }
813 } else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
814 if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
815 // Finish on time, Present late
816 if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
Alec Mouri7d436ec2021-01-27 20:40:50 -0800817 deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
818 mJankClassificationThresholds.presentThreshold)) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800819 // Delta is a factor of vsync if its within the presentTheshold on either side
820 // of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
821 // of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
822 mJankType = JankType::DisplayHAL;
823 } else {
824 // Delta is not a factor of vsync
825 mJankType = JankType::PredictionError;
826 }
827 } else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
828 // Finish late, Present late
829 mJankType = JankType::SurfaceFlingerCpuDeadlineMissed;
830 } else {
831 // Finish time unknown
832 mJankType = JankType::Unknown;
833 }
834 } else {
835 // Present unknown
836 mJankType = JankType::Unknown;
837 }
838 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800839 for (auto& surfaceFrame : mSurfaceFrames) {
Alec Mouri363faf02021-01-29 16:34:55 -0800840 surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, deadlineDelta, deltaToVsync);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800841 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800842}
843
844void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const {
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000845 int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
Adithya Srinivasan86678502021-01-19 21:50:38 +0000846 bool missingToken = false;
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000847 // Expected timeline start
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800848 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800849 auto packet = ctx.NewTracePacket();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000850 if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
Adithya Srinivasan86678502021-01-19 21:50:38 +0000851 ALOGD("Cannot trace DisplayFrame with invalid token");
852 missingToken = true;
853 return;
854 }
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800855 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000856 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800857
858 auto* event = packet->set_frame_timeline_event();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000859 auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800860
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000861 expectedDisplayFrameStartEvent->set_cookie(expectedTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800862
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000863 expectedDisplayFrameStartEvent->set_token(mToken);
864 expectedDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
865 });
Adithya Srinivasan86678502021-01-19 21:50:38 +0000866
867 if (missingToken) {
868 // If one packet can't be traced because of missing token, then no packets can be traced.
869 // Exit early in this case.
870 return;
871 }
872
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000873 // Expected timeline end
874 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
875 auto packet = ctx.NewTracePacket();
876 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
877 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800878
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000879 auto* event = packet->set_frame_timeline_event();
880 auto* expectedDisplayFrameEndEvent = event->set_frame_end();
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800881
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000882 expectedDisplayFrameEndEvent->set_cookie(expectedTimelineCookie);
883 });
884
885 int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
886 // Expected timeline start
887 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
888 auto packet = ctx.NewTracePacket();
889 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
890 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.startTime));
891
892 auto* event = packet->set_frame_timeline_event();
893 auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
894
895 actualDisplayFrameStartEvent->set_cookie(actualTimelineCookie);
896
897 actualDisplayFrameStartEvent->set_token(mToken);
898 actualDisplayFrameStartEvent->set_pid(surfaceFlingerPid);
899
900 actualDisplayFrameStartEvent->set_present_type(toProto(mFramePresentMetadata));
901 actualDisplayFrameStartEvent->set_on_time_finish(mFrameReadyMetadata ==
902 FrameReadyMetadata::OnTimeFinish);
903 actualDisplayFrameStartEvent->set_gpu_composition(mGpuComposition);
904 actualDisplayFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType));
905 });
906 // Expected timeline end
907 FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
908 auto packet = ctx.NewTracePacket();
909 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
910 packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.endTime));
911
912 auto* event = packet->set_frame_timeline_event();
913 auto* actualDisplayFrameEndEvent = event->set_frame_end();
914
915 actualDisplayFrameEndEvent->set_cookie(actualTimelineCookie);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800916 });
917
918 for (auto& surfaceFrame : mSurfaceFrames) {
919 surfaceFrame->trace(mToken);
920 }
921}
922
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700923void FrameTimeline::flushPendingPresentFences() {
924 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
925 const auto& pendingPresentFence = mPendingPresentFences[i];
926 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
927 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
928 signalTime = pendingPresentFence.first->getSignalTime();
929 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
930 continue;
931 }
932 }
933 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
934 auto& displayFrame = pendingPresentFence.second;
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800935 displayFrame->onPresent(signalTime);
936 displayFrame->trace(mSurfaceFlingerPid);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700937 }
938
939 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
940 --i;
941 }
942}
943
944void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700945 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700946 // We maintain only a fixed number of frames' data. Pop older frames
947 mDisplayFrames.pop_front();
948 }
949 mDisplayFrames.push_back(mCurrentDisplayFrame);
950 mCurrentDisplayFrame.reset();
Adithya Srinivasan05bd2d12021-01-11 18:49:58 +0000951 mCurrentDisplayFrame = std::make_shared<DisplayFrame>(mTimeStats, mJankClassificationThresholds,
952 &mTraceCookieCounter);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700953}
954
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800955nsecs_t FrameTimeline::DisplayFrame::getBaseTime() const {
956 nsecs_t baseTime =
957 getMinTime(mPredictionState, mSurfaceFlingerPredictions, mSurfaceFlingerActuals);
958 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700959 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
960 if (surfaceFrameBaseTime != 0) {
961 baseTime = std::min(baseTime, surfaceFrameBaseTime);
962 }
963 }
964 return baseTime;
965}
966
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800967void FrameTimeline::DisplayFrame::dumpJank(std::string& result, nsecs_t baseTime,
968 int displayFrameCount) const {
969 if (mJankType == JankType::None) {
970 // Check if any Surface Frame has been janky
971 bool isJanky = false;
972 for (const auto& surfaceFrame : mSurfaceFrames) {
973 if (surfaceFrame->getJankType() != JankType::None) {
974 isJanky = true;
975 break;
976 }
977 }
978 if (!isJanky) {
979 return;
980 }
981 }
982 StringAppendF(&result, "Display Frame %d", displayFrameCount);
983 dump(result, baseTime);
984}
985
986void FrameTimeline::DisplayFrame::dumpAll(std::string& result, nsecs_t baseTime) const {
987 dump(result, baseTime);
988}
989
990void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) const {
991 if (mJankType != JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700992 // Easily identify a janky Display Frame in the dump
993 StringAppendF(&result, " [*] ");
994 }
995 StringAppendF(&result, "\n");
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -0800996 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
997 StringAppendF(&result, "Jank Type : %s\n", jankTypeBitmaskToString(mJankType).c_str());
998 StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
999 StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
1000 StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001001 std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001002 StringAppendF(&result, "Vsync Period: %10f\n",
1003 std::chrono::duration<double, std::milli>(vsyncPeriod).count());
1004 nsecs_t presentDelta =
1005 mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
1006 std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
1007 StringAppendF(&result, "Present delta: %10f\n",
1008 std::chrono::duration<double, std::milli>(presentDeltaNs).count());
Alec Mouri7d436ec2021-01-27 20:40:50 -08001009 std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001010 StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
1011 std::chrono::duration<double, std::milli>(deltaToVsync).count());
1012 dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
1013 baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001014 StringAppendF(&result, "\n");
1015 std::string indent = " "; // 4 spaces
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001016 for (const auto& surfaceFrame : mSurfaceFrames) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001017 surfaceFrame->dump(result, indent, baseTime);
1018 }
1019 StringAppendF(&result, "\n");
1020}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001021
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001022void FrameTimeline::dumpAll(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001023 std::scoped_lock lock(mMutex);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001024 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001025 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001026 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
1027 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001028 mDisplayFrames[i]->dumpAll(result, baseTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001029 }
1030}
1031
1032void FrameTimeline::dumpJank(std::string& result) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001033 std::scoped_lock lock(mMutex);
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001034 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001035 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001036 mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001037 }
1038}
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001039
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -07001040void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
1041 ATRACE_CALL();
1042 std::unordered_map<std::string, bool> argsMap;
1043 for (size_t i = 0; i < args.size(); i++) {
1044 argsMap[std::string(String8(args[i]).c_str())] = true;
1045 }
1046 if (argsMap.count("-jank")) {
1047 dumpJank(result);
1048 }
1049 if (argsMap.count("-all")) {
1050 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -07001051 }
1052}
1053
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001054void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -10001055 std::scoped_lock lock(mMutex);
Adithya Srinivasan2d736322020-10-01 16:53:48 -07001056
1057 // The size can either increase or decrease, clear everything, to be consistent
1058 mDisplayFrames.clear();
1059 mPendingPresentFences.clear();
1060 mMaxDisplayFrames = size;
1061}
1062
1063void FrameTimeline::reset() {
1064 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
1065}
1066
Adithya Srinivasan9b2ca3e2020-11-10 10:14:17 -08001067} // namespace impl
1068} // namespace android::frametimeline