blob: d668a41bf123bfc4828771cb7f41c00d76fcf3ce [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;
199 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800200 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700201};
202
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800203TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700204 EXPECT_CALL(mMockClock, alarmIn(_, 900));
205 EXPECT_CALL(mMockClock, alarmCancel());
206 {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800207 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker,
208 mDispatchGroupThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700209 CountingCallback cb(mDispatch);
210 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
211 }
212}
213
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800214TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700215 auto intended = mPeriod - 230;
216 EXPECT_CALL(mMockClock, alarmIn(_, 900));
217
218 CountingCallback cb(mDispatch);
219 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
220 advanceToNextCallback();
221
222 ASSERT_THAT(cb.mCalls.size(), Eq(1));
223 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
224}
225
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800226TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700227 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
228 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
229
230 CountingCallback cb(mDispatch);
231 mDispatch.schedule(cb, 100, mPeriod);
232 advanceToNextCallback();
233
234 ASSERT_THAT(cb.mCalls.size(), Eq(1));
235 EXPECT_THAT(cb.mCalls[0], Eq(1150));
236}
237
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800238TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700239 auto const now = 234;
240 mMockClock.advanceBy(234);
241 auto const workDuration = 10 * mPeriod;
242 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
243 .WillOnce(Return(mPeriod * 11));
244 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
245
246 CountingCallback cb(mDispatch);
247 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
248}
249
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800250TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700251 EXPECT_CALL(mMockClock, alarmIn(_, 900));
252 EXPECT_CALL(mMockClock, alarmCancel());
253
254 CountingCallback cb(mDispatch);
255 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
256 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
257}
258
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800259TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700260 EXPECT_CALL(mMockClock, alarmIn(_, 900));
261 EXPECT_CALL(mMockClock, alarmCancel());
262
263 CountingCallback cb(mDispatch);
264 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
265 mMockClock.advanceBy(950);
266 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
267}
268
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800269TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700270 EXPECT_CALL(mMockClock, alarmIn(_, 900));
271 EXPECT_CALL(mMockClock, alarmCancel());
272
273 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
274 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
275
276 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
277 EXPECT_TRUE(cb.waitForPause());
278 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
279 cb.unpause();
280 pausingThread.join();
281}
282
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800283TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700284 EXPECT_CALL(mMockClock, alarmIn(_, 900));
285 EXPECT_CALL(mMockClock, alarmCancel());
286
287 auto resource = std::make_shared<int>(110);
288
289 PausingCallback cb(mDispatch, 50ms);
290 cb.stashResource(resource);
291 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
292
293 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
294 EXPECT_TRUE(cb.waitForPause());
295
296 cb.unregister();
297 resource.reset();
298
299 cb.unpause();
300 pausingThread.join();
301
302 EXPECT_TRUE(cb.resourcePresent());
303}
304
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800305TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700306 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
307 .Times(4)
308 .WillOnce(Return(1055))
309 .WillOnce(Return(1063))
310 .WillOnce(Return(1063))
311 .WillOnce(Return(1075));
312
313 Sequence seq;
314 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
315 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
316 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
317
318 CountingCallback cb0(mDispatch);
319 CountingCallback cb1(mDispatch);
320
321 mDispatch.schedule(cb0, 100, mPeriod);
322 mDispatch.schedule(cb1, 250, mPeriod);
323
324 advanceToNextCallback();
325 advanceToNextCallback();
326
327 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
328 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
329 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
330 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
331}
332
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800333TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700334 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
335 .Times(4)
336 .WillOnce(Return(10000))
337 .WillOnce(Return(1000))
338 .WillOnce(Return(10000))
339 .WillOnce(Return(10000));
340
341 Sequence seq;
342 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
343 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
344 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
345
346 CountingCallback cb0(mDispatch);
347 CountingCallback cb1(mDispatch);
348
349 mDispatch.schedule(cb0, 100, mPeriod * 10);
350 mDispatch.schedule(cb1, 250, mPeriod);
351 mDispatch.cancel(cb1);
352}
353
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800354TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700355 Sequence seq;
356 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
357 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
358
359 CountingCallback cb0(mDispatch);
360 CountingCallback cb1(mDispatch);
361
362 mDispatch.schedule(cb0, 400, 1000);
363 mDispatch.schedule(cb1, 200, 1000);
364 mDispatch.schedule(cb1, 300, 1000);
365 advanceToNextCallback();
366}
367
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800368TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700369 Sequence seq;
370 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
371 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
372 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
373
374 CountingCallback cb0(mDispatch);
375 CountingCallback cb1(mDispatch);
376
377 mDispatch.schedule(cb0, 400, 1000);
378 mDispatch.schedule(cb1, 200, 1000);
379 mDispatch.schedule(cb1, 500, 1000);
380 advanceToNextCallback();
381}
382
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800383TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700384 Sequence seq;
385 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
386 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
387 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
388 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
389
390 auto offset = 400;
391 auto closeOffset = offset + mDispatchGroupThreshold - 1;
392 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
393
394 CountingCallback cb0(mDispatch);
395 CountingCallback cb1(mDispatch);
396
397 mDispatch.schedule(cb0, 400, 1000);
398 mDispatch.schedule(cb1, 200, 1000);
399 mDispatch.schedule(cb1, closeOffset, 1000);
400
401 advanceToNextCallback();
402 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
403 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
404 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
405 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
406
407 mDispatch.schedule(cb0, 400, 2000);
408 mDispatch.schedule(cb1, notCloseOffset, 2000);
409 advanceToNextCallback();
410 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
411 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
412
413 advanceToNextCallback();
414 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
415 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
416}
417
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800418TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700419 EXPECT_CALL(mMockClock, alarmIn(_, 900));
420 EXPECT_CALL(mMockClock, alarmIn(_, 800));
421 EXPECT_CALL(mMockClock, alarmIn(_, 100));
422 EXPECT_CALL(mMockClock, alarmCancel());
423
424 CountingCallback cb0(mDispatch);
425 CountingCallback cb1(mDispatch);
426
427 mDispatch.schedule(cb0, 100, 1000);
428 mDispatch.schedule(cb1, 200, 1000);
429 advanceToNextCallback();
430 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
431}
432
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800433TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700434 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
435 .Times(3)
436 .WillOnce(Return(950))
437 .WillOnce(Return(1975))
438 .WillOnce(Return(2950));
439
440 CountingCallback cb(mDispatch);
441 mDispatch.schedule(cb, 100, 920);
442
443 mMockClock.advanceBy(850);
444 EXPECT_THAT(cb.mCalls.size(), Eq(1));
445
446 mDispatch.schedule(cb, 100, 1900);
447 mMockClock.advanceBy(900);
448 EXPECT_THAT(cb.mCalls.size(), Eq(1));
449 mMockClock.advanceBy(125);
450 EXPECT_THAT(cb.mCalls.size(), Eq(2));
451
452 mDispatch.schedule(cb, 100, 2900);
453 mMockClock.advanceBy(975);
454 EXPECT_THAT(cb.mCalls.size(), Eq(3));
455}
456
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800457TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700458 Sequence seq;
459 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
460 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
461
462 VSyncDispatch::CallbackToken tmp;
463 tmp = mDispatch.registerCallback([&](auto) { mDispatch.schedule(tmp, 100, 2000); }, "o.o");
464
465 mDispatch.schedule(tmp, 100, 1000);
466 advanceToNextCallback();
467}
468
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800469TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700470 VSyncDispatch::CallbackToken tmp;
471 tmp = mDispatch.registerCallback(
472 [&](auto) {
473 EXPECT_EQ(mDispatch.schedule(tmp, 400, 1000), ScheduleResult::CannotSchedule);
474 },
475 "oo");
476
477 mDispatch.schedule(tmp, 999, 1000);
478 advanceToNextCallback();
479}
480
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800481TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700482 Sequence seq;
483 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
484 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
485 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
486 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
487
488 CountingCallback cb(mDispatch);
489 mDispatch.schedule(cb, 0, 1000);
490
491 mMockClock.advanceBy(750);
492 mDispatch.schedule(cb, 50, 1000);
493
494 advanceToNextCallback();
495 mDispatch.schedule(cb, 50, 2000);
496
497 mMockClock.advanceBy(800);
498 mDispatch.schedule(cb, 100, 2000);
499}
500
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800501TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700502 Sequence seq;
503 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
504 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
505 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
506 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
507
508 CountingCallback cb0(mDispatch);
509 CountingCallback cb1(mDispatch);
510
511 mDispatch.schedule(cb0, 500, 1000);
512 mDispatch.schedule(cb1, 100, 1000);
513
514 advanceToNextCallback();
515 mDispatch.schedule(cb0, 200, 2000);
516 mDispatch.schedule(cb1, 150, 1000);
517
518 advanceToNextCallback();
519 advanceToNextCallback();
520}
521
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800522TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700523 Sequence seq;
524 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
525
526 CountingCallback cb0(mDispatch);
527 CountingCallback cb1(mDispatch);
528 mDispatch.schedule(cb0, 500, 1000);
529 mDispatch.schedule(cb1, 500, 20000);
530}
531
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800532TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700533 Sequence seq;
534 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
535 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
536 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
537
538 CountingCallback cb0(mDispatch);
539 mDispatch.schedule(cb0, 500, 1000);
540 mDispatch.cancel(cb0);
541 mDispatch.schedule(cb0, 100, 1000);
542}
543
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800544TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700545 VSyncDispatch::CallbackToken token(100);
546 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
547 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
548}
549
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800550TEST_F(VSyncDispatchTimerQueueTest, distinguishesScheduleAndReschedule) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700551 CountingCallback cb0(mDispatch);
552 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
553 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::ReScheduled);
554}
555
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800556TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
557 CountingCallback cb0(mDispatch);
558 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
559 advanceToNextCallback();
560 EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled);
561}
562
563TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
564 Sequence seq;
565 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
566 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
567 CountingCallback cb0(mDispatch);
568 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
569 advanceToNextCallback();
570 EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled);
571}
572
573TEST_F(VSyncDispatchTimerQueueTest, cannotScheduleDoesNotAffectSchedulingState) {
574 EXPECT_CALL(mMockClock, alarmIn(_, 600));
575
576 CountingCallback cb(mDispatch);
577 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
578 advanceToNextCallback();
579 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::CannotSchedule);
580}
581
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800582TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700583 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
584 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
585
586 VSyncCallbackRegistration cb(
587 mDispatch, [](auto) {}, "");
588 VSyncCallbackRegistration cb1(std::move(cb));
589 cb.schedule(100, 1000);
590 cb.cancel();
591
592 cb1.schedule(500, 1000);
593 cb1.cancel();
594}
595
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800596TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700597 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
598 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
599
600 VSyncCallbackRegistration cb(
601 mDispatch, [](auto) {}, "");
602 VSyncCallbackRegistration cb1(
603 mDispatch, [](auto) {}, "");
604 cb1 = std::move(cb);
605 cb.schedule(100, 1000);
606 cb.cancel();
607
608 cb1.schedule(500, 1000);
609 cb1.cancel();
610}
611
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800612class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700613protected:
614 nsecs_t const mPeriod = 1000;
615 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
616};
617
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800618TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700619 std::string name("basicname");
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800620 VSyncDispatchTimerQueueEntry entry(name, [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700621 EXPECT_THAT(entry.name(), Eq(name));
622 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
623 EXPECT_FALSE(entry.wakeupTime());
624}
625
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800626TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
627 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700628
629 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800630 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
631 auto const wakeup = entry.wakeupTime();
632 ASSERT_TRUE(wakeup);
633 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700634
635 entry.disarm();
636 EXPECT_FALSE(entry.wakeupTime());
637}
638
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800639TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700640 auto const duration = 500;
641 auto const now = 8750;
642
643 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
644 .Times(1)
645 .WillOnce(Return(10000));
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800646 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700647
648 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800649 EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled));
650 auto const wakeup = entry.wakeupTime();
651 ASSERT_TRUE(wakeup);
652 EXPECT_THAT(*wakeup, Eq(9500));
Kevin DuBois305bef12019-10-09 13:23:27 -0700653}
654
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800655TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700656 auto callCount = 0;
657 auto calledTime = 0;
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800658 VSyncDispatchTimerQueueEntry entry("test", [&](auto time) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700659 callCount++;
660 calledTime = time;
661 });
662
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800663 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
664 auto const wakeup = entry.wakeupTime();
665 ASSERT_TRUE(wakeup);
666 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700667
668 entry.callback(entry.executing());
669
670 EXPECT_THAT(callCount, Eq(1));
671 EXPECT_THAT(calledTime, Eq(mPeriod));
672 EXPECT_FALSE(entry.wakeupTime());
673 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
674 ASSERT_TRUE(lastCalledTarget);
675 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
676}
677
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800678TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700679 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
680 .Times(2)
681 .WillOnce(Return(1000))
682 .WillOnce(Return(1020));
683
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800684 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700685
686 EXPECT_FALSE(entry.wakeupTime());
687 entry.update(mStubTracker, 0);
688 EXPECT_FALSE(entry.wakeupTime());
689
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800690 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
691 auto wakeup = entry.wakeupTime();
692 ASSERT_TRUE(wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700693 EXPECT_THAT(wakeup, Eq(900));
694
695 entry.update(mStubTracker, 0);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800696 wakeup = entry.wakeupTime();
697 ASSERT_TRUE(wakeup);
698 EXPECT_THAT(*wakeup, Eq(920));
Kevin DuBois305bef12019-10-09 13:23:27 -0700699}
700
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800701TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
702 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800703 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700704 entry.update(mStubTracker, 0);
705
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800706 auto const wakeup = entry.wakeupTime();
707 ASSERT_TRUE(wakeup);
708 EXPECT_THAT(*wakeup, Eq(wakeup));
709}
710
711TEST_F(VSyncDispatchTimerQueueEntryTest, reportsCannotScheduleIfMissedOpportunity) {
712 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
713 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
714 entry.executing();
715 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::CannotSchedule));
716 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::CannotSchedule));
717 EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
718}
719
720TEST_F(VSyncDispatchTimerQueueEntryTest, reportsReScheduleIfStillTime) {
721 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
722 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
723 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::ReScheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700724}
725
726} // namespace android::scheduler