summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin DuBois <kevindubois@google.com> 2020-07-16 10:21:36 -0700
committer Kevin DuBois <kevindubois@google.com> 2020-07-21 21:37:36 +0000
commit8cd2bf53e6c2cd96216679c6530a9f18fb7deb6f (patch)
treeed712018708fc59687cd5c89758d6e48f98b4c59
parent56892df0aa2edcfd2f0a00a1aad402a615cdebc5 (diff)
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)
-rw-r--r--services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp6
-rw-r--r--services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp31
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<Invocation> invocations;
{
std::lock_guard<decltype(mMutex)> 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<nsecs_t>(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<nsecs_t> mCalls;
+ std::vector<nsecs_t> 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;