1 /*
2 * Copyright 2023 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 #include <ftl/optional.h>
18 #include <gtest/gtest.h>
19
20 #include <common/test/FlagUtils.h>
21 #include <scheduler/Fps.h>
22 #include <scheduler/FrameTargeter.h>
23 #include <scheduler/IVsyncSource.h>
24
25 #include <com_android_graphics_surfaceflinger_flags.h>
26
27 using namespace com::android::graphics::surfaceflinger;
28 using namespace std::chrono_literals;
29
30 namespace android::scheduler {
31 namespace {
32
33 struct VsyncSource final : IVsyncSource {
VsyncSourceandroid::scheduler::__anon0953a8e10111::VsyncSource34 VsyncSource(Period period, Period minFramePeriod, TimePoint deadline)
35 : vsyncPeriod(period), framePeriod(minFramePeriod), vsyncDeadline(deadline) {}
36
37 const Period vsyncPeriod;
38 const Period framePeriod;
39 const TimePoint vsyncDeadline;
40
periodandroid::scheduler::__anon0953a8e10111::VsyncSource41 Period period() const override { return vsyncPeriod; }
vsyncDeadlineAfterandroid::scheduler::__anon0953a8e10111::VsyncSource42 TimePoint vsyncDeadlineAfter(TimePoint, ftl::Optional<TimePoint> = {}) const override {
43 return vsyncDeadline;
44 }
minFramePeriodandroid::scheduler::__anon0953a8e10111::VsyncSource45 Period minFramePeriod() const override { return framePeriod; }
46 };
47
48 } // namespace
49
50 class FrameTargeterTestBase : public testing::Test {
51 public:
FrameTargeterTestBase(FeatureFlags flags)52 FrameTargeterTestBase(FeatureFlags flags) : mTargeter(PhysicalDisplayId::fromPort(13), flags) {}
53
target() const54 const auto& target() const { return mTargeter.target(); }
55
wouldPresentEarly(Period minFramePeriod) const56 bool wouldPresentEarly(Period minFramePeriod) const {
57 return target().wouldPresentEarly(minFramePeriod);
58 }
59
60 struct Frame {
Frameandroid::scheduler::FrameTargeterTestBase::Frame61 Frame(FrameTargeterTestBase* testPtr, VsyncId vsyncId, TimePoint& frameBeginTime,
62 Duration frameDuration, Fps refreshRate, Fps peakRefreshRate,
63 FrameTargeter::IsFencePendingFuncPtr isFencePendingFuncPtr = Frame::fenceSignaled,
64 const ftl::Optional<VsyncSource>& vsyncSourceOpt = std::nullopt)
65 : testPtr(testPtr),
66 frameBeginTime(frameBeginTime),
67 period(refreshRate.getPeriod()),
68 minFramePeriod(peakRefreshRate.getPeriod()) {
69 const FrameTargeter::BeginFrameArgs args{.frameBeginTime = frameBeginTime,
70 .vsyncId = vsyncId,
71 .expectedVsyncTime =
72 frameBeginTime + frameDuration,
73 .sfWorkDuration = 10ms,
74 .hwcMinWorkDuration = kHwcMinWorkDuration};
75
76 testPtr->mTargeter.beginFrame(args,
77 vsyncSourceOpt
78 .or_else([&] {
79 return std::make_optional(
80 VsyncSource(period, period,
81 args.expectedVsyncTime));
82 })
83 .value(),
84 isFencePendingFuncPtr);
85 }
86
endandroid::scheduler::FrameTargeterTestBase::Frame87 FenceTimePtr end(CompositionCoverage coverage = CompositionCoverage::Hwc) {
88 if (ended) return nullptr;
89 ended = true;
90
91 auto [fence, fenceTime] = testPtr->mFenceMap.makePendingFenceForTest();
92 testPtr->mTargeter.setPresentFence(std::move(fence), fenceTime);
93
94 testPtr->mTargeter.endFrame({.compositionCoverage = coverage});
95 return fenceTime;
96 }
97
~Frameandroid::scheduler::FrameTargeterTestBase::Frame98 ~Frame() {
99 end();
100 frameBeginTime += period;
101 }
102
fencePendingandroid::scheduler::FrameTargeterTestBase::Frame103 static bool fencePending(const FenceTimePtr&, int) { return true; }
fenceSignaledandroid::scheduler::FrameTargeterTestBase::Frame104 static bool fenceSignaled(const FenceTimePtr&, int) { return false; }
105
106 FrameTargeterTestBase* const testPtr;
107
108 TimePoint& frameBeginTime;
109 const Period period;
110 const Period minFramePeriod;
111
112 bool ended = false;
113 };
114
115 static constexpr Duration kHwcMinWorkDuration = std::chrono::nanoseconds(5ns);
116
117 private:
118 FenceToFenceTimeMap mFenceMap;
119
120 FrameTargeter mTargeter;
121 };
122
123 class FrameTargeterTest : public FrameTargeterTestBase {
124 public:
FrameTargeterTest()125 FrameTargeterTest() : FrameTargeterTestBase(Feature::kBackpressureGpuComposition) {}
126 };
127
128 class FrameTargeterWithExpectedPresentSupportTest : public FrameTargeterTestBase {
129 public:
FrameTargeterWithExpectedPresentSupportTest()130 FrameTargeterWithExpectedPresentSupportTest()
131 : FrameTargeterTestBase(FeatureFlags(Feature::kBackpressureGpuComposition) |
132 Feature::kExpectedPresentTime) {}
133 };
134
TEST_F(FrameTargeterTest,targetsFrames)135 TEST_F(FrameTargeterTest, targetsFrames) {
136 VsyncId vsyncId{42};
137 {
138 TimePoint frameBeginTime(989ms);
139 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, 60_Hz, 60_Hz);
140
141 EXPECT_EQ(target().vsyncId(), VsyncId{42});
142 EXPECT_EQ(target().frameBeginTime(), TimePoint(989ms));
143 EXPECT_EQ(target().expectedPresentTime(), TimePoint(999ms));
144 EXPECT_EQ(target().expectedFrameDuration(), 10ms);
145 }
146 {
147 TimePoint frameBeginTime(1100ms);
148 const Frame frame(this, vsyncId++, frameBeginTime, 11ms, 60_Hz, 60_Hz);
149
150 EXPECT_EQ(target().vsyncId(), VsyncId{43});
151 EXPECT_EQ(target().frameBeginTime(), TimePoint(1100ms));
152 EXPECT_EQ(target().expectedPresentTime(), TimePoint(1111ms));
153 EXPECT_EQ(target().expectedFrameDuration(), 11ms);
154 }
155 }
156
TEST_F(FrameTargeterTest,inflatesExpectedPresentTime)157 TEST_F(FrameTargeterTest, inflatesExpectedPresentTime) {
158 // Negative such that `expectedVsyncTime` is in the past.
159 constexpr Duration kFrameDuration = -3ms;
160 TimePoint frameBeginTime(777ms);
161
162 constexpr Fps kRefreshRate = 120_Hz;
163 const VsyncSource vsyncSource(kRefreshRate.getPeriod(), kRefreshRate.getPeriod(),
164 frameBeginTime + 5ms);
165 const Frame frame(this, VsyncId{123}, frameBeginTime, kFrameDuration, kRefreshRate,
166 kRefreshRate, Frame::fenceSignaled, vsyncSource);
167
168 EXPECT_EQ(target().expectedPresentTime(), vsyncSource.vsyncDeadline + vsyncSource.vsyncPeriod);
169 }
170
TEST_F(FrameTargeterTest,recallsPastVsync)171 TEST_F(FrameTargeterTest, recallsPastVsync) {
172 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
173 VsyncId vsyncId{111};
174 TimePoint frameBeginTime(1000ms);
175 constexpr Fps kRefreshRate = 60_Hz;
176 constexpr Period kPeriod = kRefreshRate.getPeriod();
177 constexpr Duration kFrameDuration = 13ms;
178
179 for (int n = 5; n-- > 0;) {
180 Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate, kRefreshRate);
181 const auto fence = frame.end();
182
183 EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - kPeriod);
184 EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), fence);
185 }
186 }
187
TEST_F(FrameTargeterTest,recallsPastVsyncTwoVsyncsAhead)188 TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAhead) {
189 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
190 VsyncId vsyncId{222};
191 TimePoint frameBeginTime(2000ms);
192 constexpr Fps kRefreshRate = 120_Hz;
193 constexpr Period kPeriod = kRefreshRate.getPeriod();
194 constexpr Duration kFrameDuration = 10ms;
195
196 FenceTimePtr previousFence = FenceTime::NO_FENCE;
197
198 for (int n = 5; n-- > 0;) {
199 Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate, kRefreshRate);
200 const auto fence = frame.end();
201
202 EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
203 EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), previousFence);
204
205 previousFence = fence;
206 }
207 }
208
TEST_F(FrameTargeterTest,recallsPastNVsyncTwoVsyncsAhead)209 TEST_F(FrameTargeterTest, recallsPastNVsyncTwoVsyncsAhead) {
210 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, true);
211 VsyncId vsyncId{222};
212 TimePoint frameBeginTime(2000ms);
213 constexpr Fps kRefreshRate = 120_Hz;
214 constexpr Period kPeriod = kRefreshRate.getPeriod();
215 constexpr Duration kFrameDuration = 10ms;
216
217 FenceTimePtr previousFence = FenceTime::NO_FENCE;
218
219 for (int n = 5; n-- > 0;) {
220 Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate, kRefreshRate);
221 const auto fence = frame.end();
222
223 const auto pastVsyncTime = frameBeginTime + kFrameDuration - 2 * kPeriod;
224 EXPECT_EQ(target().pastVsyncTime(kPeriod), pastVsyncTime);
225 EXPECT_EQ(target().presentFenceForPastVsync(kFrameDuration), previousFence);
226
227 frameBeginTime += kPeriod;
228 previousFence = fence;
229 }
230 }
231
TEST_F(FrameTargeterTest,recallsPastVsyncTwoVsyncsAheadVrr)232 TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAheadVrr) {
233 SET_FLAG_FOR_TEST(flags::vrr_config, true);
234 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
235
236 VsyncId vsyncId{222};
237 TimePoint frameBeginTime(2000ms);
238 constexpr Fps kRefreshRate = 120_Hz;
239 constexpr Fps kPeakRefreshRate = 240_Hz;
240 constexpr Period kPeriod = kRefreshRate.getPeriod();
241 constexpr Duration kFrameDuration = 10ms;
242
243 FenceTimePtr previousFence = FenceTime::NO_FENCE;
244
245 for (int n = 5; n-- > 0;) {
246 Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate,
247 kPeakRefreshRate);
248 const auto fence = frame.end();
249
250 EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
251 EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), previousFence);
252
253 previousFence = fence;
254 }
255 }
256
TEST_F(FrameTargeterTest,recallsPastNVsyncTwoVsyncsAheadVrr)257 TEST_F(FrameTargeterTest, recallsPastNVsyncTwoVsyncsAheadVrr) {
258 SET_FLAG_FOR_TEST(flags::vrr_config, true);
259 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, true);
260
261 VsyncId vsyncId{222};
262 TimePoint frameBeginTime(2000ms);
263 constexpr Fps kRefreshRate = 120_Hz;
264 constexpr Fps kPeakRefreshRate = 240_Hz;
265 constexpr Period kPeriod = kRefreshRate.getPeriod();
266 constexpr Duration kFrameDuration = 10ms;
267
268 FenceTimePtr previousFence = FenceTime::NO_FENCE;
269
270 for (int n = 5; n-- > 0;) {
271 Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate,
272 kPeakRefreshRate);
273 const auto fence = frame.end();
274
275 const auto pastVsyncTime = frameBeginTime + kFrameDuration - 2 * kPeriod;
276 EXPECT_EQ(target().pastVsyncTime(kPeriod), pastVsyncTime);
277 EXPECT_EQ(target().presentFenceForPastVsync(kFrameDuration), previousFence);
278
279 frameBeginTime += kPeriod;
280 previousFence = fence;
281 }
282 }
283
TEST_F(FrameTargeterTest,doesNotDetectEarlyPresentIfNoFence)284 TEST_F(FrameTargeterTest, doesNotDetectEarlyPresentIfNoFence) {
285 constexpr Period kPeriod = (60_Hz).getPeriod();
286 EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), FenceTime::NO_FENCE);
287 EXPECT_FALSE(wouldPresentEarly(kPeriod));
288 }
289
TEST_F(FrameTargeterTest,detectsEarlyPresent)290 TEST_F(FrameTargeterTest, detectsEarlyPresent) {
291 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
292 VsyncId vsyncId{333};
293 TimePoint frameBeginTime(3000ms);
294 constexpr Fps kRefreshRate = 60_Hz;
295 constexpr Period kPeriod = kRefreshRate.getPeriod();
296
297 // The target is not early while past present fences are pending.
298 for (int n = 3; n-- > 0;) {
299 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
300 EXPECT_FALSE(wouldPresentEarly(kPeriod));
301 EXPECT_FALSE(target().earliestPresentTime());
302 }
303
304 // The target is early if the past present fence was signaled.
305 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
306 const auto fence = frame.end();
307 fence->signalForTest(frameBeginTime.ns());
308
309 Frame finalFrame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
310
311 // `finalFrame` would present early, so it has an earliest present time.
312 EXPECT_TRUE(wouldPresentEarly(kPeriod));
313 ASSERT_NE(std::nullopt, target().earliestPresentTime());
314 EXPECT_EQ(*target().earliestPresentTime(),
315 target().expectedPresentTime() - kPeriod - kHwcMinWorkDuration);
316 }
317
318 // Same as `detectsEarlyPresent`, above, but verifies that we do not set an earliest present time
319 // when there is expected present time support.
TEST_F(FrameTargeterWithExpectedPresentSupportTest,detectsEarlyPresent)320 TEST_F(FrameTargeterWithExpectedPresentSupportTest, detectsEarlyPresent) {
321 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
322 VsyncId vsyncId{333};
323 TimePoint frameBeginTime(3000ms);
324 constexpr Fps kRefreshRate = 60_Hz;
325 constexpr Period kPeriod = kRefreshRate.getPeriod();
326
327 // The target is not early while past present fences are pending.
328 for (int n = 3; n-- > 0;) {
329 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
330 EXPECT_FALSE(wouldPresentEarly(kPeriod));
331 EXPECT_FALSE(target().earliestPresentTime());
332 }
333
334 // The target is early if the past present fence was signaled.
335 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
336 const auto fence = frame.end();
337 fence->signalForTest(frameBeginTime.ns());
338
339 Frame finalFrame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
340
341 // `finalFrame` would present early, but we have expected present time support, so it has no
342 // earliest present time.
343 EXPECT_TRUE(wouldPresentEarly(kPeriod));
344 ASSERT_EQ(std::nullopt, target().earliestPresentTime());
345 }
346
TEST_F(FrameTargeterTest,detectsEarlyPresentTwoVsyncsAhead)347 TEST_F(FrameTargeterTest, detectsEarlyPresentTwoVsyncsAhead) {
348 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
349 VsyncId vsyncId{444};
350 TimePoint frameBeginTime(4000ms);
351 constexpr Fps kRefreshRate = 120_Hz;
352 constexpr Period kPeriod = kRefreshRate.getPeriod();
353
354 // The target is not early while past present fences are pending.
355 for (int n = 3; n-- > 0;) {
356 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
357 EXPECT_FALSE(wouldPresentEarly(kPeriod));
358 EXPECT_FALSE(target().earliestPresentTime());
359 }
360
361 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
362 const auto fence = frame.end();
363 fence->signalForTest(frameBeginTime.ns());
364
365 // The target is two VSYNCs ahead, so the past present fence is still pending.
366 EXPECT_FALSE(wouldPresentEarly(kPeriod));
367 EXPECT_FALSE(target().earliestPresentTime());
368
369 { const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate); }
370
371 Frame finalFrame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
372
373 // The target is early if the past present fence was signaled.
374 EXPECT_TRUE(wouldPresentEarly(kPeriod));
375 ASSERT_NE(std::nullopt, target().earliestPresentTime());
376 EXPECT_EQ(*target().earliestPresentTime(),
377 target().expectedPresentTime() - kPeriod - kHwcMinWorkDuration);
378 }
379
TEST_F(FrameTargeterTest,detectsEarlyPresentNVsyncsAhead)380 TEST_F(FrameTargeterTest, detectsEarlyPresentNVsyncsAhead) {
381 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, true);
382 VsyncId vsyncId{444};
383 TimePoint frameBeginTime(4000ms);
384 Fps refreshRate = 120_Hz;
385 Period period = refreshRate.getPeriod();
386
387 // The target is not early while past present fences are pending.
388 for (int n = 5; n-- > 0;) {
389 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate);
390 EXPECT_FALSE(wouldPresentEarly(period));
391 EXPECT_FALSE(target().earliestPresentTime());
392 }
393
394 Frame frame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate);
395 auto fence = frame.end();
396 frameBeginTime += period;
397 fence->signalForTest(frameBeginTime.ns());
398
399 // The target is two VSYNCs ahead, so the past present fence is still pending.
400 EXPECT_FALSE(wouldPresentEarly(period));
401 EXPECT_FALSE(target().earliestPresentTime());
402
403 { const Frame frame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate); }
404
405 Frame oneEarlyPresentFrame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate);
406 // The target is early if the past present fence was signaled.
407 EXPECT_TRUE(wouldPresentEarly(period));
408 ASSERT_NE(std::nullopt, target().earliestPresentTime());
409 EXPECT_EQ(*target().earliestPresentTime(),
410 target().expectedPresentTime() - period - kHwcMinWorkDuration);
411
412 fence = oneEarlyPresentFrame.end();
413 frameBeginTime += period;
414 fence->signalForTest(frameBeginTime.ns());
415
416 // Change rate to track frame more than 2 vsyncs ahead
417 refreshRate = 144_Hz;
418 period = refreshRate.getPeriod();
419 Frame onePresentEarlyFrame(this, vsyncId++, frameBeginTime, 16ms, refreshRate, refreshRate);
420 // The target is not early as last frame as the past frame is tracked for pending.
421 EXPECT_FALSE(wouldPresentEarly(period));
422 }
423
TEST_F(FrameTargeterTest,detectsEarlyPresentThreeVsyncsAhead)424 TEST_F(FrameTargeterTest, detectsEarlyPresentThreeVsyncsAhead) {
425 SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
426 TimePoint frameBeginTime(5000ms);
427 constexpr Fps kRefreshRate = 144_Hz;
428 constexpr Period kPeriod = kRefreshRate.getPeriod();
429
430 const Frame frame(this, VsyncId{555}, frameBeginTime, 16ms, kRefreshRate, kRefreshRate);
431
432 // The target is more than two VSYNCs ahead, but present fences are not tracked that far back.
433 EXPECT_TRUE(wouldPresentEarly(kPeriod));
434 EXPECT_TRUE(target().earliestPresentTime());
435 EXPECT_EQ(*target().earliestPresentTime(),
436 target().expectedPresentTime() - kPeriod - kHwcMinWorkDuration);
437 }
438
TEST_F(FrameTargeterTest,detectsMissedFrames)439 TEST_F(FrameTargeterTest, detectsMissedFrames) {
440 VsyncId vsyncId{555};
441 TimePoint frameBeginTime(5000ms);
442 constexpr Fps kRefreshRate = 60_Hz;
443 constexpr Period kPeriod = kRefreshRate.getPeriod();
444
445 EXPECT_FALSE(target().isFramePending());
446 EXPECT_FALSE(target().didMissFrame());
447 EXPECT_FALSE(target().didMissHwcFrame());
448
449 {
450 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
451 EXPECT_FALSE(target().isFramePending());
452
453 // The frame did not miss if the past present fence is invalid.
454 EXPECT_FALSE(target().didMissFrame());
455 EXPECT_FALSE(target().didMissHwcFrame());
456 }
457 {
458 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate,
459 Frame::fencePending);
460 EXPECT_TRUE(target().isFramePending());
461
462 // The frame missed if the past present fence is pending.
463 EXPECT_TRUE(target().didMissFrame());
464 EXPECT_TRUE(target().didMissHwcFrame());
465
466 frame.end(CompositionCoverage::Gpu);
467 }
468 {
469 const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate,
470 Frame::fencePending);
471 EXPECT_TRUE(target().isFramePending());
472
473 // The GPU frame missed if the past present fence is pending.
474 EXPECT_TRUE(target().didMissFrame());
475 EXPECT_FALSE(target().didMissHwcFrame());
476 }
477 {
478 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
479 EXPECT_FALSE(target().isFramePending());
480
481 const auto fence = frame.end();
482 const auto expectedPresentTime = target().expectedPresentTime();
483 fence->signalForTest(expectedPresentTime.ns() + kPeriod.ns() / 2 + 1);
484 }
485 {
486 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
487 EXPECT_FALSE(target().isFramePending());
488
489 const auto fence = frame.end();
490 const auto expectedPresentTime = target().expectedPresentTime();
491 fence->signalForTest(expectedPresentTime.ns() + kPeriod.ns() / 2);
492
493 // The frame missed if the past present fence was signaled but not within slop.
494 EXPECT_TRUE(target().didMissFrame());
495 EXPECT_TRUE(target().didMissHwcFrame());
496 }
497 {
498 Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
499 EXPECT_FALSE(target().isFramePending());
500
501 // The frame did not miss if the past present fence was signaled within slop.
502 EXPECT_FALSE(target().didMissFrame());
503 EXPECT_FALSE(target().didMissHwcFrame());
504 }
505 }
506
507 } // namespace android::scheduler
508