1 /*
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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 #pragma clang diagnostic ignored "-Wextra"
21
22 #undef LOG_TAG
23 #define LOG_TAG "LibSurfaceFlingerUnittests"
24 #define LOG_NDEBUG 0
25
26 #include <thread>
27
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30
31 #include <scheduler/TimeKeeper.h>
32
33 #include <common/test/FlagUtils.h>
34 #include "Scheduler/VSyncDispatchTimerQueue.h"
35 #include "Scheduler/VSyncTracker.h"
36 #include "mock/MockVSyncTracker.h"
37
38 #include <com_android_graphics_surfaceflinger_flags.h>
39
40 using namespace testing;
41 using namespace std::literals;
42
43 namespace android::scheduler {
44 using namespace com::android::graphics::surfaceflinger;
45
46 class MockVSyncTracker : public mock::VSyncTracker {
47 public:
MockVSyncTracker(nsecs_t period)48 MockVSyncTracker(nsecs_t period) : mPeriod{period} {
49 ON_CALL(*this, nextAnticipatedVSyncTimeFrom(_, _))
50 .WillByDefault(Invoke(this, &MockVSyncTracker::nextVSyncTime));
51 ON_CALL(*this, addVsyncTimestamp(_)).WillByDefault(Return(true));
52 ON_CALL(*this, currentPeriod())
53 .WillByDefault(Invoke(this, &MockVSyncTracker::getCurrentPeriod));
54 }
55
nextVSyncTime(nsecs_t timePoint,std::optional<nsecs_t>) const56 nsecs_t nextVSyncTime(nsecs_t timePoint, std::optional<nsecs_t>) const {
57 if (timePoint % mPeriod == 0) {
58 return timePoint;
59 }
60 return (timePoint - (timePoint % mPeriod) + mPeriod);
61 }
62
getCurrentPeriod() const63 nsecs_t getCurrentPeriod() const { return mPeriod; }
64
65 protected:
66 nsecs_t const mPeriod;
67 };
68
69 class ControllableClock : public TimeKeeper {
70 public:
ControllableClock()71 ControllableClock() {
72 ON_CALL(*this, alarmAt(_, _))
73 .WillByDefault(Invoke(this, &ControllableClock::alarmAtDefaultBehavior));
74 ON_CALL(*this, now()).WillByDefault(Invoke(this, &ControllableClock::fakeTime));
75 }
76
77 MOCK_METHOD(nsecs_t, now, (), (const));
78 MOCK_METHOD(void, alarmAt, (std::function<void()>, nsecs_t), (override));
79 MOCK_METHOD(void, alarmCancel, (), (override));
80 MOCK_METHOD(void, dump, (std::string&), (const, override));
81
alarmAtDefaultBehavior(std::function<void ()> const & callback,nsecs_t time)82 void alarmAtDefaultBehavior(std::function<void()> const& callback, nsecs_t time) {
83 mCallback = callback;
84 mNextCallbackTime = time;
85 }
86
fakeTime() const87 nsecs_t fakeTime() const { return mCurrentTime; }
88
advanceToNextCallback()89 void advanceToNextCallback() {
90 mCurrentTime = mNextCallbackTime;
91 if (mCallback) {
92 mCallback();
93 }
94 }
95
advanceBy(nsecs_t advancement)96 void advanceBy(nsecs_t advancement) {
97 mCurrentTime += advancement;
98 if (mCurrentTime >= (mNextCallbackTime + mLag) && mCallback) {
99 mCallback();
100 }
101 };
102
setLag(nsecs_t lag)103 void setLag(nsecs_t lag) { mLag = lag; }
104
105 private:
106 std::function<void()> mCallback;
107 nsecs_t mNextCallbackTime = 0;
108 nsecs_t mCurrentTime = 0;
109 nsecs_t mLag = 0;
110 };
111
112 class CountingCallback {
113 public:
CountingCallback(std::shared_ptr<VSyncDispatch> dispatch)114 CountingCallback(std::shared_ptr<VSyncDispatch> dispatch)
115 : mDispatch(std::move(dispatch)),
116 mToken(mDispatch->registerCallback(std::bind(&CountingCallback::counter, this,
117 std::placeholders::_1,
118 std::placeholders::_2,
119 std::placeholders::_3),
120 "test")) {}
~CountingCallback()121 ~CountingCallback() { mDispatch->unregisterCallback(mToken); }
122
operator VSyncDispatch::CallbackToken() const123 operator VSyncDispatch::CallbackToken() const { return mToken; }
124
counter(nsecs_t time,nsecs_t wakeup_time,nsecs_t readyTime)125 void counter(nsecs_t time, nsecs_t wakeup_time, nsecs_t readyTime) {
126 mCalls.push_back(time);
127 mWakeupTime.push_back(wakeup_time);
128 mReadyTime.push_back(readyTime);
129 }
130
131 std::shared_ptr<VSyncDispatch> mDispatch;
132 VSyncDispatch::CallbackToken mToken;
133 std::vector<nsecs_t> mCalls;
134 std::vector<nsecs_t> mWakeupTime;
135 std::vector<nsecs_t> mReadyTime;
136 };
137
138 class PausingCallback {
139 public:
PausingCallback(std::shared_ptr<VSyncDispatch> dispatch,std::chrono::milliseconds pauseAmount)140 PausingCallback(std::shared_ptr<VSyncDispatch> dispatch, std::chrono::milliseconds pauseAmount)
141 : mDispatch(std::move(dispatch)),
142 mToken(mDispatch->registerCallback(std::bind(&PausingCallback::pause, this,
143 std::placeholders::_1,
144 std::placeholders::_2),
145 "test")),
146 mRegistered(true),
147 mPauseAmount(pauseAmount) {}
~PausingCallback()148 ~PausingCallback() { unregister(); }
149
operator VSyncDispatch::CallbackToken() const150 operator VSyncDispatch::CallbackToken() const { return mToken; }
151
pause(nsecs_t,nsecs_t)152 void pause(nsecs_t, nsecs_t) {
153 std::unique_lock lock(mMutex);
154 mPause = true;
155 mCv.notify_all();
156
157 mCv.wait_for(lock, mPauseAmount, [this] { return !mPause; });
158
159 mResourcePresent = (mResource.lock() != nullptr);
160 }
161
waitForPause()162 bool waitForPause() {
163 std::unique_lock lock(mMutex);
164 auto waiting = mCv.wait_for(lock, 10s, [this] { return mPause; });
165 return waiting;
166 }
167
stashResource(std::weak_ptr<void> const & resource)168 void stashResource(std::weak_ptr<void> const& resource) { mResource = resource; }
169
resourcePresent()170 bool resourcePresent() { return mResourcePresent; }
171
unpause()172 void unpause() {
173 std::unique_lock lock(mMutex);
174 mPause = false;
175 mCv.notify_all();
176 }
177
unregister()178 void unregister() {
179 if (mRegistered) {
180 mDispatch->unregisterCallback(mToken);
181 mRegistered = false;
182 }
183 }
184
185 std::shared_ptr<VSyncDispatch> mDispatch;
186 VSyncDispatch::CallbackToken mToken;
187 bool mRegistered = true;
188
189 std::mutex mMutex;
190 std::condition_variable mCv;
191 bool mPause = false;
192 std::weak_ptr<void> mResource;
193 bool mResourcePresent = false;
194 std::chrono::milliseconds const mPauseAmount;
195 };
196
197 class VSyncDispatchTimerQueueTest : public testing::Test {
198 protected:
createTimeKeeper()199 std::unique_ptr<TimeKeeper> createTimeKeeper() {
200 class TimeKeeperWrapper : public TimeKeeper {
201 public:
202 TimeKeeperWrapper(TimeKeeper& control) : mControllableClock(control) {}
203
204 nsecs_t now() const final { return mControllableClock.now(); }
205
206 void alarmAt(std::function<void()> callback, nsecs_t time) final {
207 mControllableClock.alarmAt(std::move(callback), time);
208 }
209
210 void alarmCancel() final { mControllableClock.alarmCancel(); }
211 void dump(std::string&) const final {}
212
213 private:
214 TimeKeeper& mControllableClock;
215 };
216 return std::make_unique<TimeKeeperWrapper>(mMockClock);
217 }
218
~VSyncDispatchTimerQueueTest()219 ~VSyncDispatchTimerQueueTest() {
220 // destructor of dispatch will cancelAlarm(). Ignore final cancel in common test.
221 Mock::VerifyAndClearExpectations(&mMockClock);
222 }
223
advanceToNextCallback()224 void advanceToNextCallback() { mMockClock.advanceToNextCallback(); }
225
226 NiceMock<ControllableClock> mMockClock;
227 static nsecs_t constexpr mDispatchGroupThreshold = 5;
228 nsecs_t const mPeriod = 1000;
229 nsecs_t const mVsyncMoveThreshold = 300;
230 std::shared_ptr<NiceMock<MockVSyncTracker>> mStubTracker =
231 std::make_shared<NiceMock<MockVSyncTracker>>(mPeriod);
232 std::shared_ptr<VSyncDispatch> mDispatch =
233 std::make_shared<VSyncDispatchTimerQueue>(createTimeKeeper(), mStubTracker,
234 mDispatchGroupThreshold, mVsyncMoveThreshold);
235 };
236
TEST_F(VSyncDispatchTimerQueueTest,unregistersSetAlarmOnDestruction)237 TEST_F(VSyncDispatchTimerQueueTest, unregistersSetAlarmOnDestruction) {
238 EXPECT_CALL(mMockClock, alarmAt(_, 900));
239 EXPECT_CALL(mMockClock, alarmCancel());
240 {
241 std::shared_ptr<VSyncDispatch> mDispatch =
242 std::make_shared<VSyncDispatchTimerQueue>(createTimeKeeper(), mStubTracker,
243 mDispatchGroupThreshold,
244 mVsyncMoveThreshold);
245 CountingCallback cb(mDispatch);
246 const auto result =
247 mDispatch->schedule(cb,
248 {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
249 EXPECT_TRUE(result.has_value());
250 EXPECT_EQ(900, result->callbackTime.ns());
251 EXPECT_EQ(1000, result->vsyncTime.ns());
252 }
253 }
254
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingFuture)255 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFuture) {
256 auto intended = mPeriod - 230;
257 EXPECT_CALL(mMockClock, alarmAt(_, 900));
258
259 CountingCallback cb(mDispatch);
260 const auto result =
261 mDispatch->schedule(cb,
262 {.workDuration = 100, .readyDuration = 0, .lastVsync = intended});
263 EXPECT_TRUE(result.has_value());
264 EXPECT_EQ(900, result->callbackTime.ns());
265 EXPECT_EQ(1000, result->vsyncTime.ns());
266
267 advanceToNextCallback();
268
269 ASSERT_THAT(cb.mCalls.size(), Eq(1));
270 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
271 }
272
TEST_F(VSyncDispatchTimerQueueTest,updateAlarmSettingFuture)273 TEST_F(VSyncDispatchTimerQueueTest, updateAlarmSettingFuture) {
274 auto intended = mPeriod - 230;
275 Sequence seq;
276 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
277 EXPECT_CALL(mMockClock, alarmAt(_, 700)).InSequence(seq);
278
279 CountingCallback cb(mDispatch);
280 auto result =
281 mDispatch->schedule(cb,
282 {.workDuration = 100, .readyDuration = 0, .lastVsync = intended});
283 EXPECT_TRUE(result.has_value());
284 EXPECT_EQ(900, result->callbackTime.ns());
285 EXPECT_EQ(1000, result->vsyncTime.ns());
286
287 result =
288 mDispatch->update(cb, {.workDuration = 300, .readyDuration = 0, .lastVsync = intended});
289 EXPECT_TRUE(result.has_value());
290 EXPECT_EQ(700, result->callbackTime.ns());
291 EXPECT_EQ(1000, result->vsyncTime.ns());
292
293 advanceToNextCallback();
294
295 ASSERT_THAT(cb.mCalls.size(), Eq(1));
296 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
297 EXPECT_THAT(cb.mWakeupTime[0], Eq(700));
298 }
299
TEST_F(VSyncDispatchTimerQueueTest,updateDoesntSchedule)300 TEST_F(VSyncDispatchTimerQueueTest, updateDoesntSchedule) {
301 auto intended = mPeriod - 230;
302 EXPECT_CALL(mMockClock, alarmAt(_, _)).Times(0);
303
304 CountingCallback cb(mDispatch);
305 const auto result =
306 mDispatch->update(cb, {.workDuration = 300, .readyDuration = 0, .lastVsync = intended});
307 EXPECT_FALSE(result.has_value());
308 }
309
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingFutureWithAdjustmentToTrueVsync)310 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithAdjustmentToTrueVsync) {
311 EXPECT_CALL(*mStubTracker.get(),
312 nextAnticipatedVSyncTimeFrom(1000, std::optional<nsecs_t>(mPeriod)))
313 .WillOnce(Return(1150));
314 EXPECT_CALL(mMockClock, alarmAt(_, 1050));
315
316 CountingCallback cb(mDispatch);
317 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod});
318 advanceToNextCallback();
319
320 ASSERT_THAT(cb.mCalls.size(), Eq(1));
321 EXPECT_THAT(cb.mCalls[0], Eq(1150));
322 }
323
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingAdjustmentPast)324 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingAdjustmentPast) {
325 auto const now = 234;
326 mMockClock.advanceBy(234);
327 auto const workDuration = 10 * mPeriod;
328 EXPECT_CALL(*mStubTracker.get(),
329 nextAnticipatedVSyncTimeFrom(now + workDuration, std::optional<nsecs_t>(mPeriod)))
330 .WillOnce(Return(mPeriod * 11));
331 EXPECT_CALL(mMockClock, alarmAt(_, mPeriod));
332
333 CountingCallback cb(mDispatch);
334 const auto result = mDispatch->schedule(cb,
335 {.workDuration = workDuration,
336 .readyDuration = 0,
337 .lastVsync = mPeriod});
338 EXPECT_TRUE(result.has_value());
339 EXPECT_EQ(mPeriod, result->callbackTime.ns());
340 EXPECT_EQ(workDuration + mPeriod, result->vsyncTime.ns());
341 }
342
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmCancel)343 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancel) {
344 EXPECT_CALL(mMockClock, alarmAt(_, 900));
345 EXPECT_CALL(mMockClock, alarmCancel());
346
347 CountingCallback cb(mDispatch);
348 const auto result =
349 mDispatch->schedule(cb,
350 {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod});
351 EXPECT_TRUE(result.has_value());
352 EXPECT_EQ(mPeriod - 100, result->callbackTime.ns());
353 EXPECT_EQ(mPeriod, result->vsyncTime.ns());
354 EXPECT_EQ(mDispatch->cancel(cb), CancelResult::Cancelled);
355 }
356
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmCancelTooLate)357 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLate) {
358 EXPECT_CALL(mMockClock, alarmAt(_, 900));
359 EXPECT_CALL(mMockClock, alarmCancel());
360
361 CountingCallback cb(mDispatch);
362 const auto result =
363 mDispatch->schedule(cb,
364 {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod});
365 EXPECT_TRUE(result.has_value());
366 EXPECT_EQ(mPeriod - 100, result->callbackTime.ns());
367 EXPECT_EQ(mPeriod, result->vsyncTime.ns());
368 mMockClock.advanceBy(950);
369 EXPECT_EQ(mDispatch->cancel(cb), CancelResult::TooLate);
370 }
371
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmCancelTooLateWhenRunning)372 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmCancelTooLateWhenRunning) {
373 EXPECT_CALL(mMockClock, alarmAt(_, 900));
374 EXPECT_CALL(mMockClock, alarmCancel());
375
376 PausingCallback cb(mDispatch, std::chrono::duration_cast<std::chrono::milliseconds>(1s));
377 const auto result =
378 mDispatch->schedule(cb,
379 {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod});
380 EXPECT_TRUE(result.has_value());
381 EXPECT_EQ(mPeriod - 100, result->callbackTime.ns());
382 EXPECT_EQ(mPeriod, result->vsyncTime.ns());
383
384 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
385 EXPECT_TRUE(cb.waitForPause());
386 EXPECT_EQ(mDispatch->cancel(cb), CancelResult::TooLate);
387 cb.unpause();
388 pausingThread.join();
389 }
390
TEST_F(VSyncDispatchTimerQueueTest,unregisterSynchronizes)391 TEST_F(VSyncDispatchTimerQueueTest, unregisterSynchronizes) {
392 EXPECT_CALL(mMockClock, alarmAt(_, 900));
393 EXPECT_CALL(mMockClock, alarmCancel());
394
395 auto resource = std::make_shared<int>(110);
396
397 PausingCallback cb(mDispatch, 50ms);
398 cb.stashResource(resource);
399 const auto result =
400 mDispatch->schedule(cb,
401 {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod});
402 EXPECT_TRUE(result.has_value());
403 EXPECT_EQ(mPeriod - 100, result->callbackTime.ns());
404 EXPECT_EQ(mPeriod, result->vsyncTime.ns());
405
406 std::thread pausingThread([&] { mMockClock.advanceToNextCallback(); });
407 EXPECT_TRUE(cb.waitForPause());
408
409 cb.unregister();
410 resource.reset();
411
412 cb.unpause();
413 pausingThread.join();
414
415 EXPECT_TRUE(cb.resourcePresent());
416 }
417
TEST_F(VSyncDispatchTimerQueueTest,basicTwoAlarmSetting)418 TEST_F(VSyncDispatchTimerQueueTest, basicTwoAlarmSetting) {
419 EXPECT_CALL(*mStubTracker.get(),
420 nextAnticipatedVSyncTimeFrom(1000, std::optional<nsecs_t>(1000)))
421 .Times(4)
422 .WillOnce(Return(1055))
423 .WillOnce(Return(1063))
424 .WillOnce(Return(1063))
425 .WillOnce(Return(1075));
426
427 Sequence seq;
428 EXPECT_CALL(mMockClock, alarmAt(_, 955)).InSequence(seq);
429 EXPECT_CALL(mMockClock, alarmAt(_, 813)).InSequence(seq);
430 EXPECT_CALL(mMockClock, alarmAt(_, 975)).InSequence(seq);
431
432 CountingCallback cb0(mDispatch);
433 CountingCallback cb1(mDispatch);
434
435 mDispatch->schedule(cb0, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod});
436 mDispatch->schedule(cb1, {.workDuration = 250, .readyDuration = 0, .lastVsync = mPeriod});
437
438 advanceToNextCallback();
439 advanceToNextCallback();
440
441 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
442 EXPECT_THAT(cb0.mCalls[0], Eq(1075));
443 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
444 EXPECT_THAT(cb1.mCalls[0], Eq(1063));
445 }
446
TEST_F(VSyncDispatchTimerQueueTest,noCloseCallbacksAfterPeriodChange)447 TEST_F(VSyncDispatchTimerQueueTest, noCloseCallbacksAfterPeriodChange) {
448 EXPECT_CALL(*mStubTracker.get(), nextAnticipatedVSyncTimeFrom(_, _))
449 .Times(4)
450 .WillOnce(Return(1000))
451 .WillOnce(Return(2000))
452 .WillOnce(Return(2500))
453 .WillOnce(Return(4000));
454
455 Sequence seq;
456 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
457 EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
458 EXPECT_CALL(mMockClock, alarmAt(_, 3900)).InSequence(seq);
459
460 CountingCallback cb(mDispatch);
461
462 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 0});
463
464 advanceToNextCallback();
465
466 ASSERT_THAT(cb.mCalls.size(), Eq(1));
467 EXPECT_THAT(cb.mCalls[0], Eq(1000));
468
469 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
470
471 advanceToNextCallback();
472
473 ASSERT_THAT(cb.mCalls.size(), Eq(2));
474 EXPECT_THAT(cb.mCalls[1], Eq(2000));
475
476 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000});
477
478 advanceToNextCallback();
479
480 ASSERT_THAT(cb.mCalls.size(), Eq(3));
481 EXPECT_THAT(cb.mCalls[2], Eq(4000));
482 }
483
TEST_F(VSyncDispatchTimerQueueTest,rearmsFaroutTimeoutWhenCancellingCloseOne)484 TEST_F(VSyncDispatchTimerQueueTest, rearmsFaroutTimeoutWhenCancellingCloseOne) {
485 EXPECT_CALL(*mStubTracker.get(), nextAnticipatedVSyncTimeFrom(_, _))
486 .Times(4)
487 .WillOnce(Return(10000))
488 .WillOnce(Return(1000))
489 .WillOnce(Return(10000))
490 .WillOnce(Return(10000));
491
492 Sequence seq;
493 EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
494 EXPECT_CALL(mMockClock, alarmAt(_, 750)).InSequence(seq);
495 EXPECT_CALL(mMockClock, alarmAt(_, 9900)).InSequence(seq);
496
497 CountingCallback cb0(mDispatch);
498 CountingCallback cb1(mDispatch);
499
500 mDispatch->schedule(cb0, {.workDuration = 100, .readyDuration = 0, .lastVsync = mPeriod * 10});
501 mDispatch->schedule(cb1, {.workDuration = 250, .readyDuration = 0, .lastVsync = mPeriod});
502 mDispatch->cancel(cb1);
503 }
504
TEST_F(VSyncDispatchTimerQueueTest,noUnnecessaryRearmsWhenRescheduling)505 TEST_F(VSyncDispatchTimerQueueTest, noUnnecessaryRearmsWhenRescheduling) {
506 Sequence seq;
507 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
508 EXPECT_CALL(mMockClock, alarmAt(_, 700)).InSequence(seq);
509
510 CountingCallback cb0(mDispatch);
511 CountingCallback cb1(mDispatch);
512
513 mDispatch->schedule(cb0, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
514 mDispatch->schedule(cb1, {.workDuration = 200, .readyDuration = 0, .lastVsync = 1000});
515 mDispatch->schedule(cb1, {.workDuration = 300, .readyDuration = 0, .lastVsync = 1000});
516 advanceToNextCallback();
517 }
518
TEST_F(VSyncDispatchTimerQueueTest,necessaryRearmsWhenModifying)519 TEST_F(VSyncDispatchTimerQueueTest, necessaryRearmsWhenModifying) {
520 Sequence seq;
521 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
522 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
523 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
524
525 CountingCallback cb0(mDispatch);
526 CountingCallback cb1(mDispatch);
527
528 mDispatch->schedule(cb0, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
529 mDispatch->schedule(cb1, {.workDuration = 200, .readyDuration = 0, .lastVsync = 1000});
530 mDispatch->schedule(cb1, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
531 advanceToNextCallback();
532 }
533
TEST_F(VSyncDispatchTimerQueueTest,modifyIntoGroup)534 TEST_F(VSyncDispatchTimerQueueTest, modifyIntoGroup) {
535 Sequence seq;
536 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
537 EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
538 EXPECT_CALL(mMockClock, alarmAt(_, 1590)).InSequence(seq);
539 EXPECT_CALL(mMockClock, alarmAt(_, 1600)).InSequence(seq);
540
541 auto offset = 400;
542 auto closeOffset = offset + mDispatchGroupThreshold - 1;
543 auto notCloseOffset = offset + 2 * mDispatchGroupThreshold;
544
545 CountingCallback cb0(mDispatch);
546 CountingCallback cb1(mDispatch);
547
548 mDispatch->schedule(cb0, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
549 mDispatch->schedule(cb1, {.workDuration = 200, .readyDuration = 0, .lastVsync = 1000});
550 mDispatch->schedule(cb1, {.workDuration = closeOffset, .readyDuration = 0, .lastVsync = 1000});
551
552 advanceToNextCallback();
553 ASSERT_THAT(cb0.mCalls.size(), Eq(1));
554 EXPECT_THAT(cb0.mCalls[0], Eq(mPeriod));
555 ASSERT_THAT(cb1.mCalls.size(), Eq(1));
556 EXPECT_THAT(cb1.mCalls[0], Eq(mPeriod));
557
558 mDispatch->schedule(cb0, {.workDuration = 400, .readyDuration = 0, .lastVsync = 2000});
559 mDispatch->schedule(cb1,
560 {.workDuration = notCloseOffset, .readyDuration = 0, .lastVsync = 2000});
561 advanceToNextCallback();
562 ASSERT_THAT(cb1.mCalls.size(), Eq(2));
563 EXPECT_THAT(cb1.mCalls[1], Eq(2000));
564
565 advanceToNextCallback();
566 ASSERT_THAT(cb0.mCalls.size(), Eq(2));
567 EXPECT_THAT(cb0.mCalls[1], Eq(2000));
568 }
569
TEST_F(VSyncDispatchTimerQueueTest,rearmsWhenEndingAndDoesntCancel)570 TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenEndingAndDoesntCancel) {
571 Sequence seq;
572 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
573 EXPECT_CALL(mMockClock, alarmAt(_, 800)).InSequence(seq);
574 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
575 EXPECT_CALL(mMockClock, alarmCancel());
576
577 CountingCallback cb0(mDispatch);
578 CountingCallback cb1(mDispatch);
579
580 mDispatch->schedule(cb0, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
581 mDispatch->schedule(cb1, {.workDuration = 200, .readyDuration = 0, .lastVsync = 1000});
582 advanceToNextCallback();
583 EXPECT_EQ(mDispatch->cancel(cb0), CancelResult::Cancelled);
584 }
585
TEST_F(VSyncDispatchTimerQueueTest,setAlarmCallsAtCorrectTimeWithChangingVsync)586 TEST_F(VSyncDispatchTimerQueueTest, setAlarmCallsAtCorrectTimeWithChangingVsync) {
587 EXPECT_CALL(*mStubTracker.get(), nextAnticipatedVSyncTimeFrom(_, _))
588 .Times(3)
589 .WillOnce(Return(950))
590 .WillOnce(Return(1975))
591 .WillOnce(Return(2950));
592
593 CountingCallback cb(mDispatch);
594 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 920});
595
596 mMockClock.advanceBy(850);
597 EXPECT_THAT(cb.mCalls.size(), Eq(1));
598
599 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1900});
600 mMockClock.advanceBy(900);
601 EXPECT_THAT(cb.mCalls.size(), Eq(1));
602 mMockClock.advanceBy(125);
603 EXPECT_THAT(cb.mCalls.size(), Eq(2));
604
605 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2900});
606 mMockClock.advanceBy(975);
607 EXPECT_THAT(cb.mCalls.size(), Eq(3));
608 }
609
TEST_F(VSyncDispatchTimerQueueTest,callbackReentrancy)610 TEST_F(VSyncDispatchTimerQueueTest, callbackReentrancy) {
611 Sequence seq;
612 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
613 EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
614
615 VSyncDispatch::CallbackToken tmp;
616 tmp = mDispatch->registerCallback(
617 [&](auto, auto, auto) {
618 mDispatch->schedule(tmp,
619 {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000});
620 },
621 "o.o");
622
623 mDispatch->schedule(tmp, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
624 advanceToNextCallback();
625 }
626
TEST_F(VSyncDispatchTimerQueueTest,callbackReentrantWithPastWakeup)627 TEST_F(VSyncDispatchTimerQueueTest, callbackReentrantWithPastWakeup) {
628 VSyncDispatch::CallbackToken tmp;
629 std::optional<nsecs_t> lastTarget;
630 tmp = mDispatch->registerCallback(
631 [&](auto timestamp, auto, auto) {
632 auto result = mDispatch->schedule(tmp,
633 {.workDuration = 400,
634 .readyDuration = 0,
635 .lastVsync = timestamp - mVsyncMoveThreshold});
636 EXPECT_TRUE(result.has_value());
637 EXPECT_EQ(mPeriod + timestamp - 400, result->callbackTime.ns());
638 EXPECT_EQ(mPeriod + timestamp, result->vsyncTime.ns());
639 result = mDispatch->schedule(tmp,
640 {.workDuration = 400,
641 .readyDuration = 0,
642 .lastVsync = timestamp});
643 EXPECT_TRUE(result.has_value());
644 EXPECT_EQ(mPeriod + timestamp - 400, result->callbackTime.ns());
645 EXPECT_EQ(mPeriod + timestamp, result->vsyncTime.ns());
646 result = mDispatch->schedule(tmp,
647 {.workDuration = 400,
648 .readyDuration = 0,
649 .lastVsync = timestamp + mVsyncMoveThreshold});
650 EXPECT_TRUE(result.has_value());
651 EXPECT_EQ(mPeriod + timestamp - 400, result->callbackTime.ns());
652 EXPECT_EQ(mPeriod + timestamp, result->vsyncTime.ns());
653 lastTarget = timestamp;
654 },
655 "oo");
656
657 mDispatch->schedule(tmp, {.workDuration = 999, .readyDuration = 0, .lastVsync = 1000});
658 advanceToNextCallback();
659 EXPECT_THAT(lastTarget, Eq(1000));
660
661 advanceToNextCallback();
662 EXPECT_THAT(lastTarget, Eq(2000));
663 }
664
TEST_F(VSyncDispatchTimerQueueTest,modificationsAroundVsyncTime)665 TEST_F(VSyncDispatchTimerQueueTest, modificationsAroundVsyncTime) {
666 Sequence seq;
667 EXPECT_CALL(mMockClock, alarmAt(_, 1000)).InSequence(seq);
668 EXPECT_CALL(mMockClock, alarmAt(_, 950)).InSequence(seq);
669 EXPECT_CALL(mMockClock, alarmAt(_, 1950)).InSequence(seq);
670 EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
671
672 CountingCallback cb(mDispatch);
673 mDispatch->schedule(cb, {.workDuration = 0, .readyDuration = 0, .lastVsync = 1000});
674
675 mMockClock.advanceBy(750);
676 mDispatch->schedule(cb, {.workDuration = 50, .readyDuration = 0, .lastVsync = 1000});
677
678 advanceToNextCallback();
679 mDispatch->schedule(cb, {.workDuration = 50, .readyDuration = 0, .lastVsync = 2000});
680
681 mMockClock.advanceBy(800);
682 mDispatch->schedule(cb, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000});
683 }
684
TEST_F(VSyncDispatchTimerQueueTest,lateModifications)685 TEST_F(VSyncDispatchTimerQueueTest, lateModifications) {
686 Sequence seq;
687 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
688 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
689 EXPECT_CALL(mMockClock, alarmAt(_, 850)).InSequence(seq);
690 EXPECT_CALL(mMockClock, alarmAt(_, 1800)).InSequence(seq);
691
692 CountingCallback cb0(mDispatch);
693 CountingCallback cb1(mDispatch);
694
695 mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
696 mDispatch->schedule(cb1, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
697
698 advanceToNextCallback();
699 mDispatch->schedule(cb0, {.workDuration = 200, .readyDuration = 0, .lastVsync = 2000});
700 mDispatch->schedule(cb1, {.workDuration = 150, .readyDuration = 0, .lastVsync = 1000});
701
702 advanceToNextCallback();
703 advanceToNextCallback();
704 }
705
TEST_F(VSyncDispatchTimerQueueTest,doesntCancelPriorValidTimerForFutureMod)706 TEST_F(VSyncDispatchTimerQueueTest, doesntCancelPriorValidTimerForFutureMod) {
707 Sequence seq;
708 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
709
710 CountingCallback cb0(mDispatch);
711 CountingCallback cb1(mDispatch);
712 mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
713 mDispatch->schedule(cb1, {.workDuration = 500, .readyDuration = 0, .lastVsync = 20000});
714 }
715
TEST_F(VSyncDispatchTimerQueueTest,setsTimerAfterCancellation)716 TEST_F(VSyncDispatchTimerQueueTest, setsTimerAfterCancellation) {
717 Sequence seq;
718 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
719 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
720 EXPECT_CALL(mMockClock, alarmAt(_, 900)).InSequence(seq);
721
722 CountingCallback cb0(mDispatch);
723 mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
724 mDispatch->cancel(cb0);
725 mDispatch->schedule(cb0, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
726 }
727
TEST_F(VSyncDispatchTimerQueueTest,makingUpIdsError)728 TEST_F(VSyncDispatchTimerQueueTest, makingUpIdsError) {
729 VSyncDispatch::CallbackToken token(100);
730 EXPECT_FALSE(
731 mDispatch->schedule(token, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000})
732 .has_value());
733 EXPECT_THAT(mDispatch->cancel(token), Eq(CancelResult::Error));
734 }
735
TEST_F(VSyncDispatchTimerQueueTest,canMoveCallbackBackwardsInTime)736 TEST_F(VSyncDispatchTimerQueueTest, canMoveCallbackBackwardsInTime) {
737 CountingCallback cb0(mDispatch);
738 auto result =
739 mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
740 EXPECT_TRUE(result.has_value());
741 EXPECT_EQ(500, result->callbackTime.ns());
742 EXPECT_EQ(1000, result->vsyncTime.ns());
743 result = mDispatch->schedule(cb0, {.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
744 EXPECT_TRUE(result.has_value());
745 EXPECT_EQ(900, result->callbackTime.ns());
746 EXPECT_EQ(1000, result->vsyncTime.ns());
747 }
748
749 // b/1450138150
TEST_F(VSyncDispatchTimerQueueTest,doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync)750 TEST_F(VSyncDispatchTimerQueueTest, doesNotMoveCallbackBackwardsAndSkipAScheduledTargetVSync) {
751 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false);
752
753 EXPECT_CALL(mMockClock, alarmAt(_, 500));
754 CountingCallback cb(mDispatch);
755 auto result =
756 mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
757 EXPECT_TRUE(result.has_value());
758 EXPECT_EQ(500, result->callbackTime.ns());
759 EXPECT_EQ(1000, result->vsyncTime.ns());
760 mMockClock.advanceBy(400);
761
762 result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000});
763 EXPECT_TRUE(result.has_value());
764 EXPECT_EQ(1200, result->callbackTime.ns());
765 EXPECT_EQ(2000, result->vsyncTime.ns());
766
767 advanceToNextCallback();
768 ASSERT_THAT(cb.mCalls.size(), Eq(1));
769 }
770
771 // b/1450138150
TEST_F(VSyncDispatchTimerQueueTest,movesCallbackBackwardsAndSkipAScheduledTargetVSync)772 TEST_F(VSyncDispatchTimerQueueTest, movesCallbackBackwardsAndSkipAScheduledTargetVSync) {
773 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true);
774
775 Sequence seq;
776 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
777 EXPECT_CALL(mMockClock, alarmAt(_, 400)).InSequence(seq);
778 CountingCallback cb(mDispatch);
779 auto result =
780 mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
781 EXPECT_TRUE(result.has_value());
782 EXPECT_EQ(500, result->callbackTime.ns());
783 EXPECT_EQ(1000, result->vsyncTime.ns());
784 mMockClock.advanceBy(400);
785
786 result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000});
787 EXPECT_TRUE(result.has_value());
788 EXPECT_EQ(400, result->callbackTime.ns());
789 EXPECT_EQ(1000, result->vsyncTime.ns());
790
791 advanceToNextCallback();
792 ASSERT_THAT(cb.mCalls.size(), Eq(1));
793 }
794
TEST_F(VSyncDispatchTimerQueueTest,targetOffsetMovingBackALittleCanStillSchedule)795 TEST_F(VSyncDispatchTimerQueueTest, targetOffsetMovingBackALittleCanStillSchedule) {
796 EXPECT_CALL(*mStubTracker.get(),
797 nextAnticipatedVSyncTimeFrom(1000, std::optional<nsecs_t>(1000)))
798 .Times(2)
799 .WillOnce(Return(1000))
800 .WillOnce(Return(1002));
801 CountingCallback cb(mDispatch);
802 auto result =
803 mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
804 EXPECT_TRUE(result.has_value());
805 EXPECT_EQ(500, result->callbackTime.ns());
806 EXPECT_EQ(1000, result->vsyncTime.ns());
807 mMockClock.advanceBy(400);
808 result = mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
809 EXPECT_TRUE(result.has_value());
810 EXPECT_EQ(602, result->callbackTime.ns());
811 EXPECT_EQ(1002, result->vsyncTime.ns());
812 }
813
TEST_F(VSyncDispatchTimerQueueTest,canScheduleNegativeOffsetAgainstDifferentPeriods)814 TEST_F(VSyncDispatchTimerQueueTest, canScheduleNegativeOffsetAgainstDifferentPeriods) {
815 CountingCallback cb0(mDispatch);
816 auto result =
817 mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
818 EXPECT_TRUE(result.has_value());
819 EXPECT_EQ(500, result->callbackTime.ns());
820 EXPECT_EQ(1000, result->vsyncTime.ns());
821 advanceToNextCallback();
822 result =
823 mDispatch->schedule(cb0, {.workDuration = 1100, .readyDuration = 0, .lastVsync = 2000});
824 EXPECT_TRUE(result.has_value());
825 EXPECT_EQ(900, result->callbackTime.ns());
826 EXPECT_EQ(2000, result->vsyncTime.ns());
827 }
828
TEST_F(VSyncDispatchTimerQueueTest,canScheduleLargeNegativeOffset)829 TEST_F(VSyncDispatchTimerQueueTest, canScheduleLargeNegativeOffset) {
830 Sequence seq;
831 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
832 EXPECT_CALL(mMockClock, alarmAt(_, 1100)).InSequence(seq);
833 CountingCallback cb0(mDispatch);
834 auto result =
835 mDispatch->schedule(cb0, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
836 EXPECT_TRUE(result.has_value());
837 EXPECT_EQ(500, result->callbackTime.ns());
838 EXPECT_EQ(1000, result->vsyncTime.ns());
839 advanceToNextCallback();
840 result =
841 mDispatch->schedule(cb0, {.workDuration = 1900, .readyDuration = 0, .lastVsync = 2000});
842 EXPECT_TRUE(result.has_value());
843 EXPECT_EQ(1100, result->callbackTime.ns());
844 EXPECT_EQ(3000, result->vsyncTime.ns());
845 }
846
TEST_F(VSyncDispatchTimerQueueTest,scheduleUpdatesDoesNotAffectSchedulingState)847 TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesNotAffectSchedulingState) {
848 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false);
849
850 EXPECT_CALL(mMockClock, alarmAt(_, 600));
851
852 CountingCallback cb(mDispatch);
853 auto result =
854 mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
855 EXPECT_TRUE(result.has_value());
856 EXPECT_EQ(600, result->callbackTime.ns());
857 EXPECT_EQ(1000, result->vsyncTime.ns());
858
859 result = mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .lastVsync = 1000});
860 EXPECT_TRUE(result.has_value());
861 EXPECT_EQ(600, result->callbackTime.ns());
862 EXPECT_EQ(2000, result->vsyncTime.ns());
863
864 advanceToNextCallback();
865 }
866
TEST_F(VSyncDispatchTimerQueueTest,scheduleUpdatesDoesAffectSchedulingState)867 TEST_F(VSyncDispatchTimerQueueTest, scheduleUpdatesDoesAffectSchedulingState) {
868 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true);
869
870 Sequence seq;
871 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
872 EXPECT_CALL(mMockClock, alarmAt(_, 0)).InSequence(seq);
873
874 CountingCallback cb(mDispatch);
875 auto result =
876 mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
877 EXPECT_TRUE(result.has_value());
878 EXPECT_EQ(600, result->callbackTime.ns());
879 EXPECT_EQ(1000, result->vsyncTime.ns());
880
881 result = mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .lastVsync = 1000});
882 EXPECT_TRUE(result.has_value());
883 EXPECT_EQ(0, result->callbackTime.ns());
884 EXPECT_EQ(1000, result->vsyncTime.ns());
885
886 advanceToNextCallback();
887 }
888
TEST_F(VSyncDispatchTimerQueueTest,helperMove)889 TEST_F(VSyncDispatchTimerQueueTest, helperMove) {
890 EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
891 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
892
893 VSyncCallbackRegistration cb(
894 mDispatch, [](auto, auto, auto) {}, "");
895 VSyncCallbackRegistration cb1(std::move(cb));
896 cb.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
897 cb.cancel();
898
899 cb1.schedule({.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
900 cb1.cancel();
901 }
902
TEST_F(VSyncDispatchTimerQueueTest,helperMoveAssign)903 TEST_F(VSyncDispatchTimerQueueTest, helperMoveAssign) {
904 EXPECT_CALL(mMockClock, alarmAt(_, 500)).Times(1);
905 EXPECT_CALL(mMockClock, alarmCancel()).Times(1);
906
907 VSyncCallbackRegistration cb(
908 mDispatch, [](auto, auto, auto) {}, "");
909 VSyncCallbackRegistration cb1(
910 mDispatch, [](auto, auto, auto) {}, "");
911 cb1 = std::move(cb);
912 cb.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 1000});
913 cb.cancel();
914
915 cb1.schedule({.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
916 cb1.cancel();
917 }
918
919 // b/154303580
TEST_F(VSyncDispatchTimerQueueTest,skipsSchedulingIfTimerReschedulingIsImminent)920 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminent) {
921 Sequence seq;
922 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
923 EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
924 CountingCallback cb1(mDispatch);
925 CountingCallback cb2(mDispatch);
926
927 auto result =
928 mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
929 EXPECT_TRUE(result.has_value());
930 EXPECT_EQ(600, result->callbackTime.ns());
931 EXPECT_EQ(1000, result->vsyncTime.ns());
932
933 mMockClock.setLag(100);
934 mMockClock.advanceBy(620);
935
936 result = mDispatch->schedule(cb2, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000});
937 EXPECT_TRUE(result.has_value());
938 EXPECT_EQ(1900, result->callbackTime.ns());
939 EXPECT_EQ(2000, result->vsyncTime.ns());
940 mMockClock.advanceBy(80);
941
942 EXPECT_THAT(cb1.mCalls.size(), Eq(1));
943 EXPECT_THAT(cb2.mCalls.size(), Eq(0));
944 }
945
946 // b/154303580.
947 // If the same callback tries to reschedule itself after it's too late, timer opts to apply the
948 // update later, as opposed to blocking the calling thread.
TEST_F(VSyncDispatchTimerQueueTest,skipsSchedulingIfTimerReschedulingIsImminentSameCallback)949 TEST_F(VSyncDispatchTimerQueueTest, skipsSchedulingIfTimerReschedulingIsImminentSameCallback) {
950 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false);
951
952 Sequence seq;
953 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
954 EXPECT_CALL(mMockClock, alarmAt(_, 1630)).InSequence(seq);
955 CountingCallback cb(mDispatch);
956
957 auto result =
958 mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
959 EXPECT_TRUE(result.has_value());
960 EXPECT_EQ(600, result->callbackTime.ns());
961 EXPECT_EQ(1000, result->vsyncTime.ns());
962
963 mMockClock.setLag(100);
964 mMockClock.advanceBy(620);
965
966 result = mDispatch->schedule(cb, {.workDuration = 370, .readyDuration = 0, .lastVsync = 2000});
967 EXPECT_TRUE(result.has_value());
968 EXPECT_EQ(1630, result->callbackTime.ns());
969 EXPECT_EQ(2000, result->vsyncTime.ns());
970 mMockClock.advanceBy(80);
971
972 EXPECT_THAT(cb.mCalls.size(), Eq(1));
973 }
974
975 // b/154303580.
976 // If the same callback tries to reschedule itself after it's too late, timer opts to apply the
977 // update later, as opposed to blocking the calling thread.
TEST_F(VSyncDispatchTimerQueueTest,doesntSkipSchedulingIfTimerReschedulingIsImminentSameCallback)978 TEST_F(VSyncDispatchTimerQueueTest, doesntSkipSchedulingIfTimerReschedulingIsImminentSameCallback) {
979 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true);
980
981 Sequence seq;
982 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
983 EXPECT_CALL(mMockClock, alarmAt(_, 1630)).InSequence(seq);
984 CountingCallback cb(mDispatch);
985
986 auto result =
987 mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
988 EXPECT_TRUE(result.has_value());
989 EXPECT_EQ(600, result->callbackTime.ns());
990 EXPECT_EQ(1000, result->vsyncTime.ns());
991
992 mMockClock.setLag(100);
993 mMockClock.advanceBy(620);
994
995 result = mDispatch->schedule(cb, {.workDuration = 370, .readyDuration = 0, .lastVsync = 2000});
996 EXPECT_TRUE(result.has_value());
997 EXPECT_EQ(600, result->callbackTime.ns());
998 EXPECT_EQ(1000, result->vsyncTime.ns());
999 mMockClock.advanceBy(80);
1000
1001 ASSERT_EQ(1, cb.mCalls.size());
1002 EXPECT_EQ(1000, cb.mCalls[0]);
1003
1004 ASSERT_EQ(1, cb.mWakeupTime.size());
1005 EXPECT_EQ(600, cb.mWakeupTime[0]);
1006 }
1007
1008 // b/154303580.
TEST_F(VSyncDispatchTimerQueueTest,skipsRearmingWhenNotNextScheduled)1009 TEST_F(VSyncDispatchTimerQueueTest, skipsRearmingWhenNotNextScheduled) {
1010 Sequence seq;
1011 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
1012 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
1013 CountingCallback cb1(mDispatch);
1014 CountingCallback cb2(mDispatch);
1015
1016 auto result =
1017 mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
1018 EXPECT_TRUE(result.has_value());
1019 EXPECT_EQ(600, result->callbackTime.ns());
1020 EXPECT_EQ(1000, result->vsyncTime.ns());
1021 result = mDispatch->schedule(cb2, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000});
1022 EXPECT_TRUE(result.has_value());
1023 EXPECT_EQ(1900, result->callbackTime.ns());
1024 EXPECT_EQ(2000, result->vsyncTime.ns());
1025
1026 mMockClock.setLag(100);
1027 mMockClock.advanceBy(620);
1028
1029 EXPECT_EQ(mDispatch->cancel(cb2), CancelResult::Cancelled);
1030
1031 mMockClock.advanceBy(80);
1032
1033 EXPECT_THAT(cb1.mCalls.size(), Eq(1));
1034 EXPECT_THAT(cb2.mCalls.size(), Eq(0));
1035 }
1036
TEST_F(VSyncDispatchTimerQueueTest,rearmsWhenCancelledAndIsNextScheduled)1037 TEST_F(VSyncDispatchTimerQueueTest, rearmsWhenCancelledAndIsNextScheduled) {
1038 Sequence seq;
1039 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
1040 EXPECT_CALL(mMockClock, alarmAt(_, 1900)).InSequence(seq);
1041 EXPECT_CALL(mMockClock, alarmCancel()).InSequence(seq);
1042 CountingCallback cb1(mDispatch);
1043 CountingCallback cb2(mDispatch);
1044
1045 auto result =
1046 mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
1047 EXPECT_TRUE(result.has_value());
1048 EXPECT_EQ(600, result->callbackTime.ns());
1049 EXPECT_EQ(1000, result->vsyncTime.ns());
1050 result = mDispatch->schedule(cb2, {.workDuration = 100, .readyDuration = 0, .lastVsync = 2000});
1051 EXPECT_TRUE(result.has_value());
1052 EXPECT_EQ(1900, result->callbackTime.ns());
1053 EXPECT_EQ(2000, result->vsyncTime.ns());
1054
1055 mMockClock.setLag(100);
1056 mMockClock.advanceBy(620);
1057
1058 EXPECT_EQ(mDispatch->cancel(cb1), CancelResult::Cancelled);
1059
1060 EXPECT_THAT(cb1.mCalls.size(), Eq(0));
1061 EXPECT_THAT(cb2.mCalls.size(), Eq(0));
1062 mMockClock.advanceToNextCallback();
1063
1064 EXPECT_THAT(cb1.mCalls.size(), Eq(0));
1065 EXPECT_THAT(cb2.mCalls.size(), Eq(1));
1066 }
1067
TEST_F(VSyncDispatchTimerQueueTest,laggedTimerGroupsCallbacksWithinLag)1068 TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) {
1069 CountingCallback cb1(mDispatch);
1070 CountingCallback cb2(mDispatch);
1071
1072 Sequence seq;
1073 EXPECT_CALL(*mStubTracker.get(),
1074 nextAnticipatedVSyncTimeFrom(1000, std::optional<nsecs_t>(1000)))
1075 .InSequence(seq)
1076 .WillOnce(Return(1000));
1077 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
1078 EXPECT_CALL(*mStubTracker.get(),
1079 nextAnticipatedVSyncTimeFrom(1000, std::optional<nsecs_t>(1000)))
1080 .InSequence(seq)
1081 .WillOnce(Return(1000));
1082
1083 auto result =
1084 mDispatch->schedule(cb1, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
1085 EXPECT_TRUE(result.has_value());
1086 EXPECT_EQ(600, result->callbackTime.ns());
1087 EXPECT_EQ(1000, result->vsyncTime.ns());
1088 result = mDispatch->schedule(cb2, {.workDuration = 390, .readyDuration = 0, .lastVsync = 1000});
1089 EXPECT_TRUE(result.has_value());
1090 EXPECT_EQ(610, result->callbackTime.ns());
1091 EXPECT_EQ(1000, result->vsyncTime.ns());
1092
1093 mMockClock.setLag(100);
1094 mMockClock.advanceBy(700);
1095
1096 ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1));
1097 EXPECT_THAT(cb1.mWakeupTime[0], Eq(600));
1098 ASSERT_THAT(cb1.mReadyTime.size(), Eq(1));
1099 EXPECT_THAT(cb1.mReadyTime[0], Eq(1000));
1100 ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1));
1101 EXPECT_THAT(cb2.mWakeupTime[0], Eq(610));
1102 ASSERT_THAT(cb2.mReadyTime.size(), Eq(1));
1103 EXPECT_THAT(cb2.mReadyTime[0], Eq(1000));
1104 }
1105
TEST_F(VSyncDispatchTimerQueueTest,basicAlarmSettingFutureWithReadyDuration)1106 TEST_F(VSyncDispatchTimerQueueTest, basicAlarmSettingFutureWithReadyDuration) {
1107 auto intended = mPeriod - 230;
1108 EXPECT_CALL(mMockClock, alarmAt(_, 900));
1109
1110 CountingCallback cb(mDispatch);
1111 const auto result =
1112 mDispatch->schedule(cb,
1113 {.workDuration = 70, .readyDuration = 30, .lastVsync = intended});
1114 EXPECT_TRUE(result.has_value());
1115 EXPECT_EQ(900, result->callbackTime.ns());
1116 EXPECT_EQ(1000, result->vsyncTime.ns());
1117 advanceToNextCallback();
1118
1119 ASSERT_THAT(cb.mCalls.size(), Eq(1));
1120 EXPECT_THAT(cb.mCalls[0], Eq(mPeriod));
1121 ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
1122 EXPECT_THAT(cb.mWakeupTime[0], 900);
1123 ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
1124 EXPECT_THAT(cb.mReadyTime[0], 970);
1125 }
1126
TEST_F(VSyncDispatchTimerQueueTest,updatesVsyncTimeForCloseWakeupTime)1127 TEST_F(VSyncDispatchTimerQueueTest, updatesVsyncTimeForCloseWakeupTime) {
1128 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false);
1129
1130 Sequence seq;
1131 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
1132
1133 CountingCallback cb(mDispatch);
1134
1135 mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
1136 mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .lastVsync = 1000});
1137
1138 advanceToNextCallback();
1139
1140 advanceToNextCallback();
1141
1142 ASSERT_THAT(cb.mCalls.size(), Eq(1));
1143 EXPECT_THAT(cb.mCalls[0], Eq(2000));
1144 ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
1145 EXPECT_THAT(cb.mWakeupTime[0], Eq(600));
1146 ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
1147 EXPECT_THAT(cb.mReadyTime[0], Eq(2000));
1148 }
1149
TEST_F(VSyncDispatchTimerQueueTest,doesNotUpdatesVsyncTimeForCloseWakeupTime)1150 TEST_F(VSyncDispatchTimerQueueTest, doesNotUpdatesVsyncTimeForCloseWakeupTime) {
1151 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true);
1152
1153 Sequence seq;
1154 EXPECT_CALL(mMockClock, alarmAt(_, 600)).InSequence(seq);
1155 EXPECT_CALL(mMockClock, alarmAt(_, 0)).InSequence(seq);
1156
1157 CountingCallback cb(mDispatch);
1158
1159 mDispatch->schedule(cb, {.workDuration = 400, .readyDuration = 0, .lastVsync = 1000});
1160 mDispatch->schedule(cb, {.workDuration = 1400, .readyDuration = 0, .lastVsync = 1000});
1161
1162 advanceToNextCallback();
1163
1164 advanceToNextCallback();
1165
1166 ASSERT_THAT(cb.mCalls.size(), Eq(1));
1167 EXPECT_THAT(cb.mCalls[0], Eq(1000));
1168 ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
1169 EXPECT_THAT(cb.mWakeupTime[0], Eq(0));
1170 ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
1171 EXPECT_THAT(cb.mReadyTime[0], Eq(1000));
1172 }
1173
TEST_F(VSyncDispatchTimerQueueTest,skipAVsyc)1174 TEST_F(VSyncDispatchTimerQueueTest, skipAVsyc) {
1175 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false);
1176
1177 EXPECT_CALL(mMockClock, alarmAt(_, 500));
1178 CountingCallback cb(mDispatch);
1179 auto result =
1180 mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
1181 EXPECT_TRUE(result.has_value());
1182 EXPECT_EQ(500, result->callbackTime.ns());
1183 EXPECT_EQ(1000, result->vsyncTime.ns());
1184 mMockClock.advanceBy(300);
1185
1186 result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000});
1187 EXPECT_TRUE(result.has_value());
1188 EXPECT_EQ(1200, result->callbackTime.ns());
1189 EXPECT_EQ(2000, result->vsyncTime.ns());
1190
1191 advanceToNextCallback();
1192 ASSERT_THAT(cb.mCalls.size(), Eq(1));
1193 }
1194
TEST_F(VSyncDispatchTimerQueueTest,dontskipAVsyc)1195 TEST_F(VSyncDispatchTimerQueueTest, dontskipAVsyc) {
1196 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true);
1197
1198 Sequence seq;
1199 EXPECT_CALL(mMockClock, alarmAt(_, 500)).InSequence(seq);
1200 EXPECT_CALL(mMockClock, alarmAt(_, 300)).InSequence(seq);
1201 CountingCallback cb(mDispatch);
1202 auto result =
1203 mDispatch->schedule(cb, {.workDuration = 500, .readyDuration = 0, .lastVsync = 1000});
1204 EXPECT_TRUE(result.has_value());
1205 EXPECT_EQ(500, result->callbackTime.ns());
1206 EXPECT_EQ(1000, result->vsyncTime.ns());
1207 mMockClock.advanceBy(300);
1208
1209 result = mDispatch->schedule(cb, {.workDuration = 800, .readyDuration = 0, .lastVsync = 1000});
1210 EXPECT_TRUE(result.has_value());
1211 EXPECT_EQ(300, result->callbackTime.ns());
1212 EXPECT_EQ(1000, result->vsyncTime.ns());
1213
1214 advanceToNextCallback();
1215 ASSERT_THAT(cb.mCalls.size(), Eq(1));
1216 EXPECT_THAT(cb.mCalls[0], Eq(1000));
1217 ASSERT_THAT(cb.mWakeupTime.size(), Eq(1));
1218 EXPECT_THAT(cb.mWakeupTime[0], Eq(300));
1219 ASSERT_THAT(cb.mReadyTime.size(), Eq(1));
1220 EXPECT_THAT(cb.mReadyTime[0], Eq(1000));
1221 }
1222
1223 class VSyncDispatchTimerQueueEntryTest : public testing::Test {
1224 protected:
1225 nsecs_t const mPeriod = 1000;
1226 nsecs_t const mVsyncMoveThreshold = 200;
1227 std::shared_ptr<NiceMock<MockVSyncTracker>> mStubTracker =
1228 std::make_shared<NiceMock<MockVSyncTracker>>(mPeriod);
1229 };
1230
TEST_F(VSyncDispatchTimerQueueEntryTest,stateAfterInitialization)1231 TEST_F(VSyncDispatchTimerQueueEntryTest, stateAfterInitialization) {
1232 std::string name("basicname");
1233 VSyncDispatchTimerQueueEntry entry(
1234 name, [](auto, auto, auto) {}, mVsyncMoveThreshold);
1235 EXPECT_THAT(entry.name(), Eq(name));
1236 EXPECT_FALSE(entry.lastExecutedVsyncTarget());
1237 EXPECT_FALSE(entry.wakeupTime());
1238 }
1239
TEST_F(VSyncDispatchTimerQueueEntryTest,stateScheduling)1240 TEST_F(VSyncDispatchTimerQueueEntryTest, stateScheduling) {
1241 VSyncDispatchTimerQueueEntry entry(
1242 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1243
1244 EXPECT_FALSE(entry.wakeupTime());
1245 const auto scheduleResult =
1246 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1247 *mStubTracker, 0);
1248 EXPECT_EQ(900, scheduleResult.callbackTime.ns());
1249 EXPECT_EQ(1000, scheduleResult.vsyncTime.ns());
1250 auto const wakeup = entry.wakeupTime();
1251 ASSERT_TRUE(wakeup);
1252 EXPECT_THAT(*wakeup, Eq(900));
1253
1254 entry.disarm();
1255 EXPECT_FALSE(entry.wakeupTime());
1256 }
1257
TEST_F(VSyncDispatchTimerQueueEntryTest,stateSchedulingReallyLongWakeupLatency)1258 TEST_F(VSyncDispatchTimerQueueEntryTest, stateSchedulingReallyLongWakeupLatency) {
1259 auto const duration = 500;
1260 auto const now = 8750;
1261
1262 EXPECT_CALL(*mStubTracker.get(),
1263 nextAnticipatedVSyncTimeFrom(now + duration, std::optional<nsecs_t>(994)))
1264 .Times(1)
1265 .WillOnce(Return(10000));
1266 VSyncDispatchTimerQueueEntry entry(
1267 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1268
1269 EXPECT_FALSE(entry.wakeupTime());
1270 const auto scheduleResult =
1271 entry.schedule({.workDuration = 500, .readyDuration = 0, .lastVsync = 994},
1272 *mStubTracker, now);
1273 EXPECT_EQ(9500, scheduleResult.callbackTime.ns());
1274 EXPECT_EQ(10000, scheduleResult.vsyncTime.ns());
1275 auto const wakeup = entry.wakeupTime();
1276 ASSERT_TRUE(wakeup);
1277 EXPECT_THAT(*wakeup, Eq(9500));
1278 }
1279
TEST_F(VSyncDispatchTimerQueueEntryTest,runCallback)1280 TEST_F(VSyncDispatchTimerQueueEntryTest, runCallback) {
1281 auto callCount = 0;
1282 auto vsyncCalledTime = 0;
1283 auto wakeupCalledTime = 0;
1284 auto readyCalledTime = 0;
1285 VSyncDispatchTimerQueueEntry entry(
1286 "test",
1287 [&](auto vsyncTime, auto wakeupTime, auto readyTime) {
1288 callCount++;
1289 vsyncCalledTime = vsyncTime;
1290 wakeupCalledTime = wakeupTime;
1291 readyCalledTime = readyTime;
1292 },
1293 mVsyncMoveThreshold);
1294
1295 const auto scheduleResult =
1296 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1297 *mStubTracker, 0);
1298 EXPECT_EQ(900, scheduleResult.callbackTime.ns());
1299 EXPECT_EQ(1000, scheduleResult.vsyncTime.ns());
1300 auto const wakeup = entry.wakeupTime();
1301 ASSERT_TRUE(wakeup);
1302 EXPECT_THAT(*wakeup, Eq(900));
1303
1304 auto const ready = entry.readyTime();
1305 ASSERT_TRUE(ready);
1306 EXPECT_THAT(*ready, Eq(1000));
1307
1308 entry.callback(entry.executing(), *wakeup, *ready);
1309
1310 EXPECT_THAT(callCount, Eq(1));
1311 EXPECT_THAT(vsyncCalledTime, Eq(mPeriod));
1312 EXPECT_THAT(wakeupCalledTime, Eq(*wakeup));
1313 EXPECT_FALSE(entry.wakeupTime());
1314 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
1315 ASSERT_TRUE(lastCalledTarget);
1316 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
1317 }
1318
TEST_F(VSyncDispatchTimerQueueEntryTest,updateCallback)1319 TEST_F(VSyncDispatchTimerQueueEntryTest, updateCallback) {
1320 EXPECT_CALL(*mStubTracker.get(), nextAnticipatedVSyncTimeFrom(_, _))
1321 .Times(2)
1322 .WillOnce(Return(1000))
1323 .WillOnce(Return(1020));
1324
1325 VSyncDispatchTimerQueueEntry entry(
1326 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1327
1328 EXPECT_FALSE(entry.wakeupTime());
1329 entry.update(*mStubTracker, 0);
1330 EXPECT_FALSE(entry.wakeupTime());
1331
1332 const auto scheduleResult =
1333 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1334 *mStubTracker, 0);
1335 EXPECT_EQ(900, scheduleResult.callbackTime.ns());
1336 EXPECT_EQ(1000, scheduleResult.vsyncTime.ns());
1337 auto wakeup = entry.wakeupTime();
1338 ASSERT_TRUE(wakeup);
1339 EXPECT_THAT(wakeup, Eq(900));
1340
1341 entry.update(*mStubTracker, 0);
1342 wakeup = entry.wakeupTime();
1343 ASSERT_TRUE(wakeup);
1344 EXPECT_THAT(*wakeup, Eq(920));
1345 }
1346
TEST_F(VSyncDispatchTimerQueueEntryTest,skipsUpdateIfJustScheduled)1347 TEST_F(VSyncDispatchTimerQueueEntryTest, skipsUpdateIfJustScheduled) {
1348 VSyncDispatchTimerQueueEntry entry(
1349 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1350 EXPECT_EQ(900,
1351 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1352 *mStubTracker.get(), 0)
1353 .callbackTime.ns());
1354 entry.update(*mStubTracker.get(), 0);
1355
1356 auto const wakeup = entry.wakeupTime();
1357 ASSERT_TRUE(wakeup);
1358 EXPECT_THAT(*wakeup, Eq(wakeup));
1359 }
1360
TEST_F(VSyncDispatchTimerQueueEntryTest,willSnapToNextTargettableVSync)1361 TEST_F(VSyncDispatchTimerQueueEntryTest, willSnapToNextTargettableVSync) {
1362 VSyncDispatchTimerQueueEntry entry(
1363 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1364 auto scheduleResult =
1365 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1366 *mStubTracker, 0);
1367
1368 EXPECT_EQ(900, scheduleResult.callbackTime.ns());
1369 EXPECT_EQ(1000, scheduleResult.vsyncTime.ns());
1370 entry.executing(); // 1000 is executing
1371 // had 1000 not been executing, this could have been scheduled for time 800.
1372 scheduleResult = entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500},
1373 *mStubTracker, 0);
1374 EXPECT_EQ(1800, scheduleResult.callbackTime.ns());
1375 EXPECT_EQ(2000, scheduleResult.vsyncTime.ns());
1376 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
1377 EXPECT_THAT(*entry.readyTime(), Eq(2000));
1378
1379 scheduleResult = entry.schedule({.workDuration = 50, .readyDuration = 0, .lastVsync = 500},
1380 *mStubTracker, 0);
1381 EXPECT_EQ(1950, scheduleResult.callbackTime.ns());
1382 EXPECT_EQ(2000, scheduleResult.vsyncTime.ns());
1383 EXPECT_THAT(*entry.wakeupTime(), Eq(1950));
1384 EXPECT_THAT(*entry.readyTime(), Eq(2000));
1385
1386 scheduleResult = entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 1001},
1387 *mStubTracker, 0);
1388 EXPECT_EQ(1800, scheduleResult.callbackTime.ns());
1389 EXPECT_EQ(2000, scheduleResult.vsyncTime.ns());
1390 EXPECT_THAT(*entry.wakeupTime(), Eq(1800));
1391 EXPECT_THAT(*entry.readyTime(), Eq(2000));
1392 }
1393
TEST_F(VSyncDispatchTimerQueueEntryTest,willRequestNextEstimateWhenSnappingToNextTargettableVSync)1394 TEST_F(VSyncDispatchTimerQueueEntryTest,
1395 willRequestNextEstimateWhenSnappingToNextTargettableVSync) {
1396 VSyncDispatchTimerQueueEntry entry(
1397 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1398
1399 Sequence seq;
1400 EXPECT_CALL(*mStubTracker.get(), nextAnticipatedVSyncTimeFrom(500, std::optional<nsecs_t>(500)))
1401 .InSequence(seq)
1402 .WillOnce(Return(1000));
1403 EXPECT_CALL(*mStubTracker.get(), nextAnticipatedVSyncTimeFrom(500, std::optional<nsecs_t>(500)))
1404 .InSequence(seq)
1405 .WillOnce(Return(1000));
1406 EXPECT_CALL(*mStubTracker.get(),
1407 nextAnticipatedVSyncTimeFrom(1000 + mVsyncMoveThreshold,
1408 std::optional<nsecs_t>(1000)))
1409 .InSequence(seq)
1410 .WillOnce(Return(2000));
1411
1412 auto scheduleResult =
1413 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1414 *mStubTracker, 0);
1415 EXPECT_EQ(900, scheduleResult.callbackTime.ns());
1416 EXPECT_EQ(1000, scheduleResult.vsyncTime.ns());
1417
1418 entry.executing(); // 1000 is executing
1419
1420 scheduleResult = entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500},
1421 *mStubTracker, 0);
1422 EXPECT_EQ(1800, scheduleResult.callbackTime.ns());
1423 EXPECT_EQ(2000, scheduleResult.vsyncTime.ns());
1424 }
1425
TEST_F(VSyncDispatchTimerQueueEntryTest,reportsScheduledIfStillTime)1426 TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) {
1427 VSyncDispatchTimerQueueEntry entry("test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1428 EXPECT_EQ(900,
1429 entry.schedule({.workDuration = 100, .readyDuration = 0, .lastVsync = 500},
1430 *mStubTracker, 0)
1431 .callbackTime.ns());
1432 EXPECT_EQ(800,
1433 entry.schedule({.workDuration = 200, .readyDuration = 0, .lastVsync = 500},
1434 *mStubTracker, 0)
1435 .callbackTime.ns());
1436 EXPECT_EQ(950,
1437 entry.schedule({.workDuration = 50, .readyDuration = 0, .lastVsync = 500},
1438 *mStubTracker, 0)
1439 .callbackTime.ns());
1440 {
1441 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, true);
1442 EXPECT_EQ(0,
1443 entry.schedule({.workDuration = 1200, .readyDuration = 0, .lastVsync = 500},
1444 *mStubTracker, 0)
1445 .callbackTime.ns());
1446 }
1447 {
1448 SET_FLAG_FOR_TEST(flags::dont_skip_on_early_ro, false);
1449 EXPECT_EQ(800,
1450 entry.schedule({.workDuration = 1200, .readyDuration = 0, .lastVsync = 500},
1451 *mStubTracker, 0)
1452 .callbackTime.ns());
1453 }
1454 }
1455
TEST_F(VSyncDispatchTimerQueueEntryTest,storesPendingUpdatesUntilUpdateAndDontSkip)1456 TEST_F(VSyncDispatchTimerQueueEntryTest, storesPendingUpdatesUntilUpdateAndDontSkip) {
1457 static constexpr auto effectualOffset = 200;
1458 VSyncDispatchTimerQueueEntry entry(
1459 "test", [](auto, auto, auto) {}, mVsyncMoveThreshold);
1460 EXPECT_FALSE(entry.hasPendingWorkloadUpdate());
1461 entry.addPendingWorkloadUpdate(*mStubTracker.get(), 0,
1462 {.workDuration = 100, .readyDuration = 0, .lastVsync = 400});
1463 entry.addPendingWorkloadUpdate(*mStubTracker.get(), 0,
1464 {.workDuration = effectualOffset,
1465 .readyDuration = 0,
1466 .lastVsync = 400});
1467 EXPECT_TRUE(entry.hasPendingWorkloadUpdate());
1468 entry.update(*mStubTracker, 0);
1469 EXPECT_FALSE(entry.hasPendingWorkloadUpdate());
1470 EXPECT_THAT(*entry.wakeupTime(), Eq(mPeriod - effectualOffset));
1471 }
1472
TEST_F(VSyncDispatchTimerQueueEntryTest,runCallbackWithReadyDuration)1473 TEST_F(VSyncDispatchTimerQueueEntryTest, runCallbackWithReadyDuration) {
1474 auto callCount = 0;
1475 auto vsyncCalledTime = 0;
1476 auto wakeupCalledTime = 0;
1477 auto readyCalledTime = 0;
1478 VSyncDispatchTimerQueueEntry entry(
1479 "test",
1480 [&](auto vsyncTime, auto wakeupTime, auto readyTime) {
1481 callCount++;
1482 vsyncCalledTime = vsyncTime;
1483 wakeupCalledTime = wakeupTime;
1484 readyCalledTime = readyTime;
1485 },
1486 mVsyncMoveThreshold);
1487
1488 const auto scheduleResult =
1489 entry.schedule({.workDuration = 70, .readyDuration = 30, .lastVsync = 500},
1490 *mStubTracker, 0);
1491 EXPECT_EQ(900, scheduleResult.callbackTime.ns());
1492 EXPECT_EQ(mPeriod, scheduleResult.vsyncTime.ns());
1493 auto const wakeup = entry.wakeupTime();
1494 ASSERT_TRUE(wakeup);
1495 EXPECT_THAT(*wakeup, Eq(900));
1496
1497 auto const ready = entry.readyTime();
1498 ASSERT_TRUE(ready);
1499 EXPECT_THAT(*ready, Eq(970));
1500
1501 entry.callback(entry.executing(), *wakeup, *ready);
1502
1503 EXPECT_THAT(callCount, Eq(1));
1504 EXPECT_THAT(vsyncCalledTime, Eq(mPeriod));
1505 EXPECT_THAT(wakeupCalledTime, Eq(*wakeup));
1506 EXPECT_FALSE(entry.wakeupTime());
1507 auto lastCalledTarget = entry.lastExecutedVsyncTarget();
1508 ASSERT_TRUE(lastCalledTarget);
1509 EXPECT_THAT(*lastCalledTarget, Eq(mPeriod));
1510 }
1511
1512 } // namespace android::scheduler
1513
1514 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1515 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
1516