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