blob: bd87482dc6683ac7b35181972da9e653895c75e2 [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
29namespace android::frametimeline::impl {
30
31using base::StringAppendF;
32
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070033void dumpTable(std::string& result, TimelineItem predictions, TimelineItem actuals,
34 const std::string& indent, PredictionState predictionState, nsecs_t baseTime) {
35 StringAppendF(&result, "%s", indent.c_str());
36 StringAppendF(&result, "\t\t");
37 StringAppendF(&result, " Start time\t\t|");
38 StringAppendF(&result, " End time\t\t|");
39 StringAppendF(&result, " Present time\n");
40 if (predictionState == PredictionState::Valid) {
41 // Dump the Predictions only if they are valid
42 StringAppendF(&result, "%s", indent.c_str());
43 StringAppendF(&result, "Expected\t|");
44 std::chrono::nanoseconds startTime(predictions.startTime - baseTime);
45 std::chrono::nanoseconds endTime(predictions.endTime - baseTime);
46 std::chrono::nanoseconds presentTime(predictions.presentTime - baseTime);
47 StringAppendF(&result, "\t%10.2f\t|\t%10.2f\t|\t%10.2f\n",
48 std::chrono::duration<double, std::milli>(startTime).count(),
49 std::chrono::duration<double, std::milli>(endTime).count(),
50 std::chrono::duration<double, std::milli>(presentTime).count());
51 }
52 StringAppendF(&result, "%s", indent.c_str());
53 StringAppendF(&result, "Actual \t|");
54
55 if (actuals.startTime == 0) {
56 StringAppendF(&result, "\t\tN/A\t|");
57 } else {
58 std::chrono::nanoseconds startTime(std::max<nsecs_t>(0, actuals.startTime - baseTime));
59 StringAppendF(&result, "\t%10.2f\t|",
60 std::chrono::duration<double, std::milli>(startTime).count());
61 }
62 if (actuals.endTime == 0) {
63 StringAppendF(&result, "\t\tN/A\t|");
64 } else {
65 std::chrono::nanoseconds endTime(actuals.endTime - baseTime);
66 StringAppendF(&result, "\t%10.2f\t|",
67 std::chrono::duration<double, std::milli>(endTime).count());
68 }
69 if (actuals.presentTime == 0) {
70 StringAppendF(&result, "\t\tN/A\n");
71 } else {
72 std::chrono::nanoseconds presentTime(std::max<nsecs_t>(0, actuals.presentTime - baseTime));
73 StringAppendF(&result, "\t%10.2f\n",
74 std::chrono::duration<double, std::milli>(presentTime).count());
75 }
76
77 StringAppendF(&result, "%s", indent.c_str());
78 StringAppendF(&result, "----------------------");
79 StringAppendF(&result, "----------------------");
80 StringAppendF(&result, "----------------------");
81 StringAppendF(&result, "----------------------\n");
82}
83
84std::string toString(PredictionState predictionState) {
85 switch (predictionState) {
86 case PredictionState::Valid:
87 return "Valid";
88 case PredictionState::Expired:
89 return "Expired";
90 case PredictionState::None:
91 default:
92 return "None";
93 }
94}
95
Alec Mouri9a29e672020-09-14 12:39:14 -070096std::string toString(TimeStats::JankType jankType) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070097 switch (jankType) {
Alec Mouri9a29e672020-09-14 12:39:14 -070098 case TimeStats::JankType::None:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -070099 return "None";
Alec Mouri9a29e672020-09-14 12:39:14 -0700100 case TimeStats::JankType::Display:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700101 return "Composer/Display - outside SF and App";
Alec Mouri9a29e672020-09-14 12:39:14 -0700102 case TimeStats::JankType::SurfaceFlingerDeadlineMissed:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700103 return "SurfaceFlinger Deadline Missed";
Alec Mouri9a29e672020-09-14 12:39:14 -0700104 case TimeStats::JankType::AppDeadlineMissed:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700105 return "App Deadline Missed";
Alec Mouri9a29e672020-09-14 12:39:14 -0700106 case TimeStats::JankType::PredictionExpired:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700107 return "Prediction Expired";
Alec Mouri9a29e672020-09-14 12:39:14 -0700108 case TimeStats::JankType::SurfaceFlingerEarlyLatch:
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700109 return "SurfaceFlinger Early Latch";
110 default:
111 return "Unclassified";
112 }
113}
114
115std::string jankMetadataBitmaskToString(int32_t jankMetadata) {
116 std::vector<std::string> jankInfo;
117
118 if (jankMetadata & EarlyStart) {
119 jankInfo.emplace_back("Early Start");
120 } else if (jankMetadata & LateStart) {
121 jankInfo.emplace_back("Late Start");
122 }
123
124 if (jankMetadata & EarlyFinish) {
125 jankInfo.emplace_back("Early Finish");
126 } else if (jankMetadata & LateFinish) {
127 jankInfo.emplace_back("Late Finish");
128 }
129
130 if (jankMetadata & EarlyPresent) {
131 jankInfo.emplace_back("Early Present");
132 } else if (jankMetadata & LatePresent) {
133 jankInfo.emplace_back("Late Present");
134 }
135 // TODO(b/169876734): add GPU composition metadata here
136
137 if (jankInfo.empty()) {
138 return "None";
139 }
140 return std::accumulate(jankInfo.begin(), jankInfo.end(), std::string(),
141 [](const std::string& l, const std::string& r) {
142 return l.empty() ? r : l + ", " + r;
143 });
144}
145
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700146int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700147 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700148 std::lock_guard<std::mutex> lock(mMutex);
149 const int64_t assignedToken = mCurrentToken++;
150 mPredictions[assignedToken] = predictions;
151 mTokens.emplace_back(std::make_pair(assignedToken, systemTime()));
152 flushTokens(systemTime());
153 return assignedToken;
154}
155
156std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) {
157 std::lock_guard<std::mutex> lock(mMutex);
158 flushTokens(systemTime());
159 auto predictionsIterator = mPredictions.find(token);
160 if (predictionsIterator != mPredictions.end()) {
161 return predictionsIterator->second;
162 }
163 return {};
164}
165
166void TokenManager::flushTokens(nsecs_t flushTime) {
167 for (size_t i = 0; i < mTokens.size(); i++) {
168 if (flushTime - mTokens[i].second >= kMaxRetentionTime) {
169 mPredictions.erase(mTokens[i].first);
170 mTokens.erase(mTokens.begin() + static_cast<int>(i));
171 --i;
172 } else {
173 // Tokens are ordered by time. If i'th token is within the retention time, then the
174 // i+1'th token will also be within retention time.
175 break;
176 }
177 }
178}
179
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700180SurfaceFrame::SurfaceFrame(pid_t ownerPid, uid_t ownerUid, std::string layerName,
181 std::string debugName, PredictionState predictionState,
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700182 frametimeline::TimelineItem&& predictions)
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700183 : mOwnerPid(ownerPid),
184 mOwnerUid(ownerUid),
Alec Mouri9a29e672020-09-14 12:39:14 -0700185 mLayerName(std::move(layerName)),
186 mDebugName(std::move(debugName)),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700187 mPresentState(PresentState::Unknown),
188 mPredictionState(predictionState),
189 mPredictions(predictions),
190 mActuals({0, 0, 0}),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700191 mActualQueueTime(0),
Alec Mouri9a29e672020-09-14 12:39:14 -0700192 mJankType(TimeStats::JankType::None),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700193 mJankMetadata(0) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700194
195void SurfaceFrame::setPresentState(PresentState state) {
196 std::lock_guard<std::mutex> lock(mMutex);
197 mPresentState = state;
198}
199
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700200SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700201 std::lock_guard<std::mutex> lock(mMutex);
202 return mPresentState;
203}
204
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700205TimelineItem SurfaceFrame::getActuals() const {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700206 std::lock_guard<std::mutex> lock(mMutex);
207 return mActuals;
208}
209
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700210nsecs_t SurfaceFrame::getActualQueueTime() const {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700211 std::lock_guard<std::mutex> lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700212 return mActualQueueTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700213}
214
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700215void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
216 std::lock_guard<std::mutex> lock(mMutex);
217 mActuals.startTime = actualStartTime;
218}
219
220void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
221 std::lock_guard<std::mutex> lock(mMutex);
222 mActualQueueTime = actualQueueTime;
223}
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700224void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700225 std::lock_guard<std::mutex> lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700226 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700227}
228
229void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700230 std::lock_guard<std::mutex> lock(mMutex);
231 mActuals.presentTime = presentTime;
232}
233
Alec Mouri9a29e672020-09-14 12:39:14 -0700234void SurfaceFrame::setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700235 std::lock_guard<std::mutex> lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700236 mJankType = jankType;
237 mJankMetadata = jankMetadata;
238}
239
Alec Mouri9a29e672020-09-14 12:39:14 -0700240TimeStats::JankType SurfaceFrame::getJankType() const {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700241 std::lock_guard<std::mutex> lock(mMutex);
242 return mJankType;
243}
244
245nsecs_t SurfaceFrame::getBaseTime() const {
246 std::lock_guard<std::mutex> lock(mMutex);
247 nsecs_t baseTime = std::numeric_limits<nsecs_t>::max();
248 if (mPredictionState == PredictionState::Valid) {
249 baseTime = std::min(baseTime, mPredictions.startTime);
250 }
251 if (mActuals.startTime != 0) {
252 baseTime = std::min(baseTime, mActuals.startTime);
253 }
254 baseTime = std::min(baseTime, mActuals.endTime);
255 return baseTime;
256}
257
258std::string presentStateToString(SurfaceFrame::PresentState presentState) {
259 using PresentState = SurfaceFrame::PresentState;
260 switch (presentState) {
261 case PresentState::Presented:
262 return "Presented";
263 case PresentState::Dropped:
264 return "Dropped";
265 case PresentState::Unknown:
266 default:
267 return "Unknown";
268 }
269}
270
271void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) {
272 std::lock_guard<std::mutex> lock(mMutex);
273 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700274 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
275 if (mJankType != TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700276 // Easily identify a janky Surface Frame in the dump
277 StringAppendF(&result, " [*] ");
278 }
279 StringAppendF(&result, "\n");
280 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700281 StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
282 StringAppendF(&result, "%s", indent.c_str());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700283 StringAppendF(&result, "Present State : %s\n", presentStateToString(mPresentState).c_str());
284 StringAppendF(&result, "%s", indent.c_str());
285 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
286 StringAppendF(&result, "%s", indent.c_str());
287 StringAppendF(&result, "Jank Type : %s\n", toString(mJankType).c_str());
288 StringAppendF(&result, "%s", indent.c_str());
289 StringAppendF(&result, "Jank Metadata: %s\n",
290 jankMetadataBitmaskToString(mJankMetadata).c_str());
291 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700292}
293
Alec Mouri9a29e672020-09-14 12:39:14 -0700294FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats)
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700295 : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()),
Alec Mouri9a29e672020-09-14 12:39:14 -0700296 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
297 mTimeStats(std::move(timeStats)) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700298
299FrameTimeline::DisplayFrame::DisplayFrame()
300 : surfaceFlingerPredictions(TimelineItem()),
301 surfaceFlingerActuals(TimelineItem()),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700302 predictionState(PredictionState::None),
Alec Mouri9a29e672020-09-14 12:39:14 -0700303 jankType(TimeStats::JankType::None),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700304 jankMetadata(0) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700305 this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
306}
307
308std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700309 pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName,
310 std::optional<int64_t> token) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700311 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700312 if (!token) {
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700313 return std::make_unique<impl::SurfaceFrame>(ownerPid, ownerUid, std::move(layerName),
314 std::move(debugName), PredictionState::None,
315 TimelineItem());
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700316 }
317 std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
318 if (predictions) {
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700319 return std::make_unique<impl::SurfaceFrame>(ownerPid, ownerUid, std::move(layerName),
320 std::move(debugName), PredictionState::Valid,
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700321 std::move(*predictions));
322 }
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700323 return std::make_unique<impl::SurfaceFrame>(ownerPid, ownerUid, std::move(layerName),
324 std::move(debugName), PredictionState::Expired,
325 TimelineItem());
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700326}
327
328void FrameTimeline::addSurfaceFrame(
329 std::unique_ptr<android::frametimeline::SurfaceFrame> surfaceFrame,
330 SurfaceFrame::PresentState state) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700331 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700332 surfaceFrame->setPresentState(state);
333 std::unique_ptr<impl::SurfaceFrame> implSurfaceFrame(
334 static_cast<impl::SurfaceFrame*>(surfaceFrame.release()));
335 std::lock_guard<std::mutex> lock(mMutex);
336 mCurrentDisplayFrame->surfaceFrames.push_back(std::move(implSurfaceFrame));
337}
338
339void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700340 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700341 const std::optional<TimelineItem> prediction = mTokenManager.getPredictionsForToken(token);
342 std::lock_guard<std::mutex> lock(mMutex);
343 if (!prediction) {
344 mCurrentDisplayFrame->predictionState = PredictionState::Expired;
345 } else {
346 mCurrentDisplayFrame->surfaceFlingerPredictions = *prediction;
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700347 mCurrentDisplayFrame->predictionState = PredictionState::Valid;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700348 }
349 mCurrentDisplayFrame->surfaceFlingerActuals.startTime = wakeUpTime;
350}
351
352void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
353 const std::shared_ptr<FenceTime>& presentFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700354 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700355 std::lock_guard<std::mutex> lock(mMutex);
356 mCurrentDisplayFrame->surfaceFlingerActuals.endTime = sfPresentTime;
357 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
358 flushPendingPresentFences();
359 finalizeCurrentDisplayFrame();
360}
361
362void FrameTimeline::flushPendingPresentFences() {
363 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
364 const auto& pendingPresentFence = mPendingPresentFences[i];
365 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
366 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
367 signalTime = pendingPresentFence.first->getSignalTime();
368 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
369 continue;
370 }
371 }
372 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700373 int32_t totalJankReasons = TimeStats::JankType::None;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700374 auto& displayFrame = pendingPresentFence.second;
375 displayFrame->surfaceFlingerActuals.presentTime = signalTime;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700376
377 // Jank Analysis for DisplayFrame
378 const auto& sfActuals = displayFrame->surfaceFlingerActuals;
379 const auto& sfPredictions = displayFrame->surfaceFlingerPredictions;
380 if (std::abs(sfActuals.presentTime - sfPredictions.presentTime) > kPresentThreshold) {
381 displayFrame->jankMetadata |= sfActuals.presentTime > sfPredictions.presentTime
382 ? LatePresent
383 : EarlyPresent;
384 }
385 if (std::abs(sfActuals.endTime - sfPredictions.endTime) > kDeadlineThreshold) {
386 if (sfActuals.endTime > sfPredictions.endTime) {
387 displayFrame->jankMetadata |= LateFinish;
388 } else {
389 displayFrame->jankMetadata |= EarlyFinish;
390 }
391
Alec Mouri9a29e672020-09-14 12:39:14 -0700392 if ((displayFrame->jankMetadata & EarlyFinish) &&
393 (displayFrame->jankMetadata & EarlyPresent)) {
394 displayFrame->jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
395 } else if ((displayFrame->jankMetadata & LateFinish) &&
396 (displayFrame->jankMetadata & LatePresent)) {
397 displayFrame->jankType = TimeStats::JankType::SurfaceFlingerDeadlineMissed;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700398 } else if (displayFrame->jankMetadata & EarlyPresent ||
399 displayFrame->jankMetadata & LatePresent) {
400 // Cases where SF finished early but frame was presented late and vice versa
Alec Mouri9a29e672020-09-14 12:39:14 -0700401 displayFrame->jankType = TimeStats::JankType::Display;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700402 }
403 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700404
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700405 if (std::abs(sfActuals.startTime - sfPredictions.startTime) > kSFStartThreshold) {
406 displayFrame->jankMetadata |=
407 sfActuals.startTime > sfPredictions.startTime ? LateStart : EarlyStart;
408 }
409
Alec Mouri9a29e672020-09-14 12:39:14 -0700410 totalJankReasons |= displayFrame->jankType;
411
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700412 for (auto& surfaceFrame : displayFrame->surfaceFrames) {
413 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
414 // Only presented SurfaceFrames need to be updated
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700415 surfaceFrame->setActualPresentTime(signalTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700416
417 // Jank Analysis for SurfaceFrame
418 const auto& predictionState = surfaceFrame->getPredictionState();
419 if (predictionState == PredictionState::Expired) {
420 // Jank analysis cannot be done on apps that don't use predictions
Alec Mouri9a29e672020-09-14 12:39:14 -0700421 surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700422 continue;
423 } else if (predictionState == PredictionState::Valid) {
424 const auto& actuals = surfaceFrame->getActuals();
425 const auto& predictions = surfaceFrame->getPredictions();
426 int32_t jankMetadata = 0;
Alec Mouri9a29e672020-09-14 12:39:14 -0700427 TimeStats::JankType jankType = TimeStats::JankType::None;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700428 if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) {
429 jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish
430 : EarlyFinish;
431 }
432 if (std::abs(actuals.presentTime - predictions.presentTime) >
433 kPresentThreshold) {
434 jankMetadata |= actuals.presentTime > predictions.presentTime
435 ? LatePresent
436 : EarlyPresent;
437 }
438 if (jankMetadata & EarlyPresent) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700439 jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700440 } else if (jankMetadata & LatePresent) {
441 if (jankMetadata & EarlyFinish) {
442 // TODO(b/169890654): Classify this properly
Alec Mouri9a29e672020-09-14 12:39:14 -0700443 jankType = TimeStats::JankType::Display;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700444 } else {
Alec Mouri9a29e672020-09-14 12:39:14 -0700445 jankType = TimeStats::JankType::AppDeadlineMissed;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700446 }
447 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700448
449 totalJankReasons |= jankType;
450 mTimeStats->incrementJankyFrames(surfaceFrame->getOwnerUid(),
451 surfaceFrame->getName(),
452 jankType | displayFrame->jankType);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700453 surfaceFrame->setJankInfo(jankType, jankMetadata);
454 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700455 }
456 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700457
458 mTimeStats->incrementJankyFrames(totalJankReasons);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700459 }
460
461 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
462 --i;
463 }
464}
465
466void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700467 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700468 // We maintain only a fixed number of frames' data. Pop older frames
469 mDisplayFrames.pop_front();
470 }
471 mDisplayFrames.push_back(mCurrentDisplayFrame);
472 mCurrentDisplayFrame.reset();
473 mCurrentDisplayFrame = std::make_shared<DisplayFrame>();
474}
475
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700476nsecs_t FrameTimeline::findBaseTime(const std::shared_ptr<DisplayFrame>& displayFrame) {
477 nsecs_t baseTime = std::numeric_limits<nsecs_t>::max();
478 if (displayFrame->predictionState == PredictionState::Valid) {
479 baseTime = std::min(baseTime, displayFrame->surfaceFlingerPredictions.startTime);
480 }
481 baseTime = std::min(baseTime, displayFrame->surfaceFlingerActuals.startTime);
482 for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
483 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
484 if (surfaceFrameBaseTime != 0) {
485 baseTime = std::min(baseTime, surfaceFrameBaseTime);
486 }
487 }
488 return baseTime;
489}
490
491void FrameTimeline::dumpDisplayFrame(std::string& result,
492 const std::shared_ptr<DisplayFrame>& displayFrame,
493 nsecs_t baseTime) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700494 if (displayFrame->jankType != TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700495 // Easily identify a janky Display Frame in the dump
496 StringAppendF(&result, " [*] ");
497 }
498 StringAppendF(&result, "\n");
499 StringAppendF(&result, "Prediction State : %s\n",
500 toString(displayFrame->predictionState).c_str());
501 StringAppendF(&result, "Jank Type : %s\n", toString(displayFrame->jankType).c_str());
502 StringAppendF(&result, "Jank Metadata: %s\n",
503 jankMetadataBitmaskToString(displayFrame->jankMetadata).c_str());
504 dumpTable(result, displayFrame->surfaceFlingerPredictions, displayFrame->surfaceFlingerActuals,
505 "", displayFrame->predictionState, baseTime);
506 StringAppendF(&result, "\n");
507 std::string indent = " "; // 4 spaces
508 for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
509 surfaceFrame->dump(result, indent, baseTime);
510 }
511 StringAppendF(&result, "\n");
512}
513void FrameTimeline::dumpAll(std::string& result) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700514 std::lock_guard<std::mutex> lock(mMutex);
515 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700516 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
517 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
518 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
519 dumpDisplayFrame(result, mDisplayFrames[i], baseTime);
520 }
521}
522
523void FrameTimeline::dumpJank(std::string& result) {
524 std::lock_guard<std::mutex> lock(mMutex);
525 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
526 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
527 const auto& displayFrame = mDisplayFrames[i];
Alec Mouri9a29e672020-09-14 12:39:14 -0700528 if (displayFrame->jankType == TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700529 // Check if any Surface Frame has been janky
530 bool isJanky = false;
531 for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700532 if (surfaceFrame->getJankType() != TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700533 isJanky = true;
534 break;
535 }
536 }
537 if (!isJanky) {
538 continue;
539 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700540 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700541 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
542 dumpDisplayFrame(result, displayFrame, baseTime);
543 }
544}
545void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
546 ATRACE_CALL();
547 std::unordered_map<std::string, bool> argsMap;
548 for (size_t i = 0; i < args.size(); i++) {
549 argsMap[std::string(String8(args[i]).c_str())] = true;
550 }
551 if (argsMap.count("-jank")) {
552 dumpJank(result);
553 }
554 if (argsMap.count("-all")) {
555 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700556 }
557}
558
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700559void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
560 std::lock_guard<std::mutex> lock(mMutex);
561
562 // The size can either increase or decrease, clear everything, to be consistent
563 mDisplayFrames.clear();
564 mPendingPresentFences.clear();
565 mMaxDisplayFrames = size;
566}
567
568void FrameTimeline::reset() {
569 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
570}
571
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700572} // namespace android::frametimeline::impl