blob: 82919abe03d35f489d22a23f95deacbf1c0f64ec [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
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Kevin DuBois305bef12019-10-09 13:23:27 -070021#undef LOG_TAG
22#define LOG_TAG "LibSurfaceFlingerUnittests"
23#define LOG_NDEBUG 0
24
25#include "Scheduler/TimeKeeper.h"
Kevin DuBoise4f27a82019-11-12 11:41:41 -080026#include "Scheduler/VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070027#include "Scheduler/VSyncTracker.h"
28
29#include <gmock/gmock.h>
30#include <gtest/gtest.h>
31#include <thread>
32
33using namespace testing;
34using namespace std::literals;
35namespace android::scheduler {
36
37class MockVSyncTracker : public VSyncTracker {
38public:
39 MockVSyncTracker(nsecs_t period) : mPeriod{period} {
40 ON_CALL(*this, nextAnticipatedVSyncTimeFrom(_))
41 .WillByDefault(Invoke(this, &MockVSyncTracker::nextVSyncTime));
42 }
43
44 MOCK_METHOD1(addVsyncTimestamp, void(nsecs_t));
45 MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t));
Kevin DuBois2fd3cea2019-11-14 08:52:45 -080046 MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
Kevin DuBoisee2ad9f2019-11-21 11:10:57 -080047 MOCK_METHOD1(setPeriod, void(nsecs_t));
Kevin DuBois305bef12019-10-09 13:23:27 -070048
49 nsecs_t nextVSyncTime(nsecs_t timePoint) const {
50 if (timePoint % mPeriod == 0) {
51 return timePoint;
52 }
53 return (timePoint - (timePoint % mPeriod) + mPeriod);
54 }
55
56protected:
57 nsecs_t const mPeriod;
58};
59
60class ControllableClock : public TimeKeeper {
61public:
62 ControllableClock() {
63 ON_CALL(*this, alarmIn(_, _))
64 .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
65 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
66 }
67
68 MOCK_CONST_METHOD0(now, nsecs_t());
69 MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
70 MOCK_METHOD0(alarmCancel, void());
71
72 void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
73 mCallback = callback;
74 mNextCallbackTime = time + mCurrentTime;
75 }
76
77 nsecs_t fakeTime() const { return mCurrentTime; }
78
79 void advanceToNextCallback() {
80 mCurrentTime = mNextCallbackTime;
81 if (mCallback) {
82 mCallback();
83 }
84 }
85
86 void advanceBy(nsecs_t advancement) {
87 mCurrentTime += advancement;
88 if (mCurrentTime >= mNextCallbackTime && mCallback) {
89 mCallback();
90 }
91 };
92
93private:
94 std::function<void()> mCallback;
95 nsecs_t mNextCallbackTime = 0;
96 nsecs_t mCurrentTime = 0;
97};
98
99class CountingCallback {
100public:
101 CountingCallback(VSyncDispatch& dispatch)
102 : mDispatch(dispatch),
103 mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
104 std::placeholders::_1),
105 "test")) {}
106 ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
107
108 operator VSyncDispatch::CallbackToken() const { return mToken; }
109
110 void counter(nsecs_t time) { mCalls.push_back(time); }
111
112 VSyncDispatch& mDispatch;
113 VSyncDispatch::CallbackToken mToken;
114 std::vector<nsecs_t> mCalls;
115};
116
117class PausingCallback {
118public:
119 PausingCallback(VSyncDispatch& dispatch, std::chrono::milliseconds pauseAmount)
120 : mDispatch(dispatch),
121 mToken(dispatch.registerCallback(std::bind(&PausingCallback::pause, this,
122 std::placeholders::_1),
123 "test")),
124 mRegistered(true),
125 mPauseAmount(pauseAmount) {}
126 ~PausingCallback() { unregister(); }
127
128 operator VSyncDispatch::CallbackToken() const { return mToken; }
129
130 void pause(nsecs_t) {
131 std::unique_lock<std::mutex> lk(mMutex);
132 mPause = true;
133 mCv.notify_all();
134
135 mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; });
136
137 mResourcePresent = (mResource.lock() != nullptr);
138 }
139
140 bool waitForPause() {
141 std::unique_lock<std::mutex> lk(mMutex);
142 auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; });
143 return waiting;
144 }
145
146 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
147
148 bool resourcePresent() { return mResourcePresent; }
149
150 void unpause() {
151 std::unique_lock<std::mutex> lk(mMutex);
152 mPause = false;
153 mCv.notify_all();
154 }
155
156 void unregister() {
157 if (mRegistered) {
158 mDispatch.unregisterCallback(mToken);
159 mRegistered = false;
160 }
161 }
162
163 VSyncDispatch& mDispatch;
164 VSyncDispatch::CallbackToken mToken;
165 bool mRegistered = true;
166
167 std::mutex mMutex;
168 std::condition_variable mCv;
169 bool mPause = false;
170 std::weak_ptr<void> mResource;
171 bool mResourcePresent = false;
172 std::chrono::milliseconds const mPauseAmount;
173};
174
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800175class VSyncDispatchTimerQueueTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700176protected:
177 std::unique_ptr<TimeKeeper> createTimeKeeper() {
178 class TimeKeeperWrapper : public TimeKeeper {
179 public:
180 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
181 void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
182 mControllableClock.alarmIn(callback, time);
183 }
184 void alarmCancel() final { mControllableClock.alarmCancel(); }
185 nsecs_t now() const final { return mControllableClock.now(); }
186
187 private:
188 TimeKeeper& mControllableClock;
189 };
190 return std::make_unique<TimeKeeperWrapper>(mMockClock);
191 }
192
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800193 ~VSyncDispatchTimerQueueTest() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700194 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
195 Mock::VerifyAndClearExpectations(&mMockClock);
196 }
197
198 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
199
200 NiceMock<ControllableClock> mMockClock;
201 static nsecs_t constexpr mDispatchGroupThreshold = 5;
202 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800203 nsecs_t const mVsyncMoveThreshold = 300;
Kevin DuBois305bef12019-10-09 13:23:27 -0700204 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800205 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
206 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700207};
208
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800209TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700210 EXPECT_CALL(mMockClock, alarmIn(_, 900));
211 EXPECT_CALL(mMockClock, alarmCancel());
212 {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800213 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
214 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700215 CountingCallback cb(mDispatch);
216 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
217 }
218}
219
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800220TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700221 auto intended = mPeriod - 230;
222 EXPECT_CALL(mMockClock, alarmIn(_, 900));
223
224 CountingCallback cb(mDispatch);
225 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
226 advanceToNextCallback();
227
228 ASSERT_THAT(cb.mCalls.size(), Eq(1));
229 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
230}
231
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800232TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700233 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
234 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
235
236 CountingCallback cb(mDispatch);
237 mDispatch.schedule(cb, 100, mPeriod);
238 advanceToNextCallback();
239
240 ASSERT_THAT(cb.mCalls.size(), Eq(1));
241 EXPECT_THAT(cb.mCalls[0], Eq(1150));
242}
243
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800244TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700245 auto const now = 234;
246 mMockClock.advanceBy(234);
247 auto const workDuration = 10 * mPeriod;
248 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
249 .WillOnce(Return(mPeriod * 11));
250 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
251
252 CountingCallback cb(mDispatch);
253 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
254}
255
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800256TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700257 EXPECT_CALL(mMockClock, alarmIn(_, 900));
258 EXPECT_CALL(mMockClock, alarmCancel());
259
260 CountingCallback cb(mDispatch);
261 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
262 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
263}
264
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800265TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700266 EXPECT_CALL(mMockClock, alarmIn(_, 900));
267 EXPECT_CALL(mMockClock, alarmCancel());
268
269 CountingCallback cb(mDispatch);
270 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
271 mMockClock.advanceBy(950);
272 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
273}
274
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800275TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700276 EXPECT_CALL(mMockClock, alarmIn(_, 900));
277 EXPECT_CALL(mMockClock, alarmCancel());
278
279 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
280 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
281
282 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
283 EXPECT_TRUE(cb.waitForPause());
284 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
285 cb.unpause();
286 pausingThread.join();
287}
288
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800289TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700290 EXPECT_CALL(mMockClock, alarmIn(_, 900));
291 EXPECT_CALL(mMockClock, alarmCancel());
292
293 auto resource = std::make_shared<int>(110);
294
295 PausingCallback cb(mDispatch, 50ms);
296 cb.stashResource(resource);
297 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
298
299 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
300 EXPECT_TRUE(cb.waitForPause());
301
302 cb.unregister();
303 resource.reset();
304
305 cb.unpause();
306 pausingThread.join();
307
308 EXPECT_TRUE(cb.resourcePresent());
309}
310
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800311TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700312 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
313 .Times(4)
314 .WillOnce(Return(1055))
315 .WillOnce(Return(1063))
316 .WillOnce(Return(1063))
317 .WillOnce(Return(1075));
318
319 Sequence seq;
320 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
321 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
322 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
323
324 CountingCallback cb0(mDispatch);
325 CountingCallback cb1(mDispatch);
326
327 mDispatch.schedule(cb0, 100, mPeriod);
328 mDispatch.schedule(cb1, 250, mPeriod);
329
330 advanceToNextCallback();
331 advanceToNextCallback();
332
333 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
334 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
335 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
336 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
337}
338
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800339TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700340 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
341 .Times(4)
342 .WillOnce(Return(10000))
343 .WillOnce(Return(1000))
344 .WillOnce(Return(10000))
345 .WillOnce(Return(10000));
346
347 Sequence seq;
348 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
349 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
350 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
351
352 CountingCallback cb0(mDispatch);
353 CountingCallback cb1(mDispatch);
354
355 mDispatch.schedule(cb0, 100, mPeriod * 10);
356 mDispatch.schedule(cb1, 250, mPeriod);
357 mDispatch.cancel(cb1);
358}
359
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800360TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700361 Sequence seq;
362 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
363 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
364
365 CountingCallback cb0(mDispatch);
366 CountingCallback cb1(mDispatch);
367
368 mDispatch.schedule(cb0, 400, 1000);
369 mDispatch.schedule(cb1, 200, 1000);
370 mDispatch.schedule(cb1, 300, 1000);
371 advanceToNextCallback();
372}
373
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800374TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700375 Sequence seq;
376 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
377 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
378 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
379
380 CountingCallback cb0(mDispatch);
381 CountingCallback cb1(mDispatch);
382
383 mDispatch.schedule(cb0, 400, 1000);
384 mDispatch.schedule(cb1, 200, 1000);
385 mDispatch.schedule(cb1, 500, 1000);
386 advanceToNextCallback();
387}
388
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800389TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700390 Sequence seq;
391 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
392 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
393 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
394 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
395
396 auto offset = 400;
397 auto closeOffset = offset + mDispatchGroupThreshold - 1;
398 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
399
400 CountingCallback cb0(mDispatch);
401 CountingCallback cb1(mDispatch);
402
403 mDispatch.schedule(cb0, 400, 1000);
404 mDispatch.schedule(cb1, 200, 1000);
405 mDispatch.schedule(cb1, closeOffset, 1000);
406
407 advanceToNextCallback();
408 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
409 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
410 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
411 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
412
413 mDispatch.schedule(cb0, 400, 2000);
414 mDispatch.schedule(cb1, notCloseOffset, 2000);
415 advanceToNextCallback();
416 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
417 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
418
419 advanceToNextCallback();
420 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
421 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
422}
423
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800424TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700425 EXPECT_CALL(mMockClock, alarmIn(_, 900));
426 EXPECT_CALL(mMockClock, alarmIn(_, 800));
427 EXPECT_CALL(mMockClock, alarmIn(_, 100));
428 EXPECT_CALL(mMockClock, alarmCancel());
429
430 CountingCallback cb0(mDispatch);
431 CountingCallback cb1(mDispatch);
432
433 mDispatch.schedule(cb0, 100, 1000);
434 mDispatch.schedule(cb1, 200, 1000);
435 advanceToNextCallback();
436 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
437}
438
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800439TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700440 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
441 .Times(3)
442 .WillOnce(Return(950))
443 .WillOnce(Return(1975))
444 .WillOnce(Return(2950));
445
446 CountingCallback cb(mDispatch);
447 mDispatch.schedule(cb, 100, 920);
448
449 mMockClock.advanceBy(850);
450 EXPECT_THAT(cb.mCalls.size(), Eq(1));
451
452 mDispatch.schedule(cb, 100, 1900);
453 mMockClock.advanceBy(900);
454 EXPECT_THAT(cb.mCalls.size(), Eq(1));
455 mMockClock.advanceBy(125);
456 EXPECT_THAT(cb.mCalls.size(), Eq(2));
457
458 mDispatch.schedule(cb, 100, 2900);
459 mMockClock.advanceBy(975);
460 EXPECT_THAT(cb.mCalls.size(), Eq(3));
461}
462
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800463TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700464 Sequence seq;
465 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
466 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
467
468 VSyncDispatch::CallbackToken tmp;
469 tmp = mDispatch.registerCallback([&](auto) { mDispatch.schedule(tmp, 100, 2000); }, "o.o");
470
471 mDispatch.schedule(tmp, 100, 1000);
472 advanceToNextCallback();
473}
474
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800475TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700476 VSyncDispatch::CallbackToken tmp;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800477 std::optional<nsecs_t> lastTarget;
Kevin DuBois305bef12019-10-09 13:23:27 -0700478 tmp = mDispatch.registerCallback(
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800479 [&](auto timestamp) {
480 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp - mVsyncMoveThreshold),
481 ScheduleResult::Scheduled);
482 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp), ScheduleResult::Scheduled);
483 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp + mVsyncMoveThreshold),
484 ScheduleResult::Scheduled);
485 lastTarget = timestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700486 },
487 "oo");
488
489 mDispatch.schedule(tmp, 999, 1000);
490 advanceToNextCallback();
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800491 EXPECT_THAT(lastTarget, Eq(1000));
492
493 advanceToNextCallback();
494 EXPECT_THAT(lastTarget, Eq(2000));
Kevin DuBois305bef12019-10-09 13:23:27 -0700495}
496
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800497TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700498 Sequence seq;
499 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
500 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
501 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
502 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
503
504 CountingCallback cb(mDispatch);
505 mDispatch.schedule(cb, 0, 1000);
506
507 mMockClock.advanceBy(750);
508 mDispatch.schedule(cb, 50, 1000);
509
510 advanceToNextCallback();
511 mDispatch.schedule(cb, 50, 2000);
512
513 mMockClock.advanceBy(800);
514 mDispatch.schedule(cb, 100, 2000);
515}
516
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800517TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700518 Sequence seq;
519 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
520 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
521 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
522 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
523
524 CountingCallback cb0(mDispatch);
525 CountingCallback cb1(mDispatch);
526
527 mDispatch.schedule(cb0, 500, 1000);
528 mDispatch.schedule(cb1, 100, 1000);
529
530 advanceToNextCallback();
531 mDispatch.schedule(cb0, 200, 2000);
532 mDispatch.schedule(cb1, 150, 1000);
533
534 advanceToNextCallback();
535 advanceToNextCallback();
536}
537
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800538TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700539 Sequence seq;
540 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
541
542 CountingCallback cb0(mDispatch);
543 CountingCallback cb1(mDispatch);
544 mDispatch.schedule(cb0, 500, 1000);
545 mDispatch.schedule(cb1, 500, 20000);
546}
547
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800548TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700549 Sequence seq;
550 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
551 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
552 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
553
554 CountingCallback cb0(mDispatch);
555 mDispatch.schedule(cb0, 500, 1000);
556 mDispatch.cancel(cb0);
557 mDispatch.schedule(cb0, 100, 1000);
558}
559
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800560TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700561 VSyncDispatch::CallbackToken token(100);
562 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
563 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
564}
565
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800566TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700567 CountingCallback cb0(mDispatch);
568 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800569 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::Scheduled);
570}
571
572// b/1450138150
573TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
574 EXPECT_CALL(mMockClock, alarmIn(_, 500));
575 CountingCallback cb(mDispatch);
576 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
577 mMockClock.advanceBy(400);
578
579 EXPECT_EQ(mDispatch.schedule(cb, 800, 1000), ScheduleResult::Scheduled);
580 advanceToNextCallback();
581 ASSERT_THAT(cb.mCalls.size(), Eq(1));
582}
583
584TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedule) {
585 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
586 .Times(2)
587 .WillOnce(Return(1000))
588 .WillOnce(Return(1002));
589 CountingCallback cb(mDispatch);
590 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
591 mMockClock.advanceBy(400);
592 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBois305bef12019-10-09 13:23:27 -0700593}
594
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800595TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
596 CountingCallback cb0(mDispatch);
597 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
598 advanceToNextCallback();
599 EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled);
600}
601
602TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
603 Sequence seq;
604 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
605 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
606 CountingCallback cb0(mDispatch);
607 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
608 advanceToNextCallback();
609 EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled);
610}
611
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800612TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800613 EXPECT_CALL(mMockClock, alarmIn(_, 600));
614
615 CountingCallback cb(mDispatch);
616 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800617
618 EXPECT_EQ(mDispatch.schedule(cb, 1400, 1000), ScheduleResult::Scheduled);
619
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800620 advanceToNextCallback();
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800621}
622
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800623TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700624 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
625 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
626
627 VSyncCallbackRegistration cb(
628 mDispatch, [](auto) {}, "");
629 VSyncCallbackRegistration cb1(std::move(cb));
630 cb.schedule(100, 1000);
631 cb.cancel();
632
633 cb1.schedule(500, 1000);
634 cb1.cancel();
635}
636
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800637TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700638 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
639 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
640
641 VSyncCallbackRegistration cb(
642 mDispatch, [](auto) {}, "");
643 VSyncCallbackRegistration cb1(
644 mDispatch, [](auto) {}, "");
645 cb1 = std::move(cb);
646 cb.schedule(100, 1000);
647 cb.cancel();
648
649 cb1.schedule(500, 1000);
650 cb1.cancel();
651}
652
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800653class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700654protected:
655 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800656 nsecs_t const mVsyncMoveThreshold = 200;
Kevin DuBois305bef12019-10-09 13:23:27 -0700657 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
658};
659
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800660TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700661 std::string name("basicname");
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800662 VSyncDispatchTimerQueueEntry entry(
663 name, [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700664 EXPECT_THAT(entry.name(), Eq(name));
665 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
666 EXPECT_FALSE(entry.wakeupTime());
667}
668
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800669TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800670 VSyncDispatchTimerQueueEntry entry(
671 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700672
673 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800674 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
675 auto const wakeup = entry.wakeupTime();
676 ASSERT_TRUE(wakeup);
677 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700678
679 entry.disarm();
680 EXPECT_FALSE(entry.wakeupTime());
681}
682
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800683TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700684 auto const duration = 500;
685 auto const now = 8750;
686
687 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
688 .Times(1)
689 .WillOnce(Return(10000));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800690 VSyncDispatchTimerQueueEntry entry(
691 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700692
693 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800694 EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled));
695 auto const wakeup = entry.wakeupTime();
696 ASSERT_TRUE(wakeup);
697 EXPECT_THAT(*wakeup, Eq(9500));
Kevin DuBois305bef12019-10-09 13:23:27 -0700698}
699
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800700TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700701 auto callCount = 0;
702 auto calledTime = 0;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800703 VSyncDispatchTimerQueueEntry entry(
704 "test",
705 [&](auto time) {
706 callCount++;
707 calledTime = time;
708 },
709 mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700710
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800711 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
712 auto const wakeup = entry.wakeupTime();
713 ASSERT_TRUE(wakeup);
714 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700715
716 entry.callback(entry.executing());
717
718 EXPECT_THAT(callCount, Eq(1));
719 EXPECT_THAT(calledTime, Eq(mPeriod));
720 EXPECT_FALSE(entry.wakeupTime());
721 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
722 ASSERT_TRUE(lastCalledTarget);
723 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
724}
725
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800726TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700727 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
728 .Times(2)
729 .WillOnce(Return(1000))
730 .WillOnce(Return(1020));
731
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800732 VSyncDispatchTimerQueueEntry entry(
733 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700734
735 EXPECT_FALSE(entry.wakeupTime());
736 entry.update(mStubTracker, 0);
737 EXPECT_FALSE(entry.wakeupTime());
738
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800739 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
740 auto wakeup = entry.wakeupTime();
741 ASSERT_TRUE(wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700742 EXPECT_THAT(wakeup, Eq(900));
743
744 entry.update(mStubTracker, 0);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800745 wakeup = entry.wakeupTime();
746 ASSERT_TRUE(wakeup);
747 EXPECT_THAT(*wakeup, Eq(920));
Kevin DuBois305bef12019-10-09 13:23:27 -0700748}
749
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800750TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800751 VSyncDispatchTimerQueueEntry entry(
752 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800753 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700754 entry.update(mStubTracker, 0);
755
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800756 auto const wakeup = entry.wakeupTime();
757 ASSERT_TRUE(wakeup);
758 EXPECT_THAT(*wakeup, Eq(wakeup));
759}
760
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800761TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) {
762 VSyncDispatchTimerQueueEntry entry(
763 "test", [](auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800764 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800765 entry.executing(); // 1000 is executing
766 // had 1000 not been executing, this could have been scheduled for time 800.
767 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
768 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
769
770 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
771 EXPECT_THAT(*entry.wakeupTime(), Eq(1950));
772
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800773 EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800774 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800775}
776
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800777TEST_F(VSyncDispatchTimerQueueEntryTest,
778 willRequestNextEstimateWhenSnappingToNextTargettableVSync) {
779 VSyncDispatchTimerQueueEntry entry(
780 "test", [](auto) {}, mVsyncMoveThreshold);
781
782 Sequence seq;
783 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
784 .InSequence(seq)
785 .WillOnce(Return(1000));
786 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
787 .InSequence(seq)
788 .WillOnce(Return(1000));
789 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000 + mVsyncMoveThreshold))
790 .InSequence(seq)
791 .WillOnce(Return(2000));
792
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800793 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800794
795 entry.executing(); // 1000 is executing
796
797 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
798}
799
800TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) {
801 VSyncDispatchTimerQueueEntry entry(
802 "test", [](auto) {}, mVsyncMoveThreshold);
803 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
804 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
805 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
806 EXPECT_THAT(entry.schedule(1200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700807}
808
809} // namespace android::scheduler
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800810
811// TODO(b/129481165): remove the #pragma below and fix conversion issues
812#pragma clang diagnostic pop // ignored "-Wconversion"