blob: 82b1051a6d62d6a202efd28bd7450f50d0a6c479 [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 DuBois305bef12019-10-09 13:23:27 -070043
44 nsecs_t nextVSyncTime(nsecs_t timePoint) const {
45 if (timePoint % mPeriod == 0) {
46 return timePoint;
47 }
48 return (timePoint - (timePoint % mPeriod) + mPeriod);
49 }
50
51protected:
52 nsecs_t const mPeriod;
53};
54
55class ControllableClock : public TimeKeeper {
56public:
57 ControllableClock() {
58 ON_CALL(*this, alarmIn(_, _))
59 .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
60 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
61 }
62
63 MOCK_CONST_METHOD0(now, nsecs_t());
64 MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
65 MOCK_METHOD0(alarmCancel, void());
66
67 void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
68 mCallback = callback;
69 mNextCallbackTime = time + mCurrentTime;
70 }
71
72 nsecs_t fakeTime() const { return mCurrentTime; }
73
74 void advanceToNextCallback() {
75 mCurrentTime = mNextCallbackTime;
76 if (mCallback) {
77 mCallback();
78 }
79 }
80
81 void advanceBy(nsecs_t advancement) {
82 mCurrentTime += advancement;
83 if (mCurrentTime >= mNextCallbackTime && mCallback) {
84 mCallback();
85 }
86 };
87
88private:
89 std::function<void()> mCallback;
90 nsecs_t mNextCallbackTime = 0;
91 nsecs_t mCurrentTime = 0;
92};
93
94class CountingCallback {
95public:
96 CountingCallback(VSyncDispatch& dispatch)
97 : mDispatch(dispatch),
98 mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
99 std::placeholders::_1),
100 "test")) {}
101 ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
102
103 operator VSyncDispatch::CallbackToken() const { return mToken; }
104
105 void counter(nsecs_t time) { mCalls.push_back(time); }
106
107 VSyncDispatch& mDispatch;
108 VSyncDispatch::CallbackToken mToken;
109 std::vector<nsecs_t> mCalls;
110};
111
112class PausingCallback {
113public:
114 PausingCallback(VSyncDispatch& dispatch, std::chrono::milliseconds pauseAmount)
115 : mDispatch(dispatch),
116 mToken(dispatch.registerCallback(std::bind(&PausingCallback::pause, this,
117 std::placeholders::_1),
118 "test")),
119 mRegistered(true),
120 mPauseAmount(pauseAmount) {}
121 ~PausingCallback() { unregister(); }
122
123 operator VSyncDispatch::CallbackToken() const { return mToken; }
124
125 void pause(nsecs_t) {
126 std::unique_lock<std::mutex> lk(mMutex);
127 mPause = true;
128 mCv.notify_all();
129
130 mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; });
131
132 mResourcePresent = (mResource.lock() != nullptr);
133 }
134
135 bool waitForPause() {
136 std::unique_lock<std::mutex> lk(mMutex);
137 auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; });
138 return waiting;
139 }
140
141 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
142
143 bool resourcePresent() { return mResourcePresent; }
144
145 void unpause() {
146 std::unique_lock<std::mutex> lk(mMutex);
147 mPause = false;
148 mCv.notify_all();
149 }
150
151 void unregister() {
152 if (mRegistered) {
153 mDispatch.unregisterCallback(mToken);
154 mRegistered = false;
155 }
156 }
157
158 VSyncDispatch& mDispatch;
159 VSyncDispatch::CallbackToken mToken;
160 bool mRegistered = true;
161
162 std::mutex mMutex;
163 std::condition_variable mCv;
164 bool mPause = false;
165 std::weak_ptr<void> mResource;
166 bool mResourcePresent = false;
167 std::chrono::milliseconds const mPauseAmount;
168};
169
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800170class VSyncDispatchTimerQueueTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700171protected:
172 std::unique_ptr<TimeKeeper> createTimeKeeper() {
173 class TimeKeeperWrapper : public TimeKeeper {
174 public:
175 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
176 void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
177 mControllableClock.alarmIn(callback, time);
178 }
179 void alarmCancel() final { mControllableClock.alarmCancel(); }
180 nsecs_t now() const final { return mControllableClock.now(); }
181
182 private:
183 TimeKeeper& mControllableClock;
184 };
185 return std::make_unique<TimeKeeperWrapper>(mMockClock);
186 }
187
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800188 ~VSyncDispatchTimerQueueTest() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700189 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
190 Mock::VerifyAndClearExpectations(&mMockClock);
191 }
192
193 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
194
195 NiceMock<ControllableClock> mMockClock;
196 static nsecs_t constexpr mDispatchGroupThreshold = 5;
197 nsecs_t const mPeriod = 1000;
198 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800199 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700200};
201
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800202TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700203 EXPECT_CALL(mMockClock, alarmIn(_, 900));
204 EXPECT_CALL(mMockClock, alarmCancel());
205 {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800206 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker,
207 mDispatchGroupThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700208 CountingCallback cb(mDispatch);
209 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
210 }
211}
212
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800213TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700214 auto intended = mPeriod - 230;
215 EXPECT_CALL(mMockClock, alarmIn(_, 900));
216
217 CountingCallback cb(mDispatch);
218 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
219 advanceToNextCallback();
220
221 ASSERT_THAT(cb.mCalls.size(), Eq(1));
222 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
223}
224
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800225TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700226 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
227 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
228
229 CountingCallback cb(mDispatch);
230 mDispatch.schedule(cb, 100, mPeriod);
231 advanceToNextCallback();
232
233 ASSERT_THAT(cb.mCalls.size(), Eq(1));
234 EXPECT_THAT(cb.mCalls[0], Eq(1150));
235}
236
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800237TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700238 auto const now = 234;
239 mMockClock.advanceBy(234);
240 auto const workDuration = 10 * mPeriod;
241 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
242 .WillOnce(Return(mPeriod * 11));
243 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
244
245 CountingCallback cb(mDispatch);
246 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
247}
248
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800249TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700250 EXPECT_CALL(mMockClock, alarmIn(_, 900));
251 EXPECT_CALL(mMockClock, alarmCancel());
252
253 CountingCallback cb(mDispatch);
254 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
255 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
256}
257
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800258TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700259 EXPECT_CALL(mMockClock, alarmIn(_, 900));
260 EXPECT_CALL(mMockClock, alarmCancel());
261
262 CountingCallback cb(mDispatch);
263 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
264 mMockClock.advanceBy(950);
265 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
266}
267
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800268TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700269 EXPECT_CALL(mMockClock, alarmIn(_, 900));
270 EXPECT_CALL(mMockClock, alarmCancel());
271
272 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
273 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
274
275 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
276 EXPECT_TRUE(cb.waitForPause());
277 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
278 cb.unpause();
279 pausingThread.join();
280}
281
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800282TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700283 EXPECT_CALL(mMockClock, alarmIn(_, 900));
284 EXPECT_CALL(mMockClock, alarmCancel());
285
286 auto resource = std::make_shared<int>(110);
287
288 PausingCallback cb(mDispatch, 50ms);
289 cb.stashResource(resource);
290 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
291
292 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
293 EXPECT_TRUE(cb.waitForPause());
294
295 cb.unregister();
296 resource.reset();
297
298 cb.unpause();
299 pausingThread.join();
300
301 EXPECT_TRUE(cb.resourcePresent());
302}
303
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800304TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700305 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
306 .Times(4)
307 .WillOnce(Return(1055))
308 .WillOnce(Return(1063))
309 .WillOnce(Return(1063))
310 .WillOnce(Return(1075));
311
312 Sequence seq;
313 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
314 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
315 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
316
317 CountingCallback cb0(mDispatch);
318 CountingCallback cb1(mDispatch);
319
320 mDispatch.schedule(cb0, 100, mPeriod);
321 mDispatch.schedule(cb1, 250, mPeriod);
322
323 advanceToNextCallback();
324 advanceToNextCallback();
325
326 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
327 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
328 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
329 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
330}
331
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800332TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700333 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
334 .Times(4)
335 .WillOnce(Return(10000))
336 .WillOnce(Return(1000))
337 .WillOnce(Return(10000))
338 .WillOnce(Return(10000));
339
340 Sequence seq;
341 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
342 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
343 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
344
345 CountingCallback cb0(mDispatch);
346 CountingCallback cb1(mDispatch);
347
348 mDispatch.schedule(cb0, 100, mPeriod * 10);
349 mDispatch.schedule(cb1, 250, mPeriod);
350 mDispatch.cancel(cb1);
351}
352
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800353TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700354 Sequence seq;
355 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
356 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
357
358 CountingCallback cb0(mDispatch);
359 CountingCallback cb1(mDispatch);
360
361 mDispatch.schedule(cb0, 400, 1000);
362 mDispatch.schedule(cb1, 200, 1000);
363 mDispatch.schedule(cb1, 300, 1000);
364 advanceToNextCallback();
365}
366
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800367TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700368 Sequence seq;
369 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
370 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
371 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
372
373 CountingCallback cb0(mDispatch);
374 CountingCallback cb1(mDispatch);
375
376 mDispatch.schedule(cb0, 400, 1000);
377 mDispatch.schedule(cb1, 200, 1000);
378 mDispatch.schedule(cb1, 500, 1000);
379 advanceToNextCallback();
380}
381
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800382TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700383 Sequence seq;
384 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
385 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
386 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
387 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
388
389 auto offset = 400;
390 auto closeOffset = offset + mDispatchGroupThreshold - 1;
391 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
392
393 CountingCallback cb0(mDispatch);
394 CountingCallback cb1(mDispatch);
395
396 mDispatch.schedule(cb0, 400, 1000);
397 mDispatch.schedule(cb1, 200, 1000);
398 mDispatch.schedule(cb1, closeOffset, 1000);
399
400 advanceToNextCallback();
401 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
402 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
403 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
404 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
405
406 mDispatch.schedule(cb0, 400, 2000);
407 mDispatch.schedule(cb1, notCloseOffset, 2000);
408 advanceToNextCallback();
409 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
410 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
411
412 advanceToNextCallback();
413 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
414 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
415}
416
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800417TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700418 EXPECT_CALL(mMockClock, alarmIn(_, 900));
419 EXPECT_CALL(mMockClock, alarmIn(_, 800));
420 EXPECT_CALL(mMockClock, alarmIn(_, 100));
421 EXPECT_CALL(mMockClock, alarmCancel());
422
423 CountingCallback cb0(mDispatch);
424 CountingCallback cb1(mDispatch);
425
426 mDispatch.schedule(cb0, 100, 1000);
427 mDispatch.schedule(cb1, 200, 1000);
428 advanceToNextCallback();
429 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
430}
431
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800432TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700433 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
434 .Times(3)
435 .WillOnce(Return(950))
436 .WillOnce(Return(1975))
437 .WillOnce(Return(2950));
438
439 CountingCallback cb(mDispatch);
440 mDispatch.schedule(cb, 100, 920);
441
442 mMockClock.advanceBy(850);
443 EXPECT_THAT(cb.mCalls.size(), Eq(1));
444
445 mDispatch.schedule(cb, 100, 1900);
446 mMockClock.advanceBy(900);
447 EXPECT_THAT(cb.mCalls.size(), Eq(1));
448 mMockClock.advanceBy(125);
449 EXPECT_THAT(cb.mCalls.size(), Eq(2));
450
451 mDispatch.schedule(cb, 100, 2900);
452 mMockClock.advanceBy(975);
453 EXPECT_THAT(cb.mCalls.size(), Eq(3));
454}
455
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800456TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700457 Sequence seq;
458 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
459 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
460
461 VSyncDispatch::CallbackToken tmp;
462 tmp = mDispatch.registerCallback([&](auto) { mDispatch.schedule(tmp, 100, 2000); }, "o.o");
463
464 mDispatch.schedule(tmp, 100, 1000);
465 advanceToNextCallback();
466}
467
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800468TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700469 VSyncDispatch::CallbackToken tmp;
470 tmp = mDispatch.registerCallback(
471 [&](auto) {
472 EXPECT_EQ(mDispatch.schedule(tmp, 400, 1000), ScheduleResult::CannotSchedule);
473 },
474 "oo");
475
476 mDispatch.schedule(tmp, 999, 1000);
477 advanceToNextCallback();
478}
479
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800480TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700481 Sequence seq;
482 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
483 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
484 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
485 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
486
487 CountingCallback cb(mDispatch);
488 mDispatch.schedule(cb, 0, 1000);
489
490 mMockClock.advanceBy(750);
491 mDispatch.schedule(cb, 50, 1000);
492
493 advanceToNextCallback();
494 mDispatch.schedule(cb, 50, 2000);
495
496 mMockClock.advanceBy(800);
497 mDispatch.schedule(cb, 100, 2000);
498}
499
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800500TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700501 Sequence seq;
502 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
503 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
504 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
505 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
506
507 CountingCallback cb0(mDispatch);
508 CountingCallback cb1(mDispatch);
509
510 mDispatch.schedule(cb0, 500, 1000);
511 mDispatch.schedule(cb1, 100, 1000);
512
513 advanceToNextCallback();
514 mDispatch.schedule(cb0, 200, 2000);
515 mDispatch.schedule(cb1, 150, 1000);
516
517 advanceToNextCallback();
518 advanceToNextCallback();
519}
520
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800521TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700522 Sequence seq;
523 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
524
525 CountingCallback cb0(mDispatch);
526 CountingCallback cb1(mDispatch);
527 mDispatch.schedule(cb0, 500, 1000);
528 mDispatch.schedule(cb1, 500, 20000);
529}
530
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800531TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700532 Sequence seq;
533 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
534 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
535 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
536
537 CountingCallback cb0(mDispatch);
538 mDispatch.schedule(cb0, 500, 1000);
539 mDispatch.cancel(cb0);
540 mDispatch.schedule(cb0, 100, 1000);
541}
542
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800543TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700544 VSyncDispatch::CallbackToken token(100);
545 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
546 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
547}
548
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800549TEST_F(VSyncDispatchTimerQueueTest, distinguishesScheduleAndReschedule) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700550 CountingCallback cb0(mDispatch);
551 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
552 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::ReScheduled);
553}
554
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800555TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700556 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
557 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
558
559 VSyncCallbackRegistration cb(
560 mDispatch, [](auto) {}, "");
561 VSyncCallbackRegistration cb1(std::move(cb));
562 cb.schedule(100, 1000);
563 cb.cancel();
564
565 cb1.schedule(500, 1000);
566 cb1.cancel();
567}
568
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800569TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700570 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
571 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
572
573 VSyncCallbackRegistration cb(
574 mDispatch, [](auto) {}, "");
575 VSyncCallbackRegistration cb1(
576 mDispatch, [](auto) {}, "");
577 cb1 = std::move(cb);
578 cb.schedule(100, 1000);
579 cb.cancel();
580
581 cb1.schedule(500, 1000);
582 cb1.cancel();
583}
584
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800585class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700586protected:
587 nsecs_t const mPeriod = 1000;
588 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
589};
590
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800591TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700592 std::string name("basicname");
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800593 VSyncDispatchTimerQueueEntry entry(name, [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700594 EXPECT_THAT(entry.name(), Eq(name));
595 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
596 EXPECT_FALSE(entry.wakeupTime());
597}
598
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800599TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
600 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700601
602 EXPECT_FALSE(entry.wakeupTime());
603 auto const wakeup = entry.schedule(100, 500, mStubTracker, 0);
604 auto const queried = entry.wakeupTime();
605 ASSERT_TRUE(queried);
606 EXPECT_THAT(*queried, Eq(wakeup));
607 EXPECT_THAT(*queried, Eq(900));
608
609 entry.disarm();
610 EXPECT_FALSE(entry.wakeupTime());
611}
612
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800613TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700614 auto const duration = 500;
615 auto const now = 8750;
616
617 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
618 .Times(1)
619 .WillOnce(Return(10000));
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800620 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700621
622 EXPECT_FALSE(entry.wakeupTime());
623 auto const wakeup = entry.schedule(500, 994, mStubTracker, now);
624 auto const queried = entry.wakeupTime();
625 ASSERT_TRUE(queried);
626 EXPECT_THAT(*queried, Eq(wakeup));
627 EXPECT_THAT(*queried, Eq(9500));
628}
629
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800630TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700631 auto callCount = 0;
632 auto calledTime = 0;
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800633 VSyncDispatchTimerQueueEntry entry("test", [&](auto time) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700634 callCount++;
635 calledTime = time;
636 });
637
638 auto const wakeup = entry.schedule(100, 500, mStubTracker, 0);
639 EXPECT_THAT(wakeup, Eq(900));
640
641 entry.callback(entry.executing());
642
643 EXPECT_THAT(callCount, Eq(1));
644 EXPECT_THAT(calledTime, Eq(mPeriod));
645 EXPECT_FALSE(entry.wakeupTime());
646 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
647 ASSERT_TRUE(lastCalledTarget);
648 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
649}
650
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800651TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700652 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
653 .Times(2)
654 .WillOnce(Return(1000))
655 .WillOnce(Return(1020));
656
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800657 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700658
659 EXPECT_FALSE(entry.wakeupTime());
660 entry.update(mStubTracker, 0);
661 EXPECT_FALSE(entry.wakeupTime());
662
663 auto const wakeup = entry.schedule(100, 500, mStubTracker, 0);
664 EXPECT_THAT(wakeup, Eq(900));
665
666 entry.update(mStubTracker, 0);
667 auto const queried = entry.wakeupTime();
668 ASSERT_TRUE(queried);
669 EXPECT_THAT(*queried, Eq(920));
670}
671
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800672TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
673 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700674 auto const wakeup = entry.schedule(100, 500, mStubTracker, 0);
675 entry.update(mStubTracker, 0);
676
677 auto const queried = entry.wakeupTime();
678 ASSERT_TRUE(queried);
679 EXPECT_THAT(*queried, Eq(wakeup));
680}
681
682} // namespace android::scheduler