1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 #pragma clang diagnostic ignored "-Wextra"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "LibSurfaceFlingerUnittests"
24 #define LOG_NDEBUG 0
25 
26 #include "Scheduler/TimeKeeper.h"
27 #include "Scheduler/VSyncDispatchTimerQueue.h"
28 #include "Scheduler/VSyncTracker.h"
29 
30 #include <gmock/gmock.h>
31 #include <gtest/gtest.h>
32 #include <thread>
33 
34 using namespace testing;
35 using namespace std::literals;
36 namespace android::scheduler {
37 
38 class MockVSyncTracker : public VSyncTracker {
39 public:
MockVSyncTracker(nsecs_t period)40     MockVSyncTracker(nsecs_t period) : mPeriod{period} {
41         ON_CALL(*this, nextAnticipatedVSyncTimeFrom(_))
42                 .WillByDefault(Invoke(this, &MockVSyncTracker::nextVSyncTime));
43         ON_CALL(*this, addVsyncTimestamp(_)).WillByDefault(Return(true));
44     }
45 
46     MOCK_METHOD1(addVsyncTimestamp, bool(nsecs_t));
47     MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t));
48     MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
49     MOCK_METHOD1(setPeriod, void(nsecs_t));
50     MOCK_METHOD0(resetModel, void());
51     MOCK_CONST_METHOD0(needsMoreSamples, bool());
52     MOCK_CONST_METHOD2(isVSyncInPhase, bool(nsecs_t, Fps));
53     MOCK_CONST_METHOD1(dump, void(std::string&));
54 
nextVSyncTime(nsecs_t timePoint) const55     nsecs_t nextVSyncTime(nsecs_t timePoint) const {
56         if (timePoint % mPeriod == 0) {
57             return timePoint;
58         }
59         return (timePoint - (timePoint % mPeriod) + mPeriod);
60     }
61 
62 protected:
63     nsecs_t const mPeriod;
64 };
65 
66 class ControllableClock : public TimeKeeper {
67 public:
ControllableClock()68     ControllableClock() {
69         ON_CALL(*this, alarmAt(_, _))
70                 .WillByDefault(Invoke(this, &ControllableClock::alarmAtDefaultBehavior));
71         ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
72     }
73 
74     MOCK_CONST_METHOD0(now, nsecs_t());
75     MOCK_METHOD2(alarmAt, void(std::function<void()> const&, nsecs_t time));
76     MOCK_METHOD0(alarmCancel, void());
77     MOCK_CONST_METHOD1(dump, void(std::string&));
78 
alarmAtDefaultBehavior(std::function<void ()> const & callback,nsecs_t time)79     void alarmAtDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
80         mCallback = callback;
81         mNextCallbackTime = time;
82     }
83 
fakeTime() const84     nsecs_t fakeTime() const { return mCurrentTime; }
85 
advanceToNextCallback()86     void advanceToNextCallback() {
87         mCurrentTime = mNextCallbackTime;
88         if (mCallback) {
89             mCallback();
90         }
91     }
92 
advanceBy(nsecs_t advancement)93     void advanceBy(nsecs_t advancement) {
94         mCurrentTime += advancement;
95         if (mCurrentTime >= (mNextCallbackTime + mLag) && mCallback) {
96             mCallback();
97         }
98     };
99 
setLag(nsecs_t lag)100     void setLag(nsecs_t lag) { mLag = lag; }
101 
102 private:
103     std::function<void()> mCallback;
104     nsecs_t mNextCallbackTime = 0;
105     nsecs_t mCurrentTime = 0;
106     nsecs_t mLag = 0;
107 };
108 
109 class CountingCallback {
110 public:
CountingCallback(VSyncDispatch & dispatch)111     CountingCallback(VSyncDispatch& dispatch)
112           : mDispatch(dispatch),
113             mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
114                                                        std::placeholders::_1, std::placeholders::_2,
115                                                        std::placeholders::_3),
116                                              "test")) {}
~CountingCallback()117     ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
118 
119     operator VSyncDispatch::CallbackToken() const { return mToken; }
120 
counter(nsecs_t time,nsecs_t wakeup_time,nsecs_t readyTime)121     void counter(nsecs_t time, nsecs_t wakeup_time, nsecs_t readyTime) {
122         mCalls.push_back(time);
123         mWakeupTime.push_back(wakeup_time);
124         mReadyTime.push_back(readyTime);
125     }
126 
127     VSyncDispatch& mDispatch;
128     VSyncDispatch::CallbackToken mToken;
129     std::vector<nsecs_t> mCalls;
130     std::vector<nsecs_t> mWakeupTime;
131     std::vector<nsecs_t> mReadyTime;
132 };
133 
134 class PausingCallback {
135 public:
PausingCallback(VSyncDispatch & dispatch,std::chrono::milliseconds pauseAmount)136     PausingCallback(VSyncDispatch& dispatch, std::chrono::milliseconds pauseAmount)
137           : mDispatch(dispatch),
138             mToken(dispatch.registerCallback(std::bind(&PausingCallback::pause, this,
139                                                        std::placeholders::_1,
140                                                        std::placeholders::_2),
141                                              "test")),
142             mRegistered(true),
143             mPauseAmount(pauseAmount) {}
~PausingCallback()144     ~PausingCallback() { unregister(); }
145 
146     operator VSyncDispatch::CallbackToken() const { return mToken; }
147 
pause(nsecs_t,nsecs_t)148     void pause(nsecs_t, nsecs_t) {
149         std::unique_lock lock(mMutex);
150         mPause = true;
151         mCv.notify_all();
152 
153         mCv.wait_for(lock, mPauseAmount, [this] { return !mPause; });
154 
155         mResourcePresent = (mResource.lock() != nullptr);
156     }
157 
waitForPause()158     bool waitForPause() {
159         std::unique_lock lock(mMutex);
160         auto waiting = mCv.wait_for(lock, 10s, [this] { return mPause; });
161         return waiting;
162     }
163 
stashResource(std::weak_ptr<void> const & resource)164     void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
165 
resourcePresent()166     bool resourcePresent() { return mResourcePresent; }
167 
unpause()168     void unpause() {
169         std::unique_lock lock(mMutex);
170         mPause = false;
171         mCv.notify_all();
172     }
173 
unregister()174     void unregister() {
175         if (mRegistered) {
176             mDispatch.unregisterCallback(mToken);
177             mRegistered = false;
178         }
179     }
180 
181     VSyncDispatch& mDispatch;
182     VSyncDispatch::CallbackToken mToken;
183     bool mRegistered = true;
184 
185     std::mutex mMutex;
186     std::condition_variable mCv;
187     bool mPause = false;
188     std::weak_ptr<void> mResource;
189     bool mResourcePresent = false;
190     std::chrono::milliseconds const mPauseAmount;
191 };
192 
193 class VSyncDispatchTimerQueueTest : public testing::Test {
194 protected:
createTimeKeeper()195     std::unique_ptr<TimeKeeper> createTimeKeeper() {
196         class TimeKeeperWrapper : public TimeKeeper {
197         public:
198             TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
199             void alarmAt(std::function<void()> const& callback, nsecs_t time) final {
200                 mControllableClock.alarmAt(callback, time);
201             }
202             void alarmCancel() final { mControllableClock.alarmCancel(); }
203             nsecs_t now() const final { return mControllableClock.now(); }
204             void dump(std::string&) const final {}
205 
206         private:
207             TimeKeeper& mControllableClock;
208         };
209         return std::make_unique<TimeKeeperWrapper>(mMockClock);
210     }
211 
~VSyncDispatchTimerQueueTest()212     ~VSyncDispatchTimerQueueTest() {
213         // destructor of  dispatch will cancelAlarm(). Ignore final cancel in common test.
214         Mock::VerifyAndClearExpectations(&mMockClock);
215     }
216 
advanceToNextCallback()217     void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
218 
219     NiceMock<ControllableClock> mMockClock;
220     static nsecs_t constexpr mDispatchGroupThreshold = 5;
221     nsecs_t const mPeriod = 1000;
222     nsecs_t const mVsyncMoveThreshold = 300;
223     NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
224     VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
225                                       mVsyncMoveThreshold};
226 };
227 
TEST_F(VSyncDispatchTimerQueueTest,unregistersSetAlarmOnDestruction)228 TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
229     EXPECT_CALL(mMockClock, alarmAt(_, 900));
230     EXPECT_CALL(mMockClock, alarmCancel());
231     {
232         VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
233                                           mVsyncMoveThreshold};
234         CountingCallback cb(mDispatch);
235         const auto result = mDispatch.schedule(cb,
236                                                {.workDuration = 100,
237                                                 .readyDuration = 0,
238                                                 .earliestVsync = 1000});
239         EXPECT_TRUE(result.has_value());
240         EXPECT_EQ(900, *result);
241     }
242 }
243 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingFuture)244 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
245     auto intended = mPeriod - 230;
246     EXPECT_CALL(mMockClock, alarmAt(_, 900));
247 
248     CountingCallback cb(mDispatch);
249     const auto result = mDispatch.schedule(cb,
250                                            {.workDuration = 100,
251                                             .readyDuration = 0,
252                                             .earliestVsync = intended});
253     EXPECT_TRUE(result.has_value());
254     EXPECT_EQ(900, *result);
255 
256     advanceToNextCallback();
257 
258     ASSERT_THAT(cb.mCalls.size(), Eq(1));
259     EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
260 }
261 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingFutureWithAdjustmentToTrueVsync)262 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
263     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
264     EXPECT_CALL(mMockClock, alarmAt(_, 1050));
265 
266     CountingCallback cb(mDispatch);
267     mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod});
268     advanceToNextCallback();
269 
270     ASSERT_THAT(cb.mCalls.size(), Eq(1));
271     EXPECT_THAT(cb.mCalls[0], Eq(1150));
272 }
273 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingAdjustmentPast)274 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
275     auto const now = 234;
276     mMockClock.advanceBy(234);
277     auto const workDuration = 10 * mPeriod;
278     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
279             .WillOnce(Return(mPeriod * 11));
280     EXPECT_CALL(mMockClock, alarmAt(_, mPeriod));
281 
282     CountingCallback cb(mDispatch);
283     const auto result = mDispatch.schedule(cb,
284                                            {.workDuration = workDuration,
285                                             .readyDuration = 0,
286                                             .earliestVsync = mPeriod});
287     EXPECT_TRUE(result.has_value());
288     EXPECT_EQ(mPeriod, *result);
289 }
290 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmCancel)291 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
292     EXPECT_CALL(mMockClock, alarmAt(_, 900));
293     EXPECT_CALL(mMockClock, alarmCancel());
294 
295     CountingCallback cb(mDispatch);
296     const auto result =
297             mDispatch.schedule(cb,
298                                {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod});
299     EXPECT_TRUE(result.has_value());
300     EXPECT_EQ(mPeriod - 100, *result);
301     EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
302 }
303 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmCancelTooLate)304 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
305     EXPECT_CALL(mMockClock, alarmAt(_, 900));
306     EXPECT_CALL(mMockClock, alarmCancel());
307 
308     CountingCallback cb(mDispatch);
309     const auto result =
310             mDispatch.schedule(cb,
311                                {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod});
312     EXPECT_TRUE(result.has_value());
313     EXPECT_EQ(mPeriod - 100, *result);
314     mMockClock.advanceBy(950);
315     EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
316 }
317 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmCancelTooLateWhenRunning)318 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
319     EXPECT_CALL(mMockClock, alarmAt(_, 900));
320     EXPECT_CALL(mMockClock, alarmCancel());
321 
322     PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
323     const auto result =
324             mDispatch.schedule(cb,
325                                {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod});
326     EXPECT_TRUE(result.has_value());
327     EXPECT_EQ(mPeriod - 100, *result);
328 
329     std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
330     EXPECT_TRUE(cb.waitForPause());
331     EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
332     cb.unpause();
333     pausingThread.join();
334 }
335 
TEST_F(VSyncDispatchTimerQueueTest,unregisterSynchronizes)336 TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
337     EXPECT_CALL(mMockClock, alarmAt(_, 900));
338     EXPECT_CALL(mMockClock, alarmCancel());
339 
340     auto resource = std::make_shared<int>(110);
341 
342     PausingCallback cb(mDispatch, 50ms);
343     cb.stashResource(resource);
344     const auto result =
345             mDispatch.schedule(cb,
346                                {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod});
347     EXPECT_TRUE(result.has_value());
348     EXPECT_EQ(mPeriod - 100, *result);
349 
350     std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
351     EXPECT_TRUE(cb.waitForPause());
352 
353     cb.unregister();
354     resource.reset();
355 
356     cb.unpause();
357     pausingThread.join();
358 
359     EXPECT_TRUE(cb.resourcePresent());
360 }
361 
TEST_F(VSyncDispatchTimerQueueTest,basicTwoAlarmSetting)362 TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
363     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
364             .Times(4)
365             .WillOnce(Return(1055))
366             .WillOnce(Return(1063))
367             .WillOnce(Return(1063))
368             .WillOnce(Return(1075));
369 
370     Sequence seq;
371     EXPECT_CALL(mMockClock, alarmAt(_, 955)).InSequence(seq);
372     EXPECT_CALL(mMockClock, alarmAt(_, 813)).InSequence(seq);
373     EXPECT_CALL(mMockClock, alarmAt(_, 975)).InSequence(seq);
374 
375     CountingCallback cb0(mDispatch);
376     CountingCallback cb1(mDispatch);
377 
378     mDispatch.schedule(cb0, {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod});
379     mDispatch.schedule(cb1, {.workDuration = 250, .readyDuration = 0, .earliestVsync = mPeriod});
380 
381     advanceToNextCallback();
382     advanceToNextCallback();
383 
384     ASSERT_THAT(cb0.mCalls.size(), Eq(1));
385     EXPECT_THAT(cb0.mCalls[0], Eq(1075));
386     ASSERT_THAT(cb1.mCalls.size(), Eq(1));
387     EXPECT_THAT(cb1.mCalls[0], Eq(1063));
388 }
389 
TEST_F(VSyncDispatchTimerQueueTest,rearmsFaroutTimeoutWhenCancellingCloseOne)390 TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
391     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
392             .Times(4)
393             .WillOnce(Return(10000))
394             .WillOnce(Return(1000))
395             .WillOnce(Return(10000))
396             .WillOnce(Return(10000));
397 
398     Sequence seq;
399     EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
400     EXPECT_CALL(mMockClock, alarmAt(_, 750)).InSequence(seq);
401     EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
402 
403     CountingCallback cb0(mDispatch);
404     CountingCallback cb1(mDispatch);
405 
406     mDispatch.schedule(cb0,
407                        {.workDuration = 100, .readyDuration = 0, .earliestVsync = mPeriod * 10});
408     mDispatch.schedule(cb1, {.workDuration = 250, .readyDuration = 0, .earliestVsync = mPeriod});
409     mDispatch.cancel(cb1);
410 }
411 
TEST_F(VSyncDispatchTimerQueueTest,noUnnecessaryRearmsWhenRescheduling)412 TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
413     Sequence seq;
414     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
415     EXPECT_CALL(mMockClock, alarmAt(_, 700)).InSequence(seq);
416 
417     CountingCallback cb0(mDispatch);
418     CountingCallback cb1(mDispatch);
419 
420     mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
421     mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000});
422     mDispatch.schedule(cb1, {.workDuration = 300, .readyDuration = 0, .earliestVsync = 1000});
423     advanceToNextCallback();
424 }
425 
TEST_F(VSyncDispatchTimerQueueTest,necessaryRearmsWhenModifying)426 TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
427     Sequence seq;
428     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
429     EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
430     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
431 
432     CountingCallback cb0(mDispatch);
433     CountingCallback cb1(mDispatch);
434 
435     mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
436     mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000});
437     mDispatch.schedule(cb1, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
438     advanceToNextCallback();
439 }
440 
TEST_F(VSyncDispatchTimerQueueTest,modifyIntoGroup)441 TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
442     Sequence seq;
443     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
444     EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
445     EXPECT_CALL(mMockClock, alarmAt(_, 1590)).InSequence(seq);
446     EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
447 
448     auto offset = 400;
449     auto closeOffset = offset + mDispatchGroupThreshold - 1;
450     auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
451 
452     CountingCallback cb0(mDispatch);
453     CountingCallback cb1(mDispatch);
454 
455     mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
456     mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000});
457     mDispatch.schedule(cb1,
458                        {.workDuration = closeOffset, .readyDuration = 0, .earliestVsync = 1000});
459 
460     advanceToNextCallback();
461     ASSERT_THAT(cb0.mCalls.size(), Eq(1));
462     EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
463     ASSERT_THAT(cb1.mCalls.size(), Eq(1));
464     EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
465 
466     mDispatch.schedule(cb0, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 2000});
467     mDispatch.schedule(cb1,
468                        {.workDuration = notCloseOffset, .readyDuration = 0, .earliestVsync = 2000});
469     advanceToNextCallback();
470     ASSERT_THAT(cb1.mCalls.size(), Eq(2));
471     EXPECT_THAT(cb1.mCalls[1], Eq(2000));
472 
473     advanceToNextCallback();
474     ASSERT_THAT(cb0.mCalls.size(), Eq(2));
475     EXPECT_THAT(cb0.mCalls[1], Eq(2000));
476 }
477 
TEST_F(VSyncDispatchTimerQueueTest,rearmsWhenEndingAndDoesntCancel)478 TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
479     Sequence seq;
480     EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
481     EXPECT_CALL(mMockClock, alarmAt(_, 800)).InSequence(seq);
482     EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
483     EXPECT_CALL(mMockClock, alarmCancel());
484 
485     CountingCallback cb0(mDispatch);
486     CountingCallback cb1(mDispatch);
487 
488     mDispatch.schedule(cb0, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
489     mDispatch.schedule(cb1, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 1000});
490     advanceToNextCallback();
491     EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
492 }
493 
TEST_F(VSyncDispatchTimerQueueTest,setAlarmCallsAtCorrectTimeWithChangingVsync)494 TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
495     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
496             .Times(3)
497             .WillOnce(Return(950))
498             .WillOnce(Return(1975))
499             .WillOnce(Return(2950));
500 
501     CountingCallback cb(mDispatch);
502     mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 920});
503 
504     mMockClock.advanceBy(850);
505     EXPECT_THAT(cb.mCalls.size(), Eq(1));
506 
507     mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1900});
508     mMockClock.advanceBy(900);
509     EXPECT_THAT(cb.mCalls.size(), Eq(1));
510     mMockClock.advanceBy(125);
511     EXPECT_THAT(cb.mCalls.size(), Eq(2));
512 
513     mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2900});
514     mMockClock.advanceBy(975);
515     EXPECT_THAT(cb.mCalls.size(), Eq(3));
516 }
517 
TEST_F(VSyncDispatchTimerQueueTest,callbackReentrancy)518 TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
519     Sequence seq;
520     EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
521     EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
522 
523     VSyncDispatch::CallbackToken tmp;
524     tmp = mDispatch.registerCallback(
525             [&](auto, auto, auto) {
526                 mDispatch.schedule(tmp,
527                                    {.workDuration = 100,
528                                     .readyDuration = 0,
529                                     .earliestVsync = 2000});
530             },
531             "o.o");
532 
533     mDispatch.schedule(tmp, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
534     advanceToNextCallback();
535 }
536 
TEST_F(VSyncDispatchTimerQueueTest,callbackReentrantWithPastWakeup)537 TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
538     VSyncDispatch::CallbackToken tmp;
539     std::optional<nsecs_t> lastTarget;
540     tmp = mDispatch.registerCallback(
541             [&](auto timestamp, auto, auto) {
542                 auto result =
543                         mDispatch.schedule(tmp,
544                                            {.workDuration = 400,
545                                             .readyDuration = 0,
546                                             .earliestVsync = timestamp - mVsyncMoveThreshold});
547                 EXPECT_TRUE(result.has_value());
548                 EXPECT_EQ(mPeriod + timestamp - 400, *result);
549                 result = mDispatch.schedule(tmp,
550                                             {.workDuration = 400,
551                                              .readyDuration = 0,
552                                              .earliestVsync = timestamp});
553                 EXPECT_TRUE(result.has_value());
554                 EXPECT_EQ(mPeriod + timestamp - 400, *result);
555                 result = mDispatch.schedule(tmp,
556                                             {.workDuration = 400,
557                                              .readyDuration = 0,
558                                              .earliestVsync = timestamp + mVsyncMoveThreshold});
559                 EXPECT_TRUE(result.has_value());
560                 EXPECT_EQ(mPeriod + timestamp - 400, *result);
561                 lastTarget = timestamp;
562             },
563             "oo");
564 
565     mDispatch.schedule(tmp, {.workDuration = 999, .readyDuration = 0, .earliestVsync = 1000});
566     advanceToNextCallback();
567     EXPECT_THAT(lastTarget, Eq(1000));
568 
569     advanceToNextCallback();
570     EXPECT_THAT(lastTarget, Eq(2000));
571 }
572 
TEST_F(VSyncDispatchTimerQueueTest,modificationsAroundVsyncTime)573 TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
574     Sequence seq;
575     EXPECT_CALL(mMockClock, alarmAt(_, 1000)).InSequence(seq);
576     EXPECT_CALL(mMockClock, alarmAt(_, 950)).InSequence(seq);
577     EXPECT_CALL(mMockClock, alarmAt(_, 1950)).InSequence(seq);
578     EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
579 
580     CountingCallback cb(mDispatch);
581     mDispatch.schedule(cb, {.workDuration = 0, .readyDuration = 0, .earliestVsync = 1000});
582 
583     mMockClock.advanceBy(750);
584     mDispatch.schedule(cb, {.workDuration = 50, .readyDuration = 0, .earliestVsync = 1000});
585 
586     advanceToNextCallback();
587     mDispatch.schedule(cb, {.workDuration = 50, .readyDuration = 0, .earliestVsync = 2000});
588 
589     mMockClock.advanceBy(800);
590     mDispatch.schedule(cb, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000});
591 }
592 
TEST_F(VSyncDispatchTimerQueueTest,lateModifications)593 TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
594     Sequence seq;
595     EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
596     EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
597     EXPECT_CALL(mMockClock, alarmAt(_, 850)).InSequence(seq);
598     EXPECT_CALL(mMockClock, alarmAt(_, 1800)).InSequence(seq);
599 
600     CountingCallback cb0(mDispatch);
601     CountingCallback cb1(mDispatch);
602 
603     mDispatch.schedule(cb0, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
604     mDispatch.schedule(cb1, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
605 
606     advanceToNextCallback();
607     mDispatch.schedule(cb0, {.workDuration = 200, .readyDuration = 0, .earliestVsync = 2000});
608     mDispatch.schedule(cb1, {.workDuration = 150, .readyDuration = 0, .earliestVsync = 1000});
609 
610     advanceToNextCallback();
611     advanceToNextCallback();
612 }
613 
TEST_F(VSyncDispatchTimerQueueTest,doesntCancelPriorValidTimerForFutureMod)614 TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
615     Sequence seq;
616     EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
617 
618     CountingCallback cb0(mDispatch);
619     CountingCallback cb1(mDispatch);
620     mDispatch.schedule(cb0, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
621     mDispatch.schedule(cb1, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 20000});
622 }
623 
TEST_F(VSyncDispatchTimerQueueTest,setsTimerAfterCancellation)624 TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
625     Sequence seq;
626     EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
627     EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
628     EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
629 
630     CountingCallback cb0(mDispatch);
631     mDispatch.schedule(cb0, {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
632     mDispatch.cancel(cb0);
633     mDispatch.schedule(cb0, {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
634 }
635 
TEST_F(VSyncDispatchTimerQueueTest,makingUpIdsError)636 TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
637     VSyncDispatch::CallbackToken token(100);
638     EXPECT_FALSE(mDispatch
639                          .schedule(token,
640                                    {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000})
641                          .has_value());
642     EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
643 }
644 
TEST_F(VSyncDispatchTimerQueueTest,canMoveCallbackBackwardsInTime)645 TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) {
646     CountingCallback cb0(mDispatch);
647     auto result =
648             mDispatch.schedule(cb0,
649                                {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
650     EXPECT_TRUE(result.has_value());
651     EXPECT_EQ(500, *result);
652     result = mDispatch.schedule(cb0,
653                                 {.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
654     EXPECT_TRUE(result.has_value());
655     EXPECT_EQ(900, *result);
656 }
657 
658 // b/1450138150
TEST_F(VSyncDispatchTimerQueueTest,doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync)659 TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
660     EXPECT_CALL(mMockClock, alarmAt(_, 500));
661     CountingCallback cb(mDispatch);
662     auto result =
663             mDispatch.schedule(cb,
664                                {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
665     EXPECT_TRUE(result.has_value());
666     EXPECT_EQ(500, *result);
667     mMockClock.advanceBy(400);
668 
669     result = mDispatch.schedule(cb,
670                                 {.workDuration = 800, .readyDuration = 0, .earliestVsync = 1000});
671     EXPECT_TRUE(result.has_value());
672     EXPECT_EQ(1200, *result);
673     advanceToNextCallback();
674     ASSERT_THAT(cb.mCalls.size(), Eq(1));
675 }
676 
TEST_F(VSyncDispatchTimerQueueTest,targetOffsetMovingBackALittleCanStillSchedule)677 TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedule) {
678     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
679             .Times(2)
680             .WillOnce(Return(1000))
681             .WillOnce(Return(1002));
682     CountingCallback cb(mDispatch);
683     auto result =
684             mDispatch.schedule(cb,
685                                {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
686     EXPECT_TRUE(result.has_value());
687     EXPECT_EQ(500, *result);
688     mMockClock.advanceBy(400);
689     result = mDispatch.schedule(cb,
690                                 {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
691     EXPECT_TRUE(result.has_value());
692     EXPECT_EQ(602, *result);
693 }
694 
TEST_F(VSyncDispatchTimerQueueTest,canScheduleNegativeOffsetAgainstDifferentPeriods)695 TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
696     CountingCallback cb0(mDispatch);
697     auto result =
698             mDispatch.schedule(cb0,
699                                {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
700     EXPECT_TRUE(result.has_value());
701     EXPECT_EQ(500, *result);
702     advanceToNextCallback();
703     result = mDispatch.schedule(cb0,
704                                 {.workDuration = 1100, .readyDuration = 0, .earliestVsync = 2000});
705     EXPECT_TRUE(result.has_value());
706     EXPECT_EQ(900, *result);
707 }
708 
TEST_F(VSyncDispatchTimerQueueTest,canScheduleLargeNegativeOffset)709 TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
710     Sequence seq;
711     EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
712     EXPECT_CALL(mMockClock, alarmAt(_, 1100)).InSequence(seq);
713     CountingCallback cb0(mDispatch);
714     auto result =
715             mDispatch.schedule(cb0,
716                                {.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
717     EXPECT_TRUE(result.has_value());
718     EXPECT_EQ(500, *result);
719     advanceToNextCallback();
720     result = mDispatch.schedule(cb0,
721                                 {.workDuration = 1900, .readyDuration = 0, .earliestVsync = 2000});
722     EXPECT_TRUE(result.has_value());
723     EXPECT_EQ(1100, *result);
724 }
725 
TEST_F(VSyncDispatchTimerQueueTest,scheduleUpdatesDoesNotAffectSchedulingState)726 TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
727     EXPECT_CALL(mMockClock, alarmAt(_, 600));
728 
729     CountingCallback cb(mDispatch);
730     auto result =
731             mDispatch.schedule(cb,
732                                {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
733     EXPECT_TRUE(result.has_value());
734     EXPECT_EQ(600, *result);
735 
736     result = mDispatch.schedule(cb,
737                                 {.workDuration = 1400, .readyDuration = 0, .earliestVsync = 1000});
738     EXPECT_TRUE(result.has_value());
739     EXPECT_EQ(600, *result);
740 
741     advanceToNextCallback();
742 }
743 
TEST_F(VSyncDispatchTimerQueueTest,helperMove)744 TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
745     EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
746     EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
747 
748     VSyncCallbackRegistration cb(
749             mDispatch, [](auto, auto, auto) {}, "");
750     VSyncCallbackRegistration cb1(std::move(cb));
751     cb.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
752     cb.cancel();
753 
754     cb1.schedule({.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
755     cb1.cancel();
756 }
757 
TEST_F(VSyncDispatchTimerQueueTest,helperMoveAssign)758 TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
759     EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
760     EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
761 
762     VSyncCallbackRegistration cb(
763             mDispatch, [](auto, auto, auto) {}, "");
764     VSyncCallbackRegistration cb1(
765             mDispatch, [](auto, auto, auto) {}, "");
766     cb1 = std::move(cb);
767     cb.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 1000});
768     cb.cancel();
769 
770     cb1.schedule({.workDuration = 500, .readyDuration = 0, .earliestVsync = 1000});
771     cb1.cancel();
772 }
773 
774 // b/154303580
TEST_F(VSyncDispatchTimerQueueTest,skipsSchedulingIfTimerReschedulingIsImminent)775 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent) {
776     Sequence seq;
777     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
778     EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
779     CountingCallback cb1(mDispatch);
780     CountingCallback cb2(mDispatch);
781 
782     auto result =
783             mDispatch.schedule(cb1,
784                                {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
785     EXPECT_TRUE(result.has_value());
786     EXPECT_EQ(600, *result);
787 
788     mMockClock.setLag(100);
789     mMockClock.advanceBy(620);
790 
791     result = mDispatch.schedule(cb2,
792                                 {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000});
793     EXPECT_TRUE(result.has_value());
794     EXPECT_EQ(1900, *result);
795     mMockClock.advanceBy(80);
796 
797     EXPECT_THAT(cb1.mCalls.size(), Eq(1));
798     EXPECT_THAT(cb2.mCalls.size(), Eq(0));
799 }
800 
801 // b/154303580.
802 // If the same callback tries to reschedule itself after it's too late, timer opts to apply the
803 // update later, as opposed to blocking the calling thread.
TEST_F(VSyncDispatchTimerQueueTest,skipsSchedulingIfTimerReschedulingIsImminentSameCallback)804 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminentSameCallback) {
805     Sequence seq;
806     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
807     EXPECT_CALL(mMockClock, alarmAt(_, 1630)).InSequence(seq);
808     CountingCallback cb(mDispatch);
809 
810     auto result =
811             mDispatch.schedule(cb,
812                                {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
813     EXPECT_TRUE(result.has_value());
814     EXPECT_EQ(600, *result);
815 
816     mMockClock.setLag(100);
817     mMockClock.advanceBy(620);
818 
819     result = mDispatch.schedule(cb,
820                                 {.workDuration = 370, .readyDuration = 0, .earliestVsync = 2000});
821     EXPECT_TRUE(result.has_value());
822     EXPECT_EQ(1630, *result);
823     mMockClock.advanceBy(80);
824 
825     EXPECT_THAT(cb.mCalls.size(), Eq(1));
826 }
827 
828 // b/154303580.
TEST_F(VSyncDispatchTimerQueueTest,skipsRearmingWhenNotNextScheduled)829 TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) {
830     Sequence seq;
831     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
832     EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
833     CountingCallback cb1(mDispatch);
834     CountingCallback cb2(mDispatch);
835 
836     auto result =
837             mDispatch.schedule(cb1,
838                                {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
839     EXPECT_TRUE(result.has_value());
840     EXPECT_EQ(600, *result);
841     result = mDispatch.schedule(cb2,
842                                 {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000});
843     EXPECT_TRUE(result.has_value());
844     EXPECT_EQ(1900, *result);
845 
846     mMockClock.setLag(100);
847     mMockClock.advanceBy(620);
848 
849     EXPECT_EQ(mDispatch.cancel(cb2), CancelResult::Cancelled);
850 
851     mMockClock.advanceBy(80);
852 
853     EXPECT_THAT(cb1.mCalls.size(), Eq(1));
854     EXPECT_THAT(cb2.mCalls.size(), Eq(0));
855 }
856 
TEST_F(VSyncDispatchTimerQueueTest,rearmsWhenCancelledAndIsNextScheduled)857 TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) {
858     Sequence seq;
859     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
860     EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
861     EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
862     CountingCallback cb1(mDispatch);
863     CountingCallback cb2(mDispatch);
864 
865     auto result =
866             mDispatch.schedule(cb1,
867                                {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
868     EXPECT_TRUE(result.has_value());
869     EXPECT_EQ(600, *result);
870     result = mDispatch.schedule(cb2,
871                                 {.workDuration = 100, .readyDuration = 0, .earliestVsync = 2000});
872     EXPECT_TRUE(result.has_value());
873     EXPECT_EQ(1900, *result);
874 
875     mMockClock.setLag(100);
876     mMockClock.advanceBy(620);
877 
878     EXPECT_EQ(mDispatch.cancel(cb1), CancelResult::Cancelled);
879 
880     EXPECT_THAT(cb1.mCalls.size(), Eq(0));
881     EXPECT_THAT(cb2.mCalls.size(), Eq(0));
882     mMockClock.advanceToNextCallback();
883 
884     EXPECT_THAT(cb1.mCalls.size(), Eq(0));
885     EXPECT_THAT(cb2.mCalls.size(), Eq(1));
886 }
887 
TEST_F(VSyncDispatchTimerQueueTest,laggedTimerGroupsCallbacksWithinLag)888 TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) {
889     CountingCallback cb1(mDispatch);
890     CountingCallback cb2(mDispatch);
891 
892     Sequence seq;
893     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
894             .InSequence(seq)
895             .WillOnce(Return(1000));
896     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
897     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
898             .InSequence(seq)
899             .WillOnce(Return(1000));
900 
901     auto result =
902             mDispatch.schedule(cb1,
903                                {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
904     EXPECT_TRUE(result.has_value());
905     EXPECT_EQ(600, *result);
906     result = mDispatch.schedule(cb2,
907                                 {.workDuration = 390, .readyDuration = 0, .earliestVsync = 1000});
908     EXPECT_TRUE(result.has_value());
909     EXPECT_EQ(610, *result);
910 
911     mMockClock.setLag(100);
912     mMockClock.advanceBy(700);
913 
914     ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1));
915     EXPECT_THAT(cb1.mWakeupTime[0], Eq(600));
916     ASSERT_THAT(cb1.mReadyTime.size(), Eq(1));
917     EXPECT_THAT(cb1.mReadyTime[0], Eq(1000));
918     ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1));
919     EXPECT_THAT(cb2.mWakeupTime[0], Eq(610));
920     ASSERT_THAT(cb2.mReadyTime.size(), Eq(1));
921     EXPECT_THAT(cb2.mReadyTime[0], Eq(1000));
922 }
923 
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingFutureWithReadyDuration)924 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithReadyDuration) {
925     auto intended = mPeriod - 230;
926     EXPECT_CALL(mMockClock, alarmAt(_, 900));
927 
928     CountingCallback cb(mDispatch);
929     const auto result = mDispatch.schedule(cb,
930                                            {.workDuration = 70,
931                                             .readyDuration = 30,
932                                             .earliestVsync = intended});
933     EXPECT_TRUE(result.has_value());
934     EXPECT_EQ(900, *result);
935     advanceToNextCallback();
936 
937     ASSERT_THAT(cb.mCalls.size(), Eq(1));
938     EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
939     ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
940     EXPECT_THAT(cb.mWakeupTime[0], 900);
941     ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
942     EXPECT_THAT(cb.mReadyTime[0], 970);
943 }
944 
TEST_F(VSyncDispatchTimerQueueTest,updatesVsyncTimeForCloseWakeupTime)945 TEST_F(VSyncDispatchTimerQueueTest, updatesVsyncTimeForCloseWakeupTime) {
946     Sequence seq;
947     EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
948 
949     CountingCallback cb(mDispatch);
950 
951     mDispatch.schedule(cb, {.workDuration = 400, .readyDuration = 0, .earliestVsync = 1000});
952     mDispatch.schedule(cb, {.workDuration = 1400, .readyDuration = 0, .earliestVsync = 1000});
953 
954     advanceToNextCallback();
955 
956     advanceToNextCallback();
957 
958     ASSERT_THAT(cb.mCalls.size(), Eq(1));
959     EXPECT_THAT(cb.mCalls[0], Eq(2000));
960     ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
961     EXPECT_THAT(cb.mWakeupTime[0], Eq(600));
962     ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
963     EXPECT_THAT(cb.mReadyTime[0], Eq(2000));
964 }
965 
966 class VSyncDispatchTimerQueueEntryTest : public testing::Test {
967 protected:
968     nsecs_t const mPeriod = 1000;
969     nsecs_t const mVsyncMoveThreshold = 200;
970     NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
971 };
972 
TEST_F(VSyncDispatchTimerQueueEntryTest,stateAfterInitialization)973 TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
974     std::string name("basicname");
975     VSyncDispatchTimerQueueEntry entry(
976             name, [](auto, auto, auto) {}, mVsyncMoveThreshold);
977     EXPECT_THAT(entry.name(), Eq(name));
978     EXPECT_FALSE(entry.lastExecutedVsyncTarget());
979     EXPECT_FALSE(entry.wakeupTime());
980 }
981 
TEST_F(VSyncDispatchTimerQueueEntryTest,stateScheduling)982 TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
983     VSyncDispatchTimerQueueEntry entry(
984             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
985 
986     EXPECT_FALSE(entry.wakeupTime());
987     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
988                                mStubTracker, 0)
989                         .has_value());
990     auto const wakeup = entry.wakeupTime();
991     ASSERT_TRUE(wakeup);
992     EXPECT_THAT(*wakeup, Eq(900));
993 
994     entry.disarm();
995     EXPECT_FALSE(entry.wakeupTime());
996 }
997 
TEST_F(VSyncDispatchTimerQueueEntryTest,stateSchedulingReallyLongWakeupLatency)998 TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
999     auto const duration = 500;
1000     auto const now = 8750;
1001 
1002     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
1003             .Times(1)
1004             .WillOnce(Return(10000));
1005     VSyncDispatchTimerQueueEntry entry(
1006             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1007 
1008     EXPECT_FALSE(entry.wakeupTime());
1009     EXPECT_TRUE(entry.schedule({.workDuration = 500, .readyDuration = 0, .earliestVsync = 994},
1010                                mStubTracker, now)
1011                         .has_value());
1012     auto const wakeup = entry.wakeupTime();
1013     ASSERT_TRUE(wakeup);
1014     EXPECT_THAT(*wakeup, Eq(9500));
1015 }
1016 
TEST_F(VSyncDispatchTimerQueueEntryTest,runCallback)1017 TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
1018     auto callCount = 0;
1019     auto vsyncCalledTime = 0;
1020     auto wakeupCalledTime = 0;
1021     auto readyCalledTime = 0;
1022     VSyncDispatchTimerQueueEntry entry(
1023             "test",
1024             [&](auto vsyncTime, auto wakeupTime, auto readyTime) {
1025                 callCount++;
1026                 vsyncCalledTime = vsyncTime;
1027                 wakeupCalledTime = wakeupTime;
1028                 readyCalledTime = readyTime;
1029             },
1030             mVsyncMoveThreshold);
1031 
1032     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
1033                                mStubTracker, 0)
1034                         .has_value());
1035     auto const wakeup = entry.wakeupTime();
1036     ASSERT_TRUE(wakeup);
1037     EXPECT_THAT(*wakeup, Eq(900));
1038 
1039     auto const ready = entry.readyTime();
1040     ASSERT_TRUE(ready);
1041     EXPECT_THAT(*ready, Eq(1000));
1042 
1043     entry.callback(entry.executing(), *wakeup, *ready);
1044 
1045     EXPECT_THAT(callCount, Eq(1));
1046     EXPECT_THAT(vsyncCalledTime, Eq(mPeriod));
1047     EXPECT_THAT(wakeupCalledTime, Eq(*wakeup));
1048     EXPECT_FALSE(entry.wakeupTime());
1049     auto lastCalledTarget = entry.lastExecutedVsyncTarget();
1050     ASSERT_TRUE(lastCalledTarget);
1051     EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
1052 }
1053 
TEST_F(VSyncDispatchTimerQueueEntryTest,updateCallback)1054 TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
1055     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
1056             .Times(2)
1057             .WillOnce(Return(1000))
1058             .WillOnce(Return(1020));
1059 
1060     VSyncDispatchTimerQueueEntry entry(
1061             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1062 
1063     EXPECT_FALSE(entry.wakeupTime());
1064     entry.update(mStubTracker, 0);
1065     EXPECT_FALSE(entry.wakeupTime());
1066 
1067     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
1068                                mStubTracker, 0)
1069                         .has_value());
1070     auto wakeup = entry.wakeupTime();
1071     ASSERT_TRUE(wakeup);
1072     EXPECT_THAT(wakeup, Eq(900));
1073 
1074     entry.update(mStubTracker, 0);
1075     wakeup = entry.wakeupTime();
1076     ASSERT_TRUE(wakeup);
1077     EXPECT_THAT(*wakeup, Eq(920));
1078 }
1079 
TEST_F(VSyncDispatchTimerQueueEntryTest,skipsUpdateIfJustScheduled)1080 TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
1081     VSyncDispatchTimerQueueEntry entry(
1082             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1083     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
1084                                mStubTracker, 0)
1085                         .has_value());
1086     entry.update(mStubTracker, 0);
1087 
1088     auto const wakeup = entry.wakeupTime();
1089     ASSERT_TRUE(wakeup);
1090     EXPECT_THAT(*wakeup, Eq(wakeup));
1091 }
1092 
TEST_F(VSyncDispatchTimerQueueEntryTest,willSnapToNextTargettableVSync)1093 TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) {
1094     VSyncDispatchTimerQueueEntry entry(
1095             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1096     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
1097                                mStubTracker, 0)
1098                         .has_value());
1099     entry.executing(); // 1000 is executing
1100     // had 1000 not been executing, this could have been scheduled for time 800.
1101     EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 500},
1102                                mStubTracker, 0)
1103                         .has_value());
1104     EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
1105     EXPECT_THAT(*entry.readyTime(), Eq(2000));
1106 
1107     EXPECT_TRUE(entry.schedule({.workDuration = 50, .readyDuration = 0, .earliestVsync = 500},
1108                                mStubTracker, 0)
1109                         .has_value());
1110     EXPECT_THAT(*entry.wakeupTime(), Eq(1950));
1111     EXPECT_THAT(*entry.readyTime(), Eq(2000));
1112 
1113     EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 1001},
1114                                mStubTracker, 0)
1115                         .has_value());
1116     EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
1117     EXPECT_THAT(*entry.readyTime(), Eq(2000));
1118 }
1119 
TEST_F(VSyncDispatchTimerQueueEntryTest,willRequestNextEstimateWhenSnappingToNextTargettableVSync)1120 TEST_F(VSyncDispatchTimerQueueEntryTest,
1121        willRequestNextEstimateWhenSnappingToNextTargettableVSync) {
1122     VSyncDispatchTimerQueueEntry entry(
1123             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1124 
1125     Sequence seq;
1126     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
1127             .InSequence(seq)
1128             .WillOnce(Return(1000));
1129     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
1130             .InSequence(seq)
1131             .WillOnce(Return(1000));
1132     EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000 + mVsyncMoveThreshold))
1133             .InSequence(seq)
1134             .WillOnce(Return(2000));
1135 
1136     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
1137                                mStubTracker, 0)
1138                         .has_value());
1139 
1140     entry.executing(); // 1000 is executing
1141 
1142     EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 500},
1143                                mStubTracker, 0)
1144                         .has_value());
1145 }
1146 
TEST_F(VSyncDispatchTimerQueueEntryTest,reportsScheduledIfStillTime)1147 TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) {
1148     VSyncDispatchTimerQueueEntry entry(
1149             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1150     EXPECT_TRUE(entry.schedule({.workDuration = 100, .readyDuration = 0, .earliestVsync = 500},
1151                                mStubTracker, 0)
1152                         .has_value());
1153     EXPECT_TRUE(entry.schedule({.workDuration = 200, .readyDuration = 0, .earliestVsync = 500},
1154                                mStubTracker, 0)
1155                         .has_value());
1156     EXPECT_TRUE(entry.schedule({.workDuration = 50, .readyDuration = 0, .earliestVsync = 500},
1157                                mStubTracker, 0)
1158                         .has_value());
1159     EXPECT_TRUE(entry.schedule({.workDuration = 1200, .readyDuration = 0, .earliestVsync = 500},
1160                                mStubTracker, 0)
1161                         .has_value());
1162 }
1163 
TEST_F(VSyncDispatchTimerQueueEntryTest,storesPendingUpdatesUntilUpdate)1164 TEST_F(VSyncDispatchTimerQueueEntryTest, storesPendingUpdatesUntilUpdate) {
1165     static constexpr auto effectualOffset = 200;
1166     VSyncDispatchTimerQueueEntry entry(
1167             "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1168     EXPECT_FALSE(entry.hasPendingWorkloadUpdate());
1169     entry.addPendingWorkloadUpdate({.workDuration = 100, .readyDuration = 0, .earliestVsync = 400});
1170     entry.addPendingWorkloadUpdate(
1171             {.workDuration = effectualOffset, .readyDuration = 0, .earliestVsync = 400});
1172     EXPECT_TRUE(entry.hasPendingWorkloadUpdate());
1173     entry.update(mStubTracker, 0);
1174     EXPECT_FALSE(entry.hasPendingWorkloadUpdate());
1175     EXPECT_THAT(*entry.wakeupTime(), Eq(mPeriod - effectualOffset));
1176 }
1177 
TEST_F(VSyncDispatchTimerQueueEntryTest,runCallbackWithReadyDuration)1178 TEST_F(VSyncDispatchTimerQueueEntryTest, runCallbackWithReadyDuration) {
1179     auto callCount = 0;
1180     auto vsyncCalledTime = 0;
1181     auto wakeupCalledTime = 0;
1182     auto readyCalledTime = 0;
1183     VSyncDispatchTimerQueueEntry entry(
1184             "test",
1185             [&](auto vsyncTime, auto wakeupTime, auto readyTime) {
1186                 callCount++;
1187                 vsyncCalledTime = vsyncTime;
1188                 wakeupCalledTime = wakeupTime;
1189                 readyCalledTime = readyTime;
1190             },
1191             mVsyncMoveThreshold);
1192 
1193     EXPECT_TRUE(entry.schedule({.workDuration = 70, .readyDuration = 30, .earliestVsync = 500},
1194                                mStubTracker, 0)
1195                         .has_value());
1196     auto const wakeup = entry.wakeupTime();
1197     ASSERT_TRUE(wakeup);
1198     EXPECT_THAT(*wakeup, Eq(900));
1199 
1200     auto const ready = entry.readyTime();
1201     ASSERT_TRUE(ready);
1202     EXPECT_THAT(*ready, Eq(970));
1203 
1204     entry.callback(entry.executing(), *wakeup, *ready);
1205 
1206     EXPECT_THAT(callCount, Eq(1));
1207     EXPECT_THAT(vsyncCalledTime, Eq(mPeriod));
1208     EXPECT_THAT(wakeupCalledTime, Eq(*wakeup));
1209     EXPECT_FALSE(entry.wakeupTime());
1210     auto lastCalledTarget = entry.lastExecutedVsyncTarget();
1211     ASSERT_TRUE(lastCalledTarget);
1212     EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
1213 }
1214 
1215 } // namespace android::scheduler
1216 
1217 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1218 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
1219