diff options
Diffstat (limited to 'services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp')
-rw-r--r-- | services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp | 620 |
1 files changed, 446 insertions, 174 deletions
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index d940dc5870..d59d64bc02 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -47,6 +48,8 @@ public: MOCK_CONST_METHOD0(currentPeriod, nsecs_t()); MOCK_METHOD1(setPeriod, void(nsecs_t)); MOCK_METHOD0(resetModel, void()); + MOCK_CONST_METHOD0(needsMoreSamples, bool()); + MOCK_CONST_METHOD2(isVSyncInPhase, bool(nsecs_t, Fps)); MOCK_CONST_METHOD1(dump, void(std::string&)); nsecs_t nextVSyncTime(nsecs_t timePoint) const { @@ -63,19 +66,19 @@ protected: class ControllableClock : public TimeKeeper { public: ControllableClock() { - ON_CALL(*this, alarmIn(_, _)) - .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior)); + ON_CALL(*this, alarmAt(_, _)) + .WillByDefault(Invoke(this, &ControllableClock::alarmAtDefaultBehavior)); ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime)); } MOCK_CONST_METHOD0(now, nsecs_t()); - MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time)); + MOCK_METHOD2(alarmAt, void(std::function<void()> const&, nsecs_t time)); MOCK_METHOD0(alarmCancel, void()); MOCK_CONST_METHOD1(dump, void(std::string&)); - void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) { + void alarmAtDefaultBehavior(std::function<void()> const& callback, nsecs_t time) { mCallback = callback; - mNextCallbackTime = time + mCurrentTime; + mNextCallbackTime = time; } nsecs_t fakeTime() const { return mCurrentTime; } @@ -108,18 +111,24 @@ public: CountingCallback(VSyncDispatch& dispatch) : mDispatch(dispatch), mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this, - std::placeholders::_1, - std::placeholders::_2), + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), "test")) {} ~CountingCallback() { mDispatch.unregisterCallback(mToken); } 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, nsecs_t readyTime) { + mCalls.push_back(time); + mWakeupTime.push_back(wakeup_time); + mReadyTime.push_back(readyTime); + } VSyncDispatch& mDispatch; VSyncDispatch::CallbackToken mToken; std::vector<nsecs_t> mCalls; + std::vector<nsecs_t> mWakeupTime; + std::vector<nsecs_t> mReadyTime; }; class PausingCallback { @@ -137,18 +146,18 @@ public: operator VSyncDispatch::CallbackToken() const { return mToken; } void pause(nsecs_t, nsecs_t) { - std::unique_lock<std::mutex> lk(mMutex); + std::unique_lock lock(mMutex); mPause = true; mCv.notify_all(); - mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; }); + mCv.wait_for(lock, mPauseAmount, [this] { return !mPause; }); mResourcePresent = (mResource.lock() != nullptr); } bool waitForPause() { - std::unique_lock<std::mutex> lk(mMutex); - auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; }); + std::unique_lock lock(mMutex); + auto waiting = mCv.wait_for(lock, 10s, [this] { return mPause; }); return waiting; } @@ -157,7 +166,7 @@ public: bool resourcePresent() { return mResourcePresent; } void unpause() { - std::unique_lock<std::mutex> lk(mMutex); + std::unique_lock lock(mMutex); mPause = false; mCv.notify_all(); } @@ -187,8 +196,8 @@ protected: class TimeKeeperWrapper : public TimeKeeper { public: TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {} - void alarmIn(std::function<void()> const& callback, nsecs_t time) final { - mControllableClock.alarmIn(callback, time); + void alarmAt(std::function<void()> const& callback, nsecs_t time) final { + mControllableClock.alarmAt(callback, time); } void alarmCancel() final { mControllableClock.alarmCancel(); } nsecs_t now() const final { return mControllableClock.now(); } @@ -217,22 +226,33 @@ protected: }; TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) { - EXPECT_CALL(mMockClock, alarmIn(_, 900)); + EXPECT_CALL(mMockClock, alarmAt(_, 900)); EXPECT_CALL(mMockClock, alarmCancel()); { VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold, mVsyncMoveThreshold}; CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled); + const auto result = mDispatch.schedule(cb, + {.workDuration = 100, + .readyDuration = 0, + .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(900, *result); } } TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) { auto intended = mPeriod - 230; - EXPECT_CALL(mMockClock, alarmIn(_, 900)); + EXPECT_CALL(mMockClock, alarmAt(_, 900)); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled); + const auto result = mDispatch.schedule(cb, + {.workDuration = 100, + .readyDuration = 0, + .earliestVsync = intended}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(900, *result); + advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -241,10 +261,10 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) { TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) { EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150)); - EXPECT_CALL(mMockClock, alarmIn(_, 1050)); + EXPECT_CALL(mMockClock, alarmAt(_, 1050)); CountingCallback cb(mDispatch); - mDispatch.schedule(cb, 100, mPeriod); + mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod}); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); @@ -257,37 +277,54 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) { auto const workDuration = 10 * mPeriod; EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration)) .WillOnce(Return(mPeriod * 11)); - EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now)); + EXPECT_CALL(mMockClock, alarmAt(_, mPeriod)); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled); + const auto result = mDispatch.schedule(cb, + {.workDuration = workDuration, + .readyDuration = 0, + .earliestVsync = mPeriod}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod, *result); } TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) { - EXPECT_CALL(mMockClock, alarmIn(_, 900)); + EXPECT_CALL(mMockClock, alarmAt(_, 900)); EXPECT_CALL(mMockClock, alarmCancel()); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled); + const auto result = + mDispatch.schedule(cb, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod - 100, *result); EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled); } TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) { - EXPECT_CALL(mMockClock, alarmIn(_, 900)); + EXPECT_CALL(mMockClock, alarmAt(_, 900)); EXPECT_CALL(mMockClock, alarmCancel()); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled); + const auto result = + mDispatch.schedule(cb, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod - 100, *result); mMockClock.advanceBy(950); EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate); } TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) { - EXPECT_CALL(mMockClock, alarmIn(_, 900)); + EXPECT_CALL(mMockClock, alarmAt(_, 900)); EXPECT_CALL(mMockClock, alarmCancel()); PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s)); - EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled); + const auto result = + mDispatch.schedule(cb, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod - 100, *result); std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); }); EXPECT_TRUE(cb.waitForPause()); @@ -297,14 +334,18 @@ TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) { } TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) { - EXPECT_CALL(mMockClock, alarmIn(_, 900)); + EXPECT_CALL(mMockClock, alarmAt(_, 900)); EXPECT_CALL(mMockClock, alarmCancel()); auto resource = std::make_shared<int>(110); PausingCallback cb(mDispatch, 50ms); cb.stashResource(resource); - EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled); + const auto result = + mDispatch.schedule(cb, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod - 100, *result); std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); }); EXPECT_TRUE(cb.waitForPause()); @@ -327,15 +368,15 @@ TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) { .WillOnce(Return(1075)); Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 955)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 813)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 975)).InSequence(seq); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 100, mPeriod); - mDispatch.schedule(cb1, 250, mPeriod); + mDispatch.schedule(cb0, {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod}); + mDispatch.schedule(cb1, {.workDuration = 250, .readyDuration = 0, .earliestVsync = mPeriod}); advanceToNextCallback(); advanceToNextCallback(); @@ -355,53 +396,54 @@ TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) { .WillOnce(Return(10000)); Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 750)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 100, mPeriod * 10); - mDispatch.schedule(cb1, 250, mPeriod); + mDispatch.schedule(cb0, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod * 10}); + mDispatch.schedule(cb1, {.workDuration = 250, .readyDuration = 0, .earliestVsync = mPeriod}); mDispatch.cancel(cb1); } TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 700)).InSequence(seq); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 400, 1000); - mDispatch.schedule(cb1, 200, 1000); - mDispatch.schedule(cb1, 300, 1000); + mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 300, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); } TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 400, 1000); - mDispatch.schedule(cb1, 200, 1000); - mDispatch.schedule(cb1, 500, 1000); + mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); } TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1590)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq); auto offset = 400; auto closeOffset = offset + mDispatchGroupThreshold - 1; @@ -410,9 +452,10 @@ TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) { CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 400, 1000); - mDispatch.schedule(cb1, 200, 1000); - mDispatch.schedule(cb1, closeOffset, 1000); + mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, + {.workDuration = closeOffset, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); ASSERT_THAT(cb0.mCalls.size(), Eq(1)); @@ -420,8 +463,9 @@ TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) { ASSERT_THAT(cb1.mCalls.size(), Eq(1)); EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod)); - mDispatch.schedule(cb0, 400, 2000); - mDispatch.schedule(cb1, notCloseOffset, 2000); + mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 2000}); + mDispatch.schedule(cb1, + {.workDuration = notCloseOffset, .readyDuration = 0, .earliestVsync = 2000}); advanceToNextCallback(); ASSERT_THAT(cb1.mCalls.size(), Eq(2)); EXPECT_THAT(cb1.mCalls[1], Eq(2000)); @@ -432,16 +476,17 @@ TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) { } TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) { - EXPECT_CALL(mMockClock, alarmIn(_, 900)); - EXPECT_CALL(mMockClock, alarmIn(_, 800)); - EXPECT_CALL(mMockClock, alarmIn(_, 100)); + Sequence seq; + EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 800)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq); EXPECT_CALL(mMockClock, alarmCancel()); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 100, 1000); - mDispatch.schedule(cb1, 200, 1000); + mDispatch.schedule(cb0, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled); } @@ -454,32 +499,38 @@ TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) .WillOnce(Return(2950)); CountingCallback cb(mDispatch); - mDispatch.schedule(cb, 100, 920); + mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 920}); mMockClock.advanceBy(850); EXPECT_THAT(cb.mCalls.size(), Eq(1)); - mDispatch.schedule(cb, 100, 1900); + mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1900}); mMockClock.advanceBy(900); EXPECT_THAT(cb.mCalls.size(), Eq(1)); mMockClock.advanceBy(125); EXPECT_THAT(cb.mCalls.size(), Eq(2)); - mDispatch.schedule(cb, 100, 2900); + mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2900}); mMockClock.advanceBy(975); EXPECT_THAT(cb.mCalls.size(), Eq(3)); } TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq); VSyncDispatch::CallbackToken tmp; - tmp = mDispatch.registerCallback([&](auto, auto) { mDispatch.schedule(tmp, 100, 2000); }, - "o.o"); + tmp = mDispatch.registerCallback( + [&](auto, auto, auto) { + mDispatch.schedule(tmp, + {.workDuration = 100, + .readyDuration = 0, + .earliestVsync = 2000}); + }, + "o.o"); - mDispatch.schedule(tmp, 100, 1000); + mDispatch.schedule(tmp, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); } @@ -487,17 +538,31 @@ TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) { VSyncDispatch::CallbackToken tmp; std::optional<nsecs_t> lastTarget; tmp = mDispatch.registerCallback( - [&](auto timestamp, auto) { - EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp - mVsyncMoveThreshold), - ScheduleResult::Scheduled); - EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp), ScheduleResult::Scheduled); - EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp + mVsyncMoveThreshold), - ScheduleResult::Scheduled); + [&](auto timestamp, auto, auto) { + auto result = + mDispatch.schedule(tmp, + {.workDuration = 400, + .readyDuration = 0, + .earliestVsync = timestamp - mVsyncMoveThreshold}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod + timestamp - 400, *result); + result = mDispatch.schedule(tmp, + {.workDuration = 400, + .readyDuration = 0, + .earliestVsync = timestamp}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod + timestamp - 400, *result); + result = mDispatch.schedule(tmp, + {.workDuration = 400, + .readyDuration = 0, + .earliestVsync = timestamp + mVsyncMoveThreshold}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(mPeriod + timestamp - 400, *result); lastTarget = timestamp; }, "oo"); - mDispatch.schedule(tmp, 999, 1000); + mDispatch.schedule(tmp, {.workDuration = 999, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); EXPECT_THAT(lastTarget, Eq(1000)); @@ -507,40 +572,40 @@ TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) { TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1000)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 950)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1950)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq); CountingCallback cb(mDispatch); - mDispatch.schedule(cb, 0, 1000); + mDispatch.schedule(cb, {.workDuration = 0, .readyDuration = 0, .earliestVsync = 1000}); mMockClock.advanceBy(750); - mDispatch.schedule(cb, 50, 1000); + mDispatch.schedule(cb, {.workDuration = 50, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); - mDispatch.schedule(cb, 50, 2000); + mDispatch.schedule(cb, {.workDuration = 50, .readyDuration = 0, .earliestVsync = 2000}); mMockClock.advanceBy(800); - mDispatch.schedule(cb, 100, 2000); + mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000}); } TEST_F(VSyncDispatchTimerQueueTest, lateModifications) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 850)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1800)).InSequence(seq); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 500, 1000); - mDispatch.schedule(cb1, 100, 1000); + mDispatch.schedule(cb0, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); - mDispatch.schedule(cb0, 200, 2000); - mDispatch.schedule(cb1, 150, 1000); + mDispatch.schedule(cb0, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 2000}); + mDispatch.schedule(cb1, {.workDuration = 150, .readyDuration = 0, .earliestVsync = 1000}); advanceToNextCallback(); advanceToNextCallback(); @@ -548,46 +613,63 @@ TEST_F(VSyncDispatchTimerQueueTest, lateModifications) { TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq); CountingCallback cb0(mDispatch); CountingCallback cb1(mDispatch); - mDispatch.schedule(cb0, 500, 1000); - mDispatch.schedule(cb1, 500, 20000); + mDispatch.schedule(cb0, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + mDispatch.schedule(cb1, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 20000}); } TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq); EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq); CountingCallback cb0(mDispatch); - mDispatch.schedule(cb0, 500, 1000); + mDispatch.schedule(cb0, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); mDispatch.cancel(cb0); - mDispatch.schedule(cb0, 100, 1000); + mDispatch.schedule(cb0, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); } TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) { VSyncDispatch::CallbackToken token(100); - EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error)); + EXPECT_FALSE(mDispatch + .schedule(token, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}) + .has_value()); EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error)); } TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) { CountingCallback cb0(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled); - EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb0, + {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(500, *result); + result = mDispatch.schedule(cb0, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(900, *result); } // b/1450138150 TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) { - EXPECT_CALL(mMockClock, alarmIn(_, 500)); + EXPECT_CALL(mMockClock, alarmAt(_, 500)); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb, + {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(500, *result); mMockClock.advanceBy(400); - EXPECT_EQ(mDispatch.schedule(cb, 800, 1000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb, + {.workDuration = 800, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(1200, *result); advanceToNextCallback(); ASSERT_THAT(cb.mCalls.size(), Eq(1)); } @@ -598,83 +680,118 @@ TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedul .WillOnce(Return(1000)) .WillOnce(Return(1002)); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb, + {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(500, *result); mMockClock.advanceBy(400); - EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(602, *result); } TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) { CountingCallback cb0(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb0, + {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(500, *result); advanceToNextCallback(); - EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb0, + {.workDuration = 1100, .readyDuration = 0, .earliestVsync = 2000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(900, *result); } TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1100)).InSequence(seq); CountingCallback cb0(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb0, + {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(500, *result); advanceToNextCallback(); - EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb0, + {.workDuration = 1900, .readyDuration = 0, .earliestVsync = 2000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(1100, *result); } TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) { - EXPECT_CALL(mMockClock, alarmIn(_, 600)); + EXPECT_CALL(mMockClock, alarmAt(_, 600)); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); - EXPECT_EQ(mDispatch.schedule(cb, 1400, 1000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb, + {.workDuration = 1400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); advanceToNextCallback(); } TEST_F(VSyncDispatchTimerQueueTest, helperMove) { - EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1); EXPECT_CALL(mMockClock, alarmCancel()).Times(1); VSyncCallbackRegistration cb( - mDispatch, [](auto, auto) {}, ""); + mDispatch, [](auto, auto, auto) {}, ""); VSyncCallbackRegistration cb1(std::move(cb)); - cb.schedule(100, 1000); + cb.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); cb.cancel(); - cb1.schedule(500, 1000); + cb1.schedule({.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); cb1.cancel(); } TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) { - EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1); + EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1); EXPECT_CALL(mMockClock, alarmCancel()).Times(1); VSyncCallbackRegistration cb( - mDispatch, [](auto, auto) {}, ""); + mDispatch, [](auto, auto, auto) {}, ""); VSyncCallbackRegistration cb1( - mDispatch, [](auto, auto) {}, ""); + mDispatch, [](auto, auto, auto) {}, ""); cb1 = std::move(cb); - cb.schedule(100, 1000); + cb.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000}); cb.cancel(); - cb1.schedule(500, 1000); + cb1.schedule({.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000}); cb1.cancel(); } // b/154303580 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 1200)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq); CountingCallback cb1(mDispatch); CountingCallback cb2(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb1, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); mMockClock.setLag(100); mMockClock.advanceBy(620); - EXPECT_EQ(mDispatch.schedule(cb2, 100, 2000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb2, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(1900, *result); mMockClock.advanceBy(80); EXPECT_THAT(cb1.mCalls.size(), Eq(1)); @@ -686,16 +803,23 @@ TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent // update later, as opposed to blocking the calling thread. TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminentSameCallback) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 930)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1630)).InSequence(seq); CountingCallback cb(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); mMockClock.setLag(100); mMockClock.advanceBy(620); - EXPECT_EQ(mDispatch.schedule(cb, 370, 2000), ScheduleResult::Scheduled); + result = mDispatch.schedule(cb, + {.workDuration = 370, .readyDuration = 0, .earliestVsync = 2000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(1630, *result); mMockClock.advanceBy(80); EXPECT_THAT(cb.mCalls.size(), Eq(1)); @@ -704,13 +828,20 @@ TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent // b/154303580. TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq); CountingCallback cb1(mDispatch); CountingCallback cb2(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled); - EXPECT_EQ(mDispatch.schedule(cb2, 100, 2000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb1, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); + result = mDispatch.schedule(cb2, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(1900, *result); mMockClock.setLag(100); mMockClock.advanceBy(620); @@ -725,14 +856,21 @@ TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) { TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) { Sequence seq; - EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq); - EXPECT_CALL(mMockClock, alarmIn(_, 1280)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq); EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq); CountingCallback cb1(mDispatch); CountingCallback cb2(mDispatch); - EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled); - EXPECT_EQ(mDispatch.schedule(cb2, 100, 2000), ScheduleResult::Scheduled); + auto result = + mDispatch.schedule(cb1, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); + result = mDispatch.schedule(cb2, + {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(1900, *result); mMockClock.setLag(100); mMockClock.advanceBy(620); @@ -747,6 +885,63 @@ 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, alarmAt(_, 600)).InSequence(seq); + EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)) + .InSequence(seq) + .WillOnce(Return(1000)); + + auto result = + mDispatch.schedule(cb1, + {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(600, *result); + result = mDispatch.schedule(cb2, + {.workDuration = 390, .readyDuration = 0, .earliestVsync = 1000}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(610, *result); + + mMockClock.setLag(100); + mMockClock.advanceBy(700); + + ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1)); + EXPECT_THAT(cb1.mWakeupTime[0], Eq(600)); + ASSERT_THAT(cb1.mReadyTime.size(), Eq(1)); + EXPECT_THAT(cb1.mReadyTime[0], Eq(1000)); + ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1)); + EXPECT_THAT(cb2.mWakeupTime[0], Eq(610)); + ASSERT_THAT(cb2.mReadyTime.size(), Eq(1)); + EXPECT_THAT(cb2.mReadyTime[0], Eq(1000)); +} + +TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithReadyDuration) { + auto intended = mPeriod - 230; + EXPECT_CALL(mMockClock, alarmAt(_, 900)); + + CountingCallback cb(mDispatch); + const auto result = mDispatch.schedule(cb, + {.workDuration = 70, + .readyDuration = 30, + .earliestVsync = intended}); + EXPECT_TRUE(result.has_value()); + EXPECT_EQ(900, *result); + advanceToNextCallback(); + + ASSERT_THAT(cb.mCalls.size(), Eq(1)); + EXPECT_THAT(cb.mCalls[0], Eq(mPeriod)); + ASSERT_THAT(cb.mWakeupTime.size(), Eq(1)); + EXPECT_THAT(cb.mWakeupTime[0], 900); + ASSERT_THAT(cb.mReadyTime.size(), Eq(1)); + EXPECT_THAT(cb.mReadyTime[0], 970); +} + class VSyncDispatchTimerQueueEntryTest : public testing::Test { protected: nsecs_t const mPeriod = 1000; @@ -757,7 +952,7 @@ protected: TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) { std::string name("basicname"); VSyncDispatchTimerQueueEntry entry( - name, [](auto, auto) {}, mVsyncMoveThreshold); + name, [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_THAT(entry.name(), Eq(name)); EXPECT_FALSE(entry.lastExecutedVsyncTarget()); EXPECT_FALSE(entry.wakeupTime()); @@ -765,10 +960,12 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) { TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) { VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.wakeupTime()); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(900)); @@ -785,10 +982,12 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) .Times(1) .WillOnce(Return(10000)); VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.wakeupTime()); - EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 500, .readyDuration = 0, .earliestVsync = 994}, + mStubTracker, now) + .has_value()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(9500)); @@ -798,21 +997,29 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) { auto callCount = 0; auto vsyncCalledTime = 0; auto wakeupCalledTime = 0; + auto readyCalledTime = 0; VSyncDispatchTimerQueueEntry entry( "test", - [&](auto vsyncTime, auto wakeupTime) { + [&](auto vsyncTime, auto wakeupTime, auto readyTime) { callCount++; vsyncCalledTime = vsyncTime; wakeupCalledTime = wakeupTime; + readyCalledTime = readyTime; }, mVsyncMoveThreshold); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); auto const wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(*wakeup, Eq(900)); - entry.callback(entry.executing(), *wakeup); + auto const ready = entry.readyTime(); + ASSERT_TRUE(ready); + EXPECT_THAT(*ready, Eq(1000)); + + entry.callback(entry.executing(), *wakeup, *ready); EXPECT_THAT(callCount, Eq(1)); EXPECT_THAT(vsyncCalledTime, Eq(mPeriod)); @@ -830,13 +1037,15 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) { .WillOnce(Return(1020)); VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.wakeupTime()); entry.update(mStubTracker, 0); EXPECT_FALSE(entry.wakeupTime()); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); auto wakeup = entry.wakeupTime(); ASSERT_TRUE(wakeup); EXPECT_THAT(wakeup, Eq(900)); @@ -849,8 +1058,10 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) { TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) { VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); entry.update(mStubTracker, 0); auto const wakeup = entry.wakeupTime(); @@ -860,24 +1071,35 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) { TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) { VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); entry.executing(); // 1000 is executing // had 1000 not been executing, this could have been scheduled for time 800. - EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); EXPECT_THAT(*entry.wakeupTime(), Eq(1800)); + EXPECT_THAT(*entry.readyTime(), Eq(2000)); - EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 50, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); EXPECT_THAT(*entry.wakeupTime(), Eq(1950)); + EXPECT_THAT(*entry.readyTime(), Eq(2000)); - EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 1001}, + mStubTracker, 0) + .has_value()); EXPECT_THAT(*entry.wakeupTime(), Eq(1800)); + EXPECT_THAT(*entry.readyTime(), Eq(2000)); } TEST_F(VSyncDispatchTimerQueueEntryTest, willRequestNextEstimateWhenSnappingToNextTargettableVSync) { VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); Sequence seq; EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500)) @@ -890,36 +1112,86 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, .InSequence(seq) .WillOnce(Return(2000)); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); entry.executing(); // 1000 is executing - EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); } TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) { VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); - EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); - EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); - EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); - EXPECT_THAT(entry.schedule(1200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled)); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); + EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); + EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); + EXPECT_TRUE(entry.schedule({.workDuration = 50, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); + EXPECT_TRUE(entry.schedule({.workDuration = 1200, .readyDuration = 0, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); } TEST_F(VSyncDispatchTimerQueueEntryTest, storesPendingUpdatesUntilUpdate) { static constexpr auto effectualOffset = 200; VSyncDispatchTimerQueueEntry entry( - "test", [](auto, auto) {}, mVsyncMoveThreshold); + "test", [](auto, auto, auto) {}, mVsyncMoveThreshold); EXPECT_FALSE(entry.hasPendingWorkloadUpdate()); - entry.addPendingWorkloadUpdate(100, 400); - entry.addPendingWorkloadUpdate(effectualOffset, 700); + entry.addPendingWorkloadUpdate({.workDuration = 100, .readyDuration = 0, .earliestVsync = 400}); + entry.addPendingWorkloadUpdate( + {.workDuration = effectualOffset, .readyDuration = 0, .earliestVsync = 400}); EXPECT_TRUE(entry.hasPendingWorkloadUpdate()); entry.update(mStubTracker, 0); EXPECT_FALSE(entry.hasPendingWorkloadUpdate()); EXPECT_THAT(*entry.wakeupTime(), Eq(mPeriod - effectualOffset)); } +TEST_F(VSyncDispatchTimerQueueEntryTest, runCallbackWithReadyDuration) { + auto callCount = 0; + auto vsyncCalledTime = 0; + auto wakeupCalledTime = 0; + auto readyCalledTime = 0; + VSyncDispatchTimerQueueEntry entry( + "test", + [&](auto vsyncTime, auto wakeupTime, auto readyTime) { + callCount++; + vsyncCalledTime = vsyncTime; + wakeupCalledTime = wakeupTime; + readyCalledTime = readyTime; + }, + mVsyncMoveThreshold); + + EXPECT_TRUE(entry.schedule({.workDuration = 70, .readyDuration = 30, .earliestVsync = 500}, + mStubTracker, 0) + .has_value()); + auto const wakeup = entry.wakeupTime(); + ASSERT_TRUE(wakeup); + EXPECT_THAT(*wakeup, Eq(900)); + + auto const ready = entry.readyTime(); + ASSERT_TRUE(ready); + EXPECT_THAT(*ready, Eq(970)); + + entry.callback(entry.executing(), *wakeup, *ready); + + EXPECT_THAT(callCount, Eq(1)); + EXPECT_THAT(vsyncCalledTime, Eq(mPeriod)); + EXPECT_THAT(wakeupCalledTime, Eq(*wakeup)); + EXPECT_FALSE(entry.wakeupTime()); + auto lastCalledTarget = entry.lastExecutedVsyncTarget(); + ASSERT_TRUE(lastCalledTarget); + EXPECT_THAT(*lastCalledTarget, Eq(mPeriod)); +} + } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" |