• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,recoverAfterDriftedVSyncAreReplacedWithCorrectVSync)307 TEST_F(VSyncPredictorTest, recoverAfterDriftedVSyncAreReplacedWithCorrectVSync) {
308     SET_FLAG_FOR_TEST(flags::vsync_predictor_recovery, true);
309     auto constexpr idealPeriodNs = 4166666;
310     auto constexpr minFrameIntervalNs = 8333333;
311     auto constexpr idealPeriod = Fps::fromPeriodNsecs(idealPeriodNs);
312     auto constexpr minFrameRate = Fps::fromPeriodNsecs(minFrameIntervalNs);
313     hal::VrrConfig vrrConfig{.minFrameIntervalNs = minFrameIntervalNs};
314     ftl::NonNull<DisplayModePtr> mode =
315             ftl::as_non_null(createVrrDisplayMode(DisplayModeId(0), idealPeriod, vrrConfig));
316     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), mode, kHistorySize,
317                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
318     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ true);
319     // Curated list of VSyncs that causes the VSync drift.
320     std::vector<nsecs_t> const simulatedVsyncs{74473665741, 74481774375, 74489911818, 74497993491,
321                                                74506000833, 74510002150, 74513904390, 74517748707,
322                                                74521550947, 74525383187, 74529165427, 74533067667,
323                                                74536751484, 74540653724, 74544282649, 74548084889,
324                                                74551917129, 74555699369, 74559601609, 74563601611,
325                                                74567503851, 74571358168, 74575260408, 74578889333,
326                                                74582691573, 74586523813, 74590306053, 74593589870,
327                                                74597492110, 74601121035, 74604923275, 74608755515,
328                                                74612537755, 74616166680, 74619795605, 74623424530,
329                                                74627043455, 74630645695, 74634245935, 74637778175,
330                                                74641291992, 74644794232, 74648275157, 74651575397,
331                                                74654807637, 74658007877, 74661176117, 74664345357};
332     for (auto const& timestamp : simulatedVsyncs) {
333         vrrTracker.addVsyncTimestamp(timestamp);
334     }
335     auto slope = vrrTracker.getVSyncPredictionModel().slope;
336     // Without using the idealPeriod for the calculation of the VSync predictor mode the
337     // the slope would be 3343031
338     EXPECT_THAT(slope, IsCloseTo(4347805, mMaxRoundingError));
339     EXPECT_FALSE(vrrTracker.needsMoreSamples());
340 
341     auto lastVsync = 74664345357;
342     // Add valid VSyncs to replace the drifted VSyncs
343     for (int i = 0; i <= kHistorySize; i++) {
344         lastVsync += minFrameIntervalNs;
345         EXPECT_TRUE(vrrTracker.addVsyncTimestamp(lastVsync));
346     }
347     EXPECT_FALSE(vrrTracker.needsMoreSamples());
348     slope = vrrTracker.getVSyncPredictionModel().slope;
349     // Corrected slop is closer to the idealPeriod
350     // when valid vsync are inserted otherwise this would still be 3349673
351     EXPECT_THAT(slope, IsCloseTo(idealPeriodNs, mMaxRoundingError));
352 }
353 
TEST_F(VSyncPredictorTest,handlesVsyncChange)354 TEST_F(VSyncPredictorTest, handlesVsyncChange) {
355     auto const fastPeriod = 100;
356     auto const fastTimeBase = 100;
357     auto const slowPeriod = 400;
358     auto const slowTimeBase = 800;
359     auto const simulatedVsyncsFast =
360             generateVsyncTimestamps(kMinimumSamplesForPrediction, fastPeriod, fastTimeBase);
361     auto const simulatedVsyncsSlow =
362             generateVsyncTimestamps(kMinimumSamplesForPrediction, slowPeriod, slowTimeBase);
363 
364     tracker.setDisplayModePtr(displayMode(fastPeriod));
365     for (auto const& timestamp : simulatedVsyncsFast) {
366         tracker.addVsyncTimestamp(timestamp);
367     }
368 
369     auto const mMaxRoundingError = 100;
370     auto model = tracker.getVSyncPredictionModel();
371     EXPECT_THAT(model.slope, IsCloseTo(fastPeriod, mMaxRoundingError));
372     EXPECT_THAT(model.intercept, IsCloseTo(0, mMaxRoundingError));
373 
374     tracker.setDisplayModePtr(displayMode(slowPeriod));
375     for (auto const& timestamp : simulatedVsyncsSlow) {
376         tracker.addVsyncTimestamp(timestamp);
377     }
378     model = tracker.getVSyncPredictionModel();
379     EXPECT_THAT(model.slope, IsCloseTo(slowPeriod, mMaxRoundingError));
380     EXPECT_THAT(model.intercept, IsCloseTo(0, mMaxRoundingError));
381 }
382 
TEST_F(VSyncPredictorTest,willBeAccurateUsingPriorResultsForRate)383 TEST_F(VSyncPredictorTest, willBeAccurateUsingPriorResultsForRate) {
384     auto const fastPeriod = 101000;
385     auto const fastTimeBase = fastPeriod - 500;
386     auto const fastPeriod2 = 99000;
387 
388     auto const slowPeriod = 400000;
389     auto const slowTimeBase = 800000 - 201;
390     auto const simulatedVsyncsFast =
391             generateVsyncTimestamps(kMinimumSamplesForPrediction, fastPeriod, fastTimeBase);
392     auto const simulatedVsyncsSlow =
393             generateVsyncTimestamps(kMinimumSamplesForPrediction, slowPeriod, slowTimeBase);
394     auto const simulatedVsyncsFast2 =
395             generateVsyncTimestamps(kMinimumSamplesForPrediction, fastPeriod2, fastTimeBase);
396 
397     auto idealPeriod = 100000;
398     tracker.setDisplayModePtr(displayMode(idealPeriod));
399     for (auto const& timestamp : simulatedVsyncsFast) {
400         tracker.addVsyncTimestamp(timestamp);
401     }
402     auto model = tracker.getVSyncPredictionModel();
403     EXPECT_THAT(model.slope, Eq(fastPeriod));
404     EXPECT_THAT(model.intercept, Eq(0));
405 
406     tracker.setDisplayModePtr(displayMode(slowPeriod));
407     for (auto const& timestamp : simulatedVsyncsSlow) {
408         tracker.addVsyncTimestamp(timestamp);
409     }
410 
411     // we had a model for 100ns mPeriod before, use that until the new samples are
412     // sufficiently built up
413     tracker.setDisplayModePtr(displayMode(idealPeriod));
414     model = tracker.getVSyncPredictionModel();
415     EXPECT_THAT(model.slope, Eq(fastPeriod));
416     EXPECT_THAT(model.intercept, Eq(0));
417 
418     for (auto const& timestamp : simulatedVsyncsFast2) {
419         tracker.addVsyncTimestamp(timestamp);
420     }
421     model = tracker.getVSyncPredictionModel();
422     EXPECT_THAT(model.slope, Eq(fastPeriod2));
423     EXPECT_THAT(model.intercept, Eq(0));
424 }
425 
TEST_F(VSyncPredictorTest,idealModelPredictionsBeforeRegressionModelIsBuilt)426 TEST_F(VSyncPredictorTest, idealModelPredictionsBeforeRegressionModelIsBuilt) {
427     auto const simulatedVsyncs =
428             generateVsyncTimestamps(kMinimumSamplesForPrediction + 1, mPeriod, 0);
429     nsecs_t const mNow = 0;
430     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mPeriod));
431 
432     nsecs_t const aBitOfTime = 422;
433 
434     for (auto i = 0; i < kMinimumSamplesForPrediction; i++) {
435         tracker.addVsyncTimestamp(simulatedVsyncs[i]);
436         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(simulatedVsyncs[i] + aBitOfTime),
437                     Eq(mPeriod + simulatedVsyncs[i]));
438     }
439 
440     for (auto i = kMinimumSamplesForPrediction; i < simulatedVsyncs.size(); i++) {
441         tracker.addVsyncTimestamp(simulatedVsyncs[i]);
442         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(simulatedVsyncs[i] + aBitOfTime),
443                     Eq(mPeriod + simulatedVsyncs[i]));
444     }
445 }
446 
447 // See b/145667109, and comment in prod code under test.
TEST_F(VSyncPredictorTest,doesNotPredictBeforeTimePointWithHigherIntercept)448 TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) {
449     std::vector<nsecs_t> const simulatedVsyncs{
450             158929578733000,
451             158929306806205, // oldest TS in ringbuffer
452             158929650879052, 158929661969209, 158929684198847, 158929695268171, 158929706370359,
453     };
454     auto const idealPeriod = 11111111;
455     auto const expectedPeriod = 11113919;
456     auto const expectedIntercept = -1195945;
457 
458     tracker.setDisplayModePtr(displayMode(idealPeriod));
459     for (auto const& timestamp : simulatedVsyncs) {
460         tracker.addVsyncTimestamp(timestamp);
461     }
462 
463     auto [slope, intercept] = tracker.getVSyncPredictionModel();
464     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
465     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
466 
467     // (timePoint - oldestTS) % expectedPeriod works out to be: 10702663
468     // (timePoint - oldestTS) / expectedPeriod works out to be: 37.96
469     // so failure to account for the offset will floor the ordinal to 37, which was in the past.
470     auto const timePoint = 158929728723871;
471     auto const prediction = tracker.nextAnticipatedVSyncTimeFrom(timePoint);
472     EXPECT_THAT(prediction, Ge(timePoint));
473 }
474 
475 // See b/151146131
TEST_F(VSyncPredictorTest,hasEnoughPrecision)476 TEST_F(VSyncPredictorTest, hasEnoughPrecision) {
477     const auto mode = displayMode(mPeriod);
478     VSyncPredictor tracker{std::make_unique<ClockWrapper>(mClock), mode, 20,
479                            kMinimumSamplesForPrediction, kOutlierTolerancePercent};
480     std::vector<nsecs_t> const simulatedVsyncs{840873348817, 840890049444, 840906762675,
481                                                840923581635, 840940161584, 840956868096,
482                                                840973702473, 840990256277, 841007116851,
483                                                841023722530, 841040452167, 841057073002,
484                                                841073800920, 841090474360, 841107278632,
485                                                841123898634, 841140750875, 841157287127,
486                                                841591357014, 840856664232
487 
488     };
489     auto const idealPeriod = 16666666;
490     auto const expectedPeriod = 16698426;
491     auto const expectedIntercept = 58055;
492 
493     tracker.setDisplayModePtr(displayMode(idealPeriod));
494     for (auto const& timestamp : simulatedVsyncs) {
495         tracker.addVsyncTimestamp(timestamp);
496     }
497 
498     auto [slope, intercept] = tracker.getVSyncPredictionModel();
499     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
500     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
501 }
502 
TEST_F(VSyncPredictorTest,resetsWhenInstructed)503 TEST_F(VSyncPredictorTest, resetsWhenInstructed) {
504     auto const idealPeriod = 10000;
505     auto const realPeriod = 10500;
506     tracker.setDisplayModePtr(displayMode(idealPeriod));
507     for (auto i = 0; i < kMinimumSamplesForPrediction; i++) {
508         tracker.addVsyncTimestamp(i * realPeriod);
509     }
510 
511     EXPECT_THAT(tracker.getVSyncPredictionModel().slope, IsCloseTo(realPeriod, mMaxRoundingError));
512     tracker.resetModel();
513     EXPECT_THAT(tracker.getVSyncPredictionModel().slope, IsCloseTo(idealPeriod, mMaxRoundingError));
514 }
515 
TEST_F(VSyncPredictorTest,slopeAlwaysValid)516 TEST_F(VSyncPredictorTest, slopeAlwaysValid) {
517     constexpr auto kNumVsyncs = 100;
518     auto invalidPeriod = mPeriod;
519     auto now = 0;
520     for (int i = 0; i < kNumVsyncs; i++) {
521         tracker.addVsyncTimestamp(now);
522         now += invalidPeriod;
523         invalidPeriod *= 0.9f;
524 
525         auto [slope, intercept] = tracker.getVSyncPredictionModel();
526         EXPECT_THAT(slope, IsCloseTo(mPeriod, mPeriod * kOutlierTolerancePercent / 100.f));
527 
528         // When VsyncPredictor returns the period it means that it doesn't know how to predict and
529         // it needs to get more samples
530         if (slope == mPeriod && intercept == 0) {
531             EXPECT_TRUE(tracker.needsMoreSamples());
532         }
533     }
534 }
535 
operator ""_years(unsigned long long years)536 constexpr nsecs_t operator""_years(unsigned long long years) noexcept {
537     using namespace std::chrono_literals;
538     return years * 365 * 24 * 3600 *
539             std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
540 }
TEST_F(VSyncPredictorTest,aPhoneThatHasBeenAroundAWhileCanStillComputePeriod)541 TEST_F(VSyncPredictorTest, aPhoneThatHasBeenAroundAWhileCanStillComputePeriod) {
542     constexpr nsecs_t timeBase = 100_years;
543 
544     for (auto i = 0; i < kHistorySize; i++) {
545         tracker.addVsyncTimestamp(timeBase + i * mPeriod);
546     }
547     auto [slope, intercept] = tracker.getVSyncPredictionModel();
548     EXPECT_THAT(slope, IsCloseTo(mPeriod, mMaxRoundingError));
549     EXPECT_THAT(intercept, Eq(0));
550 }
551 
TEST_F(VSyncPredictorTest,isVSyncInPhase)552 TEST_F(VSyncPredictorTest, isVSyncInPhase) {
553     auto last = mNow;
554     auto const bias = 10;
555     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
556         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
557         mNow += mPeriod - bias;
558         last = mNow;
559         tracker.addVsyncTimestamp(mNow);
560         mNow += bias;
561     }
562 
563     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod - bias));
564     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + mPeriod - bias));
565     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 990), Eq(mNow + 2 * mPeriod - bias));
566 
567     const auto maxDivisor = 5;
568     const auto maxPeriods = 15;
569     for (int divisor = 1; divisor < maxDivisor; divisor++) {
570         for (int i = 0; i < maxPeriods; i++) {
571             const bool expectedInPhase = ((kMinimumSamplesForPrediction - 1 + i) % divisor) == 0;
572             EXPECT_THAT(expectedInPhase,
573                         tracker.isVSyncInPhase(mNow + i * mPeriod - bias,
574                                                Fps::fromPeriodNsecs(divisor * mPeriod)))
575                     << "vsync at " << mNow + (i + 1) * mPeriod - bias << " is "
576                     << (expectedInPhase ? "not " : "") << "in phase for divisor " << divisor;
577         }
578     }
579 }
580 
TEST_F(VSyncPredictorTest,isVSyncInPhaseWithRenderRate)581 TEST_F(VSyncPredictorTest, isVSyncInPhaseWithRenderRate) {
582     SET_FLAG_FOR_TEST(flags::vrr_bugfix_24q4, true);
583     auto last = mNow;
584     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
585         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
586         mNow += mPeriod;
587         last = mNow;
588         tracker.addVsyncTimestamp(mNow);
589     }
590 
591     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
592     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + mPeriod), Eq(mNow + 2 * mPeriod));
593 
594     const auto renderRateFps = Fps::fromPeriodNsecs(mPeriod * 2);
595     tracker.setRenderRate(renderRateFps, /*applyImmediately*/ true);
596 
597     EXPECT_FALSE(tracker.isVSyncInPhase(mNow, renderRateFps));
598     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + mPeriod, renderRateFps));
599     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 2 * mPeriod, renderRateFps));
600     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, renderRateFps));
601 }
602 
TEST_F(VSyncPredictorTest,isVSyncInPhaseForDivisors)603 TEST_F(VSyncPredictorTest, isVSyncInPhaseForDivisors) {
604     auto last = mNow;
605     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
606         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
607         mNow += mPeriod;
608         last = mNow;
609         tracker.addVsyncTimestamp(mNow);
610     }
611 
612     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
613 
614     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 1 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 2)));
615     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 2 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 2)));
616     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 2)));
617 
618     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 5 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
619     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 3 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
620     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 4 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
621     EXPECT_FALSE(tracker.isVSyncInPhase(mNow + 6 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
622     EXPECT_TRUE(tracker.isVSyncInPhase(mNow + 7 * mPeriod, Fps::fromPeriodNsecs(mPeriod * 4)));
623 }
624 
TEST_F(VSyncPredictorTest,inconsistentVsyncValueIsFlushedEventually)625 TEST_F(VSyncPredictorTest, inconsistentVsyncValueIsFlushedEventually) {
626     EXPECT_TRUE(tracker.addVsyncTimestamp(600));
627     EXPECT_TRUE(tracker.needsMoreSamples());
628 
629     EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod));
630 
631     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
632         EXPECT_TRUE(tracker.needsMoreSamples());
633         EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
634     }
635 
636     EXPECT_FALSE(tracker.needsMoreSamples());
637 }
638 
TEST_F(VSyncPredictorTest,knownVsyncIsUpdated)639 TEST_F(VSyncPredictorTest, knownVsyncIsUpdated) {
640     EXPECT_TRUE(tracker.addVsyncTimestamp(600));
641     EXPECT_TRUE(tracker.needsMoreSamples());
642     EXPECT_EQ(600, tracker.nextAnticipatedVSyncTimeFrom(mNow));
643 
644     EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod));
645     EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
646 
647     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
648         EXPECT_TRUE(tracker.needsMoreSamples());
649         EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
650         EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
651     }
652 
653     EXPECT_FALSE(tracker.needsMoreSamples());
654     EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
655 }
656 
TEST_F(VSyncPredictorTest,robustToDuplicateTimestamps_60hzRealTraceData)657 TEST_F(VSyncPredictorTest, robustToDuplicateTimestamps_60hzRealTraceData) {
658     // these are real vsync timestamps from b/190331974 which caused vsync predictor
659     // period to spike to 18ms due to very close timestamps
660     std::vector<nsecs_t> const simulatedVsyncs{
661             198353408177, 198370074844, 198371400000, 198374274000, 198390941000, 198407565000,
662             198540887994, 198607538588, 198624218276, 198657655939, 198674224176, 198690880955,
663             198724204319, 198740988133, 198758166681, 198790869196, 198824205052, 198840871678,
664             198857715631, 198890885797, 198924199640, 198940873834, 198974204401,
665     };
666     auto constexpr idealPeriod = 16'666'666;
667     auto constexpr expectedPeriod = 16'644'742;
668     auto constexpr expectedIntercept = 125'626;
669 
670     tracker.setDisplayModePtr(displayMode(idealPeriod));
671     for (auto const& timestamp : simulatedVsyncs) {
672         tracker.addVsyncTimestamp(timestamp);
673     }
674     auto [slope, intercept] = tracker.getVSyncPredictionModel();
675     EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
676     EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
677 }
678 
TEST_F(VSyncPredictorTest,setRenderRateIsRespected)679 TEST_F(VSyncPredictorTest, setRenderRateIsRespected) {
680     auto last = mNow;
681     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
682         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
683         mNow += mPeriod;
684         last = mNow;
685         tracker.addVsyncTimestamp(mNow);
686     }
687 
688     tracker.setRenderRate(Fps::fromPeriodNsecs(3 * mPeriod), /*applyImmediately*/ false);
689 
690     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + 3 * mPeriod));
691     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + 3 * mPeriod));
692     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 1100), Eq(mNow + 3 * mPeriod));
693     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 2100), Eq(mNow + 3 * mPeriod));
694     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 3100), Eq(mNow + 6 * mPeriod));
695     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 4100), Eq(mNow + 6 * mPeriod));
696     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5100), Eq(mNow + 6 * mPeriod));
697 }
698 
TEST_F(VSyncPredictorTest,setRenderRateIsIgnoredIfNotDivisor)699 TEST_F(VSyncPredictorTest, setRenderRateIsIgnoredIfNotDivisor) {
700     auto last = mNow;
701     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
702         EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(last + mPeriod));
703         mNow += mPeriod;
704         last = mNow;
705         tracker.addVsyncTimestamp(mNow);
706     }
707 
708     tracker.setRenderRate(Fps::fromPeriodNsecs(3.5f * mPeriod), /*applyImmediately*/ false);
709 
710     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow), Eq(mNow + mPeriod));
711     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + mPeriod));
712     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 1100), Eq(mNow + 2 * mPeriod));
713     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 2100), Eq(mNow + 3 * mPeriod));
714     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 3100), Eq(mNow + 4 * mPeriod));
715     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 4100), Eq(mNow + 5 * mPeriod));
716     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5100), Eq(mNow + 6 * mPeriod));
717 }
718 
TEST_F(VSyncPredictorTest,setRenderRateWhenRenderRateGoesDown)719 TEST_F(VSyncPredictorTest, setRenderRateWhenRenderRateGoesDown) {
720     SET_FLAG_FOR_TEST(flags::vrr_config, true);
721     SET_FLAG_FOR_TEST(flags::vrr_bugfix_24q4, true);
722 
723     const int32_t kGroup = 0;
724     const auto kResolution = ui::Size(1920, 1080);
725     const auto vsyncRate = Fps::fromPeriodNsecs(500);
726     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
727     hal::VrrConfig vrrConfig;
728     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
729     const ftl::NonNull<DisplayModePtr> kMode =
730             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
731                                                       kResolution, DEFAULT_DISPLAY_ID)
732                                      .setVrrConfig(std::move(vrrConfig))
733                                      .build());
734 
735     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
736                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
737 
738     Fps frameRate = Fps::fromPeriodNsecs(1000);
739     vrrTracker.setRenderRate(frameRate, /*applyImmediately*/ false);
740     vrrTracker.addVsyncTimestamp(0);
741     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
742     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
743 
744     frameRate = Fps::fromPeriodNsecs(3000);
745     vrrTracker.setRenderRate(frameRate, /*applyImmediately*/ false);
746     EXPECT_TRUE(vrrTracker.isVSyncInPhase(2000, frameRate));
747 }
748 
TEST_F(VSyncPredictorTest,setRenderRateHighIsAppliedImmediately)749 TEST_F(VSyncPredictorTest, setRenderRateHighIsAppliedImmediately) {
750     SET_FLAG_FOR_TEST(flags::vrr_config, true);
751 
752     const int32_t kGroup = 0;
753     const auto kResolution = ui::Size(1920, 1080);
754     const auto vsyncRate = Fps::fromPeriodNsecs(500);
755     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
756     hal::VrrConfig vrrConfig;
757     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
758     const ftl::NonNull<DisplayModePtr> kMode =
759             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
760                                                       kResolution, DEFAULT_DISPLAY_ID)
761                                      .setVrrConfig(std::move(vrrConfig))
762                                      .build());
763 
764     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
765                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
766 
767     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
768     vrrTracker.addVsyncTimestamp(0);
769     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
770     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
771 
772     // commit to a vsync in the future
773     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
774 
775     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ false);
776     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
777     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
778     EXPECT_EQ(8000, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
779 
780     EXPECT_EQ(12000, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
781 
782     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(3500), /*applyImmediately*/ false);
783     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
784     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
785     EXPECT_EQ(8000, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
786     EXPECT_EQ(10000, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 8000));
787     EXPECT_EQ(12000, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
788     EXPECT_EQ(15500, vrrTracker.nextAnticipatedVSyncTimeFrom(12000, 12000));
789     EXPECT_EQ(19000, vrrTracker.nextAnticipatedVSyncTimeFrom(15500, 15500));
790 
791     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(2500), /*applyImmediately*/ false);
792     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
793     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
794     EXPECT_EQ(8000, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
795     EXPECT_EQ(10000, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 8000));
796     EXPECT_EQ(12000, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
797     EXPECT_EQ(15500, vrrTracker.nextAnticipatedVSyncTimeFrom(12000, 12000));
798     EXPECT_EQ(19000, vrrTracker.nextAnticipatedVSyncTimeFrom(15500, 15500));
799     EXPECT_EQ(21500, vrrTracker.nextAnticipatedVSyncTimeFrom(19000, 19000));
800 
801     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
802     EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
803     EXPECT_EQ(6500, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
804     EXPECT_EQ(7500, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
805     EXPECT_EQ(9500, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 8000));
806     EXPECT_EQ(11500, vrrTracker.nextAnticipatedVSyncTimeFrom(10000, 10000));
807     EXPECT_EQ(13500, vrrTracker.nextAnticipatedVSyncTimeFrom(12000, 12000));
808     EXPECT_EQ(16500, vrrTracker.nextAnticipatedVSyncTimeFrom(15500, 15500));
809     EXPECT_EQ(20500, vrrTracker.nextAnticipatedVSyncTimeFrom(19000, 19000));
810 
811     // matches the previous cadence
812     EXPECT_EQ(21500, vrrTracker.nextAnticipatedVSyncTimeFrom(20500, 20500));
813 }
814 
TEST_F(VSyncPredictorTest,minFramePeriodDoesntApplyWhenSameWithRefreshRate)815 TEST_F(VSyncPredictorTest, minFramePeriodDoesntApplyWhenSameWithRefreshRate) {
816     SET_FLAG_FOR_TEST(flags::vrr_config, true);
817 
818     const int32_t kGroup = 0;
819     const auto kResolution = ui::Size(1920, 1080);
820     const auto vsyncRate = Fps::fromPeriodNsecs(1000);
821     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
822     hal::VrrConfig vrrConfig;
823     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
824     const ftl::NonNull<DisplayModePtr> kMode =
825             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
826                                                       kResolution, DEFAULT_DISPLAY_ID)
827                                      .setVrrConfig(std::move(vrrConfig))
828                                      .build());
829 
830     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
831                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
832 
833     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
834     vrrTracker.addVsyncTimestamp(0);
835     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
836     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
837 
838     // Assume that the last vsync is wrong due to a vsync drift. It shouldn't matter.
839     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1700));
840 }
841 
TEST_F(VSyncPredictorTest,setRenderRateExplicitAppliedImmediately)842 TEST_F(VSyncPredictorTest, setRenderRateExplicitAppliedImmediately) {
843     SET_FLAG_FOR_TEST(flags::vrr_config, true);
844 
845     const int32_t kGroup = 0;
846     const auto kResolution = ui::Size(1920, 1080);
847     const auto vsyncRate = Fps::fromPeriodNsecs(500);
848     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
849     hal::VrrConfig vrrConfig;
850     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
851     const ftl::NonNull<DisplayModePtr> kMode =
852             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
853                                                       kResolution, DEFAULT_DISPLAY_ID)
854                                      .setVrrConfig(std::move(vrrConfig))
855                                      .build());
856 
857     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
858                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
859 
860     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
861     vrrTracker.addVsyncTimestamp(0);
862     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
863     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000));
864 
865     // commit to a vsync in the future
866     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 2000));
867 
868     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ true);
869     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000));
870     EXPECT_EQ(7000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
871     EXPECT_EQ(9000, vrrTracker.nextAnticipatedVSyncTimeFrom(7000, 7000));
872 }
873 
TEST_F(VSyncPredictorTest,selectsClosestVsyncAfterInactivity)874 TEST_F(VSyncPredictorTest, selectsClosestVsyncAfterInactivity) {
875     SET_FLAG_FOR_TEST(flags::vrr_config, true);
876 
877     const int32_t kGroup = 0;
878     const auto kResolution = ui::Size(1920, 1080);
879     const auto vsyncRate = Fps::fromPeriodNsecs(500);
880     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
881     hal::VrrConfig vrrConfig;
882     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
883     const ftl::NonNull<DisplayModePtr> kMode =
884             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
885                                                       kResolution, DEFAULT_DISPLAY_ID)
886                                      .setVrrConfig(std::move(vrrConfig))
887                                      .build());
888 
889     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
890                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
891 
892     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(5000), /*applyImmediately*/ false);
893     vrrTracker.addVsyncTimestamp(0);
894     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4700));
895     EXPECT_EQ(10000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
896 
897     mClock->setNow(50000);
898     EXPECT_EQ(50500, vrrTracker.nextAnticipatedVSyncTimeFrom(50000, 10000));
899 }
900 
TEST_F(VSyncPredictorTest,returnsCorrectVsyncWhenLastIsNot)901 TEST_F(VSyncPredictorTest, returnsCorrectVsyncWhenLastIsNot) {
902     SET_FLAG_FOR_TEST(flags::vrr_config, true);
903 
904     const int32_t kGroup = 0;
905     const auto kResolution = ui::Size(1920, 1080);
906     const auto vsyncRate = Fps::fromPeriodNsecs(500);
907     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
908     hal::VrrConfig vrrConfig;
909     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
910     const ftl::NonNull<DisplayModePtr> kMode =
911             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup,
912                                                       kResolution, DEFAULT_DISPLAY_ID)
913                                      .setVrrConfig(std::move(vrrConfig))
914                                      .build());
915 
916     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
917                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
918 
919     vrrTracker.setRenderRate(Fps::fromPeriodNsecs(1000), /*applyImmediately*/ false);
920     vrrTracker.addVsyncTimestamp(0);
921     EXPECT_EQ(2500, vrrTracker.nextAnticipatedVSyncTimeFrom(1234, 1234));
922 }
923 
TEST_F(VSyncPredictorTest,adjustsVrrTimeline)924 TEST_F(VSyncPredictorTest, adjustsVrrTimeline) {
925     SET_FLAG_FOR_TEST(flags::vrr_config, true);
926 
927     const int32_t kGroup = 0;
928     const auto kResolution = ui::Size(1920, 1080);
929     const auto refreshRate = Fps::fromPeriodNsecs(500);
930     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
931     hal::VrrConfig vrrConfig;
932     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
933     const ftl::NonNull<DisplayModePtr> kMode =
934             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
935                                                       kResolution, DEFAULT_DISPLAY_ID)
936                                      .setVrrConfig(std::move(vrrConfig))
937                                      .build());
938 
939     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
940                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
941 
942     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
943     vrrTracker.addVsyncTimestamp(0);
944     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
945     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
946 
947     vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
948                             {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
949     EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 2000));
950     EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(3500, 3500));
951 
952     // Miss when starting 4500 and expect the next vsync will be at 5000 (next one)
953     vrrTracker.onFrameBegin(TimePoint::fromNs(3500),
954                             {TimePoint::fromNs(2500), TimePoint::fromNs(2500)});
955     vrrTracker.onFrameMissed(TimePoint::fromNs(4500));
956     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
957     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
958 
959     vrrTracker.onFrameBegin(TimePoint::fromNs(7000),
960                             {TimePoint::fromNs(6500), TimePoint::fromNs(6500)});
961     EXPECT_EQ(8500, vrrTracker.nextAnticipatedVSyncTimeFrom(8000, 7000));
962     EXPECT_EQ(9500, vrrTracker.nextAnticipatedVSyncTimeFrom(9000, 7000));
963 }
964 
TEST_F(VSyncPredictorTest,adjustsVrrTimelineTwoClients)965 TEST_F(VSyncPredictorTest, adjustsVrrTimelineTwoClients) {
966     SET_FLAG_FOR_TEST(flags::vrr_config, true);
967 
968     const int32_t kGroup = 0;
969     const auto kResolution = ui::Size(1920, 1080);
970     const auto refreshRate = Fps::fromPeriodNsecs(500);
971     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
972     hal::VrrConfig vrrConfig;
973     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
974     const ftl::NonNull<DisplayModePtr> kMode =
975             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
976                                                       kResolution, DEFAULT_DISPLAY_ID)
977                                      .setVrrConfig(std::move(vrrConfig))
978                                      .build());
979 
980     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
981                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
982 
983     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
984     vrrTracker.addVsyncTimestamp(0);
985 
986     // App runs ahead
987     EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2700));
988     EXPECT_EQ(4000, vrrTracker.nextAnticipatedVSyncTimeFrom(3000, 3000));
989     EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
990 
991     // SF starts to catch up
992     EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2700));
993     vrrTracker.onFrameBegin(TimePoint::fromNs(3000), {TimePoint::fromNs(0), TimePoint::fromNs(0)});
994 
995     // SF misses last frame (3000) and observes that when committing (4000)
996     EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
997     EXPECT_EQ(4000, vrrTracker.nextAnticipatedVSyncTimeFrom(3700));
998     vrrTracker.onFrameMissed(TimePoint::fromNs(4000));
999 
1000     // SF wakes up again instead of the (4000) missed frame
1001     EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
1002     vrrTracker.onFrameBegin(TimePoint::fromNs(4500),
1003                             {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
1004 
1005     // Timeline shifted. The app needs to get the next frame at (7500) as its last frame (6500) will
1006     // be presented at (7500)
1007     EXPECT_EQ(7500, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
1008     EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
1009     vrrTracker.onFrameBegin(TimePoint::fromNs(5500),
1010                             {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
1011 
1012     EXPECT_EQ(8500, vrrTracker.nextAnticipatedVSyncTimeFrom(7500, 7500));
1013     EXPECT_EQ(6500, vrrTracker.nextAnticipatedVSyncTimeFrom(5500, 5500));
1014     vrrTracker.onFrameBegin(TimePoint::fromNs(6500),
1015                             {TimePoint::fromNs(5500), TimePoint::fromNs(5500)});
1016 }
1017 
TEST_F(VSyncPredictorTest,renderRateIsPreservedForCommittedVsyncs)1018 TEST_F(VSyncPredictorTest, renderRateIsPreservedForCommittedVsyncs) {
1019     tracker.addVsyncTimestamp(1000);
1020 
1021     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1022     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
1023     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
1024 
1025     tracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ false);
1026     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1027     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
1028     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
1029     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(7001), Eq(9000));
1030     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(8001), Eq(9000));
1031     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(11000));
1032     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(10001), Eq(11000));
1033 
1034     tracker.setRenderRate(Fps::fromPeriodNsecs(3000), /*applyImmediately*/ false);
1035     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1036     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(6000));
1037     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(7000));
1038     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(7001), Eq(9000));
1039     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(8001), Eq(9000));
1040     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(11000));
1041     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(10001), Eq(11000));
1042     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(11001), Eq(14000));
1043     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(12001), Eq(14000));
1044 
1045     // Check the purge logic works
1046     mClock->setNow(20000);
1047     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(2000));
1048     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(8000));
1049     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(6001), Eq(8000));
1050 }
1051 
1052 // b/329310308
TEST_F(VSyncPredictorTest,renderRateChangeAfterAppliedImmediately)1053 TEST_F(VSyncPredictorTest, renderRateChangeAfterAppliedImmediately) {
1054     tracker.addVsyncTimestamp(1000);
1055 
1056     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1057     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1001), Eq(2000));
1058     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(2001), Eq(3000));
1059 
1060     tracker.setRenderRate(Fps::fromPeriodNsecs(2000), /*applyImmediately*/ true);
1061     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1062     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1001), Eq(3000));
1063     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(3001), Eq(5000));
1064 
1065     tracker.setRenderRate(Fps::fromPeriodNsecs(4000), /*applyImmediately*/ false);
1066     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1), Eq(1000));
1067     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(1001), Eq(3000));
1068     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(3001), Eq(5000));
1069     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(5001), Eq(9000));
1070     EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(13000));
1071 }
1072 
TEST_F(VSyncPredictorTest,timelineNotAdjustedForEarlyPresent)1073 TEST_F(VSyncPredictorTest, timelineNotAdjustedForEarlyPresent) {
1074     SET_FLAG_FOR_TEST(flags::vrr_config, true);
1075 
1076     const int32_t kGroup = 0;
1077     const auto kResolution = ui::Size(1920, 1080);
1078     const auto refreshRate = Fps::fromPeriodNsecs(500);
1079     const auto minFrameRate = Fps::fromPeriodNsecs(1000);
1080     hal::VrrConfig vrrConfig;
1081     vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
1082     const ftl::NonNull<DisplayModePtr> kMode =
1083             ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
1084                                                       kResolution, DEFAULT_DISPLAY_ID)
1085                                      .setVrrConfig(std::move(vrrConfig))
1086                                      .build());
1087 
1088     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
1089                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
1090 
1091     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
1092     vrrTracker.addVsyncTimestamp(0);
1093     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
1094 
1095     constexpr auto kLastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
1096     constexpr auto kLastActualSignalTime = TimePoint::fromNs(700); // presented early
1097     vrrTracker.onFrameBegin(TimePoint::fromNs(1400),
1098                             {kLastActualSignalTime, kLastConfirmedExpectedPresentTime});
1099     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1400, 1000));
1100     EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 1000));
1101 }
1102 
TEST_F(VSyncPredictorTest,adjustsOnlyMinFrameViolatingVrrTimeline)1103 TEST_F(VSyncPredictorTest, adjustsOnlyMinFrameViolatingVrrTimeline) {
1104     const auto refreshRate = Fps::fromPeriodNsecs(500);
1105     auto minFrameRate = Fps::fromPeriodNsecs(1000);
1106     hal::VrrConfig vrrConfig{.minFrameIntervalNs =
1107                                      static_cast<int32_t>(minFrameRate.getPeriodNsecs())};
1108     ftl::NonNull<DisplayModePtr> mode =
1109             ftl::as_non_null(createVrrDisplayMode(DisplayModeId(0), refreshRate, vrrConfig));
1110     VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), mode, kHistorySize,
1111                               kMinimumSamplesForPrediction, kOutlierTolerancePercent};
1112     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
1113     vrrTracker.addVsyncTimestamp(0);
1114 
1115     EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
1116     EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
1117     auto lastConfirmedSignalTime = TimePoint::fromNs(1500);
1118     auto lastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
1119     vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
1120                             {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime});
1121     EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(3000, 1500));
1122 
1123     minFrameRate = Fps::fromPeriodNsecs(2000);
1124     vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
1125     lastConfirmedSignalTime = TimePoint::fromNs(2500);
1126     lastConfirmedExpectedPresentTime = TimePoint::fromNs(2500);
1127     vrrTracker.onFrameBegin(TimePoint::fromNs(3000),
1128                             {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime});
1129     // Enough time without adjusting vsync to present with new rate on time, no need of adjustment
1130     EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 3500));
1131 }
1132 } // namespace android::scheduler
1133 
1134 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1135 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
1136