blob: 5aff4296f90c2ba33555acfba82d5596403a011f [file] [log] [blame]
Kevin DuBois305bef12019-10-09 13:23:27 -07001/*
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#undef LOG_TAG
18#define LOG_TAG "LibSurfaceFlingerUnittests"
19#define LOG_NDEBUG 0
20
21#include "Scheduler/TimeKeeper.h"
Kevin DuBoise4f27a82019-11-12 11:41:41 -080022#include "Scheduler/VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070023#include "Scheduler/VSyncTracker.h"
24
25#include <gmock/gmock.h>
26#include <gtest/gtest.h>
27#include <thread>
28
29using namespace testing;
30using namespace std::literals;
31namespace android::scheduler {
32
33class MockVSyncTracker : public VSyncTracker {
34public:
35 MockVSyncTracker(nsecs_t period) : mPeriod{period} {
36 ON_CALL(*this, nextAnticipatedVSyncTimeFrom(_))
37 .WillByDefault(Invoke(this, &MockVSyncTracker::nextVSyncTime));
38 }
39
40 MOCK_METHOD1(addVsyncTimestamp, void(nsecs_t));
41 MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t));
Kevin DuBois2fd3cea2019-11-14 08:52:45 -080042 MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
Kevin DuBoisee2ad9f2019-11-21 11:10:57 -080043 MOCK_METHOD1(setPeriod, void(nsecs_t));
Kevin DuBois305bef12019-10-09 13:23:27 -070044
45 nsecs_t nextVSyncTime(nsecs_t timePoint) const {
46 if (timePoint % mPeriod == 0) {
47 return timePoint;
48 }
49 return (timePoint - (timePoint % mPeriod) + mPeriod);
50 }
51
52protected:
53 nsecs_t const mPeriod;
54};
55
56class ControllableClock : public TimeKeeper {
57public:
58 ControllableClock() {
59 ON_CALL(*this, alarmIn(_, _))
60 .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
61 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
62 }
63
64 MOCK_CONST_METHOD0(now, nsecs_t());
65 MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
66 MOCK_METHOD0(alarmCancel, void());
67
68 void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
69 mCallback = callback;
70 mNextCallbackTime = time + mCurrentTime;
71 }
72
73 nsecs_t fakeTime() const { return mCurrentTime; }
74
75 void advanceToNextCallback() {
76 mCurrentTime = mNextCallbackTime;
77 if (mCallback) {
78 mCallback();
79 }
80 }
81
82 void advanceBy(nsecs_t advancement) {
83 mCurrentTime += advancement;
84 if (mCurrentTime >= mNextCallbackTime && mCallback) {
85 mCallback();
86 }
87 };
88
89private:
90 std::function<void()> mCallback;
91 nsecs_t mNextCallbackTime = 0;
92 nsecs_t mCurrentTime = 0;
93};
94
95class CountingCallback {
96public:
97 CountingCallback(VSyncDispatch& dispatch)
98 : mDispatch(dispatch),
99 mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
100 std::placeholders::_1),
101 "test")) {}
102 ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
103
104 operator VSyncDispatch::CallbackToken() const { return mToken; }
105
106 void counter(nsecs_t time) { mCalls.push_back(time); }
107
108 VSyncDispatch& mDispatch;
109 VSyncDispatch::CallbackToken mToken;
110 std::vector<nsecs_t> mCalls;
111};
112
113class PausingCallback {
114public:
115 PausingCallback(VSyncDispatch& dispatch, std::chrono::milliseconds pauseAmount)
116 : mDispatch(dispatch),
117 mToken(dispatch.registerCallback(std::bind(&PausingCallback::pause, this,
118 std::placeholders::_1),
119 "test")),
120 mRegistered(true),
121 mPauseAmount(pauseAmount) {}
122 ~PausingCallback() { unregister(); }
123
124 operator VSyncDispatch::CallbackToken() const { return mToken; }
125
126 void pause(nsecs_t) {
127 std::unique_lock<std::mutex> lk(mMutex);
128 mPause = true;
129 mCv.notify_all();
130
131 mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; });
132
133 mResourcePresent = (mResource.lock() != nullptr);
134 }
135
136 bool waitForPause() {
137 std::unique_lock<std::mutex> lk(mMutex);
138 auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; });
139 return waiting;
140 }
141
142 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
143
144 bool resourcePresent() { return mResourcePresent; }
145
146 void unpause() {
147 std::unique_lock<std::mutex> lk(mMutex);
148 mPause = false;
149 mCv.notify_all();
150 }
151
152 void unregister() {
153 if (mRegistered) {
154 mDispatch.unregisterCallback(mToken);
155 mRegistered = false;
156 }
157 }
158
159 VSyncDispatch& mDispatch;
160 VSyncDispatch::CallbackToken mToken;
161 bool mRegistered = true;
162
163 std::mutex mMutex;
164 std::condition_variable mCv;
165 bool mPause = false;
166 std::weak_ptr<void> mResource;
167 bool mResourcePresent = false;
168 std::chrono::milliseconds const mPauseAmount;
169};
170
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800171class VSyncDispatchTimerQueueTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700172protected:
173 std::unique_ptr<TimeKeeper> createTimeKeeper() {
174 class TimeKeeperWrapper : public TimeKeeper {
175 public:
176 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
177 void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
178 mControllableClock.alarmIn(callback, time);
179 }
180 void alarmCancel() final { mControllableClock.alarmCancel(); }
181 nsecs_t now() const final { return mControllableClock.now(); }
182
183 private:
184 TimeKeeper& mControllableClock;
185 };
186 return std::make_unique<TimeKeeperWrapper>(mMockClock);
187 }
188
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800189 ~VSyncDispatchTimerQueueTest() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700190 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
191 Mock::VerifyAndClearExpectations(&mMockClock);
192 }
193
194 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
195
196 NiceMock<ControllableClock> mMockClock;
197 static nsecs_t constexpr mDispatchGroupThreshold = 5;
198 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800199 nsecs_t const mVsyncMoveThreshold = 300;
Kevin DuBois305bef12019-10-09 13:23:27 -0700200 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800201 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
202 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700203};
204
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800205TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700206 EXPECT_CALL(mMockClock, alarmIn(_, 900));
207 EXPECT_CALL(mMockClock, alarmCancel());
208 {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800209 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
210 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700211 CountingCallback cb(mDispatch);
212 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
213 }
214}
215
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800216TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700217 auto intended = mPeriod - 230;
218 EXPECT_CALL(mMockClock, alarmIn(_, 900));
219
220 CountingCallback cb(mDispatch);
221 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
222 advanceToNextCallback();
223
224 ASSERT_THAT(cb.mCalls.size(), Eq(1));
225 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
226}
227
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800228TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700229 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
230 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
231
232 CountingCallback cb(mDispatch);
233 mDispatch.schedule(cb, 100, mPeriod);
234 advanceToNextCallback();
235
236 ASSERT_THAT(cb.mCalls.size(), Eq(1));
237 EXPECT_THAT(cb.mCalls[0], Eq(1150));
238}
239
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800240TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700241 auto const now = 234;
242 mMockClock.advanceBy(234);
243 auto const workDuration = 10 * mPeriod;
244 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
245 .WillOnce(Return(mPeriod * 11));
246 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
247
248 CountingCallback cb(mDispatch);
249 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
250}
251
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800252TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700253 EXPECT_CALL(mMockClock, alarmIn(_, 900));
254 EXPECT_CALL(mMockClock, alarmCancel());
255
256 CountingCallback cb(mDispatch);
257 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
258 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
259}
260
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800261TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700262 EXPECT_CALL(mMockClock, alarmIn(_, 900));
263 EXPECT_CALL(mMockClock, alarmCancel());
264
265 CountingCallback cb(mDispatch);
266 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
267 mMockClock.advanceBy(950);
268 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
269}
270
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800271TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700272 EXPECT_CALL(mMockClock, alarmIn(_, 900));
273 EXPECT_CALL(mMockClock, alarmCancel());
274
275 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
276 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
277
278 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
279 EXPECT_TRUE(cb.waitForPause());
280 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
281 cb.unpause();
282 pausingThread.join();
283}
284
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800285TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700286 EXPECT_CALL(mMockClock, alarmIn(_, 900));
287 EXPECT_CALL(mMockClock, alarmCancel());
288
289 auto resource = std::make_shared<int>(110);
290
291 PausingCallback cb(mDispatch, 50ms);
292 cb.stashResource(resource);
293 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
294
295 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
296 EXPECT_TRUE(cb.waitForPause());
297
298 cb.unregister();
299 resource.reset();
300
301 cb.unpause();
302 pausingThread.join();
303
304 EXPECT_TRUE(cb.resourcePresent());
305}
306
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800307TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700308 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
309 .Times(4)
310 .WillOnce(Return(1055))
311 .WillOnce(Return(1063))
312 .WillOnce(Return(1063))
313 .WillOnce(Return(1075));
314
315 Sequence seq;
316 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
317 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
318 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
319
320 CountingCallback cb0(mDispatch);
321 CountingCallback cb1(mDispatch);
322
323 mDispatch.schedule(cb0, 100, mPeriod);
324 mDispatch.schedule(cb1, 250, mPeriod);
325
326 advanceToNextCallback();
327 advanceToNextCallback();
328
329 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
330 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
331 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
332 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
333}
334
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800335TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700336 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
337 .Times(4)
338 .WillOnce(Return(10000))
339 .WillOnce(Return(1000))
340 .WillOnce(Return(10000))
341 .WillOnce(Return(10000));
342
343 Sequence seq;
344 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
345 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
346 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
347
348 CountingCallback cb0(mDispatch);
349 CountingCallback cb1(mDispatch);
350
351 mDispatch.schedule(cb0, 100, mPeriod * 10);
352 mDispatch.schedule(cb1, 250, mPeriod);
353 mDispatch.cancel(cb1);
354}
355
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800356TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700357 Sequence seq;
358 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
359 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
360
361 CountingCallback cb0(mDispatch);
362 CountingCallback cb1(mDispatch);
363
364 mDispatch.schedule(cb0, 400, 1000);
365 mDispatch.schedule(cb1, 200, 1000);
366 mDispatch.schedule(cb1, 300, 1000);
367 advanceToNextCallback();
368}
369
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800370TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700371 Sequence seq;
372 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
373 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
374 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
375
376 CountingCallback cb0(mDispatch);
377 CountingCallback cb1(mDispatch);
378
379 mDispatch.schedule(cb0, 400, 1000);
380 mDispatch.schedule(cb1, 200, 1000);
381 mDispatch.schedule(cb1, 500, 1000);
382 advanceToNextCallback();
383}
384
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800385TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700386 Sequence seq;
387 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
388 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
389 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
390 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
391
392 auto offset = 400;
393 auto closeOffset = offset + mDispatchGroupThreshold - 1;
394 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
395
396 CountingCallback cb0(mDispatch);
397 CountingCallback cb1(mDispatch);
398
399 mDispatch.schedule(cb0, 400, 1000);
400 mDispatch.schedule(cb1, 200, 1000);
401 mDispatch.schedule(cb1, closeOffset, 1000);
402
403 advanceToNextCallback();
404 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
405 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
406 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
407 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
408
409 mDispatch.schedule(cb0, 400, 2000);
410 mDispatch.schedule(cb1, notCloseOffset, 2000);
411 advanceToNextCallback();
412 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
413 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
414
415 advanceToNextCallback();
416 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
417 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
418}
419
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800420TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700421 EXPECT_CALL(mMockClock, alarmIn(_, 900));
422 EXPECT_CALL(mMockClock, alarmIn(_, 800));
423 EXPECT_CALL(mMockClock, alarmIn(_, 100));
424 EXPECT_CALL(mMockClock, alarmCancel());
425
426 CountingCallback cb0(mDispatch);
427 CountingCallback cb1(mDispatch);
428
429 mDispatch.schedule(cb0, 100, 1000);
430 mDispatch.schedule(cb1, 200, 1000);
431 advanceToNextCallback();
432 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
433}
434
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800435TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700436 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
437 .Times(3)
438 .WillOnce(Return(950))
439 .WillOnce(Return(1975))
440 .WillOnce(Return(2950));
441
442 CountingCallback cb(mDispatch);
443 mDispatch.schedule(cb, 100, 920);
444
445 mMockClock.advanceBy(850);
446 EXPECT_THAT(cb.mCalls.size(), Eq(1));
447
448 mDispatch.schedule(cb, 100, 1900);
449 mMockClock.advanceBy(900);
450 EXPECT_THAT(cb.mCalls.size(), Eq(1));
451 mMockClock.advanceBy(125);
452 EXPECT_THAT(cb.mCalls.size(), Eq(2));
453
454 mDispatch.schedule(cb, 100, 2900);
455 mMockClock.advanceBy(975);
456 EXPECT_THAT(cb.mCalls.size(), Eq(3));
457}
458
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800459TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700460 Sequence seq;
461 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
462 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
463
464 VSyncDispatch::CallbackToken tmp;
465 tmp = mDispatch.registerCallback([&](auto) { mDispatch.schedule(tmp, 100, 2000); }, "o.o");
466
467 mDispatch.schedule(tmp, 100, 1000);
468 advanceToNextCallback();
469}
470
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800471TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700472 VSyncDispatch::CallbackToken tmp;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800473 std::optional<nsecs_t> lastTarget;
Kevin DuBois305bef12019-10-09 13:23:27 -0700474 tmp = mDispatch.registerCallback(
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800475 [&](auto timestamp) {
476 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp - mVsyncMoveThreshold),
477 ScheduleResult::Scheduled);
478 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp), ScheduleResult::Scheduled);
479 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp + mVsyncMoveThreshold),
480 ScheduleResult::Scheduled);
481 lastTarget = timestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700482 },
483 "oo");
484
485 mDispatch.schedule(tmp, 999, 1000);
486 advanceToNextCallback();
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800487 EXPECT_THAT(lastTarget, Eq(1000));
488
489 advanceToNextCallback();
490 EXPECT_THAT(lastTarget, Eq(2000));
Kevin DuBois305bef12019-10-09 13:23:27 -0700491}
492
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800493TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700494 Sequence seq;
495 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
496 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
497 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
498 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
499
500 CountingCallback cb(mDispatch);
501 mDispatch.schedule(cb, 0, 1000);
502
503 mMockClock.advanceBy(750);
504 mDispatch.schedule(cb, 50, 1000);
505
506 advanceToNextCallback();
507 mDispatch.schedule(cb, 50, 2000);
508
509 mMockClock.advanceBy(800);
510 mDispatch.schedule(cb, 100, 2000);
511}
512
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800513TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700514 Sequence seq;
515 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
516 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
517 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
518 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
519
520 CountingCallback cb0(mDispatch);
521 CountingCallback cb1(mDispatch);
522
523 mDispatch.schedule(cb0, 500, 1000);
524 mDispatch.schedule(cb1, 100, 1000);
525
526 advanceToNextCallback();
527 mDispatch.schedule(cb0, 200, 2000);
528 mDispatch.schedule(cb1, 150, 1000);
529
530 advanceToNextCallback();
531 advanceToNextCallback();
532}
533
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800534TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700535 Sequence seq;
536 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
537
538 CountingCallback cb0(mDispatch);
539 CountingCallback cb1(mDispatch);
540 mDispatch.schedule(cb0, 500, 1000);
541 mDispatch.schedule(cb1, 500, 20000);
542}
543
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800544TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700545 Sequence seq;
546 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
547 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
548 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
549
550 CountingCallback cb0(mDispatch);
551 mDispatch.schedule(cb0, 500, 1000);
552 mDispatch.cancel(cb0);
553 mDispatch.schedule(cb0, 100, 1000);
554}
555
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800556TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700557 VSyncDispatch::CallbackToken token(100);
558 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
559 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
560}
561
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800562TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700563 CountingCallback cb0(mDispatch);
564 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800565 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::Scheduled);
566}
567
568// b/1450138150
569TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
570 EXPECT_CALL(mMockClock, alarmIn(_, 500));
571 CountingCallback cb(mDispatch);
572 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
573 mMockClock.advanceBy(400);
574
575 EXPECT_EQ(mDispatch.schedule(cb, 800, 1000), ScheduleResult::Scheduled);
576 advanceToNextCallback();
577 ASSERT_THAT(cb.mCalls.size(), Eq(1));
578}
579
580TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedule) {
581 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
582 .Times(2)
583 .WillOnce(Return(1000))
584 .WillOnce(Return(1002));
585 CountingCallback cb(mDispatch);
586 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
587 mMockClock.advanceBy(400);
588 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBois305bef12019-10-09 13:23:27 -0700589}
590
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800591TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
592 CountingCallback cb0(mDispatch);
593 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
594 advanceToNextCallback();
595 EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled);
596}
597
598TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
599 Sequence seq;
600 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
601 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
602 CountingCallback cb0(mDispatch);
603 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
604 advanceToNextCallback();
605 EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled);
606}
607
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800608TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800609 EXPECT_CALL(mMockClock, alarmIn(_, 600));
610
611 CountingCallback cb(mDispatch);
612 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800613
614 EXPECT_EQ(mDispatch.schedule(cb, 1400, 1000), ScheduleResult::Scheduled);
615
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800616 advanceToNextCallback();
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800617}
618
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800619TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700620 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
621 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
622
623 VSyncCallbackRegistration cb(
624 mDispatch, [](auto) {}, "");
625 VSyncCallbackRegistration cb1(std::move(cb));
626 cb.schedule(100, 1000);
627 cb.cancel();
628
629 cb1.schedule(500, 1000);
630 cb1.cancel();
631}
632
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800633TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700634 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
635 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
636
637 VSyncCallbackRegistration cb(
638 mDispatch, [](auto) {}, "");
639 VSyncCallbackRegistration cb1(
640 mDispatch, [](auto) {}, "");
641 cb1 = std::move(cb);
642 cb.schedule(100, 1000);
643 cb.cancel();
644
645 cb1.schedule(500, 1000);
646 cb1.cancel();
647}
648
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800649class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700650protected:
651 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800652 nsecs_t const mVsyncMoveThreshold = 200;
Kevin DuBois305bef12019-10-09 13:23:27 -0700653 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
654};
655
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800656TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700657 std::string name("basicname");
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800658 VSyncDispatchTimerQueueEntry entry(
659 name, [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700660 EXPECT_THAT(entry.name(), Eq(name));
661 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
662 EXPECT_FALSE(entry.wakeupTime());
663}
664
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800665TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800666 VSyncDispatchTimerQueueEntry entry(
667 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700668
669 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800670 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
671 auto const wakeup = entry.wakeupTime();
672 ASSERT_TRUE(wakeup);
673 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700674
675 entry.disarm();
676 EXPECT_FALSE(entry.wakeupTime());
677}
678
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800679TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700680 auto const duration = 500;
681 auto const now = 8750;
682
683 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
684 .Times(1)
685 .WillOnce(Return(10000));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800686 VSyncDispatchTimerQueueEntry entry(
687 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700688
689 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800690 EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled));
691 auto const wakeup = entry.wakeupTime();
692 ASSERT_TRUE(wakeup);
693 EXPECT_THAT(*wakeup, Eq(9500));
Kevin DuBois305bef12019-10-09 13:23:27 -0700694}
695
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800696TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700697 auto callCount = 0;
698 auto calledTime = 0;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800699 VSyncDispatchTimerQueueEntry entry(
700 "test",
701 [&](auto time) {
702 callCount++;
703 calledTime = time;
704 },
705 mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700706
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800707 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
708 auto const wakeup = entry.wakeupTime();
709 ASSERT_TRUE(wakeup);
710 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700711
712 entry.callback(entry.executing());
713
714 EXPECT_THAT(callCount, Eq(1));
715 EXPECT_THAT(calledTime, Eq(mPeriod));
716 EXPECT_FALSE(entry.wakeupTime());
717 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
718 ASSERT_TRUE(lastCalledTarget);
719 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
720}
721
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800722TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700723 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
724 .Times(2)
725 .WillOnce(Return(1000))
726 .WillOnce(Return(1020));
727
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800728 VSyncDispatchTimerQueueEntry entry(
729 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700730
731 EXPECT_FALSE(entry.wakeupTime());
732 entry.update(mStubTracker, 0);
733 EXPECT_FALSE(entry.wakeupTime());
734
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800735 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
736 auto wakeup = entry.wakeupTime();
737 ASSERT_TRUE(wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700738 EXPECT_THAT(wakeup, Eq(900));
739
740 entry.update(mStubTracker, 0);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800741 wakeup = entry.wakeupTime();
742 ASSERT_TRUE(wakeup);
743 EXPECT_THAT(*wakeup, Eq(920));
Kevin DuBois305bef12019-10-09 13:23:27 -0700744}
745
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800746TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800747 VSyncDispatchTimerQueueEntry entry(
748 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800749 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700750 entry.update(mStubTracker, 0);
751
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800752 auto const wakeup = entry.wakeupTime();
753 ASSERT_TRUE(wakeup);
754 EXPECT_THAT(*wakeup, Eq(wakeup));
755}
756
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800757TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) {
758 VSyncDispatchTimerQueueEntry entry(
759 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800760 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800761 entry.executing(); // 1000 is executing
762 // had 1000 not been executing, this could have been scheduled for time 800.
763 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
764 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
765
766 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
767 EXPECT_THAT(*entry.wakeupTime(), Eq(1950));
768
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800769 EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800770 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800771}
772
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800773TEST_F(VSyncDispatchTimerQueueEntryTest,
774 willRequestNextEstimateWhenSnappingToNextTargettableVSync) {
775 VSyncDispatchTimerQueueEntry entry(
776 "test", [](auto) {}, mVsyncMoveThreshold);
777
778 Sequence seq;
779 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
780 .InSequence(seq)
781 .WillOnce(Return(1000));
782 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
783 .InSequence(seq)
784 .WillOnce(Return(1000));
785 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000 + mVsyncMoveThreshold))
786 .InSequence(seq)
787 .WillOnce(Return(2000));
788
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800789 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800790
791 entry.executing(); // 1000 is executing
792
793 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
794}
795
796TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) {
797 VSyncDispatchTimerQueueEntry entry(
798 "test", [](auto) {}, mVsyncMoveThreshold);
799 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
800 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
801 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
802 EXPECT_THAT(entry.schedule(1200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700803}
804
805} // namespace android::scheduler