blob: 996479c1c7caa0969d4f9b4565aaa2a82f181fe7 [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
Alec Mouri9a29e672020-09-14 12:39:14 -0700180SurfaceFrame::SurfaceFrame(uid_t ownerUid, std::string layerName, std::string debugName,
181 PredictionState predictionState,
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700182 frametimeline::TimelineItem&& predictions)
Alec Mouri9a29e672020-09-14 12:39:14 -0700183 : mOwnerUid(ownerUid),
184 mLayerName(std::move(layerName)),
185 mDebugName(std::move(debugName)),
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700186 mPresentState(PresentState::Unknown),
187 mPredictionState(predictionState),
188 mPredictions(predictions),
189 mActuals({0, 0, 0}),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700190 mActualQueueTime(0),
Alec Mouri9a29e672020-09-14 12:39:14 -0700191 mJankType(TimeStats::JankType::None),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700192 mJankMetadata(0) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700193
194void SurfaceFrame::setPresentState(PresentState state) {
195 std::lock_guard<std::mutex> lock(mMutex);
196 mPresentState = state;
197}
198
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700199SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700200 std::lock_guard<std::mutex> lock(mMutex);
201 return mPresentState;
202}
203
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700204TimelineItem SurfaceFrame::getActuals() const {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700205 std::lock_guard<std::mutex> lock(mMutex);
206 return mActuals;
207}
208
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700209nsecs_t SurfaceFrame::getActualQueueTime() const {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700210 std::lock_guard<std::mutex> lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700211 return mActualQueueTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700212}
213
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700214void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
215 std::lock_guard<std::mutex> lock(mMutex);
216 mActuals.startTime = actualStartTime;
217}
218
219void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
220 std::lock_guard<std::mutex> lock(mMutex);
221 mActualQueueTime = actualQueueTime;
222}
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700223void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700224 std::lock_guard<std::mutex> lock(mMutex);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700225 mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700226}
227
228void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700229 std::lock_guard<std::mutex> lock(mMutex);
230 mActuals.presentTime = presentTime;
231}
232
Alec Mouri9a29e672020-09-14 12:39:14 -0700233void SurfaceFrame::setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700234 std::lock_guard<std::mutex> lock(mMutex);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700235 mJankType = jankType;
236 mJankMetadata = jankMetadata;
237}
238
Alec Mouri9a29e672020-09-14 12:39:14 -0700239TimeStats::JankType SurfaceFrame::getJankType() const {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700240 std::lock_guard<std::mutex> lock(mMutex);
241 return mJankType;
242}
243
Alec Mouri9a29e672020-09-14 12:39:14 -0700244uid_t SurfaceFrame::getOwnerUid() const {
245 return mOwnerUid;
246}
247
248const std::string& SurfaceFrame::getName() const {
249 return mLayerName;
250}
251
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700252nsecs_t SurfaceFrame::getBaseTime() const {
253 std::lock_guard<std::mutex> lock(mMutex);
254 nsecs_t baseTime = std::numeric_limits<nsecs_t>::max();
255 if (mPredictionState == PredictionState::Valid) {
256 baseTime = std::min(baseTime, mPredictions.startTime);
257 }
258 if (mActuals.startTime != 0) {
259 baseTime = std::min(baseTime, mActuals.startTime);
260 }
261 baseTime = std::min(baseTime, mActuals.endTime);
262 return baseTime;
263}
264
265std::string presentStateToString(SurfaceFrame::PresentState presentState) {
266 using PresentState = SurfaceFrame::PresentState;
267 switch (presentState) {
268 case PresentState::Presented:
269 return "Presented";
270 case PresentState::Dropped:
271 return "Dropped";
272 case PresentState::Unknown:
273 default:
274 return "Unknown";
275 }
276}
277
278void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) {
279 std::lock_guard<std::mutex> lock(mMutex);
280 StringAppendF(&result, "%s", indent.c_str());
Alec Mouri9a29e672020-09-14 12:39:14 -0700281 StringAppendF(&result, "Layer - %s", mDebugName.c_str());
282 if (mJankType != TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700283 // Easily identify a janky Surface Frame in the dump
284 StringAppendF(&result, " [*] ");
285 }
286 StringAppendF(&result, "\n");
287 StringAppendF(&result, "%s", indent.c_str());
288 StringAppendF(&result, "Present State : %s\n", presentStateToString(mPresentState).c_str());
289 StringAppendF(&result, "%s", indent.c_str());
290 StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
291 StringAppendF(&result, "%s", indent.c_str());
292 StringAppendF(&result, "Jank Type : %s\n", toString(mJankType).c_str());
293 StringAppendF(&result, "%s", indent.c_str());
294 StringAppendF(&result, "Jank Metadata: %s\n",
295 jankMetadataBitmaskToString(mJankMetadata).c_str());
296 dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700297}
298
Alec Mouri9a29e672020-09-14 12:39:14 -0700299FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats)
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700300 : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()),
Alec Mouri9a29e672020-09-14 12:39:14 -0700301 mMaxDisplayFrames(kDefaultMaxDisplayFrames),
302 mTimeStats(std::move(timeStats)) {}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700303
304FrameTimeline::DisplayFrame::DisplayFrame()
305 : surfaceFlingerPredictions(TimelineItem()),
306 surfaceFlingerActuals(TimelineItem()),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700307 predictionState(PredictionState::None),
Alec Mouri9a29e672020-09-14 12:39:14 -0700308 jankType(TimeStats::JankType::None),
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700309 jankMetadata(0) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700310 this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
311}
312
313std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
Alec Mouri9a29e672020-09-14 12:39:14 -0700314 uid_t uid, std::string layerName, std::string debugName, std::optional<int64_t> token) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700315 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700316 if (!token) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700317 return std::make_unique<impl::SurfaceFrame>(uid, std::move(layerName), std::move(debugName),
318 PredictionState::None, TimelineItem());
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700319 }
320 std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
321 if (predictions) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700322 return std::make_unique<impl::SurfaceFrame>(uid, std::move(layerName), std::move(debugName),
323 PredictionState::Valid,
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700324 std::move(*predictions));
325 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700326 return std::make_unique<impl::SurfaceFrame>(uid, std::move(layerName), std::move(debugName),
327 PredictionState::Expired, TimelineItem());
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700328}
329
330void FrameTimeline::addSurfaceFrame(
331 std::unique_ptr<android::frametimeline::SurfaceFrame> surfaceFrame,
332 SurfaceFrame::PresentState state) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700333 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700334 surfaceFrame->setPresentState(state);
335 std::unique_ptr<impl::SurfaceFrame> implSurfaceFrame(
336 static_cast<impl::SurfaceFrame*>(surfaceFrame.release()));
337 std::lock_guard<std::mutex> lock(mMutex);
338 mCurrentDisplayFrame->surfaceFrames.push_back(std::move(implSurfaceFrame));
339}
340
341void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700342 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700343 const std::optional<TimelineItem> prediction = mTokenManager.getPredictionsForToken(token);
344 std::lock_guard<std::mutex> lock(mMutex);
345 if (!prediction) {
346 mCurrentDisplayFrame->predictionState = PredictionState::Expired;
347 } else {
348 mCurrentDisplayFrame->surfaceFlingerPredictions = *prediction;
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700349 mCurrentDisplayFrame->predictionState = PredictionState::Valid;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700350 }
351 mCurrentDisplayFrame->surfaceFlingerActuals.startTime = wakeUpTime;
352}
353
354void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
355 const std::shared_ptr<FenceTime>& presentFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700356 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700357 std::lock_guard<std::mutex> lock(mMutex);
358 mCurrentDisplayFrame->surfaceFlingerActuals.endTime = sfPresentTime;
359 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
360 flushPendingPresentFences();
361 finalizeCurrentDisplayFrame();
362}
363
364void FrameTimeline::flushPendingPresentFences() {
365 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
366 const auto& pendingPresentFence = mPendingPresentFences[i];
367 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
368 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
369 signalTime = pendingPresentFence.first->getSignalTime();
370 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
371 continue;
372 }
373 }
374 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700375 int32_t totalJankReasons = TimeStats::JankType::None;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700376 auto& displayFrame = pendingPresentFence.second;
377 displayFrame->surfaceFlingerActuals.presentTime = signalTime;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700378
379 // Jank Analysis for DisplayFrame
380 const auto& sfActuals = displayFrame->surfaceFlingerActuals;
381 const auto& sfPredictions = displayFrame->surfaceFlingerPredictions;
382 if (std::abs(sfActuals.presentTime - sfPredictions.presentTime) > kPresentThreshold) {
383 displayFrame->jankMetadata |= sfActuals.presentTime > sfPredictions.presentTime
384 ? LatePresent
385 : EarlyPresent;
386 }
387 if (std::abs(sfActuals.endTime - sfPredictions.endTime) > kDeadlineThreshold) {
388 if (sfActuals.endTime > sfPredictions.endTime) {
389 displayFrame->jankMetadata |= LateFinish;
390 } else {
391 displayFrame->jankMetadata |= EarlyFinish;
392 }
393
Alec Mouri9a29e672020-09-14 12:39:14 -0700394 if ((displayFrame->jankMetadata & EarlyFinish) &&
395 (displayFrame->jankMetadata & EarlyPresent)) {
396 displayFrame->jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
397 } else if ((displayFrame->jankMetadata & LateFinish) &&
398 (displayFrame->jankMetadata & LatePresent)) {
399 displayFrame->jankType = TimeStats::JankType::SurfaceFlingerDeadlineMissed;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700400 } else if (displayFrame->jankMetadata & EarlyPresent ||
401 displayFrame->jankMetadata & LatePresent) {
402 // Cases where SF finished early but frame was presented late and vice versa
Alec Mouri9a29e672020-09-14 12:39:14 -0700403 displayFrame->jankType = TimeStats::JankType::Display;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700404 }
405 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700406
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700407 if (std::abs(sfActuals.startTime - sfPredictions.startTime) > kSFStartThreshold) {
408 displayFrame->jankMetadata |=
409 sfActuals.startTime > sfPredictions.startTime ? LateStart : EarlyStart;
410 }
411
Alec Mouri9a29e672020-09-14 12:39:14 -0700412 totalJankReasons |= displayFrame->jankType;
413
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700414 for (auto& surfaceFrame : displayFrame->surfaceFrames) {
415 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
416 // Only presented SurfaceFrames need to be updated
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700417 surfaceFrame->setActualPresentTime(signalTime);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700418
419 // Jank Analysis for SurfaceFrame
420 const auto& predictionState = surfaceFrame->getPredictionState();
421 if (predictionState == PredictionState::Expired) {
422 // Jank analysis cannot be done on apps that don't use predictions
Alec Mouri9a29e672020-09-14 12:39:14 -0700423 surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700424 continue;
425 } else if (predictionState == PredictionState::Valid) {
426 const auto& actuals = surfaceFrame->getActuals();
427 const auto& predictions = surfaceFrame->getPredictions();
428 int32_t jankMetadata = 0;
Alec Mouri9a29e672020-09-14 12:39:14 -0700429 TimeStats::JankType jankType = TimeStats::JankType::None;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700430 if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) {
431 jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish
432 : EarlyFinish;
433 }
434 if (std::abs(actuals.presentTime - predictions.presentTime) >
435 kPresentThreshold) {
436 jankMetadata |= actuals.presentTime > predictions.presentTime
437 ? LatePresent
438 : EarlyPresent;
439 }
440 if (jankMetadata & EarlyPresent) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700441 jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700442 } else if (jankMetadata & LatePresent) {
443 if (jankMetadata & EarlyFinish) {
444 // TODO(b/169890654): Classify this properly
Alec Mouri9a29e672020-09-14 12:39:14 -0700445 jankType = TimeStats::JankType::Display;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700446 } else {
Alec Mouri9a29e672020-09-14 12:39:14 -0700447 jankType = TimeStats::JankType::AppDeadlineMissed;
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700448 }
449 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700450
451 totalJankReasons |= jankType;
452 mTimeStats->incrementJankyFrames(surfaceFrame->getOwnerUid(),
453 surfaceFrame->getName(),
454 jankType | displayFrame->jankType);
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700455 surfaceFrame->setJankInfo(jankType, jankMetadata);
456 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700457 }
458 }
Alec Mouri9a29e672020-09-14 12:39:14 -0700459
460 mTimeStats->incrementJankyFrames(totalJankReasons);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700461 }
462
463 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
464 --i;
465 }
466}
467
468void FrameTimeline::finalizeCurrentDisplayFrame() {
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700469 while (mDisplayFrames.size() >= mMaxDisplayFrames) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700470 // We maintain only a fixed number of frames' data. Pop older frames
471 mDisplayFrames.pop_front();
472 }
473 mDisplayFrames.push_back(mCurrentDisplayFrame);
474 mCurrentDisplayFrame.reset();
475 mCurrentDisplayFrame = std::make_shared<DisplayFrame>();
476}
477
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700478nsecs_t FrameTimeline::findBaseTime(const std::shared_ptr<DisplayFrame>& displayFrame) {
479 nsecs_t baseTime = std::numeric_limits<nsecs_t>::max();
480 if (displayFrame->predictionState == PredictionState::Valid) {
481 baseTime = std::min(baseTime, displayFrame->surfaceFlingerPredictions.startTime);
482 }
483 baseTime = std::min(baseTime, displayFrame->surfaceFlingerActuals.startTime);
484 for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
485 nsecs_t surfaceFrameBaseTime = surfaceFrame->getBaseTime();
486 if (surfaceFrameBaseTime != 0) {
487 baseTime = std::min(baseTime, surfaceFrameBaseTime);
488 }
489 }
490 return baseTime;
491}
492
493void FrameTimeline::dumpDisplayFrame(std::string& result,
494 const std::shared_ptr<DisplayFrame>& displayFrame,
495 nsecs_t baseTime) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700496 if (displayFrame->jankType != TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700497 // Easily identify a janky Display Frame in the dump
498 StringAppendF(&result, " [*] ");
499 }
500 StringAppendF(&result, "\n");
501 StringAppendF(&result, "Prediction State : %s\n",
502 toString(displayFrame->predictionState).c_str());
503 StringAppendF(&result, "Jank Type : %s\n", toString(displayFrame->jankType).c_str());
504 StringAppendF(&result, "Jank Metadata: %s\n",
505 jankMetadataBitmaskToString(displayFrame->jankMetadata).c_str());
506 dumpTable(result, displayFrame->surfaceFlingerPredictions, displayFrame->surfaceFlingerActuals,
507 "", displayFrame->predictionState, baseTime);
508 StringAppendF(&result, "\n");
509 std::string indent = " "; // 4 spaces
510 for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
511 surfaceFrame->dump(result, indent, baseTime);
512 }
513 StringAppendF(&result, "\n");
514}
515void FrameTimeline::dumpAll(std::string& result) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700516 std::lock_guard<std::mutex> lock(mMutex);
517 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700518 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
519 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
520 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
521 dumpDisplayFrame(result, mDisplayFrames[i], baseTime);
522 }
523}
524
525void FrameTimeline::dumpJank(std::string& result) {
526 std::lock_guard<std::mutex> lock(mMutex);
527 nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
528 for (size_t i = 0; i < mDisplayFrames.size(); i++) {
529 const auto& displayFrame = mDisplayFrames[i];
Alec Mouri9a29e672020-09-14 12:39:14 -0700530 if (displayFrame->jankType == TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700531 // Check if any Surface Frame has been janky
532 bool isJanky = false;
533 for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
Alec Mouri9a29e672020-09-14 12:39:14 -0700534 if (surfaceFrame->getJankType() != TimeStats::JankType::None) {
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700535 isJanky = true;
536 break;
537 }
538 }
539 if (!isJanky) {
540 continue;
541 }
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700542 }
Adithya Srinivasan8fc601d2020-09-25 13:51:09 -0700543 StringAppendF(&result, "Display Frame %d", static_cast<int>(i));
544 dumpDisplayFrame(result, displayFrame, baseTime);
545 }
546}
547void FrameTimeline::parseArgs(const Vector<String16>& args, std::string& result) {
548 ATRACE_CALL();
549 std::unordered_map<std::string, bool> argsMap;
550 for (size_t i = 0; i < args.size(); i++) {
551 argsMap[std::string(String8(args[i]).c_str())] = true;
552 }
553 if (argsMap.count("-jank")) {
554 dumpJank(result);
555 }
556 if (argsMap.count("-all")) {
557 dumpAll(result);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700558 }
559}
560
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700561void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
562 std::lock_guard<std::mutex> lock(mMutex);
563
564 // The size can either increase or decrease, clear everything, to be consistent
565 mDisplayFrames.clear();
566 mPendingPresentFences.clear();
567 mMaxDisplayFrames = size;
568}
569
570void FrameTimeline::reset() {
571 setMaxDisplayFrames(kDefaultMaxDisplayFrames);
572}
573
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700574} // namespace android::frametimeline::impl