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 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19 #define LOG_NDEBUG 0
20 
21 #include "Scheduler/TimeKeeper.h"
22 #include "Scheduler/VSyncDispatch.h"
23 #include "Scheduler/VSyncReactor.h"
24 #include "Scheduler/VSyncTracker.h"
25 
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 #include <ui/Fence.h>
29 #include <ui/FenceTime.h>
30 #include <array>
31 
32 using namespace testing;
33 using namespace std::literals;
34 namespace android::scheduler {
35 
36 class MockVSyncTracker : public VSyncTracker {
37 public:
MockVSyncTracker()38     MockVSyncTracker() { ON_CALL(*this, addVsyncTimestamp(_)).WillByDefault(Return(true)); }
39     MOCK_METHOD1(addVsyncTimestamp, bool(nsecs_t));
40     MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t));
41     MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
42     MOCK_METHOD1(setPeriod, void(nsecs_t));
43     MOCK_METHOD0(resetModel, void());
44     MOCK_CONST_METHOD1(dump, void(std::string&));
45 };
46 
47 class VSyncTrackerWrapper : public VSyncTracker {
48 public:
VSyncTrackerWrapper(std::shared_ptr<VSyncTracker> const & tracker)49     VSyncTrackerWrapper(std::shared_ptr<VSyncTracker> const& tracker) : mTracker(tracker) {}
50 
addVsyncTimestamp(nsecs_t timestamp)51     bool addVsyncTimestamp(nsecs_t timestamp) final {
52         return mTracker->addVsyncTimestamp(timestamp);
53     }
nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const54     nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final {
55         return mTracker->nextAnticipatedVSyncTimeFrom(timePoint);
56     }
currentPeriod() const57     nsecs_t currentPeriod() const final { return mTracker->currentPeriod(); }
setPeriod(nsecs_t period)58     void setPeriod(nsecs_t period) final { mTracker->setPeriod(period); }
resetModel()59     void resetModel() final { mTracker->resetModel(); }
dump(std::string & result) const60     void dump(std::string& result) const final { mTracker->dump(result); }
61 
62 private:
63     std::shared_ptr<VSyncTracker> const mTracker;
64 };
65 
66 class MockClock : public Clock {
67 public:
68     MOCK_CONST_METHOD0(now, nsecs_t());
69 };
70 
71 class ClockWrapper : public Clock {
72 public:
ClockWrapper(std::shared_ptr<Clock> const & clock)73     ClockWrapper(std::shared_ptr<Clock> const& clock) : mClock(clock) {}
74 
now() const75     nsecs_t now() const { return mClock->now(); }
76 
77 private:
78     std::shared_ptr<Clock> const mClock;
79 };
80 
81 class MockVSyncDispatch : public VSyncDispatch {
82 public:
83     MOCK_METHOD2(registerCallback,
84                  CallbackToken(std::function<void(nsecs_t, nsecs_t)> const&, std::string));
85     MOCK_METHOD1(unregisterCallback, void(CallbackToken));
86     MOCK_METHOD3(schedule, ScheduleResult(CallbackToken, nsecs_t, nsecs_t));
87     MOCK_METHOD1(cancel, CancelResult(CallbackToken token));
88     MOCK_CONST_METHOD1(dump, void(std::string&));
89 };
90 
91 class VSyncDispatchWrapper : public VSyncDispatch {
92 public:
VSyncDispatchWrapper(std::shared_ptr<VSyncDispatch> const & dispatch)93     VSyncDispatchWrapper(std::shared_ptr<VSyncDispatch> const& dispatch) : mDispatch(dispatch) {}
registerCallback(std::function<void (nsecs_t,nsecs_t)> const & callbackFn,std::string callbackName)94     CallbackToken registerCallback(std::function<void(nsecs_t, nsecs_t)> const& callbackFn,
95                                    std::string callbackName) final {
96         return mDispatch->registerCallback(callbackFn, callbackName);
97     }
98 
unregisterCallback(CallbackToken token)99     void unregisterCallback(CallbackToken token) final { mDispatch->unregisterCallback(token); }
100 
schedule(CallbackToken token,nsecs_t workDuration,nsecs_t earliestVsync)101     ScheduleResult schedule(CallbackToken token, nsecs_t workDuration,
102                             nsecs_t earliestVsync) final {
103         return mDispatch->schedule(token, workDuration, earliestVsync);
104     }
105 
cancel(CallbackToken token)106     CancelResult cancel(CallbackToken token) final { return mDispatch->cancel(token); }
107 
dump(std::string & result) const108     void dump(std::string& result) const final { return mDispatch->dump(result); }
109 
110 private:
111     std::shared_ptr<VSyncDispatch> const mDispatch;
112 };
113 
generateInvalidFence()114 std::shared_ptr<FenceTime> generateInvalidFence() {
115     sp<Fence> fence = new Fence();
116     return std::make_shared<FenceTime>(fence);
117 }
118 
generatePendingFence()119 std::shared_ptr<FenceTime> generatePendingFence() {
120     sp<Fence> fence = new Fence(dup(fileno(tmpfile())));
121     return std::make_shared<FenceTime>(fence);
122 }
123 
signalFenceWithTime(std::shared_ptr<FenceTime> const & fence,nsecs_t time)124 void signalFenceWithTime(std::shared_ptr<FenceTime> const& fence, nsecs_t time) {
125     FenceTime::Snapshot snap(time);
126     fence->applyTrustedSnapshot(snap);
127 }
128 
generateSignalledFenceWithTime(nsecs_t time)129 std::shared_ptr<FenceTime> generateSignalledFenceWithTime(nsecs_t time) {
130     sp<Fence> fence = new Fence(dup(fileno(tmpfile())));
131     std::shared_ptr<FenceTime> ft = std::make_shared<FenceTime>(fence);
132     signalFenceWithTime(ft, time);
133     return ft;
134 }
135 
136 class StubCallback : public DispSync::Callback {
137 public:
onDispSyncEvent(nsecs_t when,nsecs_t)138     void onDispSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) final {
139         std::lock_guard<std::mutex> lk(mMutex);
140         mLastCallTime = when;
141     }
lastCallTime() const142     std::optional<nsecs_t> lastCallTime() const {
143         std::lock_guard<std::mutex> lk(mMutex);
144         return mLastCallTime;
145     }
146 
147 private:
148     std::mutex mutable mMutex;
149     std::optional<nsecs_t> mLastCallTime GUARDED_BY(mMutex);
150 };
151 
152 class VSyncReactorTest : public testing::Test {
153 protected:
VSyncReactorTest()154     VSyncReactorTest()
155           : mMockDispatch(std::make_shared<NiceMock<MockVSyncDispatch>>()),
156             mMockTracker(std::make_shared<NiceMock<MockVSyncTracker>>()),
157             mMockClock(std::make_shared<NiceMock<MockClock>>()),
158             mReactor(std::make_unique<ClockWrapper>(mMockClock),
159                      std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
160                      std::make_unique<VSyncTrackerWrapper>(mMockTracker), kPendingLimit,
161                      false /* supportKernelIdleTimer */) {
162         ON_CALL(*mMockClock, now()).WillByDefault(Return(mFakeNow));
163         ON_CALL(*mMockTracker, currentPeriod()).WillByDefault(Return(period));
164     }
165 
166     std::shared_ptr<MockVSyncDispatch> mMockDispatch;
167     std::shared_ptr<MockVSyncTracker> mMockTracker;
168     std::shared_ptr<MockClock> mMockClock;
169     static constexpr size_t kPendingLimit = 3;
170     static constexpr nsecs_t mDummyTime = 47;
171     static constexpr nsecs_t mPhase = 3000;
172     static constexpr nsecs_t mAnotherPhase = 5200;
173     static constexpr nsecs_t period = 10000;
174     static constexpr nsecs_t mFakeVSyncTime = 2093;
175     static constexpr nsecs_t mFakeWakeupTime = 1892;
176     static constexpr nsecs_t mFakeNow = 2214;
177     static constexpr const char mName[] = "callbacky";
178     VSyncDispatch::CallbackToken const mFakeToken{2398};
179 
180     nsecs_t lastCallbackTime = 0;
181     StubCallback outerCb;
182     std::function<void(nsecs_t, nsecs_t)> innerCb;
183 
184     VSyncReactor mReactor;
185 };
186 
TEST_F(VSyncReactorTest,addingNullFenceCheck)187 TEST_F(VSyncReactorTest, addingNullFenceCheck) {
188     EXPECT_FALSE(mReactor.addPresentFence(nullptr));
189 }
190 
TEST_F(VSyncReactorTest,addingInvalidFenceSignalsNeedsMoreInfo)191 TEST_F(VSyncReactorTest, addingInvalidFenceSignalsNeedsMoreInfo) {
192     EXPECT_TRUE(mReactor.addPresentFence(generateInvalidFence()));
193 }
194 
TEST_F(VSyncReactorTest,addingSignalledFenceAddsToTracker)195 TEST_F(VSyncReactorTest, addingSignalledFenceAddsToTracker) {
196     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(mDummyTime));
197     EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(mDummyTime)));
198 }
199 
TEST_F(VSyncReactorTest,addingPendingFenceAddsSignalled)200 TEST_F(VSyncReactorTest, addingPendingFenceAddsSignalled) {
201     nsecs_t anotherDummyTime = 2919019201;
202 
203     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(0);
204     auto pendingFence = generatePendingFence();
205     EXPECT_FALSE(mReactor.addPresentFence(pendingFence));
206     Mock::VerifyAndClearExpectations(mMockTracker.get());
207 
208     signalFenceWithTime(pendingFence, mDummyTime);
209 
210     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(mDummyTime));
211     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(anotherDummyTime));
212     EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(anotherDummyTime)));
213 }
214 
TEST_F(VSyncReactorTest,limitsPendingFences)215 TEST_F(VSyncReactorTest, limitsPendingFences) {
216     std::array<std::shared_ptr<FenceTime>, kPendingLimit * 2> fences;
217     std::array<nsecs_t, fences.size()> fakeTimes;
218     std::generate(fences.begin(), fences.end(), [] { return generatePendingFence(); });
219     std::generate(fakeTimes.begin(), fakeTimes.end(), [i = 10]() mutable {
220         i++;
221         return i * i;
222     });
223 
224     for (auto const& fence : fences) {
225         mReactor.addPresentFence(fence);
226     }
227 
228     for (auto i = fences.size() - kPendingLimit; i < fences.size(); i++) {
229         EXPECT_CALL(*mMockTracker, addVsyncTimestamp(fakeTimes[i]));
230     }
231 
232     for (auto i = 0u; i < fences.size(); i++) {
233         signalFenceWithTime(fences[i], fakeTimes[i]);
234     }
235     mReactor.addPresentFence(generatePendingFence());
236 }
237 
TEST_F(VSyncReactorTest,ignoresPresentFencesWhenToldTo)238 TEST_F(VSyncReactorTest, ignoresPresentFencesWhenToldTo) {
239     static constexpr size_t aFewTimes = 8;
240     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(mDummyTime)).Times(1);
241 
242     mReactor.setIgnorePresentFences(true);
243     for (auto i = 0; i < aFewTimes; i++) {
244         mReactor.addPresentFence(generateSignalledFenceWithTime(mDummyTime));
245     }
246 
247     mReactor.setIgnorePresentFences(false);
248     EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(mDummyTime)));
249 }
250 
TEST_F(VSyncReactorTest,ignoresProperlyAfterAPeriodConfirmation)251 TEST_F(VSyncReactorTest, ignoresProperlyAfterAPeriodConfirmation) {
252     bool periodFlushed = true;
253     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
254     mReactor.setIgnorePresentFences(true);
255 
256     nsecs_t const newPeriod = 5000;
257     mReactor.setPeriod(newPeriod);
258 
259     EXPECT_TRUE(mReactor.addResyncSample(0, std::nullopt, &periodFlushed));
260     EXPECT_FALSE(periodFlushed);
261     EXPECT_FALSE(mReactor.addResyncSample(newPeriod, std::nullopt, &periodFlushed));
262     EXPECT_TRUE(periodFlushed);
263 
264     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
265 }
266 
TEST_F(VSyncReactorTest,queriesTrackerForNextRefreshNow)267 TEST_F(VSyncReactorTest, queriesTrackerForNextRefreshNow) {
268     nsecs_t const fakeTimestamp = 4839;
269     EXPECT_CALL(*mMockTracker, currentPeriod()).Times(0);
270     EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(_))
271             .Times(1)
272             .WillOnce(Return(fakeTimestamp));
273 
274     EXPECT_THAT(mReactor.computeNextRefresh(0, mMockClock->now()), Eq(fakeTimestamp));
275 }
276 
TEST_F(VSyncReactorTest,queriesTrackerForExpectedPresentTime)277 TEST_F(VSyncReactorTest, queriesTrackerForExpectedPresentTime) {
278     nsecs_t const fakeTimestamp = 4839;
279     EXPECT_CALL(*mMockTracker, currentPeriod()).Times(0);
280     EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(_))
281             .Times(1)
282             .WillOnce(Return(fakeTimestamp));
283 
284     EXPECT_THAT(mReactor.expectedPresentTime(mMockClock->now()), Eq(fakeTimestamp));
285 }
286 
TEST_F(VSyncReactorTest,queriesTrackerForNextRefreshFuture)287 TEST_F(VSyncReactorTest, queriesTrackerForNextRefreshFuture) {
288     nsecs_t const fakeTimestamp = 4839;
289     nsecs_t const fakePeriod = 1010;
290     nsecs_t const mFakeNow = 2214;
291     int const numPeriodsOut = 3;
292     EXPECT_CALL(*mMockClock, now()).WillOnce(Return(mFakeNow));
293     EXPECT_CALL(*mMockTracker, currentPeriod()).WillOnce(Return(fakePeriod));
294     EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(mFakeNow + numPeriodsOut * fakePeriod))
295             .WillOnce(Return(fakeTimestamp));
296     EXPECT_THAT(mReactor.computeNextRefresh(numPeriodsOut, mMockClock->now()), Eq(fakeTimestamp));
297 }
298 
TEST_F(VSyncReactorTest,getPeriod)299 TEST_F(VSyncReactorTest, getPeriod) {
300     nsecs_t const fakePeriod = 1010;
301     EXPECT_CALL(*mMockTracker, currentPeriod()).WillOnce(Return(fakePeriod));
302     EXPECT_THAT(mReactor.getPeriod(), Eq(fakePeriod));
303 }
304 
TEST_F(VSyncReactorTest,setPeriodCalledOnceConfirmedChange)305 TEST_F(VSyncReactorTest, setPeriodCalledOnceConfirmedChange) {
306     nsecs_t const newPeriod = 5000;
307     EXPECT_CALL(*mMockTracker, setPeriod(_)).Times(0);
308     mReactor.setPeriod(newPeriod);
309 
310     bool periodFlushed = true;
311     EXPECT_TRUE(mReactor.addResyncSample(10000, std::nullopt, &periodFlushed));
312     EXPECT_FALSE(periodFlushed);
313 
314     EXPECT_TRUE(mReactor.addResyncSample(20000, std::nullopt, &periodFlushed));
315     EXPECT_FALSE(periodFlushed);
316 
317     Mock::VerifyAndClearExpectations(mMockTracker.get());
318     EXPECT_CALL(*mMockTracker, setPeriod(newPeriod)).Times(1);
319 
320     EXPECT_FALSE(mReactor.addResyncSample(25000, std::nullopt, &periodFlushed));
321     EXPECT_TRUE(periodFlushed);
322 }
323 
TEST_F(VSyncReactorTest,changingPeriodBackAbortsConfirmationProcess)324 TEST_F(VSyncReactorTest, changingPeriodBackAbortsConfirmationProcess) {
325     nsecs_t sampleTime = 0;
326     nsecs_t const newPeriod = 5000;
327     mReactor.setPeriod(newPeriod);
328     bool periodFlushed = true;
329     EXPECT_TRUE(mReactor.addResyncSample(sampleTime += period, std::nullopt, &periodFlushed));
330     EXPECT_FALSE(periodFlushed);
331 
332     EXPECT_TRUE(mReactor.addResyncSample(sampleTime += period, std::nullopt, &periodFlushed));
333     EXPECT_FALSE(periodFlushed);
334 
335     mReactor.setPeriod(period);
336     EXPECT_FALSE(mReactor.addResyncSample(sampleTime += period, std::nullopt, &periodFlushed));
337     EXPECT_FALSE(periodFlushed);
338 }
339 
TEST_F(VSyncReactorTest,changingToAThirdPeriodWillWaitForLastPeriod)340 TEST_F(VSyncReactorTest, changingToAThirdPeriodWillWaitForLastPeriod) {
341     nsecs_t sampleTime = 0;
342     nsecs_t const secondPeriod = 5000;
343     nsecs_t const thirdPeriod = 2000;
344 
345     mReactor.setPeriod(secondPeriod);
346     bool periodFlushed = true;
347     EXPECT_TRUE(mReactor.addResyncSample(sampleTime += period, std::nullopt, &periodFlushed));
348     EXPECT_FALSE(periodFlushed);
349     EXPECT_TRUE(mReactor.addResyncSample(sampleTime += period, std::nullopt, &periodFlushed));
350     EXPECT_FALSE(periodFlushed);
351     mReactor.setPeriod(thirdPeriod);
352     EXPECT_TRUE(mReactor.addResyncSample(sampleTime += secondPeriod, std::nullopt, &periodFlushed));
353     EXPECT_FALSE(periodFlushed);
354     EXPECT_FALSE(mReactor.addResyncSample(sampleTime += thirdPeriod, std::nullopt, &periodFlushed));
355     EXPECT_TRUE(periodFlushed);
356 }
357 
TEST_F(VSyncReactorTest,reportedBadTimestampFromPredictorWillReactivateHwVSync)358 TEST_F(VSyncReactorTest, reportedBadTimestampFromPredictorWillReactivateHwVSync) {
359     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_))
360             .WillOnce(Return(false))
361             .WillOnce(Return(true))
362             .WillOnce(Return(true));
363     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
364     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
365 
366     nsecs_t skewyPeriod = period >> 1;
367     bool periodFlushed = false;
368     nsecs_t sampleTime = 0;
369     EXPECT_TRUE(mReactor.addResyncSample(sampleTime += skewyPeriod, std::nullopt, &periodFlushed));
370     EXPECT_FALSE(periodFlushed);
371     EXPECT_FALSE(mReactor.addResyncSample(sampleTime += period, std::nullopt, &periodFlushed));
372     EXPECT_FALSE(periodFlushed);
373 }
374 
TEST_F(VSyncReactorTest,reportedBadTimestampFromPredictorWillReactivateHwVSyncPendingFence)375 TEST_F(VSyncReactorTest, reportedBadTimestampFromPredictorWillReactivateHwVSyncPendingFence) {
376     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_))
377             .Times(2)
378             .WillOnce(Return(false))
379             .WillOnce(Return(true));
380 
381     auto fence = generatePendingFence();
382     EXPECT_FALSE(mReactor.addPresentFence(fence));
383     signalFenceWithTime(fence, period >> 1);
384     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
385 }
386 
TEST_F(VSyncReactorTest,presentFenceAdditionDoesNotInterruptConfirmationProcess)387 TEST_F(VSyncReactorTest, presentFenceAdditionDoesNotInterruptConfirmationProcess) {
388     nsecs_t const newPeriod = 5000;
389     mReactor.setPeriod(newPeriod);
390     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
391 }
392 
TEST_F(VSyncReactorTest,setPeriodCalledFirstTwoEventsNewPeriod)393 TEST_F(VSyncReactorTest, setPeriodCalledFirstTwoEventsNewPeriod) {
394     nsecs_t const newPeriod = 5000;
395     EXPECT_CALL(*mMockTracker, setPeriod(_)).Times(0);
396     mReactor.setPeriod(newPeriod);
397 
398     bool periodFlushed = true;
399     EXPECT_TRUE(mReactor.addResyncSample(5000, std::nullopt, &periodFlushed));
400     EXPECT_FALSE(periodFlushed);
401     Mock::VerifyAndClearExpectations(mMockTracker.get());
402 
403     EXPECT_CALL(*mMockTracker, setPeriod(newPeriod)).Times(1);
404     EXPECT_FALSE(mReactor.addResyncSample(10000, std::nullopt, &periodFlushed));
405     EXPECT_TRUE(periodFlushed);
406 }
407 
TEST_F(VSyncReactorTest,addResyncSampleTypical)408 TEST_F(VSyncReactorTest, addResyncSampleTypical) {
409     nsecs_t const fakeTimestamp = 3032;
410     bool periodFlushed = false;
411 
412     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(fakeTimestamp));
413     EXPECT_FALSE(mReactor.addResyncSample(fakeTimestamp, std::nullopt, &periodFlushed));
414     EXPECT_FALSE(periodFlushed);
415 }
416 
TEST_F(VSyncReactorTest,addResyncSamplePeriodChanges)417 TEST_F(VSyncReactorTest, addResyncSamplePeriodChanges) {
418     bool periodFlushed = false;
419     nsecs_t const newPeriod = 4000;
420 
421     mReactor.setPeriod(newPeriod);
422 
423     auto time = 0;
424     auto constexpr numTimestampSubmissions = 10;
425     for (auto i = 0; i < numTimestampSubmissions; i++) {
426         time += period;
427         EXPECT_TRUE(mReactor.addResyncSample(time, std::nullopt, &periodFlushed));
428         EXPECT_FALSE(periodFlushed);
429     }
430 
431     time += newPeriod;
432     EXPECT_FALSE(mReactor.addResyncSample(time, std::nullopt, &periodFlushed));
433     EXPECT_TRUE(periodFlushed);
434 
435     for (auto i = 0; i < numTimestampSubmissions; i++) {
436         time += newPeriod;
437         EXPECT_FALSE(mReactor.addResyncSample(time, std::nullopt, &periodFlushed));
438         EXPECT_FALSE(periodFlushed);
439     }
440 }
441 
TEST_F(VSyncReactorTest,addPresentFenceWhileAwaitingPeriodConfirmationRequestsHwVsync)442 TEST_F(VSyncReactorTest, addPresentFenceWhileAwaitingPeriodConfirmationRequestsHwVsync) {
443     auto time = 0;
444     bool periodFlushed = false;
445     nsecs_t const newPeriod = 4000;
446     mReactor.setPeriod(newPeriod);
447 
448     time += period;
449     mReactor.addResyncSample(time, std::nullopt, &periodFlushed);
450     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
451 
452     time += newPeriod;
453     mReactor.addResyncSample(time, std::nullopt, &periodFlushed);
454 
455     EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
456 }
457 
computeWorkload(nsecs_t period,nsecs_t phase)458 static nsecs_t computeWorkload(nsecs_t period, nsecs_t phase) {
459     return period - phase;
460 }
461 
TEST_F(VSyncReactorTest,addEventListener)462 TEST_F(VSyncReactorTest, addEventListener) {
463     Sequence seq;
464     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
465             .InSequence(seq)
466             .WillOnce(Return(mFakeToken));
467     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
468             .InSequence(seq);
469     EXPECT_CALL(*mMockDispatch, cancel(mFakeToken)).Times(2).InSequence(seq);
470     EXPECT_CALL(*mMockDispatch, unregisterCallback(mFakeToken)).InSequence(seq);
471 
472     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
473     mReactor.removeEventListener(&outerCb, &lastCallbackTime);
474 }
475 
TEST_F(VSyncReactorTest,addEventListenerTwiceChangesPhase)476 TEST_F(VSyncReactorTest, addEventListenerTwiceChangesPhase) {
477     Sequence seq;
478     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
479             .InSequence(seq)
480             .WillOnce(Return(mFakeToken));
481     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
482             .InSequence(seq);
483     EXPECT_CALL(*mMockDispatch,
484                 schedule(mFakeToken, computeWorkload(period, mAnotherPhase), _)) // mFakeNow))
485             .InSequence(seq);
486     EXPECT_CALL(*mMockDispatch, cancel(mFakeToken)).InSequence(seq);
487     EXPECT_CALL(*mMockDispatch, unregisterCallback(mFakeToken)).InSequence(seq);
488 
489     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
490     mReactor.addEventListener(mName, mAnotherPhase, &outerCb, lastCallbackTime);
491 }
492 
TEST_F(VSyncReactorTest,eventListenerGetsACallbackAndReschedules)493 TEST_F(VSyncReactorTest, eventListenerGetsACallbackAndReschedules) {
494     Sequence seq;
495     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
496             .InSequence(seq)
497             .WillOnce(DoAll(SaveArg<0>(&innerCb), Return(mFakeToken)));
498     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
499             .InSequence(seq);
500     EXPECT_CALL(*mMockDispatch,
501                 schedule(mFakeToken, computeWorkload(period, mPhase), mFakeVSyncTime))
502             .Times(2)
503             .InSequence(seq);
504     EXPECT_CALL(*mMockDispatch, cancel(mFakeToken)).InSequence(seq);
505     EXPECT_CALL(*mMockDispatch, unregisterCallback(mFakeToken)).InSequence(seq);
506 
507     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
508     ASSERT_TRUE(innerCb);
509     innerCb(mFakeVSyncTime, mFakeWakeupTime);
510     innerCb(mFakeVSyncTime, mFakeWakeupTime);
511 }
512 
TEST_F(VSyncReactorTest,callbackTimestampDistributedIsWakeupTime)513 TEST_F(VSyncReactorTest, callbackTimestampDistributedIsWakeupTime) {
514     Sequence seq;
515     EXPECT_CALL(*mMockDispatch, registerCallback(_, _))
516             .InSequence(seq)
517             .WillOnce(DoAll(SaveArg<0>(&innerCb), Return(mFakeToken)));
518     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
519             .InSequence(seq);
520     EXPECT_CALL(*mMockDispatch,
521                 schedule(mFakeToken, computeWorkload(period, mPhase), mFakeVSyncTime))
522             .InSequence(seq);
523 
524     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
525     ASSERT_TRUE(innerCb);
526     innerCb(mFakeVSyncTime, mFakeWakeupTime);
527     EXPECT_THAT(outerCb.lastCallTime(), Optional(mFakeWakeupTime));
528 }
529 
TEST_F(VSyncReactorTest,eventListenersRemovedOnDestruction)530 TEST_F(VSyncReactorTest, eventListenersRemovedOnDestruction) {
531     Sequence seq;
532     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
533             .InSequence(seq)
534             .WillOnce(Return(mFakeToken));
535     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
536             .InSequence(seq);
537     EXPECT_CALL(*mMockDispatch, cancel(mFakeToken)).InSequence(seq);
538     EXPECT_CALL(*mMockDispatch, unregisterCallback(mFakeToken)).InSequence(seq);
539 
540     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
541 }
542 
543 // b/149221293
TEST_F(VSyncReactorTest,selfRemovingEventListenerStopsCallbacks)544 TEST_F(VSyncReactorTest, selfRemovingEventListenerStopsCallbacks) {
545     class SelfRemovingCallback : public DispSync::Callback {
546     public:
547         SelfRemovingCallback(VSyncReactor& vsr) : mVsr(vsr) {}
548         void onDispSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) final {
549             mVsr.removeEventListener(this, &when);
550         }
551 
552     private:
553         VSyncReactor& mVsr;
554     } selfRemover(mReactor);
555 
556     Sequence seq;
557     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
558             .InSequence(seq)
559             .WillOnce(DoAll(SaveArg<0>(&innerCb), Return(mFakeToken)));
560     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
561             .InSequence(seq);
562     EXPECT_CALL(*mMockDispatch, cancel(mFakeToken)).Times(2).InSequence(seq);
563     EXPECT_CALL(*mMockDispatch, unregisterCallback(mFakeToken)).InSequence(seq);
564 
565     mReactor.addEventListener(mName, mPhase, &selfRemover, lastCallbackTime);
566     innerCb(0, 0);
567 }
568 
TEST_F(VSyncReactorTest,addEventListenerChangePeriod)569 TEST_F(VSyncReactorTest, addEventListenerChangePeriod) {
570     Sequence seq;
571     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
572             .InSequence(seq)
573             .WillOnce(Return(mFakeToken));
574     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
575             .InSequence(seq);
576     EXPECT_CALL(*mMockDispatch,
577                 schedule(mFakeToken, computeWorkload(period, mAnotherPhase), mFakeNow))
578             .InSequence(seq);
579     EXPECT_CALL(*mMockDispatch, cancel(mFakeToken)).InSequence(seq);
580     EXPECT_CALL(*mMockDispatch, unregisterCallback(mFakeToken)).InSequence(seq);
581 
582     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
583     mReactor.addEventListener(mName, mAnotherPhase, &outerCb, lastCallbackTime);
584 }
585 
TEST_F(VSyncReactorTest,changingPeriodChangesOffsetsOnNextCb)586 TEST_F(VSyncReactorTest, changingPeriodChangesOffsetsOnNextCb) {
587     static constexpr nsecs_t anotherPeriod = 23333;
588     Sequence seq;
589     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
590             .InSequence(seq)
591             .WillOnce(Return(mFakeToken));
592     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), mFakeNow))
593             .InSequence(seq);
594     EXPECT_CALL(*mMockTracker, setPeriod(anotherPeriod));
595     EXPECT_CALL(*mMockDispatch,
596                 schedule(mFakeToken, computeWorkload(anotherPeriod, mPhase), mFakeNow))
597             .InSequence(seq);
598 
599     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
600 
601     bool periodFlushed = false;
602     mReactor.setPeriod(anotherPeriod);
603     EXPECT_TRUE(mReactor.addResyncSample(anotherPeriod, std::nullopt, &periodFlushed));
604     EXPECT_FALSE(mReactor.addResyncSample(anotherPeriod * 2, std::nullopt, &periodFlushed));
605 
606     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
607 }
608 
TEST_F(VSyncReactorTest,offsetsAppliedOnNextOpportunity)609 TEST_F(VSyncReactorTest, offsetsAppliedOnNextOpportunity) {
610     Sequence seq;
611     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
612             .InSequence(seq)
613             .WillOnce(DoAll(SaveArg<0>(&innerCb), Return(mFakeToken)));
614     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mPhase), _))
615             .InSequence(seq)
616             .WillOnce(Return(ScheduleResult::Scheduled));
617 
618     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mAnotherPhase), _))
619             .InSequence(seq)
620             .WillOnce(Return(ScheduleResult::Scheduled));
621 
622     EXPECT_CALL(*mMockDispatch, schedule(mFakeToken, computeWorkload(period, mAnotherPhase), _))
623             .InSequence(seq)
624             .WillOnce(Return(ScheduleResult::Scheduled));
625 
626     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
627     mReactor.changePhaseOffset(&outerCb, mAnotherPhase);
628     ASSERT_TRUE(innerCb);
629     innerCb(mFakeVSyncTime, mFakeWakeupTime);
630 }
631 
TEST_F(VSyncReactorTest,negativeOffsetsApplied)632 TEST_F(VSyncReactorTest, negativeOffsetsApplied) {
633     nsecs_t const negativePhase = -4000;
634     Sequence seq;
635     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
636             .InSequence(seq)
637             .WillOnce(Return(mFakeToken));
638     EXPECT_CALL(*mMockDispatch,
639                 schedule(mFakeToken, computeWorkload(period, negativePhase), mFakeNow))
640             .InSequence(seq);
641     mReactor.addEventListener(mName, negativePhase, &outerCb, lastCallbackTime);
642 }
643 
TEST_F(VSyncReactorTest,beginResyncResetsModel)644 TEST_F(VSyncReactorTest, beginResyncResetsModel) {
645     EXPECT_CALL(*mMockTracker, resetModel());
646     mReactor.beginResync();
647 }
648 
TEST_F(VSyncReactorTest,periodChangeWithGivenVsyncPeriod)649 TEST_F(VSyncReactorTest, periodChangeWithGivenVsyncPeriod) {
650     bool periodFlushed = true;
651     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(3);
652     mReactor.setIgnorePresentFences(true);
653 
654     nsecs_t const newPeriod = 5000;
655     mReactor.setPeriod(newPeriod);
656 
657     EXPECT_TRUE(mReactor.addResyncSample(0, 0, &periodFlushed));
658     EXPECT_FALSE(periodFlushed);
659     EXPECT_TRUE(mReactor.addResyncSample(newPeriod, 0, &periodFlushed));
660     EXPECT_FALSE(periodFlushed);
661     EXPECT_FALSE(mReactor.addResyncSample(newPeriod, newPeriod, &periodFlushed));
662     EXPECT_TRUE(periodFlushed);
663 
664     EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
665 }
666 
TEST_F(VSyncReactorTest,periodIsMeasuredIfIgnoringComposer)667 TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) {
668     // Create a reactor which supports the kernel idle timer
669     auto idleReactor = VSyncReactor(std::make_unique<ClockWrapper>(mMockClock),
670                                     std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
671                                     std::make_unique<VSyncTrackerWrapper>(mMockTracker),
672                                     kPendingLimit, true /* supportKernelIdleTimer */);
673 
674     bool periodFlushed = true;
675     EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(5);
676     idleReactor.setIgnorePresentFences(true);
677 
678     // First, set the same period, which should only be confirmed when we receive two
679     // matching callbacks
680     idleReactor.setPeriod(10000);
681     EXPECT_TRUE(idleReactor.addResyncSample(0, 0, &periodFlushed));
682     EXPECT_FALSE(periodFlushed);
683     // Correct period but incorrect timestamp delta
684     EXPECT_TRUE(idleReactor.addResyncSample(0, 10000, &periodFlushed));
685     EXPECT_FALSE(periodFlushed);
686     // Correct period and correct timestamp delta
687     EXPECT_FALSE(idleReactor.addResyncSample(10000, 10000, &periodFlushed));
688     EXPECT_TRUE(periodFlushed);
689 
690     // Then, set a new period, which should be confirmed as soon as we receive a callback
691     // reporting the new period
692     nsecs_t const newPeriod = 5000;
693     idleReactor.setPeriod(newPeriod);
694     // Incorrect timestamp delta and period
695     EXPECT_TRUE(idleReactor.addResyncSample(20000, 10000, &periodFlushed));
696     EXPECT_FALSE(periodFlushed);
697     // Incorrect timestamp delta but correct period
698     EXPECT_FALSE(idleReactor.addResyncSample(20000, 5000, &periodFlushed));
699     EXPECT_TRUE(periodFlushed);
700 
701     EXPECT_TRUE(idleReactor.addPresentFence(generateSignalledFenceWithTime(0)));
702 }
703 
704 using VSyncReactorDeathTest = VSyncReactorTest;
TEST_F(VSyncReactorDeathTest,invalidRemoval)705 TEST_F(VSyncReactorDeathTest, invalidRemoval) {
706     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
707     mReactor.removeEventListener(&outerCb, &lastCallbackTime);
708     EXPECT_DEATH(mReactor.removeEventListener(&outerCb, &lastCallbackTime), ".*");
709 }
710 
TEST_F(VSyncReactorDeathTest,invalidChange)711 TEST_F(VSyncReactorDeathTest, invalidChange) {
712     EXPECT_DEATH(mReactor.changePhaseOffset(&outerCb, mPhase), ".*");
713 
714     // the current DispSync-interface usage pattern has evolved around an implementation quirk,
715     // which is a callback is assumed to always exist, and it is valid api usage to change the
716     // offset of an object that is in the removed state.
717     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
718     mReactor.removeEventListener(&outerCb, &lastCallbackTime);
719     mReactor.changePhaseOffset(&outerCb, mPhase);
720 }
721 
TEST_F(VSyncReactorDeathTest,cannotScheduleOnRegistration)722 TEST_F(VSyncReactorDeathTest, cannotScheduleOnRegistration) {
723     ON_CALL(*mMockDispatch, schedule(_, _, _))
724             .WillByDefault(Return(ScheduleResult::CannotSchedule));
725     EXPECT_DEATH(mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime), ".*");
726 }
727 
TEST_F(VSyncReactorDeathTest,cannotScheduleOnCallback)728 TEST_F(VSyncReactorDeathTest, cannotScheduleOnCallback) {
729     EXPECT_CALL(*mMockDispatch, registerCallback(_, std::string(mName)))
730             .WillOnce(DoAll(SaveArg<0>(&innerCb), Return(mFakeToken)));
731     EXPECT_CALL(*mMockDispatch, schedule(_, _, _)).WillOnce(Return(ScheduleResult::Scheduled));
732 
733     mReactor.addEventListener(mName, mPhase, &outerCb, lastCallbackTime);
734     ASSERT_TRUE(innerCb);
735     Mock::VerifyAndClearExpectations(mMockDispatch.get());
736 
737     ON_CALL(*mMockDispatch, schedule(_, _, _))
738             .WillByDefault(Return(ScheduleResult::CannotSchedule));
739     EXPECT_DEATH(innerCb(mFakeVSyncTime, mFakeWakeupTime), ".*");
740 }
741 
742 } // namespace android::scheduler
743