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