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