SF: Avoid adjusting the frame time when last frame is presented early
BUG: 350738983
Test: atest VSyncPredictorTest
Flag: EXEMPT bugfix
Change-Id: I7206811bc83929a45bac66d9fc1ad0a5cfb70f11
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index fc54a8b..3df724a 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -34,6 +34,7 @@
#include "mock/MockSchedulerCallback.h"
#include <FrontEnd/LayerHierarchy.h>
+#include <scheduler/FrameTime.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include "FpsOps.h"
@@ -607,7 +608,8 @@
TimePoint::fromNs(2000)));
// Not crossing the min frame period
- vrrTracker->onFrameBegin(TimePoint::fromNs(2000), TimePoint::fromNs(1500));
+ vrrTracker->onFrameBegin(TimePoint::fromNs(2000),
+ {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
EXPECT_EQ(Fps::fromPeriodNsecs(1000),
scheduler.getNextFrameInterval(kMode->getPhysicalDisplayId(),
TimePoint::fromNs(2500)));
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
index 3b09554..b63f299 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -19,6 +19,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <scheduler/FrameTime.h>
#include <scheduler/Timer.h>
#include "Scheduler/VSyncDispatchTimerQueue.h"
@@ -51,7 +52,7 @@
bool isVSyncInPhase(nsecs_t, Fps) final { return false; }
void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) final {}
void setRenderRate(Fps, bool) final {}
- void onFrameBegin(TimePoint, TimePoint) final {}
+ void onFrameBegin(TimePoint, scheduler::FrameTime) final {}
void onFrameMissed(TimePoint) final {}
void dump(std::string&) const final {}
bool isCurrentMode(const ftl::NonNull<DisplayModePtr>&) const final { return false; };
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index f36a8a6..8690dba 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -901,17 +901,20 @@
EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
- vrrTracker.onFrameBegin(TimePoint::fromNs(2000), TimePoint::fromNs(1500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
+ {TimePoint::fromNs(1500), TimePoint::fromNs(1500)});
EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 2000));
EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(3500, 3500));
// Miss when starting 4500 and expect the next vsync will be at 5000 (next one)
- vrrTracker.onFrameBegin(TimePoint::fromNs(3500), TimePoint::fromNs(2500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(3500),
+ {TimePoint::fromNs(2500), TimePoint::fromNs(2500)});
vrrTracker.onFrameMissed(TimePoint::fromNs(4500));
EXPECT_EQ(5000, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
- vrrTracker.onFrameBegin(TimePoint::fromNs(7000), TimePoint::fromNs(6500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(7000),
+ {TimePoint::fromNs(6500), TimePoint::fromNs(6500)});
EXPECT_EQ(10500, vrrTracker.nextAnticipatedVSyncTimeFrom(9000, 7000));
}
@@ -943,7 +946,7 @@
// SF starts to catch up
EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2700));
- vrrTracker.onFrameBegin(TimePoint::fromNs(3000), TimePoint::fromNs(0));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(3000), {TimePoint::fromNs(0), TimePoint::fromNs(0)});
// SF misses last frame (3000) and observes that when committing (4000)
EXPECT_EQ(6000, vrrTracker.nextAnticipatedVSyncTimeFrom(5000, 5000));
@@ -952,17 +955,20 @@
// SF wakes up again instead of the (4000) missed frame
EXPECT_EQ(4500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 4000));
- vrrTracker.onFrameBegin(TimePoint::fromNs(4500), TimePoint::fromNs(4500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(4500),
+ {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
// Timeline shifted. The app needs to get the next frame at (7500) as its last frame (6500) will
// be presented at (7500)
EXPECT_EQ(7500, vrrTracker.nextAnticipatedVSyncTimeFrom(6000, 6000));
EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4500, 4500));
- vrrTracker.onFrameBegin(TimePoint::fromNs(5500), TimePoint::fromNs(4500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(5500),
+ {TimePoint::fromNs(4500), TimePoint::fromNs(4500)});
EXPECT_EQ(8500, vrrTracker.nextAnticipatedVSyncTimeFrom(7500, 7500));
EXPECT_EQ(6500, vrrTracker.nextAnticipatedVSyncTimeFrom(5500, 5500));
- vrrTracker.onFrameBegin(TimePoint::fromNs(6500), TimePoint::fromNs(5500));
+ vrrTracker.onFrameBegin(TimePoint::fromNs(6500),
+ {TimePoint::fromNs(5500), TimePoint::fromNs(5500)});
}
TEST_F(VSyncPredictorTest, renderRateIsPreservedForCommittedVsyncs) {
@@ -1020,6 +1026,35 @@
EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(9001), Eq(13000));
}
+TEST_F(VSyncPredictorTest, timelineNotAdjustedForEarlyPresent) {
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ const int32_t kGroup = 0;
+ const auto kResolution = ui::Size(1920, 1080);
+ const auto refreshRate = Fps::fromPeriodNsecs(500);
+ const auto minFrameRate = Fps::fromPeriodNsecs(1000);
+ hal::VrrConfig vrrConfig;
+ vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs();
+ const ftl::NonNull<DisplayModePtr> kMode =
+ ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), refreshRate, kGroup,
+ kResolution, DEFAULT_DISPLAY_ID)
+ .setVrrConfig(std::move(vrrConfig))
+ .build());
+
+ VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), kMode, kHistorySize,
+ kMinimumSamplesForPrediction, kOutlierTolerancePercent};
+
+ vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
+ vrrTracker.addVsyncTimestamp(0);
+ EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
+
+ constexpr auto kLastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
+ constexpr auto kLastActualSignalTime = TimePoint::fromNs(700); // presented early
+ vrrTracker.onFrameBegin(TimePoint::fromNs(1400),
+ {kLastActualSignalTime, kLastConfirmedExpectedPresentTime});
+ EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1400, 1000));
+ EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 1000));
+}
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
index 4f44d1b..8d6d1d3 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
@@ -18,6 +18,8 @@
#include <gmock/gmock.h>
+#include <scheduler/FrameTime.h>
+
#include "Scheduler/VSyncTracker.h"
namespace android::mock {
@@ -37,7 +39,7 @@
MOCK_METHOD(bool, isVSyncInPhase, (nsecs_t, Fps), (override));
MOCK_METHOD(void, setDisplayModePtr, (ftl::NonNull<DisplayModePtr>), (override));
MOCK_METHOD(void, setRenderRate, (Fps, bool), (override));
- MOCK_METHOD(void, onFrameBegin, (TimePoint, TimePoint), (override));
+ MOCK_METHOD(void, onFrameBegin, (TimePoint, scheduler::FrameTime), (override));
MOCK_METHOD(void, onFrameMissed, (TimePoint), (override));
MOCK_METHOD(void, dump, (std::string&), (const, override));
MOCK_METHOD(bool, isCurrentMode, (const ftl::NonNull<DisplayModePtr>&), (const, override));