SF: ignore very close vsync timestamps
Check for very close vsync timestamps and mark those
as invalid.
Test: SF unit tests
Bug: 190331974
Change-Id: I13ccc09d6a07847fdfc60242a1a65246fa9674ac
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 329e4a0..e9bd92a 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -69,7 +69,21 @@
auto const aValidTimestamp = mTimestamps[mLastTimestampIndex];
auto const percent = (timestamp - aValidTimestamp) % mIdealPeriod * kMaxPercent / mIdealPeriod;
- return percent < kOutlierTolerancePercent || percent > (kMaxPercent - kOutlierTolerancePercent);
+ if (percent >= kOutlierTolerancePercent &&
+ percent <= (kMaxPercent - kOutlierTolerancePercent)) {
+ return false;
+ }
+
+ const auto iter = std::min_element(mTimestamps.begin(), mTimestamps.end(),
+ [timestamp](nsecs_t a, nsecs_t b) {
+ return std::abs(timestamp - a) < std::abs(timestamp - b);
+ });
+ const auto distancePercent = std::abs(*iter - timestamp) * kMaxPercent / mIdealPeriod;
+ if (distancePercent < kOutlierTolerancePercent) {
+ // duplicate timestamp
+ return false;
+ }
+ return true;
}
nsecs_t VSyncPredictor::currentPeriod() const {
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index ae936e4..37ecd7c 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -510,6 +510,28 @@
EXPECT_EQ(mNow + 1000, tracker.nextAnticipatedVSyncTimeFrom(mNow));
}
+TEST_F(VSyncPredictorTest, robustToDuplicateTimestamps_60hzRealTraceData) {
+ // these are real vsync timestamps from b/190331974 which caused vsync predictor
+ // period to spike to 18ms due to very close timestamps
+ std::vector<nsecs_t> const simulatedVsyncs{
+ 198353408177, 198370074844, 198371400000, 198374274000, 198390941000, 198407565000,
+ 198540887994, 198607538588, 198624218276, 198657655939, 198674224176, 198690880955,
+ 198724204319, 198740988133, 198758166681, 198790869196, 198824205052, 198840871678,
+ 198857715631, 198890885797, 198924199640, 198940873834, 198974204401,
+ };
+ auto constexpr idealPeriod = 16'666'666;
+ auto constexpr expectedPeriod = 16'644'742;
+ auto constexpr expectedIntercept = 125'626;
+
+ tracker.setPeriod(idealPeriod);
+ for (auto const& timestamp : simulatedVsyncs) {
+ tracker.addVsyncTimestamp(timestamp);
+ }
+ auto [slope, intercept] = tracker.getVSyncPredictionModel();
+ EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
+ EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
+}
+
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues