blob: 69efd7f477c20f2d3023c6ab54bcd253c9744da4 [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 "LibSurfaceFlingerUnittests"
19
20#include <FrameTimeline/FrameTimeline.h>
21#include <gtest/gtest.h>
22#include <log/log.h>
23#include <cinttypes>
24
25using namespace std::chrono_literals;
26
27namespace android::frametimeline {
28
29class FrameTimelineTest : public testing::Test {
30public:
31 FrameTimelineTest() {
32 const ::testing::TestInfo* const test_info =
33 ::testing::UnitTest::GetInstance()->current_test_info();
34 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
35 }
36
37 ~FrameTimelineTest() {
38 const ::testing::TestInfo* const test_info =
39 ::testing::UnitTest::GetInstance()->current_test_info();
40 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
41 }
42
43 void SetUp() override {
44 mFrameTimeline = std::make_unique<impl::FrameTimeline>();
45 mTokenManager = &mFrameTimeline->mTokenManager;
Adithya Srinivasan2d736322020-10-01 16:53:48 -070046 maxDisplayFrames = &mFrameTimeline->mMaxDisplayFrames;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070047 maxTokenRetentionTime = mTokenManager->kMaxRetentionTime;
48 }
49
50 void flushTokens(nsecs_t flushTime) {
51 std::lock_guard<std::mutex> lock(mTokenManager->mMutex);
52 mTokenManager->flushTokens(flushTime);
53 }
54
55 SurfaceFrame& getSurfaceFrame(size_t displayFrameIdx, size_t surfaceFrameIdx) {
56 std::lock_guard<std::mutex> lock(mFrameTimeline->mMutex);
57 return *(mFrameTimeline->mDisplayFrames[displayFrameIdx]->surfaceFrames[surfaceFrameIdx]);
58 }
59
60 std::shared_ptr<impl::FrameTimeline::DisplayFrame> getDisplayFrame(size_t idx) {
61 std::lock_guard<std::mutex> lock(mFrameTimeline->mMutex);
62 return mFrameTimeline->mDisplayFrames[idx];
63 }
64
65 static bool compareTimelineItems(const TimelineItem& a, const TimelineItem& b) {
66 return a.startTime == b.startTime && a.endTime == b.endTime &&
67 a.presentTime == b.presentTime;
68 }
69
70 const std::unordered_map<int64_t, TimelineItem>& getPredictions() {
71 return mTokenManager->mPredictions;
72 }
73
Adithya Srinivasan2d736322020-10-01 16:53:48 -070074 uint32_t getNumberOfDisplayFrames() {
75 std::lock_guard<std::mutex> lock(mFrameTimeline->mMutex);
76 return static_cast<uint32_t>(mFrameTimeline->mDisplayFrames.size());
77 }
78
Adithya Srinivasanf279e042020-08-17 14:56:27 -070079 std::unique_ptr<impl::FrameTimeline> mFrameTimeline;
80 impl::TokenManager* mTokenManager;
81 FenceToFenceTimeMap fenceFactory;
Adithya Srinivasan2d736322020-10-01 16:53:48 -070082 uint32_t* maxDisplayFrames;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070083 nsecs_t maxTokenRetentionTime;
84};
85
86TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
87 int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
88 EXPECT_EQ(getPredictions().size(), 1);
89 flushTokens(systemTime() + maxTokenRetentionTime);
90 int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
91 std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);
92
93 // token1 should have expired
94 EXPECT_EQ(getPredictions().size(), 1);
95 EXPECT_EQ(predictions.has_value(), false);
96
97 predictions = mTokenManager->getPredictionsForToken(token2);
98 EXPECT_EQ(compareTimelineItems(*predictions, TimelineItem(10, 20, 30)), true);
99}
100
101TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) {
102 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", std::nullopt);
103 EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None);
104}
105
106TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
107 int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
108 flushTokens(systemTime() + maxTokenRetentionTime);
109 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", token1);
110
111 EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired);
112}
113
114TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) {
115 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
116 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", token1);
117
118 EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid);
119 EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true);
120}
121
122TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
123 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
124 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
125
126 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
127 int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
128 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken("layer1", token1);
129
130 // Set up the display frame
131 mFrameTimeline->setSfWakeUp(token1, 20);
132 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped);
133 mFrameTimeline->setSfPresent(25, presentFence1);
134 presentFence1->signalForTest(30);
135
136 // Trigger a flush by calling setSfPresent for the next frame
137 mFrameTimeline->setSfWakeUp(token2, 50);
138 mFrameTimeline->setSfPresent(55, presentFence2);
139
140 auto& droppedSurfaceFrame = getSurfaceFrame(0, 0);
141 EXPECT_EQ(droppedSurfaceFrame.getPresentState(), SurfaceFrame::PresentState::Dropped);
142 EXPECT_EQ(droppedSurfaceFrame.getActuals().presentTime, 0);
143}
144
145TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) {
146 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
147 int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
148 int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
149 int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
150 int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60});
151 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken("layer1", surfaceFrameToken1);
152 auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken("layer2", surfaceFrameToken1);
153 mFrameTimeline->setSfWakeUp(sfToken1, 22);
154 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
155 SurfaceFrame::PresentState::Presented);
156 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame2),
157 SurfaceFrame::PresentState::Presented);
158 mFrameTimeline->setSfPresent(26, presentFence1);
159 auto displayFrame = getDisplayFrame(0);
160 SurfaceFrame& presentedSurfaceFrame1 = getSurfaceFrame(0, 0);
161 SurfaceFrame& presentedSurfaceFrame2 = getSurfaceFrame(0, 1);
162 presentFence1->signalForTest(42);
163
164 // Fences haven't been flushed yet, so it should be 0
165 EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 0);
166 EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 0);
167 EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0);
168
169 // Trigger a flush by finalizing the next DisplayFrame
170 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
171 auto surfaceFrame3 = mFrameTimeline->createSurfaceFrameForToken("layer1", surfaceFrameToken2);
172 mFrameTimeline->setSfWakeUp(sfToken2, 52);
173 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame3), SurfaceFrame::PresentState::Dropped);
174 mFrameTimeline->setSfPresent(56, presentFence2);
175 displayFrame = getDisplayFrame(0);
176
177 // Fences have flushed, so the present timestamps should be updated
178 EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 42);
179 EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 42);
180 EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42);
181}
182
183TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) {
184 // Insert kMaxDisplayFrames' count of DisplayFrames to fill the deque
185 int frameTimeFactor = 0;
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700186 for (size_t i = 0; i < *maxDisplayFrames; i++) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700187 auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
188 int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions(
189 {10 + frameTimeFactor, 20 + frameTimeFactor, 30 + frameTimeFactor});
190 int64_t sfToken = mTokenManager->generateTokenForPredictions(
191 {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
192 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", surfaceFrameToken);
193 mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor);
194 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
195 SurfaceFrame::PresentState::Presented);
196 mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
197 presentFence->signalForTest(32 + frameTimeFactor);
198 frameTimeFactor += 30;
199 }
200 auto displayFrame0 = getDisplayFrame(0);
201
202 // The 0th Display Frame should have actuals 22, 27, 32
203 EXPECT_EQ(compareTimelineItems(displayFrame0->surfaceFlingerActuals, TimelineItem(22, 27, 32)),
204 true);
205
206 // Add one more display frame
207 auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
208 int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions(
209 {10 + frameTimeFactor, 20 + frameTimeFactor, 30 + frameTimeFactor});
210 int64_t sfToken = mTokenManager->generateTokenForPredictions(
211 {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
212 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", surfaceFrameToken);
213 mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor);
214 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), SurfaceFrame::PresentState::Presented);
215 mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
216 presentFence->signalForTest(32 + frameTimeFactor);
217 displayFrame0 = getDisplayFrame(0);
218
219 // The window should have slided by 1 now and the previous 0th display frame
220 // should have been removed from the deque
221 EXPECT_EQ(compareTimelineItems(displayFrame0->surfaceFlingerActuals, TimelineItem(52, 57, 62)),
222 true);
223}
224
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700225TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) {
226 auto surfaceFrame =
227 mFrameTimeline->createSurfaceFrameForToken("acquireFenceAfterQueue", std::nullopt);
228 surfaceFrame->setActualQueueTime(123);
229 surfaceFrame->setAcquireFenceTime(456);
230 EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
231}
232
233TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) {
234 auto surfaceFrame =
235 mFrameTimeline->createSurfaceFrameForToken("acquireFenceAfterQueue", std::nullopt);
236 surfaceFrame->setActualQueueTime(456);
237 surfaceFrame->setAcquireFenceTime(123);
238 EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
239}
240
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700241TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) {
242 auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
243 presentFence->signalForTest(2);
244
245 // Size shouldn't exceed maxDisplayFrames - 64
246 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
247 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", std::nullopt);
248 int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
249 mFrameTimeline->setSfWakeUp(sfToken, 22);
250 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
251 SurfaceFrame::PresentState::Presented);
252 mFrameTimeline->setSfPresent(27, presentFence);
253 }
254 EXPECT_EQ(getNumberOfDisplayFrames(), *maxDisplayFrames);
255
256 // Increase the size to 256
257 mFrameTimeline->setMaxDisplayFrames(256);
258 EXPECT_EQ(*maxDisplayFrames, 256);
259
260 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
261 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", std::nullopt);
262 int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
263 mFrameTimeline->setSfWakeUp(sfToken, 22);
264 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
265 SurfaceFrame::PresentState::Presented);
266 mFrameTimeline->setSfPresent(27, presentFence);
267 }
268 EXPECT_EQ(getNumberOfDisplayFrames(), *maxDisplayFrames);
269
270 // Shrink the size to 128
271 mFrameTimeline->setMaxDisplayFrames(128);
272 EXPECT_EQ(*maxDisplayFrames, 128);
273
274 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
275 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken("layer1", std::nullopt);
276 int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
277 mFrameTimeline->setSfWakeUp(sfToken, 22);
278 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
279 SurfaceFrame::PresentState::Presented);
280 mFrameTimeline->setSfPresent(27, presentFence);
281 }
282 EXPECT_EQ(getNumberOfDisplayFrames(), *maxDisplayFrames);
283}
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700284} // namespace android::frametimeline