blob: b23159baa1e9af461b126c63749bf76edb276acc [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 DuBoisc3e9e8e2020-01-07 09:06:52 -080044 MOCK_METHOD0(resetModel, void());
Kevin DuBois305bef12019-10-09 13:23:27 -070045
46 nsecs_t nextVSyncTime(nsecs_t timePoint) const {
47 if (timePoint % mPeriod == 0) {
48 return timePoint;
49 }
50 return (timePoint - (timePoint % mPeriod) + mPeriod);
51 }
52
53protected:
54 nsecs_t const mPeriod;
55};
56
57class ControllableClock : public TimeKeeper {
58public:
59 ControllableClock() {
60 ON_CALL(*this, alarmIn(_, _))
61 .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
62 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
63 }
64
65 MOCK_CONST_METHOD0(now, nsecs_t());
66 MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
67 MOCK_METHOD0(alarmCancel, void());
68
69 void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
70 mCallback = callback;
71 mNextCallbackTime = time + mCurrentTime;
72 }
73
74 nsecs_t fakeTime() const { return mCurrentTime; }
75
76 void advanceToNextCallback() {
77 mCurrentTime = mNextCallbackTime;
78 if (mCallback) {
79 mCallback();
80 }
81 }
82
83 void advanceBy(nsecs_t advancement) {
84 mCurrentTime += advancement;
85 if (mCurrentTime >= mNextCallbackTime && mCallback) {
86 mCallback();
87 }
88 };
89
90private:
91 std::function<void()> mCallback;
92 nsecs_t mNextCallbackTime = 0;
93 nsecs_t mCurrentTime = 0;
94};
95
96class CountingCallback {
97public:
98 CountingCallback(VSyncDispatch& dispatch)
99 : mDispatch(dispatch),
100 mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
101 std::placeholders::_1),
102 "test")) {}
103 ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
104
105 operator VSyncDispatch::CallbackToken() const { return mToken; }
106
107 void counter(nsecs_t time) { mCalls.push_back(time); }
108
109 VSyncDispatch& mDispatch;
110 VSyncDispatch::CallbackToken mToken;
111 std::vector<nsecs_t> mCalls;
112};
113
114class PausingCallback {
115public:
116 PausingCallback(VSyncDispatch& dispatch, std::chrono::milliseconds pauseAmount)
117 : mDispatch(dispatch),
118 mToken(dispatch.registerCallback(std::bind(&PausingCallback::pause, this,
119 std::placeholders::_1),
120 "test")),
121 mRegistered(true),
122 mPauseAmount(pauseAmount) {}
123 ~PausingCallback() { unregister(); }
124
125 operator VSyncDispatch::CallbackToken() const { return mToken; }
126
127 void pause(nsecs_t) {
128 std::unique_lock<std::mutex> lk(mMutex);
129 mPause = true;
130 mCv.notify_all();
131
132 mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; });
133
134 mResourcePresent = (mResource.lock() != nullptr);
135 }
136
137 bool waitForPause() {
138 std::unique_lock<std::mutex> lk(mMutex);
139 auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; });
140 return waiting;
141 }
142
143 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
144
145 bool resourcePresent() { return mResourcePresent; }
146
147 void unpause() {
148 std::unique_lock<std::mutex> lk(mMutex);
149 mPause = false;
150 mCv.notify_all();
151 }
152
153 void unregister() {
154 if (mRegistered) {
155 mDispatch.unregisterCallback(mToken);
156 mRegistered = false;
157 }
158 }
159
160 VSyncDispatch& mDispatch;
161 VSyncDispatch::CallbackToken mToken;
162 bool mRegistered = true;
163
164 std::mutex mMutex;
165 std::condition_variable mCv;
166 bool mPause = false;
167 std::weak_ptr<void> mResource;
168 bool mResourcePresent = false;
169 std::chrono::milliseconds const mPauseAmount;
170};
171
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800172class VSyncDispatchTimerQueueTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700173protected:
174 std::unique_ptr<TimeKeeper> createTimeKeeper() {
175 class TimeKeeperWrapper : public TimeKeeper {
176 public:
177 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
178 void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
179 mControllableClock.alarmIn(callback, time);
180 }
181 void alarmCancel() final { mControllableClock.alarmCancel(); }
182 nsecs_t now() const final { return mControllableClock.now(); }
183
184 private:
185 TimeKeeper& mControllableClock;
186 };
187 return std::make_unique<TimeKeeperWrapper>(mMockClock);
188 }
189
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800190 ~VSyncDispatchTimerQueueTest() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700191 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
192 Mock::VerifyAndClearExpectations(&mMockClock);
193 }
194
195 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
196
197 NiceMock<ControllableClock> mMockClock;
198 static nsecs_t constexpr mDispatchGroupThreshold = 5;
199 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800200 nsecs_t const mVsyncMoveThreshold = 300;
Kevin DuBois305bef12019-10-09 13:23:27 -0700201 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800202 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
203 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700204};
205
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800206TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700207 EXPECT_CALL(mMockClock, alarmIn(_, 900));
208 EXPECT_CALL(mMockClock, alarmCancel());
209 {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800210 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
211 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700212 CountingCallback cb(mDispatch);
213 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
214 }
215}
216
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800217TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700218 auto intended = mPeriod - 230;
219 EXPECT_CALL(mMockClock, alarmIn(_, 900));
220
221 CountingCallback cb(mDispatch);
222 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
223 advanceToNextCallback();
224
225 ASSERT_THAT(cb.mCalls.size(), Eq(1));
226 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
227}
228
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800229TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700230 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
231 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
232
233 CountingCallback cb(mDispatch);
234 mDispatch.schedule(cb, 100, mPeriod);
235 advanceToNextCallback();
236
237 ASSERT_THAT(cb.mCalls.size(), Eq(1));
238 EXPECT_THAT(cb.mCalls[0], Eq(1150));
239}
240
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800241TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700242 auto const now = 234;
243 mMockClock.advanceBy(234);
244 auto const workDuration = 10 * mPeriod;
245 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
246 .WillOnce(Return(mPeriod * 11));
247 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
248
249 CountingCallback cb(mDispatch);
250 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
251}
252
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800253TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700254 EXPECT_CALL(mMockClock, alarmIn(_, 900));
255 EXPECT_CALL(mMockClock, alarmCancel());
256
257 CountingCallback cb(mDispatch);
258 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
259 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
260}
261
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800262TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700263 EXPECT_CALL(mMockClock, alarmIn(_, 900));
264 EXPECT_CALL(mMockClock, alarmCancel());
265
266 CountingCallback cb(mDispatch);
267 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
268 mMockClock.advanceBy(950);
269 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
270}
271
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800272TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700273 EXPECT_CALL(mMockClock, alarmIn(_, 900));
274 EXPECT_CALL(mMockClock, alarmCancel());
275
276 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
277 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
278
279 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
280 EXPECT_TRUE(cb.waitForPause());
281 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
282 cb.unpause();
283 pausingThread.join();
284}
285
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800286TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700287 EXPECT_CALL(mMockClock, alarmIn(_, 900));
288 EXPECT_CALL(mMockClock, alarmCancel());
289
290 auto resource = std::make_shared<int>(110);
291
292 PausingCallback cb(mDispatch, 50ms);
293 cb.stashResource(resource);
294 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
295
296 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
297 EXPECT_TRUE(cb.waitForPause());
298
299 cb.unregister();
300 resource.reset();
301
302 cb.unpause();
303 pausingThread.join();
304
305 EXPECT_TRUE(cb.resourcePresent());
306}
307
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800308TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700309 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
310 .Times(4)
311 .WillOnce(Return(1055))
312 .WillOnce(Return(1063))
313 .WillOnce(Return(1063))
314 .WillOnce(Return(1075));
315
316 Sequence seq;
317 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
318 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
319 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
320
321 CountingCallback cb0(mDispatch);
322 CountingCallback cb1(mDispatch);
323
324 mDispatch.schedule(cb0, 100, mPeriod);
325 mDispatch.schedule(cb1, 250, mPeriod);
326
327 advanceToNextCallback();
328 advanceToNextCallback();
329
330 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
331 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
332 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
333 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
334}
335
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800336TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700337 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
338 .Times(4)
339 .WillOnce(Return(10000))
340 .WillOnce(Return(1000))
341 .WillOnce(Return(10000))
342 .WillOnce(Return(10000));
343
344 Sequence seq;
345 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
346 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
347 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
348
349 CountingCallback cb0(mDispatch);
350 CountingCallback cb1(mDispatch);
351
352 mDispatch.schedule(cb0, 100, mPeriod * 10);
353 mDispatch.schedule(cb1, 250, mPeriod);
354 mDispatch.cancel(cb1);
355}
356
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800357TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700358 Sequence seq;
359 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
360 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
361
362 CountingCallback cb0(mDispatch);
363 CountingCallback cb1(mDispatch);
364
365 mDispatch.schedule(cb0, 400, 1000);
366 mDispatch.schedule(cb1, 200, 1000);
367 mDispatch.schedule(cb1, 300, 1000);
368 advanceToNextCallback();
369}
370
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800371TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700372 Sequence seq;
373 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
374 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
375 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
376
377 CountingCallback cb0(mDispatch);
378 CountingCallback cb1(mDispatch);
379
380 mDispatch.schedule(cb0, 400, 1000);
381 mDispatch.schedule(cb1, 200, 1000);
382 mDispatch.schedule(cb1, 500, 1000);
383 advanceToNextCallback();
384}
385
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800386TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700387 Sequence seq;
388 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
389 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
390 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
391 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
392
393 auto offset = 400;
394 auto closeOffset = offset + mDispatchGroupThreshold - 1;
395 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
396
397 CountingCallback cb0(mDispatch);
398 CountingCallback cb1(mDispatch);
399
400 mDispatch.schedule(cb0, 400, 1000);
401 mDispatch.schedule(cb1, 200, 1000);
402 mDispatch.schedule(cb1, closeOffset, 1000);
403
404 advanceToNextCallback();
405 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
406 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
407 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
408 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
409
410 mDispatch.schedule(cb0, 400, 2000);
411 mDispatch.schedule(cb1, notCloseOffset, 2000);
412 advanceToNextCallback();
413 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
414 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
415
416 advanceToNextCallback();
417 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
418 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
419}
420
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800421TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700422 EXPECT_CALL(mMockClock, alarmIn(_, 900));
423 EXPECT_CALL(mMockClock, alarmIn(_, 800));
424 EXPECT_CALL(mMockClock, alarmIn(_, 100));
425 EXPECT_CALL(mMockClock, alarmCancel());
426
427 CountingCallback cb0(mDispatch);
428 CountingCallback cb1(mDispatch);
429
430 mDispatch.schedule(cb0, 100, 1000);
431 mDispatch.schedule(cb1, 200, 1000);
432 advanceToNextCallback();
433 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
434}
435
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800436TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700437 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
438 .Times(3)
439 .WillOnce(Return(950))
440 .WillOnce(Return(1975))
441 .WillOnce(Return(2950));
442
443 CountingCallback cb(mDispatch);
444 mDispatch.schedule(cb, 100, 920);
445
446 mMockClock.advanceBy(850);
447 EXPECT_THAT(cb.mCalls.size(), Eq(1));
448
449 mDispatch.schedule(cb, 100, 1900);
450 mMockClock.advanceBy(900);
451 EXPECT_THAT(cb.mCalls.size(), Eq(1));
452 mMockClock.advanceBy(125);
453 EXPECT_THAT(cb.mCalls.size(), Eq(2));
454
455 mDispatch.schedule(cb, 100, 2900);
456 mMockClock.advanceBy(975);
457 EXPECT_THAT(cb.mCalls.size(), Eq(3));
458}
459
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800460TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700461 Sequence seq;
462 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
463 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
464
465 VSyncDispatch::CallbackToken tmp;
466 tmp = mDispatch.registerCallback([&](auto) { mDispatch.schedule(tmp, 100, 2000); }, "o.o");
467
468 mDispatch.schedule(tmp, 100, 1000);
469 advanceToNextCallback();
470}
471
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800472TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700473 VSyncDispatch::CallbackToken tmp;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800474 std::optional<nsecs_t> lastTarget;
Kevin DuBois305bef12019-10-09 13:23:27 -0700475 tmp = mDispatch.registerCallback(
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800476 [&](auto timestamp) {
477 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp - mVsyncMoveThreshold),
478 ScheduleResult::Scheduled);
479 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp), ScheduleResult::Scheduled);
480 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp + mVsyncMoveThreshold),
481 ScheduleResult::Scheduled);
482 lastTarget = timestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700483 },
484 "oo");
485
486 mDispatch.schedule(tmp, 999, 1000);
487 advanceToNextCallback();
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800488 EXPECT_THAT(lastTarget, Eq(1000));
489
490 advanceToNextCallback();
491 EXPECT_THAT(lastTarget, Eq(2000));
Kevin DuBois305bef12019-10-09 13:23:27 -0700492}
493
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800494TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700495 Sequence seq;
496 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
497 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
498 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
499 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
500
501 CountingCallback cb(mDispatch);
502 mDispatch.schedule(cb, 0, 1000);
503
504 mMockClock.advanceBy(750);
505 mDispatch.schedule(cb, 50, 1000);
506
507 advanceToNextCallback();
508 mDispatch.schedule(cb, 50, 2000);
509
510 mMockClock.advanceBy(800);
511 mDispatch.schedule(cb, 100, 2000);
512}
513
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800514TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700515 Sequence seq;
516 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
517 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
518 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
519 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
520
521 CountingCallback cb0(mDispatch);
522 CountingCallback cb1(mDispatch);
523
524 mDispatch.schedule(cb0, 500, 1000);
525 mDispatch.schedule(cb1, 100, 1000);
526
527 advanceToNextCallback();
528 mDispatch.schedule(cb0, 200, 2000);
529 mDispatch.schedule(cb1, 150, 1000);
530
531 advanceToNextCallback();
532 advanceToNextCallback();
533}
534
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800535TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700536 Sequence seq;
537 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
538
539 CountingCallback cb0(mDispatch);
540 CountingCallback cb1(mDispatch);
541 mDispatch.schedule(cb0, 500, 1000);
542 mDispatch.schedule(cb1, 500, 20000);
543}
544
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800545TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700546 Sequence seq;
547 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
548 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
549 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
550
551 CountingCallback cb0(mDispatch);
552 mDispatch.schedule(cb0, 500, 1000);
553 mDispatch.cancel(cb0);
554 mDispatch.schedule(cb0, 100, 1000);
555}
556
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800557TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700558 VSyncDispatch::CallbackToken token(100);
559 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
560 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
561}
562
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800563TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700564 CountingCallback cb0(mDispatch);
565 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800566 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::Scheduled);
567}
568
569// b/1450138150
570TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
571 EXPECT_CALL(mMockClock, alarmIn(_, 500));
572 CountingCallback cb(mDispatch);
573 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
574 mMockClock.advanceBy(400);
575
576 EXPECT_EQ(mDispatch.schedule(cb, 800, 1000), ScheduleResult::Scheduled);
577 advanceToNextCallback();
578 ASSERT_THAT(cb.mCalls.size(), Eq(1));
579}
580
581TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedule) {
582 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
583 .Times(2)
584 .WillOnce(Return(1000))
585 .WillOnce(Return(1002));
586 CountingCallback cb(mDispatch);
587 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
588 mMockClock.advanceBy(400);
589 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBois305bef12019-10-09 13:23:27 -0700590}
591
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800592TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
593 CountingCallback cb0(mDispatch);
594 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
595 advanceToNextCallback();
596 EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled);
597}
598
599TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
600 Sequence seq;
601 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
602 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
603 CountingCallback cb0(mDispatch);
604 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
605 advanceToNextCallback();
606 EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled);
607}
608
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800609TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800610 EXPECT_CALL(mMockClock, alarmIn(_, 600));
611
612 CountingCallback cb(mDispatch);
613 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800614
615 EXPECT_EQ(mDispatch.schedule(cb, 1400, 1000), ScheduleResult::Scheduled);
616
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800617 advanceToNextCallback();
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800618}
619
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800620TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700621 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
622 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
623
624 VSyncCallbackRegistration cb(
625 mDispatch, [](auto) {}, "");
626 VSyncCallbackRegistration cb1(std::move(cb));
627 cb.schedule(100, 1000);
628 cb.cancel();
629
630 cb1.schedule(500, 1000);
631 cb1.cancel();
632}
633
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800634TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700635 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
636 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
637
638 VSyncCallbackRegistration cb(
639 mDispatch, [](auto) {}, "");
640 VSyncCallbackRegistration cb1(
641 mDispatch, [](auto) {}, "");
642 cb1 = std::move(cb);
643 cb.schedule(100, 1000);
644 cb.cancel();
645
646 cb1.schedule(500, 1000);
647 cb1.cancel();
648}
649
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800650class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700651protected:
652 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800653 nsecs_t const mVsyncMoveThreshold = 200;
Kevin DuBois305bef12019-10-09 13:23:27 -0700654 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
655};
656
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800657TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700658 std::string name("basicname");
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800659 VSyncDispatchTimerQueueEntry entry(
660 name, [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700661 EXPECT_THAT(entry.name(), Eq(name));
662 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
663 EXPECT_FALSE(entry.wakeupTime());
664}
665
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800666TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800667 VSyncDispatchTimerQueueEntry entry(
668 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700669
670 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800671 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
672 auto const wakeup = entry.wakeupTime();
673 ASSERT_TRUE(wakeup);
674 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700675
676 entry.disarm();
677 EXPECT_FALSE(entry.wakeupTime());
678}
679
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800680TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700681 auto const duration = 500;
682 auto const now = 8750;
683
684 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
685 .Times(1)
686 .WillOnce(Return(10000));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800687 VSyncDispatchTimerQueueEntry entry(
688 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700689
690 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800691 EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled));
692 auto const wakeup = entry.wakeupTime();
693 ASSERT_TRUE(wakeup);
694 EXPECT_THAT(*wakeup, Eq(9500));
Kevin DuBois305bef12019-10-09 13:23:27 -0700695}
696
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800697TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700698 auto callCount = 0;
699 auto calledTime = 0;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800700 VSyncDispatchTimerQueueEntry entry(
701 "test",
702 [&](auto time) {
703 callCount++;
704 calledTime = time;
705 },
706 mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700707
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800708 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
709 auto const wakeup = entry.wakeupTime();
710 ASSERT_TRUE(wakeup);
711 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700712
713 entry.callback(entry.executing());
714
715 EXPECT_THAT(callCount, Eq(1));
716 EXPECT_THAT(calledTime, Eq(mPeriod));
717 EXPECT_FALSE(entry.wakeupTime());
718 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
719 ASSERT_TRUE(lastCalledTarget);
720 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
721}
722
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800723TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700724 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
725 .Times(2)
726 .WillOnce(Return(1000))
727 .WillOnce(Return(1020));
728
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800729 VSyncDispatchTimerQueueEntry entry(
730 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700731
732 EXPECT_FALSE(entry.wakeupTime());
733 entry.update(mStubTracker, 0);
734 EXPECT_FALSE(entry.wakeupTime());
735
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800736 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
737 auto wakeup = entry.wakeupTime();
738 ASSERT_TRUE(wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700739 EXPECT_THAT(wakeup, Eq(900));
740
741 entry.update(mStubTracker, 0);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800742 wakeup = entry.wakeupTime();
743 ASSERT_TRUE(wakeup);
744 EXPECT_THAT(*wakeup, Eq(920));
Kevin DuBois305bef12019-10-09 13:23:27 -0700745}
746
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800747TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800748 VSyncDispatchTimerQueueEntry entry(
749 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800750 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700751 entry.update(mStubTracker, 0);
752
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800753 auto const wakeup = entry.wakeupTime();
754 ASSERT_TRUE(wakeup);
755 EXPECT_THAT(*wakeup, Eq(wakeup));
756}
757
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800758TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) {
759 VSyncDispatchTimerQueueEntry entry(
760 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800761 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800762 entry.executing(); // 1000 is executing
763 // had 1000 not been executing, this could have been scheduled for time 800.
764 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
765 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
766
767 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
768 EXPECT_THAT(*entry.wakeupTime(), Eq(1950));
769
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800770 EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800771 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800772}
773
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800774TEST_F(VSyncDispatchTimerQueueEntryTest,
775 willRequestNextEstimateWhenSnappingToNextTargettableVSync) {
776 VSyncDispatchTimerQueueEntry entry(
777 "test", [](auto) {}, mVsyncMoveThreshold);
778
779 Sequence seq;
780 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
781 .InSequence(seq)
782 .WillOnce(Return(1000));
783 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
784 .InSequence(seq)
785 .WillOnce(Return(1000));
786 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000 + mVsyncMoveThreshold))
787 .InSequence(seq)
788 .WillOnce(Return(2000));
789
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800790 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800791
792 entry.executing(); // 1000 is executing
793
794 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
795}
796
797TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) {
798 VSyncDispatchTimerQueueEntry entry(
799 "test", [](auto) {}, mVsyncMoveThreshold);
800 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
801 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
802 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
803 EXPECT_THAT(entry.schedule(1200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700804}
805
806} // namespace android::scheduler