blob: 6efe0a27e6c9638fbb64c1c8eefc97c625e7ce4c [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));
42
43 nsecs_t nextVSyncTime(nsecs_t timePoint) const {
44 if (timePoint % mPeriod == 0) {
45 return timePoint;
46 }
47 return (timePoint - (timePoint % mPeriod) + mPeriod);
48 }
49
50protected:
51 nsecs_t const mPeriod;
52};
53
54class ControllableClock : public TimeKeeper {
55public:
56 ControllableClock() {
57 ON_CALL(*this, alarmIn(_, _))
58 .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
59 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
60 }
61
62 MOCK_CONST_METHOD0(now, nsecs_t());
63 MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
64 MOCK_METHOD0(alarmCancel, void());
65
66 void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
67 mCallback = callback;
68 mNextCallbackTime = time + mCurrentTime;
69 }
70
71 nsecs_t fakeTime() const { return mCurrentTime; }
72
73 void advanceToNextCallback() {
74 mCurrentTime = mNextCallbackTime;
75 if (mCallback) {
76 mCallback();
77 }
78 }
79
80 void advanceBy(nsecs_t advancement) {
81 mCurrentTime += advancement;
82 if (mCurrentTime >= mNextCallbackTime && mCallback) {
83 mCallback();
84 }
85 };
86
87private:
88 std::function<void()> mCallback;
89 nsecs_t mNextCallbackTime = 0;
90 nsecs_t mCurrentTime = 0;
91};
92
93class CountingCallback {
94public:
95 CountingCallback(VSyncDispatch& dispatch)
96 : mDispatch(dispatch),
97 mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
98 std::placeholders::_1),
99 "test")) {}
100 ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
101
102 operator VSyncDispatch::CallbackToken() const { return mToken; }
103
104 void counter(nsecs_t time) { mCalls.push_back(time); }
105
106 VSyncDispatch& mDispatch;
107 VSyncDispatch::CallbackToken mToken;
108 std::vector<nsecs_t> mCalls;
109};
110
111class PausingCallback {
112public:
113 PausingCallback(VSyncDispatch& dispatch, std::chrono::milliseconds pauseAmount)
114 : mDispatch(dispatch),
115 mToken(dispatch.registerCallback(std::bind(&PausingCallback::pause, this,
116 std::placeholders::_1),
117 "test")),
118 mRegistered(true),
119 mPauseAmount(pauseAmount) {}
120 ~PausingCallback() { unregister(); }
121
122 operator VSyncDispatch::CallbackToken() const { return mToken; }
123
124 void pause(nsecs_t) {
125 std::unique_lock<std::mutex> lk(mMutex);
126 mPause = true;
127 mCv.notify_all();
128
129 mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; });
130
131 mResourcePresent = (mResource.lock() != nullptr);
132 }
133
134 bool waitForPause() {
135 std::unique_lock<std::mutex> lk(mMutex);
136 auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; });
137 return waiting;
138 }
139
140 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
141
142 bool resourcePresent() { return mResourcePresent; }
143
144 void unpause() {
145 std::unique_lock<std::mutex> lk(mMutex);
146 mPause = false;
147 mCv.notify_all();
148 }
149
150 void unregister() {
151 if (mRegistered) {
152 mDispatch.unregisterCallback(mToken);
153 mRegistered = false;
154 }
155 }
156
157 VSyncDispatch& mDispatch;
158 VSyncDispatch::CallbackToken mToken;
159 bool mRegistered = true;
160
161 std::mutex mMutex;
162 std::condition_variable mCv;
163 bool mPause = false;
164 std::weak_ptr<void> mResource;
165 bool mResourcePresent = false;
166 std::chrono::milliseconds const mPauseAmount;
167};
168
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800169class VSyncDispatchTimerQueueTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700170protected:
171 std::unique_ptr<TimeKeeper> createTimeKeeper() {
172 class TimeKeeperWrapper : public TimeKeeper {
173 public:
174 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
175 void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
176 mControllableClock.alarmIn(callback, time);
177 }
178 void alarmCancel() final { mControllableClock.alarmCancel(); }
179 nsecs_t now() const final { return mControllableClock.now(); }
180
181 private:
182 TimeKeeper& mControllableClock;
183 };
184 return std::make_unique<TimeKeeperWrapper>(mMockClock);
185 }
186
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800187 ~VSyncDispatchTimerQueueTest() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700188 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
189 Mock::VerifyAndClearExpectations(&mMockClock);
190 }
191
192 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
193
194 NiceMock<ControllableClock> mMockClock;
195 static nsecs_t constexpr mDispatchGroupThreshold = 5;
196 nsecs_t const mPeriod = 1000;
197 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800198 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700199};
200
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800201TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700202 EXPECT_CALL(mMockClock, alarmIn(_, 900));
203 EXPECT_CALL(mMockClock, alarmCancel());
204 {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800205 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker,
206 mDispatchGroupThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700207 CountingCallback cb(mDispatch);
208 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
209 }
210}
211
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800212TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700213 auto intended = mPeriod - 230;
214 EXPECT_CALL(mMockClock, alarmIn(_, 900));
215
216 CountingCallback cb(mDispatch);
217 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
218 advanceToNextCallback();
219
220 ASSERT_THAT(cb.mCalls.size(), Eq(1));
221 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
222}
223
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800224TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700225 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
226 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
227
228 CountingCallback cb(mDispatch);
229 mDispatch.schedule(cb, 100, mPeriod);
230 advanceToNextCallback();
231
232 ASSERT_THAT(cb.mCalls.size(), Eq(1));
233 EXPECT_THAT(cb.mCalls[0], Eq(1150));
234}
235
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800236TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700237 auto const now = 234;
238 mMockClock.advanceBy(234);
239 auto const workDuration = 10 * mPeriod;
240 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
241 .WillOnce(Return(mPeriod * 11));
242 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
243
244 CountingCallback cb(mDispatch);
245 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
246}
247
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800248TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700249 EXPECT_CALL(mMockClock, alarmIn(_, 900));
250 EXPECT_CALL(mMockClock, alarmCancel());
251
252 CountingCallback cb(mDispatch);
253 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
254 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
255}
256
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800257TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700258 EXPECT_CALL(mMockClock, alarmIn(_, 900));
259 EXPECT_CALL(mMockClock, alarmCancel());
260
261 CountingCallback cb(mDispatch);
262 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
263 mMockClock.advanceBy(950);
264 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
265}
266
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800267TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700268 EXPECT_CALL(mMockClock, alarmIn(_, 900));
269 EXPECT_CALL(mMockClock, alarmCancel());
270
271 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
272 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
273
274 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
275 EXPECT_TRUE(cb.waitForPause());
276 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
277 cb.unpause();
278 pausingThread.join();
279}
280
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800281TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700282 EXPECT_CALL(mMockClock, alarmIn(_, 900));
283 EXPECT_CALL(mMockClock, alarmCancel());
284
285 auto resource = std::make_shared<int>(110);
286
287 PausingCallback cb(mDispatch, 50ms);
288 cb.stashResource(resource);
289 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
290
291 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
292 EXPECT_TRUE(cb.waitForPause());
293
294 cb.unregister();
295 resource.reset();
296
297 cb.unpause();
298 pausingThread.join();
299
300 EXPECT_TRUE(cb.resourcePresent());
301}
302
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800303TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700304 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
305 .Times(4)
306 .WillOnce(Return(1055))
307 .WillOnce(Return(1063))
308 .WillOnce(Return(1063))
309 .WillOnce(Return(1075));
310
311 Sequence seq;
312 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
313 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
314 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
315
316 CountingCallback cb0(mDispatch);
317 CountingCallback cb1(mDispatch);
318
319 mDispatch.schedule(cb0, 100, mPeriod);
320 mDispatch.schedule(cb1, 250, mPeriod);
321
322 advanceToNextCallback();
323 advanceToNextCallback();
324
325 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
326 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
327 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
328 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
329}
330
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800331TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700332 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
333 .Times(4)
334 .WillOnce(Return(10000))
335 .WillOnce(Return(1000))
336 .WillOnce(Return(10000))
337 .WillOnce(Return(10000));
338
339 Sequence seq;
340 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
341 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
342 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
343
344 CountingCallback cb0(mDispatch);
345 CountingCallback cb1(mDispatch);
346
347 mDispatch.schedule(cb0, 100, mPeriod * 10);
348 mDispatch.schedule(cb1, 250, mPeriod);
349 mDispatch.cancel(cb1);
350}
351
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800352TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700353 Sequence seq;
354 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
355 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
356
357 CountingCallback cb0(mDispatch);
358 CountingCallback cb1(mDispatch);
359
360 mDispatch.schedule(cb0, 400, 1000);
361 mDispatch.schedule(cb1, 200, 1000);
362 mDispatch.schedule(cb1, 300, 1000);
363 advanceToNextCallback();
364}
365
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800366TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700367 Sequence seq;
368 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
369 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
370 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
371
372 CountingCallback cb0(mDispatch);
373 CountingCallback cb1(mDispatch);
374
375 mDispatch.schedule(cb0, 400, 1000);
376 mDispatch.schedule(cb1, 200, 1000);
377 mDispatch.schedule(cb1, 500, 1000);
378 advanceToNextCallback();
379}
380
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800381TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700382 Sequence seq;
383 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
384 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
385 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
386 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
387
388 auto offset = 400;
389 auto closeOffset = offset + mDispatchGroupThreshold - 1;
390 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
391
392 CountingCallback cb0(mDispatch);
393 CountingCallback cb1(mDispatch);
394
395 mDispatch.schedule(cb0, 400, 1000);
396 mDispatch.schedule(cb1, 200, 1000);
397 mDispatch.schedule(cb1, closeOffset, 1000);
398
399 advanceToNextCallback();
400 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
401 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
402 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
403 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
404
405 mDispatch.schedule(cb0, 400, 2000);
406 mDispatch.schedule(cb1, notCloseOffset, 2000);
407 advanceToNextCallback();
408 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
409 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
410
411 advanceToNextCallback();
412 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
413 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
414}
415
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800416TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700417 EXPECT_CALL(mMockClock, alarmIn(_, 900));
418 EXPECT_CALL(mMockClock, alarmIn(_, 800));
419 EXPECT_CALL(mMockClock, alarmIn(_, 100));
420 EXPECT_CALL(mMockClock, alarmCancel());
421
422 CountingCallback cb0(mDispatch);
423 CountingCallback cb1(mDispatch);
424
425 mDispatch.schedule(cb0, 100, 1000);
426 mDispatch.schedule(cb1, 200, 1000);
427 advanceToNextCallback();
428 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
429}
430
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800431TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700432 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
433 .Times(3)
434 .WillOnce(Return(950))
435 .WillOnce(Return(1975))
436 .WillOnce(Return(2950));
437
438 CountingCallback cb(mDispatch);
439 mDispatch.schedule(cb, 100, 920);
440
441 mMockClock.advanceBy(850);
442 EXPECT_THAT(cb.mCalls.size(), Eq(1));
443
444 mDispatch.schedule(cb, 100, 1900);
445 mMockClock.advanceBy(900);
446 EXPECT_THAT(cb.mCalls.size(), Eq(1));
447 mMockClock.advanceBy(125);
448 EXPECT_THAT(cb.mCalls.size(), Eq(2));
449
450 mDispatch.schedule(cb, 100, 2900);
451 mMockClock.advanceBy(975);
452 EXPECT_THAT(cb.mCalls.size(), Eq(3));
453}
454
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800455TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700456 Sequence seq;
457 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
458 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
459
460 VSyncDispatch::CallbackToken tmp;
461 tmp = mDispatch.registerCallback([&](auto) { mDispatch.schedule(tmp, 100, 2000); }, "o.o");
462
463 mDispatch.schedule(tmp, 100, 1000);
464 advanceToNextCallback();
465}
466
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800467TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700468 VSyncDispatch::CallbackToken tmp;
469 tmp = mDispatch.registerCallback(
470 [&](auto) {
471 EXPECT_EQ(mDispatch.schedule(tmp, 400, 1000), ScheduleResult::CannotSchedule);
472 },
473 "oo");
474
475 mDispatch.schedule(tmp, 999, 1000);
476 advanceToNextCallback();
477}
478
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800479TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700480 Sequence seq;
481 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
482 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
483 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
484 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
485
486 CountingCallback cb(mDispatch);
487 mDispatch.schedule(cb, 0, 1000);
488
489 mMockClock.advanceBy(750);
490 mDispatch.schedule(cb, 50, 1000);
491
492 advanceToNextCallback();
493 mDispatch.schedule(cb, 50, 2000);
494
495 mMockClock.advanceBy(800);
496 mDispatch.schedule(cb, 100, 2000);
497}
498
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800499TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700500 Sequence seq;
501 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
502 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
503 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
504 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
505
506 CountingCallback cb0(mDispatch);
507 CountingCallback cb1(mDispatch);
508
509 mDispatch.schedule(cb0, 500, 1000);
510 mDispatch.schedule(cb1, 100, 1000);
511
512 advanceToNextCallback();
513 mDispatch.schedule(cb0, 200, 2000);
514 mDispatch.schedule(cb1, 150, 1000);
515
516 advanceToNextCallback();
517 advanceToNextCallback();
518}
519
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800520TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700521 Sequence seq;
522 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
523
524 CountingCallback cb0(mDispatch);
525 CountingCallback cb1(mDispatch);
526 mDispatch.schedule(cb0, 500, 1000);
527 mDispatch.schedule(cb1, 500, 20000);
528}
529
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800530TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700531 Sequence seq;
532 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
533 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
534 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
535
536 CountingCallback cb0(mDispatch);
537 mDispatch.schedule(cb0, 500, 1000);
538 mDispatch.cancel(cb0);
539 mDispatch.schedule(cb0, 100, 1000);
540}
541
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800542TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700543 VSyncDispatch::CallbackToken token(100);
544 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
545 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
546}
547
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800548TEST_F(VSyncDispatchTimerQueueTest, distinguishesScheduleAndReschedule) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700549 CountingCallback cb0(mDispatch);
550 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
551 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::ReScheduled);
552}
553
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800554TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
555 CountingCallback cb0(mDispatch);
556 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
557 advanceToNextCallback();
558 EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled);
559}
560
561TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
562 Sequence seq;
563 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
564 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
565 CountingCallback cb0(mDispatch);
566 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
567 advanceToNextCallback();
568 EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled);
569}
570
571TEST_F(VSyncDispatchTimerQueueTest, cannotScheduleDoesNotAffectSchedulingState) {
572 EXPECT_CALL(mMockClock, alarmIn(_, 600));
573
574 CountingCallback cb(mDispatch);
575 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
576 advanceToNextCallback();
577 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::CannotSchedule);
578}
579
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800580TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700581 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
582 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
583
584 VSyncCallbackRegistration cb(
585 mDispatch, [](auto) {}, "");
586 VSyncCallbackRegistration cb1(std::move(cb));
587 cb.schedule(100, 1000);
588 cb.cancel();
589
590 cb1.schedule(500, 1000);
591 cb1.cancel();
592}
593
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800594TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700595 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
596 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
597
598 VSyncCallbackRegistration cb(
599 mDispatch, [](auto) {}, "");
600 VSyncCallbackRegistration cb1(
601 mDispatch, [](auto) {}, "");
602 cb1 = std::move(cb);
603 cb.schedule(100, 1000);
604 cb.cancel();
605
606 cb1.schedule(500, 1000);
607 cb1.cancel();
608}
609
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800610class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700611protected:
612 nsecs_t const mPeriod = 1000;
613 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
614};
615
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800616TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700617 std::string name("basicname");
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800618 VSyncDispatchTimerQueueEntry entry(name, [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700619 EXPECT_THAT(entry.name(), Eq(name));
620 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
621 EXPECT_FALSE(entry.wakeupTime());
622}
623
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800624TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
625 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700626
627 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800628 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
629 auto const wakeup = entry.wakeupTime();
630 ASSERT_TRUE(wakeup);
631 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700632
633 entry.disarm();
634 EXPECT_FALSE(entry.wakeupTime());
635}
636
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800637TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700638 auto const duration = 500;
639 auto const now = 8750;
640
641 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
642 .Times(1)
643 .WillOnce(Return(10000));
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800644 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700645
646 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800647 EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled));
648 auto const wakeup = entry.wakeupTime();
649 ASSERT_TRUE(wakeup);
650 EXPECT_THAT(*wakeup, Eq(9500));
Kevin DuBois305bef12019-10-09 13:23:27 -0700651}
652
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800653TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700654 auto callCount = 0;
655 auto calledTime = 0;
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800656 VSyncDispatchTimerQueueEntry entry("test", [&](auto time) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700657 callCount++;
658 calledTime = time;
659 });
660
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800661 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
662 auto const wakeup = entry.wakeupTime();
663 ASSERT_TRUE(wakeup);
664 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700665
666 entry.callback(entry.executing());
667
668 EXPECT_THAT(callCount, Eq(1));
669 EXPECT_THAT(calledTime, Eq(mPeriod));
670 EXPECT_FALSE(entry.wakeupTime());
671 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
672 ASSERT_TRUE(lastCalledTarget);
673 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
674}
675
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800676TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700677 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
678 .Times(2)
679 .WillOnce(Return(1000))
680 .WillOnce(Return(1020));
681
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800682 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois305bef12019-10-09 13:23:27 -0700683
684 EXPECT_FALSE(entry.wakeupTime());
685 entry.update(mStubTracker, 0);
686 EXPECT_FALSE(entry.wakeupTime());
687
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800688 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
689 auto wakeup = entry.wakeupTime();
690 ASSERT_TRUE(wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700691 EXPECT_THAT(wakeup, Eq(900));
692
693 entry.update(mStubTracker, 0);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800694 wakeup = entry.wakeupTime();
695 ASSERT_TRUE(wakeup);
696 EXPECT_THAT(*wakeup, Eq(920));
Kevin DuBois305bef12019-10-09 13:23:27 -0700697}
698
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800699TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
700 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800701 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700702 entry.update(mStubTracker, 0);
703
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800704 auto const wakeup = entry.wakeupTime();
705 ASSERT_TRUE(wakeup);
706 EXPECT_THAT(*wakeup, Eq(wakeup));
707}
708
709TEST_F(VSyncDispatchTimerQueueEntryTest, reportsCannotScheduleIfMissedOpportunity) {
710 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
711 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
712 entry.executing();
713 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::CannotSchedule));
714 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::CannotSchedule));
715 EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
716}
717
718TEST_F(VSyncDispatchTimerQueueEntryTest, reportsReScheduleIfStillTime) {
719 VSyncDispatchTimerQueueEntry entry("test", [](auto) {});
720 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
721 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::ReScheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700722}
723
724} // namespace android::scheduler