blob: cb617d6e71aa633244f76958570c0b35d8d7c373 [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
Alec Mouri9a29e672020-09-14 12:39:14 -070017#include "gmock/gmock-spec-builders.h"
18#include "mock/MockTimeStats.h"
Adithya Srinivasanf279e042020-08-17 14:56:27 -070019#undef LOG_TAG
20#define LOG_TAG "LibSurfaceFlingerUnittests"
21
22#include <FrameTimeline/FrameTimeline.h>
23#include <gtest/gtest.h>
24#include <log/log.h>
Adithya Srinivasan01189672020-10-20 14:23:05 -070025#include <perfetto/trace/trace.pb.h>
Adithya Srinivasanf279e042020-08-17 14:56:27 -070026#include <cinttypes>
27
28using namespace std::chrono_literals;
Alec Mouri9a29e672020-09-14 12:39:14 -070029using testing::Contains;
Adithya Srinivasan01189672020-10-20 14:23:05 -070030using FrameTimelineEvent = perfetto::protos::FrameTimelineEvent;
31using ProtoDisplayFrame = perfetto::protos::FrameTimelineEvent_DisplayFrame;
32using ProtoSurfaceFrame = perfetto::protos::FrameTimelineEvent_SurfaceFrame;
33using ProtoPresentType = perfetto::protos::FrameTimelineEvent_PresentType;
34using ProtoJankType = perfetto::protos::FrameTimelineEvent_JankType;
Alec Mouri9a29e672020-09-14 12:39:14 -070035
36MATCHER_P(HasBit, bit, "") {
37 return (arg & bit) != 0;
38}
Adithya Srinivasanf279e042020-08-17 14:56:27 -070039
40namespace android::frametimeline {
41
42class FrameTimelineTest : public testing::Test {
43public:
44 FrameTimelineTest() {
45 const ::testing::TestInfo* const test_info =
46 ::testing::UnitTest::GetInstance()->current_test_info();
47 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
48 }
49
50 ~FrameTimelineTest() {
51 const ::testing::TestInfo* const test_info =
52 ::testing::UnitTest::GetInstance()->current_test_info();
53 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
54 }
55
Adithya Srinivasan01189672020-10-20 14:23:05 -070056 static void SetUpTestSuite() {
57 // Need to initialize tracing in process for testing, and only once per test suite.
58 perfetto::TracingInitArgs args;
59 args.backends = perfetto::kInProcessBackend;
60 perfetto::Tracing::Initialize(args);
61 }
62
Adithya Srinivasanf279e042020-08-17 14:56:27 -070063 void SetUp() override {
Alec Mouri9a29e672020-09-14 12:39:14 -070064 mTimeStats = std::make_shared<mock::TimeStats>();
65 mFrameTimeline = std::make_unique<impl::FrameTimeline>(mTimeStats);
Adithya Srinivasan01189672020-10-20 14:23:05 -070066 mFrameTimeline->registerDataSource();
Adithya Srinivasanf279e042020-08-17 14:56:27 -070067 mTokenManager = &mFrameTimeline->mTokenManager;
Adithya Srinivasan2d736322020-10-01 16:53:48 -070068 maxDisplayFrames = &mFrameTimeline->mMaxDisplayFrames;
Adithya Srinivasanf279e042020-08-17 14:56:27 -070069 maxTokenRetentionTime = mTokenManager->kMaxRetentionTime;
70 }
71
Adithya Srinivasan01189672020-10-20 14:23:05 -070072 // Each tracing session can be used for a single block of Start -> Stop.
73 static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
74 perfetto::TraceConfig cfg;
75 cfg.set_duration_ms(500);
76 cfg.add_buffers()->set_size_kb(1024);
77 auto* ds_cfg = cfg.add_data_sources()->mutable_config();
78 ds_cfg->set_name(impl::FrameTimeline::kFrameTimelineDataSource);
79
80 auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
81 tracingSession->Setup(cfg);
82 return tracingSession;
83 }
84
85 std::vector<perfetto::protos::TracePacket> readFrameTimelinePacketsBlocking(
86 perfetto::TracingSession* tracingSession) {
87 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
88 perfetto::protos::Trace trace;
89 EXPECT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
90
91 std::vector<perfetto::protos::TracePacket> packets;
92 for (const auto& packet : trace.packet()) {
93 if (!packet.has_frame_timeline_event()) {
94 continue;
95 }
96 packets.emplace_back(packet);
97 }
98 return packets;
99 }
100
101 void addEmptyDisplayFrame() {
102 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
103 mFrameTimeline->setSfPresent(2500, presentFence1);
104 }
105
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700106 void flushTokens(nsecs_t flushTime) {
107 std::lock_guard<std::mutex> lock(mTokenManager->mMutex);
108 mTokenManager->flushTokens(flushTime);
109 }
110
111 SurfaceFrame& getSurfaceFrame(size_t displayFrameIdx, size_t surfaceFrameIdx) {
112 std::lock_guard<std::mutex> lock(mFrameTimeline->mMutex);
113 return *(mFrameTimeline->mDisplayFrames[displayFrameIdx]->surfaceFrames[surfaceFrameIdx]);
114 }
115
116 std::shared_ptr<impl::FrameTimeline::DisplayFrame> getDisplayFrame(size_t idx) {
117 std::lock_guard<std::mutex> lock(mFrameTimeline->mMutex);
118 return mFrameTimeline->mDisplayFrames[idx];
119 }
120
121 static bool compareTimelineItems(const TimelineItem& a, const TimelineItem& b) {
122 return a.startTime == b.startTime && a.endTime == b.endTime &&
123 a.presentTime == b.presentTime;
124 }
125
126 const std::unordered_map<int64_t, TimelineItem>& getPredictions() {
127 return mTokenManager->mPredictions;
128 }
129
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700130 uint32_t getNumberOfDisplayFrames() {
131 std::lock_guard<std::mutex> lock(mFrameTimeline->mMutex);
132 return static_cast<uint32_t>(mFrameTimeline->mDisplayFrames.size());
133 }
134
Alec Mouri9a29e672020-09-14 12:39:14 -0700135 std::shared_ptr<mock::TimeStats> mTimeStats;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700136 std::unique_ptr<impl::FrameTimeline> mFrameTimeline;
137 impl::TokenManager* mTokenManager;
138 FenceToFenceTimeMap fenceFactory;
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700139 uint32_t* maxDisplayFrames;
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700140 nsecs_t maxTokenRetentionTime;
141};
142
Alec Mouri9a29e672020-09-14 12:39:14 -0700143static const std::string sLayerNameOne = "layer1";
144static const std::string sLayerNameTwo = "layer2";
145static constexpr const uid_t sUidOne = 0;
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700146static constexpr pid_t sPidOne = 10;
147static constexpr pid_t sPidTwo = 20;
Alec Mouri9a29e672020-09-14 12:39:14 -0700148
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700149TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
150 int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
151 EXPECT_EQ(getPredictions().size(), 1);
152 flushTokens(systemTime() + maxTokenRetentionTime);
153 int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
154 std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);
155
156 // token1 should have expired
157 EXPECT_EQ(getPredictions().size(), 1);
158 EXPECT_EQ(predictions.has_value(), false);
159
160 predictions = mTokenManager->getPredictionsForToken(token2);
161 EXPECT_EQ(compareTimelineItems(*predictions, TimelineItem(10, 20, 30)), true);
162}
163
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700164TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) {
165 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
166 sLayerNameOne, std::nullopt);
167 auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(sPidTwo, sUidOne, sLayerNameOne,
168 sLayerNameOne, std::nullopt);
169 EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne);
170 EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo);
171}
172
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700173TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) {
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700174 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
Alec Mouri9a29e672020-09-14 12:39:14 -0700175 sLayerNameOne, std::nullopt);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700176 EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None);
177}
178
179TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
180 int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
181 flushTokens(systemTime() + maxTokenRetentionTime);
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700182 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
Alec Mouri9a29e672020-09-14 12:39:14 -0700183 sLayerNameOne, token1);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700184
185 EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired);
186}
187
188TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) {
189 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700190 auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
Alec Mouri9a29e672020-09-14 12:39:14 -0700191 sLayerNameOne, token1);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700192
193 EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid);
194 EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true);
195}
196
197TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
198 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
199 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
200
201 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
202 int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700203 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
Alec Mouri9a29e672020-09-14 12:39:14 -0700204 sLayerNameOne, token1);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700205
206 // Set up the display frame
207 mFrameTimeline->setSfWakeUp(token1, 20);
208 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped);
209 mFrameTimeline->setSfPresent(25, presentFence1);
210 presentFence1->signalForTest(30);
211
212 // Trigger a flush by calling setSfPresent for the next frame
213 mFrameTimeline->setSfWakeUp(token2, 50);
214 mFrameTimeline->setSfPresent(55, presentFence2);
215
216 auto& droppedSurfaceFrame = getSurfaceFrame(0, 0);
217 EXPECT_EQ(droppedSurfaceFrame.getPresentState(), SurfaceFrame::PresentState::Dropped);
218 EXPECT_EQ(droppedSurfaceFrame.getActuals().presentTime, 0);
219}
220
221TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) {
222 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
223 int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
224 int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
225 int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
226 int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60});
Alec Mouri9a29e672020-09-14 12:39:14 -0700227 auto surfaceFrame1 =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700228 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
229 sLayerNameOne, surfaceFrameToken1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700230 auto surfaceFrame2 =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700231 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameTwo,
232 sLayerNameTwo, surfaceFrameToken1);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700233 mFrameTimeline->setSfWakeUp(sfToken1, 22);
234 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
235 SurfaceFrame::PresentState::Presented);
236 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame2),
237 SurfaceFrame::PresentState::Presented);
238 mFrameTimeline->setSfPresent(26, presentFence1);
239 auto displayFrame = getDisplayFrame(0);
240 SurfaceFrame& presentedSurfaceFrame1 = getSurfaceFrame(0, 0);
241 SurfaceFrame& presentedSurfaceFrame2 = getSurfaceFrame(0, 1);
242 presentFence1->signalForTest(42);
243
244 // Fences haven't been flushed yet, so it should be 0
245 EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 0);
246 EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 0);
247 EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0);
248
249 // Trigger a flush by finalizing the next DisplayFrame
250 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
Alec Mouri9a29e672020-09-14 12:39:14 -0700251 auto surfaceFrame3 =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700252 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
253 sLayerNameOne, surfaceFrameToken2);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700254 mFrameTimeline->setSfWakeUp(sfToken2, 52);
255 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame3), SurfaceFrame::PresentState::Dropped);
256 mFrameTimeline->setSfPresent(56, presentFence2);
257 displayFrame = getDisplayFrame(0);
258
259 // Fences have flushed, so the present timestamps should be updated
260 EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 42);
261 EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 42);
262 EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42);
263}
264
265TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) {
266 // Insert kMaxDisplayFrames' count of DisplayFrames to fill the deque
267 int frameTimeFactor = 0;
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700268 for (size_t i = 0; i < *maxDisplayFrames; i++) {
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700269 auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
270 int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions(
271 {10 + frameTimeFactor, 20 + frameTimeFactor, 30 + frameTimeFactor});
272 int64_t sfToken = mTokenManager->generateTokenForPredictions(
273 {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
Alec Mouri9a29e672020-09-14 12:39:14 -0700274 auto surfaceFrame =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700275 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
276 sLayerNameOne, surfaceFrameToken);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700277 mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor);
278 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
279 SurfaceFrame::PresentState::Presented);
280 mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
281 presentFence->signalForTest(32 + frameTimeFactor);
282 frameTimeFactor += 30;
283 }
284 auto displayFrame0 = getDisplayFrame(0);
285
286 // The 0th Display Frame should have actuals 22, 27, 32
287 EXPECT_EQ(compareTimelineItems(displayFrame0->surfaceFlingerActuals, TimelineItem(22, 27, 32)),
288 true);
289
290 // Add one more display frame
291 auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
292 int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions(
293 {10 + frameTimeFactor, 20 + frameTimeFactor, 30 + frameTimeFactor});
294 int64_t sfToken = mTokenManager->generateTokenForPredictions(
295 {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
Alec Mouri9a29e672020-09-14 12:39:14 -0700296 auto surfaceFrame =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700297 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
298 sLayerNameOne, surfaceFrameToken);
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700299 mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor);
300 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), SurfaceFrame::PresentState::Presented);
301 mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
302 presentFence->signalForTest(32 + frameTimeFactor);
303 displayFrame0 = getDisplayFrame(0);
304
305 // The window should have slided by 1 now and the previous 0th display frame
306 // should have been removed from the deque
307 EXPECT_EQ(compareTimelineItems(displayFrame0->surfaceFlingerActuals, TimelineItem(52, 57, 62)),
308 true);
309}
310
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700311TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) {
312 auto surfaceFrame =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700313 mFrameTimeline->createSurfaceFrameForToken(sPidOne, 0, "acquireFenceAfterQueue",
Alec Mouri9a29e672020-09-14 12:39:14 -0700314 "acquireFenceAfterQueue", std::nullopt);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700315 surfaceFrame->setActualQueueTime(123);
316 surfaceFrame->setAcquireFenceTime(456);
317 EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
318}
319
320TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) {
321 auto surfaceFrame =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700322 mFrameTimeline->createSurfaceFrameForToken(sPidOne, 0, "acquireFenceAfterQueue",
Alec Mouri9a29e672020-09-14 12:39:14 -0700323 "acquireFenceAfterQueue", std::nullopt);
Ady Abraham7f8a1e62020-09-28 16:09:35 -0700324 surfaceFrame->setActualQueueTime(456);
325 surfaceFrame->setAcquireFenceTime(123);
326 EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
327}
328
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700329TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) {
330 auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
331 presentFence->signalForTest(2);
332
333 // Size shouldn't exceed maxDisplayFrames - 64
334 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700335 auto surfaceFrame =
336 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
337 sLayerNameOne, std::nullopt);
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700338 int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
339 mFrameTimeline->setSfWakeUp(sfToken, 22);
340 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
341 SurfaceFrame::PresentState::Presented);
342 mFrameTimeline->setSfPresent(27, presentFence);
343 }
344 EXPECT_EQ(getNumberOfDisplayFrames(), *maxDisplayFrames);
345
346 // Increase the size to 256
347 mFrameTimeline->setMaxDisplayFrames(256);
348 EXPECT_EQ(*maxDisplayFrames, 256);
349
350 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700351 auto surfaceFrame =
352 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
353 sLayerNameOne, std::nullopt);
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700354 int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
355 mFrameTimeline->setSfWakeUp(sfToken, 22);
356 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
357 SurfaceFrame::PresentState::Presented);
358 mFrameTimeline->setSfPresent(27, presentFence);
359 }
360 EXPECT_EQ(getNumberOfDisplayFrames(), *maxDisplayFrames);
361
362 // Shrink the size to 128
363 mFrameTimeline->setMaxDisplayFrames(128);
364 EXPECT_EQ(*maxDisplayFrames, 128);
365
366 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700367 auto surfaceFrame =
368 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
369 sLayerNameOne, std::nullopt);
Adithya Srinivasan2d736322020-10-01 16:53:48 -0700370 int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
371 mFrameTimeline->setSfWakeUp(sfToken, 22);
372 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame),
373 SurfaceFrame::PresentState::Presented);
374 mFrameTimeline->setSfPresent(27, presentFence);
375 }
376 EXPECT_EQ(getNumberOfDisplayFrames(), *maxDisplayFrames);
377}
Alec Mouri9a29e672020-09-14 12:39:14 -0700378
379TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) {
380 EXPECT_CALL(*mTimeStats,
381 incrementJankyFrames(sUidOne, sLayerNameOne,
382 HasBit(TimeStats::JankType::SurfaceFlingerDeadlineMissed)));
383 EXPECT_CALL(*mTimeStats,
384 incrementJankyFrames(HasBit(TimeStats::JankType::SurfaceFlingerDeadlineMissed)));
385 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
386 int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
387 {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
388 std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
389 std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
390 int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
391 {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
392 std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
393 std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
394 auto surfaceFrame1 =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700395 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
396 sLayerNameOne, surfaceFrameToken1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700397 mFrameTimeline->setSfWakeUp(sfToken1,
398 std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count());
399 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
400 SurfaceFrame::PresentState::Presented);
401 presentFence1->signalForTest(
402 std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
403
404 mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(),
405 presentFence1);
406}
407
408TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) {
409 EXPECT_CALL(*mTimeStats,
410 incrementJankyFrames(sUidOne, sLayerNameOne, HasBit(TimeStats::JankType::Display)));
411 EXPECT_CALL(*mTimeStats, incrementJankyFrames(HasBit(TimeStats::JankType::Display)));
412 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
413 int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
414 {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
415 std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
416 std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
417 int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
418 {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
419 std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
420 std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
421 auto surfaceFrame1 =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700422 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
423 sLayerNameOne, surfaceFrameToken1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700424 mFrameTimeline->setSfWakeUp(sfToken1,
425 std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count());
426 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
427 SurfaceFrame::PresentState::Presented);
428 presentFence1->signalForTest(
429 std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
430 mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(59ms).count(),
431 presentFence1);
432}
433
434TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) {
435 EXPECT_CALL(*mTimeStats,
436 incrementJankyFrames(sUidOne, sLayerNameOne,
437 HasBit(TimeStats::JankType::AppDeadlineMissed)));
438 EXPECT_CALL(*mTimeStats, incrementJankyFrames(HasBit(TimeStats::JankType::AppDeadlineMissed)));
439 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
440 int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
441 {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
442 std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
443 std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
444 int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
445 {std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
446 std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
447 std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
448 auto surfaceFrame1 =
Adithya Srinivasan9febda82020-10-19 10:49:41 -0700449 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
450 sLayerNameOne, surfaceFrameToken1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700451 surfaceFrame1->setAcquireFenceTime(
452 std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
453 mFrameTimeline->setSfWakeUp(sfToken1,
454 std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count());
455
456 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
457 SurfaceFrame::PresentState::Presented);
458 presentFence1->signalForTest(
459 std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
460 mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
461 presentFence1);
462}
463
Adithya Srinivasan01189672020-10-20 14:23:05 -0700464/*
465 * Tracing Tests
466 *
467 * Trace packets are flushed all the way only when the next packet is traced.
468 * For example: trace<Display/Surface>Frame() will create a TracePacket but not flush it. Only when
469 * another TracePacket is created, the previous one is guaranteed to be flushed. The following tests
470 * will have additional empty frames created for this reason.
471 */
472TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) {
473 auto tracingSession = getTracingSessionForTest();
474 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
475 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
476
477 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
478 int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
479 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
480 sLayerNameOne, token1);
481
482 // Set up the display frame
483 mFrameTimeline->setSfWakeUp(token1, 20);
484 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped);
485 mFrameTimeline->setSfPresent(25, presentFence1);
486 presentFence1->signalForTest(30);
487
488 // Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
489 // next frame
490 mFrameTimeline->setSfWakeUp(token2, 50);
491 mFrameTimeline->setSfPresent(55, presentFence2);
492
493 auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
494 EXPECT_EQ(packets.size(), 0);
495}
496
497TEST_F(FrameTimelineTest, tracing_sanityTest) {
498 auto tracingSession = getTracingSessionForTest();
499 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
500 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
501
502 tracingSession->StartBlocking();
503 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
504 int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
505 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
506 sLayerNameOne, token1);
507
508 // Set up the display frame
509 mFrameTimeline->setSfWakeUp(token2, 20);
510 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
511 SurfaceFrame::PresentState::Presented);
512 mFrameTimeline->setSfPresent(25, presentFence1);
513 presentFence1->signalForTest(30);
514
515 // Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
516 // next frame
517 mFrameTimeline->setSfWakeUp(token2, 50);
518 mFrameTimeline->setSfPresent(55, presentFence2);
519 presentFence2->signalForTest(55);
520
521 // The SurfaceFrame packet from the first frame is emitted, but not flushed yet. Emitting a new
522 // packet will flush it. To emit a new packet, we'll need to call flushPendingPresentFences()
523 // again, which is done by setSfPresent().
524 addEmptyDisplayFrame();
525 tracingSession->StopBlocking();
526
527 auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
528 // Display Frame 1 has two packets - DisplayFrame and a SurfaceFrame.
529 // Display Frame 2 has one packet - DisplayFrame. However, this packet has been emitted but not
530 // flushed through traced, so this is not counted.
531 EXPECT_EQ(packets.size(), 2);
532}
533
534TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) {
535 auto tracingSession = getTracingSessionForTest();
536 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
537 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
538
539 tracingSession->StartBlocking();
540 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
541
542 // Set up the display frame
543 mFrameTimeline->setSfWakeUp(-1, 20);
544 mFrameTimeline->setSfPresent(25, presentFence1);
545 presentFence1->signalForTest(30);
546
547 // Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
548 // next frame
549 mFrameTimeline->setSfWakeUp(token1, 50);
550 mFrameTimeline->setSfPresent(55, presentFence2);
551 presentFence2->signalForTest(60);
552
553 addEmptyDisplayFrame();
554 tracingSession->StopBlocking();
555
556 auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
557 // Display Frame 1 has no packets.
558 // Display Frame 2 has one packet - DisplayFrame. However, this packet has
559 // been emitted but not flushed through traced, so this is not counted.
560 EXPECT_EQ(packets.size(), 0);
561}
562
563TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) {
564 auto tracingSession = getTracingSessionForTest();
565 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
566 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
567
568 tracingSession->StartBlocking();
569 int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
570 int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
571 auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
572 sLayerNameOne, std::nullopt);
573
574 // Set up the display frame
575 mFrameTimeline->setSfWakeUp(token1, 20);
576 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped);
577 mFrameTimeline->setSfPresent(25, presentFence1);
578 presentFence1->signalForTest(30);
579
580 // Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
581 // next frame
582 mFrameTimeline->setSfWakeUp(token2, 50);
583 mFrameTimeline->setSfPresent(55, presentFence2);
584 presentFence2->signalForTest(60);
585
586 addEmptyDisplayFrame();
587 tracingSession->StopBlocking();
588
589 auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
590 // Display Frame 1 has one packet - DisplayFrame (SurfaceFrame shouldn't be traced since it has
591 // an invalid token).
592 // Display Frame 2 has one packet - DisplayFrame. However, this packet has
593 // been emitted but not flushed through traced, so this is not counted.
594 EXPECT_EQ(packets.size(), 1);
595}
596
597void validateDisplayFrameEvent(const ProtoDisplayFrame& received, const ProtoDisplayFrame& source) {
598 ASSERT_TRUE(received.has_token());
599 EXPECT_EQ(received.token(), source.token());
600
601 ASSERT_TRUE(received.has_present_type());
602 EXPECT_EQ(received.present_type(), source.present_type());
603 ASSERT_TRUE(received.has_on_time_finish());
604 EXPECT_EQ(received.on_time_finish(), source.on_time_finish());
605 ASSERT_TRUE(received.has_gpu_composition());
606 EXPECT_EQ(received.gpu_composition(), source.gpu_composition());
607 ASSERT_TRUE(received.has_jank_type());
608 EXPECT_EQ(received.jank_type(), source.jank_type());
609
610 ASSERT_TRUE(received.has_expected_start_ns());
611 EXPECT_EQ(received.expected_start_ns(), source.expected_start_ns());
612 ASSERT_TRUE(received.has_expected_end_ns());
613 EXPECT_EQ(received.expected_end_ns(), source.expected_end_ns());
614
615 ASSERT_TRUE(received.has_actual_start_ns());
616 EXPECT_EQ(received.actual_start_ns(), source.actual_start_ns());
617 ASSERT_TRUE(received.has_actual_end_ns());
618 EXPECT_EQ(received.actual_end_ns(), source.actual_end_ns());
619}
620
621void validateSurfaceFrameEvent(const ProtoSurfaceFrame& received, const ProtoSurfaceFrame& source) {
622 ASSERT_TRUE(received.has_token());
623 EXPECT_EQ(received.token(), source.token());
624
625 ASSERT_TRUE(received.has_display_frame_token());
626 EXPECT_EQ(received.display_frame_token(), source.display_frame_token());
627
628 ASSERT_TRUE(received.has_present_type());
629 EXPECT_EQ(received.present_type(), source.present_type());
630 ASSERT_TRUE(received.has_on_time_finish());
631 EXPECT_EQ(received.on_time_finish(), source.on_time_finish());
632 ASSERT_TRUE(received.has_gpu_composition());
633 EXPECT_EQ(received.gpu_composition(), source.gpu_composition());
634 ASSERT_TRUE(received.has_jank_type());
635 EXPECT_EQ(received.jank_type(), source.jank_type());
636
637 ASSERT_TRUE(received.has_expected_start_ns());
638 EXPECT_EQ(received.expected_start_ns(), source.expected_start_ns());
639 ASSERT_TRUE(received.has_expected_end_ns());
640 EXPECT_EQ(received.expected_end_ns(), source.expected_end_ns());
641
642 ASSERT_TRUE(received.has_actual_start_ns());
643 EXPECT_EQ(received.actual_start_ns(), source.actual_start_ns());
644 ASSERT_TRUE(received.has_actual_end_ns());
645 EXPECT_EQ(received.actual_end_ns(), source.actual_end_ns());
646
647 ASSERT_TRUE(received.has_layer_name());
648 EXPECT_EQ(received.layer_name(), source.layer_name());
649 ASSERT_TRUE(received.has_pid());
650 EXPECT_EQ(received.pid(), source.pid());
651}
652
653TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) {
654 auto tracingSession = getTracingSessionForTest();
655 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
656 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
657
658 tracingSession->StartBlocking();
659 int64_t displayFrameToken1 = mTokenManager->generateTokenForPredictions({10, 25, 30});
660 int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
661
662 // Set up the display frame
663 mFrameTimeline->setSfWakeUp(displayFrameToken1, 20);
664 mFrameTimeline->setSfPresent(26, presentFence1);
665 presentFence1->signalForTest(31);
666
667 ProtoDisplayFrame protoDisplayFrame;
668 protoDisplayFrame.set_token(displayFrameToken1);
669 protoDisplayFrame.set_present_type(ProtoPresentType(FrameTimelineEvent::PRESENT_ON_TIME));
670 protoDisplayFrame.set_on_time_finish(true);
671 protoDisplayFrame.set_gpu_composition(false);
672 protoDisplayFrame.set_jank_type(ProtoJankType(FrameTimelineEvent::JANK_NONE));
673 protoDisplayFrame.set_expected_start_ns(10);
674 protoDisplayFrame.set_expected_end_ns(25);
675 protoDisplayFrame.set_actual_start_ns(20);
676 protoDisplayFrame.set_actual_end_ns(26);
677
678 // Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
679 // next frame
680 mFrameTimeline->setSfWakeUp(displayFrameToken2, 50);
681 mFrameTimeline->setSfPresent(55, presentFence2);
682 presentFence2->signalForTest(55);
683
684 addEmptyDisplayFrame();
685 tracingSession->StopBlocking();
686
687 auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
688 // Display Frame 1 has one packet - DisplayFrame.
689 // Display Frame 2 has one packet - DisplayFrame. However, this packet has been emitted but not
690 // flushed through traced, so this is not counted.
691 EXPECT_EQ(packets.size(), 1);
692
693 const auto& packet = packets[0];
694 ASSERT_TRUE(packet.has_timestamp());
695 ASSERT_TRUE(packet.has_frame_timeline_event());
696
697 const auto& event = packet.frame_timeline_event();
698 ASSERT_TRUE(event.has_display_frame());
699 ASSERT_FALSE(event.has_surface_frame());
700 const auto& displayFrameEvent = event.display_frame();
701 validateDisplayFrameEvent(displayFrameEvent, protoDisplayFrame);
702}
703
704TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) {
705 auto tracingSession = getTracingSessionForTest();
706 auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
707 auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
708
709 tracingSession->StartBlocking();
710 int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 25, 40});
711 int64_t displayFrameToken1 = mTokenManager->generateTokenForPredictions({30, 35, 40});
712 int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
713
714 auto surfaceFrame1 =
715 mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne,
716 sLayerNameOne, surfaceFrameToken);
717 surfaceFrame1->setActualStartTime(0);
718 surfaceFrame1->setActualQueueTime(15);
719 surfaceFrame1->setAcquireFenceTime(20);
720
721 ProtoSurfaceFrame protoSurfaceFrame;
722 protoSurfaceFrame.set_token(surfaceFrameToken);
723 protoSurfaceFrame.set_display_frame_token(displayFrameToken1);
724 protoSurfaceFrame.set_present_type(ProtoPresentType(FrameTimelineEvent::PRESENT_ON_TIME));
725 protoSurfaceFrame.set_on_time_finish(true);
726 protoSurfaceFrame.set_gpu_composition(false);
727 protoSurfaceFrame.set_jank_type(ProtoJankType(FrameTimelineEvent::JANK_NONE));
728 protoSurfaceFrame.set_expected_start_ns(10);
729 protoSurfaceFrame.set_expected_end_ns(25);
730 protoSurfaceFrame.set_actual_start_ns(0);
731 protoSurfaceFrame.set_actual_end_ns(20);
732 protoSurfaceFrame.set_layer_name(sLayerNameOne);
733 protoSurfaceFrame.set_pid(sPidOne);
734
735 // Set up the display frame
736 mFrameTimeline->setSfWakeUp(displayFrameToken1, 20);
737 mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1),
738 SurfaceFrame::PresentState::Presented);
739 mFrameTimeline->setSfPresent(26, presentFence1);
740 presentFence1->signalForTest(31);
741
742 // Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
743 // next frame
744 mFrameTimeline->setSfWakeUp(displayFrameToken2, 50);
745 mFrameTimeline->setSfPresent(55, presentFence2);
746 presentFence2->signalForTest(55);
747
748 addEmptyDisplayFrame();
749 tracingSession->StopBlocking();
750
751 auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
752 // Display Frame 1 has one packet - DisplayFrame and a SurfaceFrame.
753 // Display Frame 2 has one packet - DisplayFrame. However, this packet has been emitted but not
754 // flushed through traced, so this is not counted.
755 EXPECT_EQ(packets.size(), 2);
756
757 const auto& packet = packets[1];
758 ASSERT_TRUE(packet.has_timestamp());
759 ASSERT_TRUE(packet.has_frame_timeline_event());
760
761 const auto& event = packet.frame_timeline_event();
762 ASSERT_TRUE(!event.has_display_frame());
763 ASSERT_TRUE(event.has_surface_frame());
764 const auto& surfaceFrameEvent = event.surface_frame();
765 validateSurfaceFrameEvent(surfaceFrameEvent, protoSurfaceFrame);
766}
767
Adithya Srinivasanf279e042020-08-17 14:56:27 -0700768} // namespace android::frametimeline