Create a VsyncSchedule per display
In order to determine the vsync offsets between displays, keep track of
a VsyncSchedule for each display.
Store the VsyncSchedules in a SmallMap. Update getVsyncSchedule with a
parameter to choose the display. The default parameter uses the leader's
display, which is what current external callers want.
Update VsyncDispatches when the leader changes, so that they are always
listening to the leader.
Enable and disable vsync callbacks per display. Earlier attempts to turn
them on and off together could leave a secondary display on a bad
schedule. Move state and logic for enabling/disabling the callbacks into
VsyncSchedule. Add a method for resyncing all displays at once.
Use std::shared_ptrs for VsyncDispatches. This prevents lifetime issues
if a VsyncSchedule gets removed while its VsyncDispatch is still in use.
Same for VsyncTracker, which is referenced by VsyncDispatch.
When the leader VsyncSchedule changes, call cancel on
VsyncCallbackRegistrations and replace them with new ones using the new
VsyncDispatches. If a callback was scheduled, schedule a new one.
Update VsyncSchedule's members' traces so that there is a separate track
for each display.
Move SF's record of the last HWC Vsync states into VsyncSchedule, so it
sits with other related logic. Remove the pending HWC Vsync state, which
did not affect behavior.
For refresh rate changes, modulate vsync config based on the leader
display. When switching leaders, force a period transition to ensure
that a potential refresh rate change is completed.
Bug: 255601557
Bug: 256196556
Bug: 241285473
Bug: 241286146
Test: libsurfaceflinger_unittest
Test: manual (look at perfetto traces)
Change-Id: If60218e85292c786b9fa70ecb33ee374d3a385e0
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index b3aba37..5cecb8e 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -52,11 +52,9 @@
constexpr PhysicalDisplayId DISPLAY_ID_64BIT =
PhysicalDisplayId::fromEdid(0xffu, 0xffffu, 0xffff'ffffu);
-constexpr std::chrono::duration VSYNC_PERIOD(16ms);
-
} // namespace
-class EventThreadTest : public testing::Test {
+class EventThreadTest : public testing::Test, public IEventThreadCallback {
protected:
static constexpr std::chrono::nanoseconds kWorkDuration = 0ms;
static constexpr std::chrono::nanoseconds kReadyDuration = 3ms;
@@ -97,7 +95,7 @@
void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
int32_t expectedConfigId,
nsecs_t expectedVsyncPeriod);
- void expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t);
+ void expectThrottleVsyncReceived(TimePoint expectedTimestamp, uid_t);
void expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
std::vector<FrameRateOverride>);
@@ -106,6 +104,14 @@
mThread->onVsync(expectedPresentationTime, timestamp, deadlineTimestamp);
}
+ // IEventThreadCallback overrides.
+ bool isVsyncTargetForUid(TimePoint expectedVsyncTime, uid_t uid) const override {
+ mThrottleVsyncCallRecorder.getInvocable()(expectedVsyncTime, uid);
+ return uid != mThrottledConnectionUid;
+ }
+
+ Fps getLeaderRenderFrameRate(uid_t uid) const override { return 60_Hz; }
+
AsyncCallRecorderWithCannedReturn<
scheduler::ScheduleResult (*)(scheduler::VSyncDispatch::CallbackToken,
scheduler::VSyncDispatch::ScheduleTiming)>
@@ -121,11 +127,11 @@
AsyncCallRecorder<void (*)(scheduler::VSyncDispatch::CallbackToken)>
mVSyncCallbackUnregisterRecorder;
AsyncCallRecorder<void (*)()> mResyncCallRecorder;
- AsyncCallRecorder<void (*)(nsecs_t, uid_t)> mThrottleVsyncCallRecorder;
+ mutable AsyncCallRecorder<void (*)(TimePoint, uid_t)> mThrottleVsyncCallRecorder;
ConnectionEventRecorder mConnectionEventCallRecorder{0};
ConnectionEventRecorder mThrottledConnectionEventCallRecorder{0};
- std::optional<scheduler::VsyncSchedule> mVsyncSchedule;
+ std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule;
std::unique_ptr<impl::EventThread> mThread;
sp<MockEventThreadConnection> mConnection;
sp<MockEventThreadConnection> mThrottledConnection;
@@ -140,12 +146,12 @@
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
- mVsyncSchedule.emplace(scheduler::VsyncSchedule(std::make_unique<mock::VSyncTracker>(),
- std::make_unique<mock::VSyncDispatch>(),
- nullptr));
-
- mock::VSyncDispatch& mockDispatch =
- *static_cast<mock::VSyncDispatch*>(&mVsyncSchedule->getDispatch());
+ auto mockDispatchPtr = std::make_shared<mock::VSyncDispatch>();
+ mVsyncSchedule = std::shared_ptr<scheduler::VsyncSchedule>(
+ new scheduler::VsyncSchedule(INTERNAL_DISPLAY_ID,
+ std::make_shared<mock::VSyncTracker>(), mockDispatchPtr,
+ nullptr));
+ mock::VSyncDispatch& mockDispatch = *mockDispatchPtr;
EXPECT_CALL(mockDispatch, registerCallback(_, _))
.WillRepeatedly(Invoke(mVSyncCallbackRegisterRecorder.getInvocable()));
EXPECT_CALL(mockDispatch, schedule(_, _))
@@ -180,19 +186,10 @@
}
void EventThreadTest::createThread() {
- const auto throttleVsync = [&](nsecs_t expectedVsyncTimestamp, uid_t uid) {
- mThrottleVsyncCallRecorder.getInvocable()(expectedVsyncTimestamp, uid);
- return (uid == mThrottledConnectionUid);
- };
- const auto getVsyncPeriod = [](uid_t uid) {
- return VSYNC_PERIOD.count();
- };
-
mTokenManager = std::make_unique<frametimeline::impl::TokenManager>();
mThread =
- std::make_unique<impl::EventThread>(/*std::move(source), */ "EventThreadTest",
- *mVsyncSchedule, mTokenManager.get(), throttleVsync,
- getVsyncPeriod, kWorkDuration, kReadyDuration);
+ std::make_unique<impl::EventThread>("EventThreadTest", mVsyncSchedule, *this,
+ mTokenManager.get(), kWorkDuration, kReadyDuration);
// EventThread should register itself as VSyncSource callback.
EXPECT_TRUE(mVSyncCallbackRegisterRecorder.waitForCall().has_value());
@@ -225,7 +222,7 @@
EXPECT_EQ(expectedReadyDuration.count(), std::get<1>(args.value()).readyDuration);
}
-void EventThreadTest::expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t uid) {
+void EventThreadTest::expectThrottleVsyncReceived(TimePoint expectedTimestamp, uid_t uid) {
auto args = mThrottleVsyncCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
EXPECT_EQ(expectedTimestamp, std::get<0>(args.value()));
@@ -376,7 +373,7 @@
// Use the received callback to signal a first vsync event.
// The throttler should receive the event, as well as the connection.
onVSyncEvent(123, 456, 789);
- expectThrottleVsyncReceived(456, mConnectionUid);
+ expectThrottleVsyncReceived(TimePoint::fromNs(456), mConnectionUid);
expectVsyncEventReceivedByConnection(123, 1u);
// EventThread is requesting one more callback due to VsyncRequest::SingleSuppressCallback
@@ -494,17 +491,17 @@
// Send a vsync event. EventThread should then make a call to the
// throttler, and the connection.
onVSyncEvent(123, 456, 789);
- expectThrottleVsyncReceived(456, mConnectionUid);
+ expectThrottleVsyncReceived(TimePoint::fromNs(456), mConnectionUid);
expectVsyncEventReceivedByConnection(123, 1u);
// A second event should go to the same places.
onVSyncEvent(456, 123, 0);
- expectThrottleVsyncReceived(123, mConnectionUid);
+ expectThrottleVsyncReceived(TimePoint::fromNs(123), mConnectionUid);
expectVsyncEventReceivedByConnection(456, 2u);
// A third event should go to the same places.
onVSyncEvent(789, 777, 111);
- expectThrottleVsyncReceived(777, mConnectionUid);
+ expectThrottleVsyncReceived(TimePoint::fromNs(777), mConnectionUid);
expectVsyncEventReceivedByConnection(789, 3u);
}
@@ -743,7 +740,7 @@
// Use the received callback to signal a first vsync event.
// The throttler should receive the event, but not the connection.
onVSyncEvent(123, 456, 789);
- expectThrottleVsyncReceived(456, mThrottledConnectionUid);
+ expectThrottleVsyncReceived(TimePoint::fromNs(456), mThrottledConnectionUid);
mThrottledConnectionEventCallRecorder.waitForUnexpectedCall();
expectVSyncCallbackScheduleReceived(true);
@@ -751,7 +748,7 @@
// The throttler should receive the event, but the connection should
// not as it was only interested in the first.
onVSyncEvent(456, 123, 0);
- expectThrottleVsyncReceived(123, mThrottledConnectionUid);
+ expectThrottleVsyncReceived(TimePoint::fromNs(123), mThrottledConnectionUid);
EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
expectVSyncCallbackScheduleReceived(true);