xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2019 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 #pragma clang diagnostic ignored "-Wextra"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "LibSurfaceFlingerUnittests"
24 #define LOG_NDEBUG 0
25 
26 #include <common/test/FlagUtils.h>
27 #include "Scheduler/VSyncPredictor.h"
28 #include "mock/DisplayHardware/MockDisplayMode.h"
29 
30 #include <gmock/gmock.h>
31 #include <gtest/gtest.h>
32 #include <algorithm>
33 #include <chrono>
34 #include <optional>
35 #include <utility>
36 
37 #include <com_android_graphics_surfaceflinger_flags.h>
38 
39 using namespace testing;
40 using namespace std::literals;
41 using namespace com::android::graphics::surfaceflinger;
42 
43 using NotifyExpectedPresentConfig =
44         ::aidl::android::hardware::graphics::composer3::VrrConfig::NotifyExpectedPresentConfig;
45 
46 using android::mock::createDisplayMode;
47 using android::mock::createDisplayModeBuilder;
48 using android::mock::createVrrDisplayMode;
49 
50 namespace android::scheduler {
51 
52 namespace {
53 MATCHER_P2(IsCloseTo, value, tolerance, "is within tolerance") {
54     return arg <= value + tolerance && arg >= value - tolerance;
55 }
56 
57 MATCHER_P(FpsMatcher, value, "equals") {
58     using fps_approx_ops::operator==;
59     return arg == value;
60 }
61 
generateVsyncTimestamps(size_t count,nsecs_t period,nsecs_t bias)62 std::vector<nsecs_t> generateVsyncTimestamps(size_t count, nsecs_t period, nsecs_t bias) {
63     std::vector<nsecs_t> vsyncs(count);
64     std::generate(vsyncs.begin(), vsyncs.end(),
65                   [&, n = 0]() mutable { return n++ * period + bias; });
66     return vsyncs;
67 }
68 
69 constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
70 
displayMode(nsecs_t period)71 ftl::NonNull<DisplayModePtr> displayMode(nsecs_t period) {
72     const int32_t kGroup = 0;
73     const auto kResolution = ui::Size(1920, 1080);
74     const auto refreshRate = Fps::fromPeriodNsecs(period);
75     return ftl::as_non_null(createDisplayMode(DisplayModeId(0), refreshRate, kGroup, kResolution,
76                                               DEFAULT_DISPLAY_ID));
77 }
78 
79 class TestClock : public Clock {
80 public:
81     TestClock() = default;
82 
now() const83     nsecs_t now() const override { return mNow; }
setNow(nsecs_t now)84     void setNow(nsecs_t now) { mNow = now; }
85 
86 private:
87     nsecs_t mNow = 0;
88 };
89 
90 class ClockWrapper : public Clock {
91 public:
ClockWrapper(std::shared_ptr<Clock> const & clock)92     ClockWrapper(std::shared_ptr<Clock> const& clock) : mClock(clock) {}
93 
now() const94     nsecs_t now() const { return mClock->now(); }
95 
96 private:
97     std::shared_ptr<Clock> const mClock;
98 };
99 
100 } // namespace
101 
102 struct VSyncPredictorTest : testing::Test {
103     nsecs_t mNow = 0;
104     nsecs_t mPeriod = 1000;
105     ftl::NonNull<DisplayModePtr> mMode = displayMode(mPeriod);
106     static constexpr size_t kHistorySize = 10;
107     static constexpr size_t kMinimumSamplesForPrediction = 6;
108     static constexpr size_t kOutlierTolerancePercent = 25;
109     static constexpr nsecs_t mMaxRoundingError = 100;
110 
111     std::shared_ptr<TestClock> mClock{std::make_shared<TestClock>()};
112 
113     VSyncPredictor tracker{std::make_unique<ClockWrapper>(mClock), mMode, kHistorySize,
114                            kMinimumSamplesForPrediction, kOutlierTolerancePercent};
115 };
116 
TEST_F(VSyncPredictorTest,reportsAnticipatedPeriod)117 TEST_F(VSyncPredictorTest, reportsAnticipatedPeriod) {
118     auto model = tracker.getVSyncPredictionModel();
119 
120     EXPECT_THAT(model.slope, Eq(mPeriod));
121     EXPECT_THAT(model.intercept, Eq(0));
122 
123     auto const changedPeriod = 2000;
124     tracker.setDisplayModePtr(displayMode(changedPeriod));
125     model = tracker.getVSyncPredictionModel();
126     EXPECT_THAT(model.slope, Eq(changedPeriod));
127     EXPECT_THAT(model.intercept, Eq(0));
128 }
129 
TEST_F(VSyncPredictorTest,reportsSamplesNeededWhenHasNoDataPoints)130 TEST_F(VSyncPredictorTest, reportsSamplesNeededWhenHasNoDataPoints) {
131     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
132         EXPECT_TRUE(tracker.needsMoreSamples());
133         tracker.addVsyncTimestamp(mNow += mPeriod);
134     }
135     EXPECT_FALSE(tracker.needsMoreSamples());
136 }
137 
TEST_F(VSyncPredictorTest,reportsSamplesNeededAfterExplicitRateChange)138 TEST_F(VSyncPredictorTest, reportsSamplesNeededAfterExplicitRateChange) {
139     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
140         tracker.addVsyncTimestamp(mNow += mPeriod);
141     }
142     EXPECT_FALSE(tracker.needsMoreSamples());
143 
144     auto const changedPeriod = mPeriod * 2;
145     tracker.setDisplayModePtr(displayMode(changedPeriod));
146     EXPECT_TRUE(tracker.needsMoreSamples());
147 
148     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
149         EXPECT_TRUE(tracker.needsMoreSamples());
150         tracker.addVsyncTimestamp(mNow += changedPeriod);
151     }
152     EXPECT_FALSE(tracker.needsMoreSamples());
153 }
154 
TEST_F(VSyncPredictorTest,transitionsToModelledPointsAfterSynthetic)155 TEST_F(VSyncPredictorTest, transitionsToModelledPointsAfterSynthetic) {
156     auto last = mNow;
157     auto const bias = 10;
158     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
159         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
160         mNow += mPeriod - bias;
161         last = mNow;
162         tracker.addVsyncTimestamp(mNow);
163         mNow += bias;
164     }
165 
166     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod - bias));
167     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + mPeriod - bias));
168     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 990), Eq(mNow + 2 * mPeriod - bias));
169 }
170 
TEST_F(VSyncPredictorTest,uponNotifiedOfInaccuracyUsesSynthetic)171 TEST_F(VSyncPredictorTest, uponNotifiedOfInaccuracyUsesSynthetic) {
172     auto const slightlyLessPeriod = mPeriod - 10;
173     auto const changedPeriod = mPeriod - 1;
174     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
175         tracker.addVsyncTimestamp(mNow += slightlyLessPeriod);
176     }
177 
178     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + slightlyLessPeriod));
179     tracker.setDisplayModePtr(displayMode(changedPeriod));
180     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + changedPeriod));
181 }
182 
183 // b/159882858
TEST_F(VSyncPredictorTest,updatesTimebaseForSyntheticAfterIdleTime)184 TEST_F(VSyncPredictorTest, updatesTimebaseForSyntheticAfterIdleTime) {
185     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
186         EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
187     }
188 
189     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
190 
191     auto const halfPeriod = mPeriod >> 2;
192     nsecs_t relativelyLongGapWithDrift = mPeriod * 100 + halfPeriod;
193 
194     EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += relativelyLongGapWithDrift));
195 
196     tracker.resetModel();
197     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
198 }
199 
TEST_F(VSyncPredictorTest,uponBadVsyncWillSwitchToSyntheticWhileRecalibrating)200 TEST_F(VSyncPredictorTest, uponBadVsyncWillSwitchToSyntheticWhileRecalibrating) {
201     auto const slightlyMorePeriod = mPeriod + 10;
202     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
203         EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += slightlyMorePeriod));
204     }
205 
206     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + slightlyMorePeriod));
207 
208     auto const halfPeriod = mPeriod >> 2;
209     EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += halfPeriod));
210 
211     tracker.resetModel();
212     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
213 }
214 
TEST_F(VSyncPredictorTest,adaptsToFenceTimelines_60hzHighVariance)215 TEST_F(VSyncPredictorTest, adaptsToFenceTimelines_60hzHighVariance) {
216     // these are precomputed simulated 16.6s vsyncs with uniform distribution +/- 1.6ms error
217     std::vector<nsecs_t> const simulatedVsyncs{
218             15492949,  32325658,  49534984,  67496129,  84652891,
219             100332564, 117737004, 132125931, 149291099, 165199602,
220     };
221     auto constexpr idealPeriod = 16600000;
222     auto constexpr expectedPeriod = 16639242;
223     auto constexpr expectedIntercept = 1049341;
224 
225     tracker.setDisplayModePtr(displayMode(idealPeriod));
226     for (auto const& timestamp : simulatedVsyncs) {
227         tracker.addVsyncTimestamp(timestamp);
228     }
229     auto [slope, intercept] = tracker.getVSyncPredictionModel();
230     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
231     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
232 }
233 
TEST_F(VSyncPredictorTest,adaptsToFenceTimelines_90hzLowVariance)234 TEST_F(VSyncPredictorTest, adaptsToFenceTimelines_90hzLowVariance) {
235     // these are precomputed simulated 11.1 vsyncs with uniform distribution +/- 1ms error
236     std::vector<nsecs_t> const simulatedVsyncs{
237             11167047, 22603464, 32538479, 44938134, 56321268,
238             66730346, 78062637, 88171429, 99707843, 111397621,
239     };
240     auto idealPeriod = 11110000;
241     auto expectedPeriod = 11089413;
242     auto expectedIntercept = 94421;
243 
244     tracker.setDisplayModePtr(displayMode(idealPeriod));
245     for (auto const& timestamp : simulatedVsyncs) {
246         tracker.addVsyncTimestamp(timestamp);
247     }
248     auto [slope, intercept] = tracker.getVSyncPredictionModel();
249     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
250     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
251 }
252 
TEST_F(VSyncPredictorTest,adaptsToFenceTimelinesDiscontinuous_22hzLowVariance)253 TEST_F(VSyncPredictorTest, adaptsToFenceTimelinesDiscontinuous_22hzLowVariance) {
254     // these are 11.1s vsyncs with low variance, randomly computed, between -1 and 1ms
255     std::vector<nsecs_t> const simulatedVsyncs{
256             45259463,   // 0
257             91511026,   // 1
258             136307650,  // 2
259             1864501714, // 40
260             1908641034, // 41
261             1955278544, // 42
262             4590180096, // 100
263             4681594994, // 102
264             5499224734, // 120
265             5591378272, // 122
266     };
267     auto idealPeriod = 45454545;
268     auto expectedPeriod = 45450152;
269     auto expectedIntercept = 469647;
270 
271     tracker.setDisplayModePtr(displayMode(idealPeriod));
272     for (auto const& timestamp : simulatedVsyncs) {
273         tracker.addVsyncTimestamp(timestamp);
274     }
275     auto [slope, intercept] = tracker.getVSyncPredictionModel();
276     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
277     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
278 }
279 
TEST_F(VSyncPredictorTest,againstOutliersDiscontinuous_500hzLowVariance)280 TEST_F(VSyncPredictorTest, againstOutliersDiscontinuous_500hzLowVariance) {
281     std::vector<nsecs_t> const simulatedVsyncs{
282             1992548,    // 0
283             4078038,    // 1
284             6165794,    // 2
285             7958171,    // 3
286             10193537,   // 4
287             2401840200, // 1200
288             2403000000, // an outlier that should be excluded (1201 and a half)
289             2405803629, // 1202
290             2408028599, // 1203
291             2410121051, // 1204
292     };
293     auto idealPeriod = 2000000;
294     auto expectedPeriod = 1999892;
295     auto expectedIntercept = 86342;
296 
297     tracker.setDisplayModePtr(displayMode(idealPeriod));
298     for (auto const& timestamp : simulatedVsyncs) {
299         tracker.addVsyncTimestamp(timestamp);
300     }
301 
302     auto [slope, intercept] = tracker.getVSyncPredictionModel();
303     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
304     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
305 }
306 
TEST_F(VSyncPredictorTest,handlesVsyncChange)307 TEST_F(VSyncPredictorTest, handlesVsyncChange) {
308     auto const fastPeriod = 100;
309     auto const fastTimeBase = 100;
310     auto const slowPeriod = 400;
311     auto const slowTimeBase = 800;
312     auto const simulatedVsyncsFast =
313             generateVsyncTimestamps(kMinimumSamplesForPrediction, fastPeriod, fastTimeBase);
314     auto const simulatedVsyncsSlow =
315             generateVsyncTimestamps(kMinimumSamplesForPrediction, slowPeriod, slowTimeBase);
316 
317     tracker.setDisplayModePtr(displayMode(fastPeriod));
318     for (auto const& timestamp : simulatedVsyncsFast) {
319         tracker.addVsyncTimestamp(timestamp);
320     }
321 
322     auto const mMaxRoundingError = 100;
323     auto model = tracker.getVSyncPredictionModel();
324     EXPECT_THAT(model.slope, IsCloseTo(fastPeriod, mMaxRoundingError));
325     EXPECT_THAT(model.intercept, IsCloseTo(0, mMaxRoundingError));
326 
327     tracker.setDisplayModePtr(displayMode(slowPeriod));
328     for (auto const& timestamp : simulatedVsyncsSlow) {
329         tracker.addVsyncTimestamp(timestamp);
330     }
331     model = tracker.getVSyncPredictionModel();
332     EXPECT_THAT(model.slope, IsCloseTo(slowPeriod, mMaxRoundingError));
333     EXPECT_THAT(model.intercept, IsCloseTo(0, mMaxRoundingError));
334 }
335 
TEST_F(VSyncPredictorTest,willBeAccurateUsingPriorResultsForRate)336 TEST_F(VSyncPredictorTest, willBeAccurateUsingPriorResultsForRate) {
337     auto const fastPeriod = 101000;
338     auto const fastTimeBase = fastPeriod - 500;
339     auto const fastPeriod2 = 99000;
340 
341     auto const slowPeriod = 400000;
342     auto const slowTimeBase = 800000 - 201;
343     auto const simulatedVsyncsFast =
344             generateVsyncTimestamps(kMinimumSamplesForPrediction, fastPeriod, fastTimeBase);
345     auto const simulatedVsyncsSlow =
346             generateVsyncTimestamps(kMinimumSamplesForPrediction, slowPeriod, slowTimeBase);
347     auto const simulatedVsyncsFast2 =
348             generateVsyncTimestamps(kMinimumSamplesForPrediction, fastPeriod2, fastTimeBase);
349 
350     auto idealPeriod = 100000;
351     tracker.setDisplayModePtr(displayMode(idealPeriod));
352     for (auto const& timestamp : simulatedVsyncsFast) {
353         tracker.addVsyncTimestamp(timestamp);
354     }
355     auto model = tracker.getVSyncPredictionModel();
356     EXPECT_THAT(model.slope, Eq(fastPeriod));
357     EXPECT_THAT(model.intercept, Eq(0));
358 
359     tracker.setDisplayModePtr(displayMode(slowPeriod));
360     for (auto const& timestamp : simulatedVsyncsSlow) {
361         tracker.addVsyncTimestamp(timestamp);
362     }
363 
364     // we had a model for 100ns mPeriod before, use that until the new samples are
365     // sufficiently built up
366     tracker.setDisplayModePtr(displayMode(idealPeriod));
367     model = tracker.getVSyncPredictionModel();
368     EXPECT_THAT(model.slope, Eq(fastPeriod));
369     EXPECT_THAT(model.intercept, Eq(0));
370 
371     for (auto const& timestamp : simulatedVsyncsFast2) {
372         tracker.addVsyncTimestamp(timestamp);
373     }
374     model = tracker.getVSyncPredictionModel();
375     EXPECT_THAT(model.slope, Eq(fastPeriod2));
376     EXPECT_THAT(model.intercept, Eq(0));
377 }
378 
TEST_F(VSyncPredictorTest,idealModelPredictionsBeforeRegressionModelIsBuilt)379 TEST_F(VSyncPredictorTest, idealModelPredictionsBeforeRegressionModelIsBuilt) {
380     auto const simulatedVsyncs =
381             generateVsyncTimestamps(kMinimumSamplesForPrediction + 1, mPeriod, 0);
382     nsecs_t const mNow = 0;
383     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mPeriod));
384 
385     nsecs_t const aBitOfTime = 422;
386 
387     for (auto i = 0; i < kMinimumSamplesForPrediction; i++) {
388         tracker.addVsyncTimestamp(simulatedVsyncs[i]);
389         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(simulatedVsyncs[i] + aBitOfTime),
390                     Eq(mPeriod + simulatedVsyncs[i]));
391     }
392 
393     for (auto i = kMinimumSamplesForPrediction; i < simulatedVsyncs.size(); i++) {
394         tracker.addVsyncTimestamp(simulatedVsyncs[i]);
395         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(simulatedVsyncs[i] + aBitOfTime),
396                     Eq(mPeriod + simulatedVsyncs[i]));
397     }
398 }
399 
400 // See b/145667109, and comment in prod code under test.
TEST_F(VSyncPredictorTest,doesNotPredictBeforeTimePointWithHigherIntercept)401 TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) {
402     std::vector<nsecs_t> const simulatedVsyncs{
403             158929578733000,
404             158929306806205, // oldest TS in ringbuffer
405             158929650879052,
406             158929661969209,
407             158929684198847,
408             158929695268171,
409             158929706370359,
410     };
411     auto const idealPeriod = 11111111;
412     auto const expectedPeriod = 11113919;
413     auto const expectedIntercept = -1195945;
414 
415     tracker.setDisplayModePtr(displayMode(idealPeriod));
416     for (auto const& timestamp : simulatedVsyncs) {
417         tracker.addVsyncTimestamp(timestamp);
418     }
419 
420     auto [slope, intercept] = tracker.getVSyncPredictionModel();
421     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
422     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
423 
424     // (timePoint - oldestTS) % expectedPeriod works out to be: 395334
425     // (timePoint - oldestTS) / expectedPeriod works out to be: 38.96
426     // so failure to account for the offset will floor the ordinal to 38, which was in the past.
427     auto const timePoint = 158929728723871;
428     auto const prediction = tracker.nextAnticipatedVSyncTimeFrom(timePoint);
429     EXPECT_THAT(prediction, Ge(timePoint));
430 }
431 
432 // See b/151146131
TEST_F(VSyncPredictorTest,hasEnoughPrecision)433 TEST_F(VSyncPredictorTest, hasEnoughPrecision) {
434     const auto mode = displayMode(mPeriod);
435     VSyncPredictor tracker{std::make_unique<ClockWrapper>(mClock), mode, 20,
436                            kMinimumSamplesForPrediction, kOutlierTolerancePercent};
437     std::vector<nsecs_t> const simulatedVsyncs{840873348817, 840890049444, 840906762675,
438                                                840923581635, 840940161584, 840956868096,
439                                                840973702473, 840990256277, 841007116851,
440                                                841023722530, 841040452167, 841057073002,
441                                                841073800920, 841090474360, 841107278632,
442                                                841123898634, 841140750875, 841157287127,
443                                                841591357014, 840856664232
444 
445     };
446     auto const idealPeriod = 16666666;
447     auto const expectedPeriod = 16698426;
448     auto const expectedIntercept = 58055;
449 
450     tracker.setDisplayModePtr(displayMode(idealPeriod));
451     for (auto const& timestamp : simulatedVsyncs) {
452         tracker.addVsyncTimestamp(timestamp);
453     }
454 
455     auto [slope, intercept] = tracker.getVSyncPredictionModel();
456     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
457     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
458 }
459 
TEST_F(VSyncPredictorTest,resetsWhenInstructed)460 TEST_F(VSyncPredictorTest, resetsWhenInstructed) {
461     auto const idealPeriod = 10000;
462     auto const realPeriod = 10500;
463     tracker.setDisplayModePtr(displayMode(idealPeriod));
464     for (auto i = 0; i < kMinimumSamplesForPrediction; i++) {
465         tracker.addVsyncTimestamp(i * realPeriod);
466     }
467 
468     EXPECT_THAT(tracker.getVSyncPredictionModel().slope, IsCloseTo(realPeriod, mMaxRoundingError));
469     tracker.resetModel();
470     EXPECT_THAT(tracker.getVSyncPredictionModel().slope, IsCloseTo(idealPeriod, mMaxRoundingError));
471 }
472 
TEST_F(VSyncPredictorTest,slopeAlwaysValid)473 TEST_F(VSyncPredictorTest, slopeAlwaysValid) {
474     constexpr auto kNumVsyncs = 100;
475     auto invalidPeriod = mPeriod;
476     auto now = 0;
477     for (int i = 0; i < kNumVsyncs; i++) {
478         tracker.addVsyncTimestamp(now);
479         now += invalidPeriod;
480         invalidPeriod *= 0.9f;
481 
482         auto [slope, intercept] = tracker.getVSyncPredictionModel();
483         EXPECT_THAT(slope, IsCloseTo(mPeriod, mPeriod * kOutlierTolerancePercent / 100.f));
484 
485         // When VsyncPredictor returns the period it means that it doesn't know how to predict and
486         // it needs to get more samples
487         if (slope == mPeriod && intercept == 0) {
488             EXPECT_TRUE(tracker.needsMoreSamples());
489         }
490     }
491 }
492 
operator ""_years(unsigned long long years)493 constexpr nsecs_t operator""_years(unsigned long long years) noexcept {
494     using namespace std::chrono_literals;
495     return years * 365 * 24 * 3600 *
496             std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
497 }
TEST_F(VSyncPredictorTest,aPhoneThatHasBeenAroundAWhileCanStillComputePeriod)498 TEST_F(VSyncPredictorTest, aPhoneThatHasBeenAroundAWhileCanStillComputePeriod) {
499     constexpr nsecs_t timeBase = 100_years;
500 
501     for (auto i = 0; i < kHistorySize; i++) {
502         tracker.addVsyncTimestamp(timeBase + i * mPeriod);
503     }
504     auto [slope, intercept] = tracker.getVSyncPredictionModel();
505     EXPECT_THAT(slope, IsCloseTo(mPeriod, mMaxRoundingError));
506     EXPECT_THAT(intercept, Eq(0));
507 }
508 
TEST_F(VSyncPredictorTest,isVSyncInPhase)509 TEST_F(VSyncPredictorTest, isVSyncInPhase) {
510     auto last = mNow;
511     auto const bias = 10;
512     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
513         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
514         mNow += mPeriod - bias;
515         last = mNow;
516         tracker.addVsyncTimestamp(mNow);
517         mNow += bias;
518     }
519 
520     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod - bias));
521     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + mPeriod - bias));
522     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 990), Eq(mNow + 2 * mPeriod - bias));
523 
524     const auto maxDivisor = 5;
525     const auto maxPeriods = 15;
526     for (int divisor = 1; divisor < maxDivisor; divisor++) {
527         for (int i = 0; i < maxPeriods; i++) {
528             const bool expectedInPhase = ((kMinimumSamplesForPrediction - 1 + i) % divisor) == 0;
529             EXPECT_THAT(expectedInPhase,
530                         tracker.isVSyncInPhase(mNow + i * mPeriod - bias,
531                                                Fps::fromPeriodNsecs(divisor * mPeriod)))
532                     << "vsync at " << mNow + (i + 1) * mPeriod - bias << " is "
533                     << (expectedInPhase ? "not " : "") << "in phase for divisor " << divisor;
534         }
535     }
536 }
537 
TEST_F(VSyncPredictorTest,isVSyncInPhaseWithRenderRate)538 TEST_F(VSyncPredictorTest, isVSyncInPhaseWithRenderRate) {
539     SET_FLAG_FOR_TEST(flags::vrr_bugfix_24q4, true);
540     auto last = mNow;
541     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
542         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
543         mNow += mPeriod;
544         last = mNow;
545         tracker.addVsyncTimestamp(mNow);
546     }
547 
548     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
549     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + mPeriod), Eq(mNow + 2 * mPeriod));
550 
551     const auto renderRateFps = Fps::fromPeriodNsecs(mPeriod * 2);
552     tracker.setRenderRate(renderRateFps, /*applyImmediately*/ true);
553 
554     EXPECT_FALSE(tracker.isVSyncInPhase(mNow, renderRateFps));
555     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + mPeriod, renderRateFps));
556     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 2 * mPeriod, renderRateFps));
557     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, renderRateFps));
558 }
559 
TEST_F(VSyncPredictorTest,isVSyncInPhaseForDivisors)560 TEST_F(VSyncPredictorTest, isVSyncInPhaseForDivisors) {
561     auto last = mNow;
562     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
563         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
564         mNow += mPeriod;
565         last = mNow;
566         tracker.addVsyncTimestamp(mNow);
567     }
568 
569     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
570 
571     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 1 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 2)));
572     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 2 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 2)));
573     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 2)));
574 
575     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 5 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
576     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
577     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 4 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
578     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 6 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
579     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 7 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
580 }
581 
TEST_F(VSyncPredictorTest,inconsistentVsyncValueIsFlushedEventually)582 TEST_F(VSyncPredictorTest, inconsistentVsyncValueIsFlushedEventually) {
583     EXPECT_TRUE(tracker.addVsyncTimestamp(600));
584     EXPECT_TRUE(tracker.needsMoreSamples());
585 
586     EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod));
587 
588     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
589         EXPECT_TRUE(tracker.needsMoreSamples());
590         EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
591     }
592 
593     EXPECT_FALSE(tracker.needsMoreSamples());
594 }
595 
TEST_F(VSyncPredictorTest,knownVsyncIsUpdated)596 TEST_F(VSyncPredictorTest, knownVsyncIsUpdated) {
597     EXPECT_TRUE(tracker.addVsyncTimestamp(600));
598     EXPECT_TRUE(tracker.needsMoreSamples());
599     EXPECT_EQ(600, tracker.nextAnticipatedVSyncTimeFrom(mNow));
600 
601     EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod));
602     EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
603 
604     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
605         EXPECT_TRUE(tracker.needsMoreSamples());
606         EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
607         EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
608     }
609 
610     EXPECT_FALSE(tracker.needsMoreSamples());
611     EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
612 }
613 
TEST_F(VSyncPredictorTest,robustToDuplicateTimestamps_60hzRealTraceData)614 TEST_F(VSyncPredictorTest, robustToDuplicateTimestamps_60hzRealTraceData) {
615     // these are real vsync timestamps from b/190331974 which caused vsync predictor
616     // period to spike to 18ms due to very close timestamps
617     std::vector<nsecs_t> const simulatedVsyncs{
618             198353408177, 198370074844, 198371400000, 198374274000, 198390941000, 198407565000,
619             198540887994, 198607538588, 198624218276, 198657655939, 198674224176, 198690880955,
620             198724204319, 198740988133, 198758166681, 198790869196, 198824205052, 198840871678,
621             198857715631, 198890885797, 198924199640, 198940873834, 198974204401,
622     };
623     auto constexpr idealPeriod = 16'666'666;
624     auto constexpr expectedPeriod = 16'644'742;
625     auto constexpr expectedIntercept = 125'626;
626 
627     tracker.setDisplayModePtr(displayMode(idealPeriod));
628     for (auto const& timestamp : simulatedVsyncs) {
629         tracker.addVsyncTimestamp(timestamp);
630     }
631     auto [slope, intercept] = tracker.getVSyncPredictionModel();
632     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
633     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
634 }
635 
TEST_F(VSyncPredictorTest,setRenderRateIsRespected)636 TEST_F(VSyncPredictorTest, setRenderRateIsRespected) {
637     auto last = mNow;
638     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
639         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
640         mNow += mPeriod;
641         last = mNow;
642         tracker.addVsyncTimestamp(mNow);
643     }
644 
645     tracker.setRenderRate(Fps::fromPeriodNsecs(3 * mPeriod), /*applyImmediately*/ false);
646 
647     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + 3 * mPeriod));
648     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + 3 * mPeriod));
649     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 1100), Eq(mNow + 3 * mPeriod));
650     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 2100), Eq(mNow + 3 * mPeriod));
651     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 3100), Eq(mNow + 6 * mPeriod));
652     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 4100), Eq(mNow + 6 * mPeriod));
653     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5100), Eq(mNow + 6 * mPeriod));
654 }
655 
TEST_F(VSyncPredictorTest,setRenderRateIsIgnoredIfNotDivisor)656 TEST_F(VSyncPredictorTest, setRenderRateIsIgnoredIfNotDivisor) {
657     auto last = mNow;
658     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
659         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
660         mNow += mPeriod;
661         last = mNow;
662         tracker.addVsyncTimestamp(mNow);
663     }
664 
665     tracker.setRenderRate(Fps::fromPeriodNsecs(3.5f * mPeriod), /*applyImmediately*/ false);
666 
667     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
668     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + mPeriod));
669     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 1100), Eq(mNow + 2 * mPeriod));
670     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 2100), Eq(mNow + 3 * mPeriod));
671     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 3100), Eq(mNow + 4 * mPeriod));
672     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 4100), Eq(mNow + 5 * mPeriod));
673     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5100), Eq(mNow + 6 * mPeriod));
674 }
675 
TEST_F(VSyncPredictorTest,setRenderRateWhenRenderRateGoesDown)676 TEST_F(VSyncPredictorTest, setRenderRateWhenRenderRateGoesDown) {
677     SET_FLAG_FOR_TEST(flags::vrr_config, true);
678     SET_FLAG_FOR_TEST(flags::vrr_bugfix_24q4, true);
679 
680     const int32_t kGroup = 0;
681     const auto kResolution = ui::Size(1920, 1080);
682     const auto vsyncRate = Fps::fromPeriodNsecs(500);
683     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
684     hal::VrrConfig vrrConfig;
685     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
686     const ftl::NonNull<DisplayModePtr> kMode =
687             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
688                                                       kResolution, DEFAULT_DISPLAY_ID)
689                                      .setVrrConfig(std::move(vrrConfig))
690                                      .build());
691 
692     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
693                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
694 
695     Fps frameRate = Fps::fromPeriodNsecs(1000);
696     vrrTracker.setRenderRate(frameRate, /*applyImmediately*/ false);
697     vrrTracker.addVsyncTimestamp(0);
698     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
699     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
700 
701     frameRate = Fps::fromPeriodNsecs(3000);
702     vrrTracker.setRenderRate(frameRate, /*applyImmediately*/ false);
703     EXPECT_TRUE(vrrTracker.isVSyncInPhase(2000, frameRate));
704 }
705 
TEST_F(VSyncPredictorTest,setRenderRateHighIsAppliedImmediately)706 TEST_F(VSyncPredictorTest, setRenderRateHighIsAppliedImmediately) {
707     SET_FLAG_FOR_TEST(flags::vrr_config, true);
708 
709     const int32_t kGroup = 0;
710     const auto kResolution = ui::Size(1920, 1080);
711     const auto vsyncRate = Fps::fromPeriodNsecs(500);
712     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
713     hal::VrrConfig vrrConfig;
714     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
715     const ftl::NonNull<DisplayModePtr> kMode =
716             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
717                                                       kResolution, DEFAULT_DISPLAY_ID)
718                                      .setVrrConfig(std::move(vrrConfig))
719                                      .build());
720 
721     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
722                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
723 
724     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
725     vrrTracker.addVsyncTimestamp(0);
726     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
727     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
728 
729     // commit to a vsync in the future
730     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
731 
732     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ false);
733     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
734     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
735     EXPECT_EQ(8000, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
736 
737     EXPECT_EQ(12000, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
738 
739     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(3500), /*applyImmediately*/ false);
740     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
741     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
742     EXPECT_EQ(8000, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
743     EXPECT_EQ(10000, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 8000));
744     EXPECT_EQ(12000, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
745     EXPECT_EQ(15500, vrrTracker.nextAnticipatedVSyncTimeFrom(12000, 12000));
746     EXPECT_EQ(19000, vrrTracker.nextAnticipatedVSyncTimeFrom(15500, 15500));
747 
748     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(2500), /*applyImmediately*/ false);
749     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
750     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
751     EXPECT_EQ(8000, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
752     EXPECT_EQ(10000, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 8000));
753     EXPECT_EQ(12000, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
754     EXPECT_EQ(15500, vrrTracker.nextAnticipatedVSyncTimeFrom(12000, 12000));
755     EXPECT_EQ(19000, vrrTracker.nextAnticipatedVSyncTimeFrom(15500, 15500));
756     EXPECT_EQ(21500, vrrTracker.nextAnticipatedVSyncTimeFrom(19000, 19000));
757 
758     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
759     EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
760     EXPECT_EQ(6500, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
761     EXPECT_EQ(7500, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
762     EXPECT_EQ(9500, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 8000));
763     EXPECT_EQ(11500, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
764     EXPECT_EQ(13500, vrrTracker.nextAnticipatedVSyncTimeFrom(12000, 12000));
765     EXPECT_EQ(16500, vrrTracker.nextAnticipatedVSyncTimeFrom(15500, 15500));
766     EXPECT_EQ(20500, vrrTracker.nextAnticipatedVSyncTimeFrom(19000, 19000));
767 
768     // matches the previous cadence
769     EXPECT_EQ(21500, vrrTracker.nextAnticipatedVSyncTimeFrom(20500, 20500));
770 }
771 
TEST_F(VSyncPredictorTest,minFramePeriodDoesntApplyWhenSameWithRefreshRate)772 TEST_F(VSyncPredictorTest, minFramePeriodDoesntApplyWhenSameWithRefreshRate) {
773     SET_FLAG_FOR_TEST(flags::vrr_config, true);
774 
775     const int32_t kGroup = 0;
776     const auto kResolution = ui::Size(1920, 1080);
777     const auto vsyncRate = Fps::fromPeriodNsecs(1000);
778     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
779     hal::VrrConfig vrrConfig;
780     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
781     const ftl::NonNull<DisplayModePtr> kMode =
782             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
783                                                       kResolution, DEFAULT_DISPLAY_ID)
784                                      .setVrrConfig(std::move(vrrConfig))
785                                      .build());
786 
787     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
788                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
789 
790     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
791     vrrTracker.addVsyncTimestamp(0);
792     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
793     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
794 
795     // Assume that the last vsync is wrong due to a vsync drift. It shouldn't matter.
796     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1700));
797 }
798 
TEST_F(VSyncPredictorTest,setRenderRateExplicitAppliedImmediately)799 TEST_F(VSyncPredictorTest, setRenderRateExplicitAppliedImmediately) {
800     SET_FLAG_FOR_TEST(flags::vrr_config, true);
801 
802     const int32_t kGroup = 0;
803     const auto kResolution = ui::Size(1920, 1080);
804     const auto vsyncRate = Fps::fromPeriodNsecs(500);
805     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
806     hal::VrrConfig vrrConfig;
807     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
808     const ftl::NonNull<DisplayModePtr> kMode =
809             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
810                                                       kResolution, DEFAULT_DISPLAY_ID)
811                                      .setVrrConfig(std::move(vrrConfig))
812                                      .build());
813 
814     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
815                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
816 
817     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
818     vrrTracker.addVsyncTimestamp(0);
819     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
820     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
821 
822     // commit to a vsync in the future
823     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 2000));
824 
825     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ true);
826     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000));
827     EXPECT_EQ(7000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
828     EXPECT_EQ(9000, vrrTracker.nextAnticipatedVSyncTimeFrom(7000, 7000));
829 }
830 
TEST_F(VSyncPredictorTest,selectsClosestVsyncAfterInactivity)831 TEST_F(VSyncPredictorTest, selectsClosestVsyncAfterInactivity) {
832     SET_FLAG_FOR_TEST(flags::vrr_config, true);
833 
834     const int32_t kGroup = 0;
835     const auto kResolution = ui::Size(1920, 1080);
836     const auto vsyncRate = Fps::fromPeriodNsecs(500);
837     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
838     hal::VrrConfig vrrConfig;
839     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
840     const ftl::NonNull<DisplayModePtr> kMode =
841             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
842                                                       kResolution, DEFAULT_DISPLAY_ID)
843                                      .setVrrConfig(std::move(vrrConfig))
844                                      .build());
845 
846     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
847                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
848 
849     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(5000), /*applyImmediately*/ false);
850     vrrTracker.addVsyncTimestamp(0);
851     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4700));
852     EXPECT_EQ(10000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
853 
854     mClock->setNow(50000);
855     EXPECT_EQ(50500, vrrTracker.nextAnticipatedVSyncTimeFrom(50000, 10000));
856 }
857 
TEST_F(VSyncPredictorTest,returnsCorrectVsyncWhenLastIsNot)858 TEST_F(VSyncPredictorTest, returnsCorrectVsyncWhenLastIsNot) {
859     SET_FLAG_FOR_TEST(flags::vrr_config, true);
860 
861     const int32_t kGroup = 0;
862     const auto kResolution = ui::Size(1920, 1080);
863     const auto vsyncRate = Fps::fromPeriodNsecs(500);
864     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
865     hal::VrrConfig vrrConfig;
866     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
867     const ftl::NonNull<DisplayModePtr> kMode =
868             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
869                                                       kResolution, DEFAULT_DISPLAY_ID)
870                                      .setVrrConfig(std::move(vrrConfig))
871                                      .build());
872 
873     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
874                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
875 
876     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
877     vrrTracker.addVsyncTimestamp(0);
878     EXPECT_EQ(2500, vrrTracker.nextAnticipatedVSyncTimeFrom(1234, 1234));
879 }
880 
TEST_F(VSyncPredictorTest,adjustsVrrTimeline)881 TEST_F(VSyncPredictorTest, adjustsVrrTimeline) {
882     SET_FLAG_FOR_TEST(flags::vrr_config, true);
883 
884     const int32_t kGroup = 0;
885     const auto kResolution = ui::Size(1920, 1080);
886     const auto refreshRate = Fps::fromPeriodNsecs(500);
887     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
888     hal::VrrConfig vrrConfig;
889     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
890     const ftl::NonNull<DisplayModePtr> kMode =
891             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
892                                                       kResolution, DEFAULT_DISPLAY_ID)
893                                      .setVrrConfig(std::move(vrrConfig))
894                                      .build());
895 
896     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
897                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
898 
899     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
900     vrrTracker.addVsyncTimestamp(0);
901     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
902     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
903 
904     vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
905                             {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
906     EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 2000));
907     EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(3500, 3500));
908 
909     // Miss when starting 4500 and expect the next vsync will be at 5000 (next one)
910     vrrTracker.onFrameBegin(TimePoint::fromNs(3500),
911                             {TimePoint::fromNs(2500), TimePoint::fromNs(2500)});
912     vrrTracker.onFrameMissed(TimePoint::fromNs(4500));
913     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
914     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
915 
916     vrrTracker.onFrameBegin(TimePoint::fromNs(7000),
917                             {TimePoint::fromNs(6500), TimePoint::fromNs(6500)});
918     EXPECT_EQ(8500, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 7000));
919     EXPECT_EQ(9500, vrrTracker.nextAnticipatedVSyncTimeFrom(9000, 7000));
920 }
921 
TEST_F(VSyncPredictorTest,adjustsVrrTimelineTwoClients)922 TEST_F(VSyncPredictorTest, adjustsVrrTimelineTwoClients) {
923     SET_FLAG_FOR_TEST(flags::vrr_config, true);
924 
925     const int32_t kGroup = 0;
926     const auto kResolution = ui::Size(1920, 1080);
927     const auto refreshRate = Fps::fromPeriodNsecs(500);
928     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
929     hal::VrrConfig vrrConfig;
930     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
931     const ftl::NonNull<DisplayModePtr> kMode =
932             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
933                                                       kResolution, DEFAULT_DISPLAY_ID)
934                                      .setVrrConfig(std::move(vrrConfig))
935                                      .build());
936 
937     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
938                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
939 
940     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
941     vrrTracker.addVsyncTimestamp(0);
942 
943     // App runs ahead
944     EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2700));
945     EXPECT_EQ(4000, vrrTracker.nextAnticipatedVSyncTimeFrom(3000, 3000));
946     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
947 
948     // SF starts to catch up
949     EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2700));
950     vrrTracker.onFrameBegin(TimePoint::fromNs(3000), {TimePoint::fromNs(0), TimePoint::fromNs(0)});
951 
952     // SF misses last frame (3000) and observes that when committing (4000)
953     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
954     EXPECT_EQ(4000, vrrTracker.nextAnticipatedVSyncTimeFrom(3700));
955     vrrTracker.onFrameMissed(TimePoint::fromNs(4000));
956 
957     // SF wakes up again instead of the (4000) missed frame
958     EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
959     vrrTracker.onFrameBegin(TimePoint::fromNs(4500),
960                             {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
961 
962     // Timeline shifted. The app needs to get the next frame at (7500) as its last frame (6500) will
963     // be presented at (7500)
964     EXPECT_EQ(7500, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
965     EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
966     vrrTracker.onFrameBegin(TimePoint::fromNs(5500),
967                             {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
968 
969     EXPECT_EQ(8500, vrrTracker.nextAnticipatedVSyncTimeFrom(7500, 7500));
970     EXPECT_EQ(6500, vrrTracker.nextAnticipatedVSyncTimeFrom(5500, 5500));
971     vrrTracker.onFrameBegin(TimePoint::fromNs(6500),
972                             {TimePoint::fromNs(5500), TimePoint::fromNs(5500)});
973 }
974 
TEST_F(VSyncPredictorTest,renderRateIsPreservedForCommittedVsyncs)975 TEST_F(VSyncPredictorTest, renderRateIsPreservedForCommittedVsyncs) {
976     tracker.addVsyncTimestamp(1000);
977 
978     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
979     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
980     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
981 
982     tracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ false);
983     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
984     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
985     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
986     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(7001), Eq(9000));
987     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(8001), Eq(9000));
988     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(11000));
989     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(10001), Eq(11000));
990 
991     tracker.setRenderRate(Fps::fromPeriodNsecs(3000), /*applyImmediately*/ false);
992     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
993     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
994     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
995     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(7001), Eq(9000));
996     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(8001), Eq(9000));
997     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(11000));
998     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(10001), Eq(11000));
999     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(11001), Eq(14000));
1000     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(12001), Eq(14000));
1001 
1002     // Check the purge logic works
1003     mClock->setNow(20000);
1004     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(2000));
1005     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(8000));
1006     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(8000));
1007 }
1008 
1009 // b/329310308
TEST_F(VSyncPredictorTest,renderRateChangeAfterAppliedImmediately)1010 TEST_F(VSyncPredictorTest, renderRateChangeAfterAppliedImmediately) {
1011     tracker.addVsyncTimestamp(1000);
1012 
1013     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1014     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1001), Eq(2000));
1015     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(2001), Eq(3000));
1016 
1017     tracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ true);
1018     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1019     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1001), Eq(3000));
1020     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(3001), Eq(5000));
1021 
1022     tracker.setRenderRate(Fps::fromPeriodNsecs(4000), /*applyImmediately*/ false);
1023     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1024     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1001), Eq(3000));
1025     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(3001), Eq(5000));
1026     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(9000));
1027     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(13000));
1028 }
1029 
TEST_F(VSyncPredictorTest,timelineNotAdjustedForEarlyPresent)1030 TEST_F(VSyncPredictorTest, timelineNotAdjustedForEarlyPresent) {
1031     SET_FLAG_FOR_TEST(flags::vrr_config, true);
1032 
1033     const int32_t kGroup = 0;
1034     const auto kResolution = ui::Size(1920, 1080);
1035     const auto refreshRate = Fps::fromPeriodNsecs(500);
1036     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
1037     hal::VrrConfig vrrConfig;
1038     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
1039     const ftl::NonNull<DisplayModePtr> kMode =
1040             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
1041                                                       kResolution, DEFAULT_DISPLAY_ID)
1042                                      .setVrrConfig(std::move(vrrConfig))
1043                                      .build());
1044 
1045     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
1046                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
1047 
1048     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
1049     vrrTracker.addVsyncTimestamp(0);
1050     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
1051 
1052     constexpr auto kLastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
1053     constexpr auto kLastActualSignalTime = TimePoint::fromNs(700); // presented early
1054     vrrTracker.onFrameBegin(TimePoint::fromNs(1400),
1055                             {kLastActualSignalTime, kLastConfirmedExpectedPresentTime});
1056     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1400, 1000));
1057     EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 1000));
1058 }
1059 
TEST_F(VSyncPredictorTest,adjustsOnlyMinFrameViolatingVrrTimeline)1060 TEST_F(VSyncPredictorTest, adjustsOnlyMinFrameViolatingVrrTimeline) {
1061     const auto refreshRate = Fps::fromPeriodNsecs(500);
1062     auto minFrameRate = Fps::fromPeriodNsecs(1000);
1063     hal::VrrConfig vrrConfig{.minFrameIntervalNs =
1064                                      static_cast<int32_t>(minFrameRate.getPeriodNsecs())};
1065     ftl::NonNull<DisplayModePtr> mode =
1066             ftl::as_non_null(createVrrDisplayMode(DisplayModeId(0), refreshRate, vrrConfig));
1067     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), mode, kHistorySize,
1068                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
1069     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
1070     vrrTracker.addVsyncTimestamp(0);
1071 
1072     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
1073     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
1074     auto lastConfirmedSignalTime = TimePoint::fromNs(1500);
1075     auto lastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
1076     vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
1077                             {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime});
1078     EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(3000, 1500));
1079 
1080     minFrameRate = Fps::fromPeriodNsecs(2000);
1081     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
1082     lastConfirmedSignalTime = TimePoint::fromNs(2500);
1083     lastConfirmedExpectedPresentTime = TimePoint::fromNs(2500);
1084     vrrTracker.onFrameBegin(TimePoint::fromNs(3000),
1085                             {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime});
1086     // Enough time without adjusting vsync to present with new rate on time, no need of adjustment
1087     EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 3500));
1088 }
1089 } // namespace android::scheduler
1090 
1091 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1092 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
1093