blob: a12f4c7f13c7ebb281801dd646c3d9c646a0110c [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>
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070023#include <utils/Trace.h>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070024#include <cinttypes>
25
26namespace android::frametimeline::impl {
27
28using base::StringAppendF;
29
30int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070031 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -070032 std::lock_guard<std::mutex> lock(mMutex);
33 const int64_t assignedToken = mCurrentToken++;
34 mPredictions[assignedToken] = predictions;
35 mTokens.emplace_back(std::make_pair(assignedToken, systemTime()));
36 flushTokens(systemTime());
37 return assignedToken;
38}
39
40std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) {
41 std::lock_guard<std::mutex> lock(mMutex);
42 flushTokens(systemTime());
43 auto predictionsIterator = mPredictions.find(token);
44 if (predictionsIterator != mPredictions.end()) {
45 return predictionsIterator->second;
46 }
47 return {};
48}
49
50void TokenManager::flushTokens(nsecs_t flushTime) {
51 for (size_t i = 0; i < mTokens.size(); i++) {
52 if (flushTime - mTokens[i].second >= kMaxRetentionTime) {
53 mPredictions.erase(mTokens[i].first);
54 mTokens.erase(mTokens.begin() + static_cast<int>(i));
55 --i;
56 } else {
57 // Tokens are ordered by time. If i'th token is within the retention time, then the
58 // i+1'th token will also be within retention time.
59 break;
60 }
61 }
62}
63
64SurfaceFrame::SurfaceFrame(const std::string& layerName, PredictionState predictionState,
65 frametimeline::TimelineItem&& predictions)
66 : mLayerName(layerName),
67 mPresentState(PresentState::Unknown),
68 mPredictionState(predictionState),
69 mPredictions(predictions),
70 mActuals({0, 0, 0}),
71 mActualQueueTime(0) {}
72
73void SurfaceFrame::setPresentState(PresentState state) {
74 std::lock_guard<std::mutex> lock(mMutex);
75 mPresentState = state;
76}
77
78PredictionState SurfaceFrame::getPredictionState() {
79 std::lock_guard<std::mutex> lock(mMutex);
80 return mPredictionState;
81}
82
83SurfaceFrame::PresentState SurfaceFrame::getPresentState() {
84 std::lock_guard<std::mutex> lock(mMutex);
85 return mPresentState;
86}
87
88TimelineItem SurfaceFrame::getActuals() {
89 std::lock_guard<std::mutex> lock(mMutex);
90 return mActuals;
91}
92
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070093nsecs_t SurfaceFrame::getActualQueueTime() {
Adithya Srinivasanf279e042020-08-17 14:56:27 -070094 std::lock_guard<std::mutex> lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070095 return mActualQueueTime;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070096}
97
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070098void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
99 std::lock_guard<std::mutex> lock(mMutex);
100 mActuals.startTime = actualStartTime;
101}
102
103void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
104 std::lock_guard<std::mutex> lock(mMutex);
105 mActualQueueTime = actualQueueTime;
106}
107void SurfaceFrame::setActualEndTime(nsecs_t actualEndTime) {
108 std::lock_guard<std::mutex> lock(mMutex);
109 mActuals.endTime = actualEndTime;
110}
111
112void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700113 std::lock_guard<std::mutex> lock(mMutex);
114 mActuals.presentTime = presentTime;
115}
116
117void SurfaceFrame::dump(std::string& result) {
118 std::lock_guard<std::mutex> lock(mMutex);
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700119 StringAppendF(&result, "Present State : %d\n", static_cast<int>(mPresentState));
120 StringAppendF(&result, "Prediction State : %d\n", static_cast<int>(mPredictionState));
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700121 StringAppendF(&result, "Predicted Start Time : %" PRId64 "\n", mPredictions.startTime);
122 StringAppendF(&result, "Actual Start Time : %" PRId64 "\n", mActuals.startTime);
123 StringAppendF(&result, "Actual Queue Time : %" PRId64 "\n", mActualQueueTime);
124 StringAppendF(&result, "Predicted Render Complete Time : %" PRId64 "\n", mPredictions.endTime);
125 StringAppendF(&result, "Actual Render Complete Time : %" PRId64 "\n", mActuals.endTime);
126 StringAppendF(&result, "Predicted Present Time : %" PRId64 "\n", mPredictions.presentTime);
127 StringAppendF(&result, "Actual Present Time : %" PRId64 "\n", mActuals.presentTime);
128}
129
130FrameTimeline::FrameTimeline() : mCurrentDisplayFrame(std::make_shared<DisplayFrame>()) {}
131
132FrameTimeline::DisplayFrame::DisplayFrame()
133 : surfaceFlingerPredictions(TimelineItem()),
134 surfaceFlingerActuals(TimelineItem()),
135 predictionState(PredictionState::None) {
136 this->surfaceFrames.reserve(kNumSurfaceFramesInitial);
137}
138
139std::unique_ptr<android::frametimeline::SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
140 const std::string& layerName, std::optional<int64_t> token) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700141 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700142 if (!token) {
143 return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::None,
144 TimelineItem());
145 }
146 std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
147 if (predictions) {
148 return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::Valid,
149 std::move(*predictions));
150 }
151 return std::make_unique<impl::SurfaceFrame>(layerName, PredictionState::Expired,
152 TimelineItem());
153}
154
155void FrameTimeline::addSurfaceFrame(
156 std::unique_ptr<android::frametimeline::SurfaceFrame> surfaceFrame,
157 SurfaceFrame::PresentState state) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700158 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700159 surfaceFrame->setPresentState(state);
160 std::unique_ptr<impl::SurfaceFrame> implSurfaceFrame(
161 static_cast<impl::SurfaceFrame*>(surfaceFrame.release()));
162 std::lock_guard<std::mutex> lock(mMutex);
163 mCurrentDisplayFrame->surfaceFrames.push_back(std::move(implSurfaceFrame));
164}
165
166void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700167 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700168 const std::optional<TimelineItem> prediction = mTokenManager.getPredictionsForToken(token);
169 std::lock_guard<std::mutex> lock(mMutex);
170 if (!prediction) {
171 mCurrentDisplayFrame->predictionState = PredictionState::Expired;
172 } else {
173 mCurrentDisplayFrame->surfaceFlingerPredictions = *prediction;
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700174 mCurrentDisplayFrame->predictionState = PredictionState::Valid;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700175 }
176 mCurrentDisplayFrame->surfaceFlingerActuals.startTime = wakeUpTime;
177}
178
179void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
180 const std::shared_ptr<FenceTime>& presentFence) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700181 ATRACE_CALL();
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700182 std::lock_guard<std::mutex> lock(mMutex);
183 mCurrentDisplayFrame->surfaceFlingerActuals.endTime = sfPresentTime;
184 mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
185 flushPendingPresentFences();
186 finalizeCurrentDisplayFrame();
187}
188
189void FrameTimeline::flushPendingPresentFences() {
190 for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
191 const auto& pendingPresentFence = mPendingPresentFences[i];
192 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
193 if (pendingPresentFence.first && pendingPresentFence.first->isValid()) {
194 signalTime = pendingPresentFence.first->getSignalTime();
195 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
196 continue;
197 }
198 }
199 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
200 auto& displayFrame = pendingPresentFence.second;
201 displayFrame->surfaceFlingerActuals.presentTime = signalTime;
202 for (auto& surfaceFrame : displayFrame->surfaceFrames) {
203 if (surfaceFrame->getPresentState() == SurfaceFrame::PresentState::Presented) {
204 // Only presented SurfaceFrames need to be updated
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700205 surfaceFrame->setActualPresentTime(signalTime);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700206 }
207 }
208 }
209
210 mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
211 --i;
212 }
213}
214
215void FrameTimeline::finalizeCurrentDisplayFrame() {
216 while (mDisplayFrames.size() >= kMaxDisplayFrames) {
217 // We maintain only a fixed number of frames' data. Pop older frames
218 mDisplayFrames.pop_front();
219 }
220 mDisplayFrames.push_back(mCurrentDisplayFrame);
221 mCurrentDisplayFrame.reset();
222 mCurrentDisplayFrame = std::make_shared<DisplayFrame>();
223}
224
225void FrameTimeline::dump(std::string& result) {
226 std::lock_guard<std::mutex> lock(mMutex);
227 StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
228 for (const auto& displayFrame : mDisplayFrames) {
229 StringAppendF(&result, "---Display Frame---\n");
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -0700230 StringAppendF(&result, "Prediction State : %d\n",
231 static_cast<int>(displayFrame->predictionState));
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700232 StringAppendF(&result, "Predicted SF wake time : %" PRId64 "\n",
233 displayFrame->surfaceFlingerPredictions.startTime);
234 StringAppendF(&result, "Actual SF wake time : %" PRId64 "\n",
235 displayFrame->surfaceFlingerActuals.startTime);
236 StringAppendF(&result, "Predicted SF Complete time : %" PRId64 "\n",
237 displayFrame->surfaceFlingerPredictions.endTime);
238 StringAppendF(&result, "Actual SF Complete time : %" PRId64 "\n",
239 displayFrame->surfaceFlingerActuals.endTime);
240 StringAppendF(&result, "Predicted Present time : %" PRId64 "\n",
241 displayFrame->surfaceFlingerPredictions.presentTime);
242 StringAppendF(&result, "Actual Present time : %" PRId64 "\n",
243 displayFrame->surfaceFlingerActuals.presentTime);
244 for (size_t i = 0; i < displayFrame->surfaceFrames.size(); i++) {
245 StringAppendF(&result, "Surface frame - %" PRId32 "\n", (int)i);
246 displayFrame->surfaceFrames[i]->dump(result);
247 }
248 }
249}
250
251} // namespace android::frametimeline::impl