blob: 6fcb1af42628b2877fe0d6f05a71db7de1b51dc4 [file] [log] [blame]
Kevin DuBois305bef12019-10-09 13:23:27 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "LibSurfaceFlingerUnittests"
19#define LOG_NDEBUG 0
20
21#include "Scheduler/TimeKeeper.h"
Kevin DuBoise4f27a82019-11-12 11:41:41 -080022#include "Scheduler/VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070023#include "Scheduler/VSyncTracker.h"
24
25#include <gmock/gmock.h>
26#include <gtest/gtest.h>
27#include <thread>
28
29using namespace testing;
30using namespace std::literals;
31namespace android::scheduler {
32
33class MockVSyncTracker : public VSyncTracker {
34public:
35 MockVSyncTracker(nsecs_t period) : mPeriod{period} {
36 ON_CALL(*this, nextAnticipatedVSyncTimeFrom(_))
37 .WillByDefault(Invoke(this, &MockVSyncTracker::nextVSyncTime));
38 }
39
40 MOCK_METHOD1(addVsyncTimestamp, void(nsecs_t));
41 MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t));
Kevin DuBois2fd3cea2019-11-14 08:52:45 -080042 MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
Kevin DuBoisee2ad9f2019-11-21 11:10:57 -080043 MOCK_METHOD1(setPeriod, void(nsecs_t));
Kevin DuBois305bef12019-10-09 13:23:27 -070044
45 nsecs_t nextVSyncTime(nsecs_t timePoint) const {
46 if (timePoint % mPeriod == 0) {
47 return timePoint;
48 }
49 return (timePoint - (timePoint % mPeriod) + mPeriod);
50 }
51
52protected:
53 nsecs_t const mPeriod;
54};
55
56class ControllableClock : public TimeKeeper {
57public:
58 ControllableClock() {
59 ON_CALL(*this, alarmIn(_, _))
60 .WillByDefault(Invoke(this, &ControllableClock::alarmInDefaultBehavior));
61 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
62 }
63
64 MOCK_CONST_METHOD0(now, nsecs_t());
65 MOCK_METHOD2(alarmIn, void(std::function<void()> const&, nsecs_t time));
66 MOCK_METHOD0(alarmCancel, void());
67
68 void alarmInDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
69 mCallback = callback;
70 mNextCallbackTime = time + mCurrentTime;
71 }
72
73 nsecs_t fakeTime() const { return mCurrentTime; }
74
75 void advanceToNextCallback() {
76 mCurrentTime = mNextCallbackTime;
77 if (mCallback) {
78 mCallback();
79 }
80 }
81
82 void advanceBy(nsecs_t advancement) {
83 mCurrentTime += advancement;
84 if (mCurrentTime >= mNextCallbackTime && mCallback) {
85 mCallback();
86 }
87 };
88
89private:
90 std::function<void()> mCallback;
91 nsecs_t mNextCallbackTime = 0;
92 nsecs_t mCurrentTime = 0;
93};
94
95class CountingCallback {
96public:
97 CountingCallback(VSyncDispatch& dispatch)
98 : mDispatch(dispatch),
99 mToken(dispatch.registerCallback(std::bind(&CountingCallback::counter, this,
Kevin DuBois2968afc2020-01-14 09:48:50 -0800100 std::placeholders::_1,
101 std::placeholders::_2),
Kevin DuBois305bef12019-10-09 13:23:27 -0700102 "test")) {}
103 ~CountingCallback() { mDispatch.unregisterCallback(mToken); }
104
105 operator VSyncDispatch::CallbackToken() const { return mToken; }
106
Kevin DuBois2968afc2020-01-14 09:48:50 -0800107 void counter(nsecs_t time, nsecs_t) { mCalls.push_back(time); }
Kevin DuBois305bef12019-10-09 13:23:27 -0700108
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,
Kevin DuBois2968afc2020-01-14 09:48:50 -0800119 std::placeholders::_1,
120 std::placeholders::_2),
Kevin DuBois305bef12019-10-09 13:23:27 -0700121 "test")),
122 mRegistered(true),
123 mPauseAmount(pauseAmount) {}
124 ~PausingCallback() { unregister(); }
125
126 operator VSyncDispatch::CallbackToken() const { return mToken; }
127
Kevin DuBois2968afc2020-01-14 09:48:50 -0800128 void pause(nsecs_t, nsecs_t) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700129 std::unique_lock<std::mutex> lk(mMutex);
130 mPause = true;
131 mCv.notify_all();
132
133 mCv.wait_for(lk, mPauseAmount, [this] { return !mPause; });
134
135 mResourcePresent = (mResource.lock() != nullptr);
136 }
137
138 bool waitForPause() {
139 std::unique_lock<std::mutex> lk(mMutex);
140 auto waiting = mCv.wait_for(lk, 10s, [this] { return mPause; });
141 return waiting;
142 }
143
144 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
145
146 bool resourcePresent() { return mResourcePresent; }
147
148 void unpause() {
149 std::unique_lock<std::mutex> lk(mMutex);
150 mPause = false;
151 mCv.notify_all();
152 }
153
154 void unregister() {
155 if (mRegistered) {
156 mDispatch.unregisterCallback(mToken);
157 mRegistered = false;
158 }
159 }
160
161 VSyncDispatch& mDispatch;
162 VSyncDispatch::CallbackToken mToken;
163 bool mRegistered = true;
164
165 std::mutex mMutex;
166 std::condition_variable mCv;
167 bool mPause = false;
168 std::weak_ptr<void> mResource;
169 bool mResourcePresent = false;
170 std::chrono::milliseconds const mPauseAmount;
171};
172
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800173class VSyncDispatchTimerQueueTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700174protected:
175 std::unique_ptr<TimeKeeper> createTimeKeeper() {
176 class TimeKeeperWrapper : public TimeKeeper {
177 public:
178 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
179 void alarmIn(std::function<void()> const& callback, nsecs_t time) final {
180 mControllableClock.alarmIn(callback, time);
181 }
182 void alarmCancel() final { mControllableClock.alarmCancel(); }
183 nsecs_t now() const final { return mControllableClock.now(); }
184
185 private:
186 TimeKeeper& mControllableClock;
187 };
188 return std::make_unique<TimeKeeperWrapper>(mMockClock);
189 }
190
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800191 ~VSyncDispatchTimerQueueTest() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700192 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
193 Mock::VerifyAndClearExpectations(&mMockClock);
194 }
195
196 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
197
198 NiceMock<ControllableClock> mMockClock;
199 static nsecs_t constexpr mDispatchGroupThreshold = 5;
200 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800201 nsecs_t const mVsyncMoveThreshold = 300;
Kevin DuBois305bef12019-10-09 13:23:27 -0700202 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800203 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
204 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700205};
206
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800207TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700208 EXPECT_CALL(mMockClock, alarmIn(_, 900));
209 EXPECT_CALL(mMockClock, alarmCancel());
210 {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800211 VSyncDispatchTimerQueue mDispatch{createTimeKeeper(), mStubTracker, mDispatchGroupThreshold,
212 mVsyncMoveThreshold};
Kevin DuBois305bef12019-10-09 13:23:27 -0700213 CountingCallback cb(mDispatch);
214 EXPECT_EQ(mDispatch.schedule(cb, 100, 1000), ScheduleResult::Scheduled);
215 }
216}
217
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800218TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700219 auto intended = mPeriod - 230;
220 EXPECT_CALL(mMockClock, alarmIn(_, 900));
221
222 CountingCallback cb(mDispatch);
223 EXPECT_EQ(mDispatch.schedule(cb, 100, intended), ScheduleResult::Scheduled);
224 advanceToNextCallback();
225
226 ASSERT_THAT(cb.mCalls.size(), Eq(1));
227 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
228}
229
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800230TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700231 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000)).WillOnce(Return(1150));
232 EXPECT_CALL(mMockClock, alarmIn(_, 1050));
233
234 CountingCallback cb(mDispatch);
235 mDispatch.schedule(cb, 100, mPeriod);
236 advanceToNextCallback();
237
238 ASSERT_THAT(cb.mCalls.size(), Eq(1));
239 EXPECT_THAT(cb.mCalls[0], Eq(1150));
240}
241
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800242TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700243 auto const now = 234;
244 mMockClock.advanceBy(234);
245 auto const workDuration = 10 * mPeriod;
246 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + workDuration))
247 .WillOnce(Return(mPeriod * 11));
248 EXPECT_CALL(mMockClock, alarmIn(_, mPeriod - now));
249
250 CountingCallback cb(mDispatch);
251 EXPECT_EQ(mDispatch.schedule(cb, workDuration, mPeriod), ScheduleResult::Scheduled);
252}
253
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800254TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700255 EXPECT_CALL(mMockClock, alarmIn(_, 900));
256 EXPECT_CALL(mMockClock, alarmCancel());
257
258 CountingCallback cb(mDispatch);
259 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
260 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::Cancelled);
261}
262
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800263TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700264 EXPECT_CALL(mMockClock, alarmIn(_, 900));
265 EXPECT_CALL(mMockClock, alarmCancel());
266
267 CountingCallback cb(mDispatch);
268 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
269 mMockClock.advanceBy(950);
270 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
271}
272
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800273TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700274 EXPECT_CALL(mMockClock, alarmIn(_, 900));
275 EXPECT_CALL(mMockClock, alarmCancel());
276
277 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
278 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
279
280 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
281 EXPECT_TRUE(cb.waitForPause());
282 EXPECT_EQ(mDispatch.cancel(cb), CancelResult::TooLate);
283 cb.unpause();
284 pausingThread.join();
285}
286
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800287TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700288 EXPECT_CALL(mMockClock, alarmIn(_, 900));
289 EXPECT_CALL(mMockClock, alarmCancel());
290
291 auto resource = std::make_shared<int>(110);
292
293 PausingCallback cb(mDispatch, 50ms);
294 cb.stashResource(resource);
295 EXPECT_EQ(mDispatch.schedule(cb, 100, mPeriod), ScheduleResult::Scheduled);
296
297 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
298 EXPECT_TRUE(cb.waitForPause());
299
300 cb.unregister();
301 resource.reset();
302
303 cb.unpause();
304 pausingThread.join();
305
306 EXPECT_TRUE(cb.resourcePresent());
307}
308
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800309TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700310 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
311 .Times(4)
312 .WillOnce(Return(1055))
313 .WillOnce(Return(1063))
314 .WillOnce(Return(1063))
315 .WillOnce(Return(1075));
316
317 Sequence seq;
318 EXPECT_CALL(mMockClock, alarmIn(_, 955)).InSequence(seq);
319 EXPECT_CALL(mMockClock, alarmIn(_, 813)).InSequence(seq);
320 EXPECT_CALL(mMockClock, alarmIn(_, 162)).InSequence(seq);
321
322 CountingCallback cb0(mDispatch);
323 CountingCallback cb1(mDispatch);
324
325 mDispatch.schedule(cb0, 100, mPeriod);
326 mDispatch.schedule(cb1, 250, mPeriod);
327
328 advanceToNextCallback();
329 advanceToNextCallback();
330
331 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
332 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
333 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
334 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
335}
336
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800337TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700338 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
339 .Times(4)
340 .WillOnce(Return(10000))
341 .WillOnce(Return(1000))
342 .WillOnce(Return(10000))
343 .WillOnce(Return(10000));
344
345 Sequence seq;
346 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
347 EXPECT_CALL(mMockClock, alarmIn(_, 750)).InSequence(seq);
348 EXPECT_CALL(mMockClock, alarmIn(_, 9900)).InSequence(seq);
349
350 CountingCallback cb0(mDispatch);
351 CountingCallback cb1(mDispatch);
352
353 mDispatch.schedule(cb0, 100, mPeriod * 10);
354 mDispatch.schedule(cb1, 250, mPeriod);
355 mDispatch.cancel(cb1);
356}
357
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800358TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700359 Sequence seq;
360 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
361 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
362
363 CountingCallback cb0(mDispatch);
364 CountingCallback cb1(mDispatch);
365
366 mDispatch.schedule(cb0, 400, 1000);
367 mDispatch.schedule(cb1, 200, 1000);
368 mDispatch.schedule(cb1, 300, 1000);
369 advanceToNextCallback();
370}
371
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800372TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700373 Sequence seq;
374 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
375 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
376 EXPECT_CALL(mMockClock, alarmIn(_, 100)).InSequence(seq);
377
378 CountingCallback cb0(mDispatch);
379 CountingCallback cb1(mDispatch);
380
381 mDispatch.schedule(cb0, 400, 1000);
382 mDispatch.schedule(cb1, 200, 1000);
383 mDispatch.schedule(cb1, 500, 1000);
384 advanceToNextCallback();
385}
386
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800387TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700388 Sequence seq;
389 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
390 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
391 EXPECT_CALL(mMockClock, alarmIn(_, 990)).InSequence(seq);
392 EXPECT_CALL(mMockClock, alarmIn(_, 10)).InSequence(seq);
393
394 auto offset = 400;
395 auto closeOffset = offset + mDispatchGroupThreshold - 1;
396 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
397
398 CountingCallback cb0(mDispatch);
399 CountingCallback cb1(mDispatch);
400
401 mDispatch.schedule(cb0, 400, 1000);
402 mDispatch.schedule(cb1, 200, 1000);
403 mDispatch.schedule(cb1, closeOffset, 1000);
404
405 advanceToNextCallback();
406 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
407 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
408 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
409 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
410
411 mDispatch.schedule(cb0, 400, 2000);
412 mDispatch.schedule(cb1, notCloseOffset, 2000);
413 advanceToNextCallback();
414 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
415 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
416
417 advanceToNextCallback();
418 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
419 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
420}
421
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800422TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700423 EXPECT_CALL(mMockClock, alarmIn(_, 900));
424 EXPECT_CALL(mMockClock, alarmIn(_, 800));
425 EXPECT_CALL(mMockClock, alarmIn(_, 100));
426 EXPECT_CALL(mMockClock, alarmCancel());
427
428 CountingCallback cb0(mDispatch);
429 CountingCallback cb1(mDispatch);
430
431 mDispatch.schedule(cb0, 100, 1000);
432 mDispatch.schedule(cb1, 200, 1000);
433 advanceToNextCallback();
434 EXPECT_EQ(mDispatch.cancel(cb0), CancelResult::Cancelled);
435}
436
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800437TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700438 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
439 .Times(3)
440 .WillOnce(Return(950))
441 .WillOnce(Return(1975))
442 .WillOnce(Return(2950));
443
444 CountingCallback cb(mDispatch);
445 mDispatch.schedule(cb, 100, 920);
446
447 mMockClock.advanceBy(850);
448 EXPECT_THAT(cb.mCalls.size(), Eq(1));
449
450 mDispatch.schedule(cb, 100, 1900);
451 mMockClock.advanceBy(900);
452 EXPECT_THAT(cb.mCalls.size(), Eq(1));
453 mMockClock.advanceBy(125);
454 EXPECT_THAT(cb.mCalls.size(), Eq(2));
455
456 mDispatch.schedule(cb, 100, 2900);
457 mMockClock.advanceBy(975);
458 EXPECT_THAT(cb.mCalls.size(), Eq(3));
459}
460
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800461TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700462 Sequence seq;
463 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
464 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
465
466 VSyncDispatch::CallbackToken tmp;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800467 tmp = mDispatch.registerCallback([&](auto, auto) { mDispatch.schedule(tmp, 100, 2000); },
468 "o.o");
Kevin DuBois305bef12019-10-09 13:23:27 -0700469
470 mDispatch.schedule(tmp, 100, 1000);
471 advanceToNextCallback();
472}
473
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800474TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700475 VSyncDispatch::CallbackToken tmp;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800476 std::optional<nsecs_t> lastTarget;
Kevin DuBois305bef12019-10-09 13:23:27 -0700477 tmp = mDispatch.registerCallback(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800478 [&](auto timestamp, auto) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800479 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp - mVsyncMoveThreshold),
480 ScheduleResult::Scheduled);
481 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp), ScheduleResult::Scheduled);
482 EXPECT_EQ(mDispatch.schedule(tmp, 400, timestamp + mVsyncMoveThreshold),
483 ScheduleResult::Scheduled);
484 lastTarget = timestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700485 },
486 "oo");
487
488 mDispatch.schedule(tmp, 999, 1000);
489 advanceToNextCallback();
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800490 EXPECT_THAT(lastTarget, Eq(1000));
491
492 advanceToNextCallback();
493 EXPECT_THAT(lastTarget, Eq(2000));
Kevin DuBois305bef12019-10-09 13:23:27 -0700494}
495
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800496TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700497 Sequence seq;
498 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
499 EXPECT_CALL(mMockClock, alarmIn(_, 200)).InSequence(seq);
500 EXPECT_CALL(mMockClock, alarmIn(_, 1000)).InSequence(seq);
501 EXPECT_CALL(mMockClock, alarmIn(_, 150)).InSequence(seq);
502
503 CountingCallback cb(mDispatch);
504 mDispatch.schedule(cb, 0, 1000);
505
506 mMockClock.advanceBy(750);
507 mDispatch.schedule(cb, 50, 1000);
508
509 advanceToNextCallback();
510 mDispatch.schedule(cb, 50, 2000);
511
512 mMockClock.advanceBy(800);
513 mDispatch.schedule(cb, 100, 2000);
514}
515
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800516TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700517 Sequence seq;
518 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
519 EXPECT_CALL(mMockClock, alarmIn(_, 400)).InSequence(seq);
520 EXPECT_CALL(mMockClock, alarmIn(_, 350)).InSequence(seq);
521 EXPECT_CALL(mMockClock, alarmIn(_, 950)).InSequence(seq);
522
523 CountingCallback cb0(mDispatch);
524 CountingCallback cb1(mDispatch);
525
526 mDispatch.schedule(cb0, 500, 1000);
527 mDispatch.schedule(cb1, 100, 1000);
528
529 advanceToNextCallback();
530 mDispatch.schedule(cb0, 200, 2000);
531 mDispatch.schedule(cb1, 150, 1000);
532
533 advanceToNextCallback();
534 advanceToNextCallback();
535}
536
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800537TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700538 Sequence seq;
539 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
540
541 CountingCallback cb0(mDispatch);
542 CountingCallback cb1(mDispatch);
543 mDispatch.schedule(cb0, 500, 1000);
544 mDispatch.schedule(cb1, 500, 20000);
545}
546
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800547TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700548 Sequence seq;
549 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
550 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
551 EXPECT_CALL(mMockClock, alarmIn(_, 900)).InSequence(seq);
552
553 CountingCallback cb0(mDispatch);
554 mDispatch.schedule(cb0, 500, 1000);
555 mDispatch.cancel(cb0);
556 mDispatch.schedule(cb0, 100, 1000);
557}
558
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800559TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700560 VSyncDispatch::CallbackToken token(100);
561 EXPECT_THAT(mDispatch.schedule(token, 100, 1000), Eq(ScheduleResult::Error));
562 EXPECT_THAT(mDispatch.cancel(token), Eq(CancelResult::Error));
563}
564
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800565TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700566 CountingCallback cb0(mDispatch);
567 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800568 EXPECT_EQ(mDispatch.schedule(cb0, 100, 1000), ScheduleResult::Scheduled);
569}
570
571// b/1450138150
572TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
573 EXPECT_CALL(mMockClock, alarmIn(_, 500));
574 CountingCallback cb(mDispatch);
575 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
576 mMockClock.advanceBy(400);
577
578 EXPECT_EQ(mDispatch.schedule(cb, 800, 1000), ScheduleResult::Scheduled);
579 advanceToNextCallback();
580 ASSERT_THAT(cb.mCalls.size(), Eq(1));
581}
582
583TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedule) {
584 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
585 .Times(2)
586 .WillOnce(Return(1000))
587 .WillOnce(Return(1002));
588 CountingCallback cb(mDispatch);
589 EXPECT_EQ(mDispatch.schedule(cb, 500, 1000), ScheduleResult::Scheduled);
590 mMockClock.advanceBy(400);
591 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBois305bef12019-10-09 13:23:27 -0700592}
593
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800594TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
595 CountingCallback cb0(mDispatch);
596 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
597 advanceToNextCallback();
598 EXPECT_EQ(mDispatch.schedule(cb0, 1100, 2000), ScheduleResult::Scheduled);
599}
600
601TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
602 Sequence seq;
603 EXPECT_CALL(mMockClock, alarmIn(_, 500)).InSequence(seq);
604 EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
605 CountingCallback cb0(mDispatch);
606 EXPECT_EQ(mDispatch.schedule(cb0, 500, 1000), ScheduleResult::Scheduled);
607 advanceToNextCallback();
608 EXPECT_EQ(mDispatch.schedule(cb0, 1900, 2000), ScheduleResult::Scheduled);
609}
610
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800611TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800612 EXPECT_CALL(mMockClock, alarmIn(_, 600));
613
614 CountingCallback cb(mDispatch);
615 EXPECT_EQ(mDispatch.schedule(cb, 400, 1000), ScheduleResult::Scheduled);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800616
617 EXPECT_EQ(mDispatch.schedule(cb, 1400, 1000), ScheduleResult::Scheduled);
618
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800619 advanceToNextCallback();
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800620}
621
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800622TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700623 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
624 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
625
626 VSyncCallbackRegistration cb(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800627 mDispatch, [](auto, auto) {}, "");
Kevin DuBois305bef12019-10-09 13:23:27 -0700628 VSyncCallbackRegistration cb1(std::move(cb));
629 cb.schedule(100, 1000);
630 cb.cancel();
631
632 cb1.schedule(500, 1000);
633 cb1.cancel();
634}
635
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800636TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700637 EXPECT_CALL(mMockClock, alarmIn(_, 500)).Times(1);
638 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
639
640 VSyncCallbackRegistration cb(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800641 mDispatch, [](auto, auto) {}, "");
Kevin DuBois305bef12019-10-09 13:23:27 -0700642 VSyncCallbackRegistration cb1(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800643 mDispatch, [](auto, auto) {}, "");
Kevin DuBois305bef12019-10-09 13:23:27 -0700644 cb1 = std::move(cb);
645 cb.schedule(100, 1000);
646 cb.cancel();
647
648 cb1.schedule(500, 1000);
649 cb1.cancel();
650}
651
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800652class VSyncDispatchTimerQueueEntryTest : public testing::Test {
Kevin DuBois305bef12019-10-09 13:23:27 -0700653protected:
654 nsecs_t const mPeriod = 1000;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800655 nsecs_t const mVsyncMoveThreshold = 200;
Kevin DuBois305bef12019-10-09 13:23:27 -0700656 NiceMock<MockVSyncTracker> mStubTracker{mPeriod};
657};
658
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800659TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700660 std::string name("basicname");
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800661 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800662 name, [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700663 EXPECT_THAT(entry.name(), Eq(name));
664 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
665 EXPECT_FALSE(entry.wakeupTime());
666}
667
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800668TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800669 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800670 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700671
672 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800673 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
674 auto const wakeup = entry.wakeupTime();
675 ASSERT_TRUE(wakeup);
676 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700677
678 entry.disarm();
679 EXPECT_FALSE(entry.wakeupTime());
680}
681
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800682TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700683 auto const duration = 500;
684 auto const now = 8750;
685
686 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(now + duration))
687 .Times(1)
688 .WillOnce(Return(10000));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800689 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800690 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700691
692 EXPECT_FALSE(entry.wakeupTime());
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800693 EXPECT_THAT(entry.schedule(500, 994, mStubTracker, now), Eq(ScheduleResult::Scheduled));
694 auto const wakeup = entry.wakeupTime();
695 ASSERT_TRUE(wakeup);
696 EXPECT_THAT(*wakeup, Eq(9500));
Kevin DuBois305bef12019-10-09 13:23:27 -0700697}
698
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800699TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700700 auto callCount = 0;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800701 auto vsyncCalledTime = 0;
702 auto wakeupCalledTime = 0;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800703 VSyncDispatchTimerQueueEntry entry(
704 "test",
Kevin DuBois2968afc2020-01-14 09:48:50 -0800705 [&](auto vsyncTime, auto wakeupTime) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800706 callCount++;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800707 vsyncCalledTime = vsyncTime;
708 wakeupCalledTime = wakeupTime;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800709 },
710 mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700711
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800712 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
713 auto const wakeup = entry.wakeupTime();
714 ASSERT_TRUE(wakeup);
715 EXPECT_THAT(*wakeup, Eq(900));
Kevin DuBois305bef12019-10-09 13:23:27 -0700716
Kevin DuBois2968afc2020-01-14 09:48:50 -0800717 entry.callback(entry.executing(), *wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700718
719 EXPECT_THAT(callCount, Eq(1));
Kevin DuBois2968afc2020-01-14 09:48:50 -0800720 EXPECT_THAT(vsyncCalledTime, Eq(mPeriod));
721 EXPECT_THAT(wakeupCalledTime, Eq(*wakeup));
Kevin DuBois305bef12019-10-09 13:23:27 -0700722 EXPECT_FALSE(entry.wakeupTime());
723 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
724 ASSERT_TRUE(lastCalledTarget);
725 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
726}
727
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800728TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700729 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(_))
730 .Times(2)
731 .WillOnce(Return(1000))
732 .WillOnce(Return(1020));
733
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800734 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800735 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBois305bef12019-10-09 13:23:27 -0700736
737 EXPECT_FALSE(entry.wakeupTime());
738 entry.update(mStubTracker, 0);
739 EXPECT_FALSE(entry.wakeupTime());
740
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800741 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
742 auto wakeup = entry.wakeupTime();
743 ASSERT_TRUE(wakeup);
Kevin DuBois305bef12019-10-09 13:23:27 -0700744 EXPECT_THAT(wakeup, Eq(900));
745
746 entry.update(mStubTracker, 0);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800747 wakeup = entry.wakeupTime();
748 ASSERT_TRUE(wakeup);
749 EXPECT_THAT(*wakeup, Eq(920));
Kevin DuBois305bef12019-10-09 13:23:27 -0700750}
751
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800752TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800753 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800754 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800755 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700756 entry.update(mStubTracker, 0);
757
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800758 auto const wakeup = entry.wakeupTime();
759 ASSERT_TRUE(wakeup);
760 EXPECT_THAT(*wakeup, Eq(wakeup));
761}
762
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800763TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) {
764 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800765 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800766 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800767 entry.executing(); // 1000 is executing
768 // had 1000 not been executing, this could have been scheduled for time 800.
769 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
770 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
771
772 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
773 EXPECT_THAT(*entry.wakeupTime(), Eq(1950));
774
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800775 EXPECT_THAT(entry.schedule(200, 1001, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800776 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800777}
778
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800779TEST_F(VSyncDispatchTimerQueueEntryTest,
780 willRequestNextEstimateWhenSnappingToNextTargettableVSync) {
781 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800782 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800783
784 Sequence seq;
785 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
786 .InSequence(seq)
787 .WillOnce(Return(1000));
788 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(500))
789 .InSequence(seq)
790 .WillOnce(Return(1000));
791 EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000 + mVsyncMoveThreshold))
792 .InSequence(seq)
793 .WillOnce(Return(2000));
794
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800795 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800796
797 entry.executing(); // 1000 is executing
798
799 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
800}
801
802TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) {
803 VSyncDispatchTimerQueueEntry entry(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800804 "test", [](auto, auto) {}, mVsyncMoveThreshold);
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800805 EXPECT_THAT(entry.schedule(100, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
806 EXPECT_THAT(entry.schedule(200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
807 EXPECT_THAT(entry.schedule(50, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
808 EXPECT_THAT(entry.schedule(1200, 500, mStubTracker, 0), Eq(ScheduleResult::Scheduled));
Kevin DuBois305bef12019-10-09 13:23:27 -0700809}
810
811} // namespace android::scheduler