From 8cd2bf53e6c2cd96216679c6530a9f18fb7deb6f Mon Sep 17 00:00:00 2001 From: Kevin DuBois Date: Thu, 16 Jul 2020 10:21:36 -0700 Subject: VSR: dispatch cbs skipped due to timer lag. If the timer has a lot of lag relative to the intended wakeup time, there could be two callbacks that should be dispatched during this wakeup, not just one, with the additional callback being woken up being the one that was skipped because of the timer lag. Fixes: 159884130 Test: 1 new unit test Test: uibench a/b Change-Id: Ia17bc5a09a085fcb334226849214e5247e010b37 (cherry picked from commit f947783f66ddbc2275379fc1e45f991245c62967) --- .../Scheduler/VSyncDispatchTimerQueue.cpp | 6 +++-- .../unittests/VSyncDispatchTimerQueueTest.cpp | 31 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp index a596bce002..2a6fd0521f 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp @@ -243,7 +243,8 @@ void VSyncDispatchTimerQueue::timerCallback() { std::vector invocations; { std::lock_guard lk(mMutex); - mLastTimerCallback = mTimeKeeper->now(); + auto const now = mTimeKeeper->now(); + mLastTimerCallback = now; for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) { auto& callback = it->second; auto const wakeupTime = callback->wakeupTime(); @@ -251,7 +252,8 @@ void VSyncDispatchTimerQueue::timerCallback() { continue; } - if (*wakeupTime < mIntendedWakeupTime + mTimerSlack) { + auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast(0)); + if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) { callback->executing(); invocations.emplace_back( Invocation{callback, *callback->lastExecutedVsyncTarget(), *wakeupTime}); diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index d940dc5870..db5d6af611 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -115,11 +115,15 @@ public: operator VSyncDispatch::CallbackToken() const { return mToken; } - void counter(nsecs_t time, nsecs_t) { mCalls.push_back(time); } + void counter(nsecs_t time, nsecs_t wakeup_time) { + mCalls.push_back(time); + mWakeupTime.push_back(wakeup_time); + } VSyncDispatch& mDispatch; VSyncDispatch::CallbackToken mToken; std::vector mCalls; + std::vector mWakeupTime; }; class PausingCallback { @@ -747,6 +751,31 @@ TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) { EXPECT_THAT(cb2.mCalls.size(), Eq(1)); } +TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) { + CountingCallback cb1(mDispatch); + CountingCallback cb2(mDispatch); + + Sequence seq; + EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)) + .InSequence(seq) + .WillOnce(Return(1000)); + EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); + EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)) + .InSequence(seq) + .WillOnce(Return(1000)); + + EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled); + EXPECT_EQ(mDispatch.schedule(cb2, 390, 1000), ScheduleResult::Scheduled); + + mMockClock.setLag(100); + mMockClock.advanceBy(700); + + ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1)); + EXPECT_THAT(cb1.mWakeupTime[0], Eq(600)); + ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1)); + EXPECT_THAT(cb2.mWakeupTime[0], Eq(610)); +} + class VSyncDispatchTimerQueueEntryTest : public testing::Test { protected: nsecs_t const mPeriod = 1000; -- cgit v1.2.3-59-g8ed1b