diff options
| author | 2019-11-14 08:52:45 -0800 | |
|---|---|---|
| committer | 2019-11-26 11:10:28 -0800 | |
| commit | 2fd3ceaf9834d1a0056ff59c454c643f7ab14f75 (patch) | |
| tree | 102379b55c35b9b7e9ba01a756197f13c4aeb126 | |
| parent | b2501bad7ccb2000237ccb2b08ca04f7ca6c5ec1 (diff) | |
SF: VSyncReactor add timestamp querying functions
Adds 2 more functions from the DispSync interface to VSyncReactor,
computeNextRefresh, and expectedPresentTime
Bug: 140303479
Test: 3 new units
Change-Id: I75ea79ed749f05daf3337ddc8ca145e2ecceabcd
9 files changed, 113 insertions, 11 deletions
diff --git a/services/surfaceflinger/Scheduler/TimeKeeper.h b/services/surfaceflinger/Scheduler/TimeKeeper.h index 699cd504fa..38f07081bb 100644 --- a/services/surfaceflinger/Scheduler/TimeKeeper.h +++ b/services/surfaceflinger/Scheduler/TimeKeeper.h @@ -21,10 +21,24 @@ namespace android::scheduler { +class Clock { +public: + virtual ~Clock(); + /* + * Returns the SYSTEM_TIME_MONOTONIC, used by testing infra to stub time. + */ + virtual nsecs_t now() const = 0; + +protected: + Clock() = default; + Clock(Clock const&) = delete; + Clock& operator=(Clock const&) = delete; +}; + /* * TimeKeeper is the interface for a single-shot timer primitive. */ -class TimeKeeper { +class TimeKeeper : public Clock { public: virtual ~TimeKeeper(); @@ -39,11 +53,6 @@ public: */ virtual void alarmCancel() = 0; - /* - * Returns the SYSTEM_TIME_MONOTONIC, used by testing infra to stub time. - */ - virtual nsecs_t now() const = 0; - protected: TimeKeeper(TimeKeeper const&) = delete; TimeKeeper& operator=(TimeKeeper const&) = delete; diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index 643c5d2a5a..3894992ad1 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -54,6 +54,11 @@ bool VSyncPredictor::validate(nsecs_t timestamp) const { return percent < kOutlierTolerancePercent || percent > (kMaxPercent - kOutlierTolerancePercent); } +nsecs_t VSyncPredictor::currentPeriod() const { + std::lock_guard<std::mutex> lk(mMutex); + return std::get<0>(mRateMap.find(mIdealPeriod)->second); +} + void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { std::lock_guard<std::mutex> lk(mMutex); diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h index 1590f490aa..4210b3cf46 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.h +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h @@ -39,6 +39,7 @@ public: void addVsyncTimestamp(nsecs_t timestamp) final; nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final; + nsecs_t currentPeriod() const final; /* * Inform the model that the period is anticipated to change to a new value. diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp index 1398362b00..9ce440c084 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp @@ -15,14 +15,18 @@ */ #include "VSyncReactor.h" +#include "TimeKeeper.h" #include "VSyncDispatch.h" #include "VSyncTracker.h" namespace android::scheduler { -VSyncReactor::VSyncReactor(std::unique_ptr<VSyncDispatch> dispatch, +Clock::~Clock() = default; + +VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch, std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit) - : mDispatch(std::move(dispatch)), + : mClock(std::move(clock)), + mDispatch(std::move(dispatch)), mTracker(std::move(tracker)), mPendingLimit(pendingFenceLimit) {} @@ -73,4 +77,14 @@ void VSyncReactor::setIgnorePresentFences(bool ignoration) { } } +nsecs_t VSyncReactor::computeNextRefresh(int periodOffset) const { + auto const now = mClock->now(); + auto const currentPeriod = periodOffset ? mTracker->currentPeriod() : 0; + return mTracker->nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod); +} + +nsecs_t VSyncReactor::expectedPresentTime() { + return mTracker->nextAnticipatedVSyncTimeFrom(mClock->now()); +} + } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h index 05fd0fdec3..8436e8a8ce 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.h +++ b/services/surfaceflinger/Scheduler/VSyncReactor.h @@ -24,19 +24,24 @@ namespace android::scheduler { +class Clock; class VSyncDispatch; class VSyncTracker; // TODO (b/145217110): consider renaming. class VSyncReactor /* TODO (b/140201379): : public android::DispSync */ { public: - VSyncReactor(std::unique_ptr<VSyncDispatch> dispatch, std::unique_ptr<VSyncTracker> tracker, - size_t pendingFenceLimit); + VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch, + std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit); bool addPresentFence(const std::shared_ptr<FenceTime>& fence); void setIgnorePresentFences(bool ignoration); + nsecs_t computeNextRefresh(int periodOffset) const; + nsecs_t expectedPresentTime(); + private: + std::unique_ptr<Clock> const mClock; std::unique_ptr<VSyncDispatch> const mDispatch; std::unique_ptr<VSyncTracker> const mTracker; size_t const mPendingLimit; diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h index 97b9620cd6..335042d430 100644 --- a/services/surfaceflinger/Scheduler/VSyncTracker.h +++ b/services/surfaceflinger/Scheduler/VSyncTracker.h @@ -47,6 +47,13 @@ public: */ virtual nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const = 0; + /* + * The current period of the vsync signal. + * + * \return The current period of the vsync signal + */ + virtual nsecs_t currentPeriod() const = 0; + protected: VSyncTracker(VSyncTracker const&) = delete; VSyncTracker& operator=(VSyncTracker const&) = delete; diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp index c01261619e..448954fbf4 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp @@ -47,6 +47,8 @@ public: return timePoint - floor + mPeriod; } + nsecs_t currentPeriod() const final { return mPeriod; } + private: nsecs_t const mPeriod; }; @@ -73,6 +75,11 @@ public: mBase = last_known; } + nsecs_t currentPeriod() const final { + std::lock_guard<decltype(mMutex)> lk(mMutex); + return mPeriod; + } + private: std::mutex mutable mMutex; nsecs_t mPeriod; diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index 82950b5792..82b1051a6d 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -39,6 +39,7 @@ public: MOCK_METHOD1(addVsyncTimestamp, void(nsecs_t)); MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t)); + MOCK_CONST_METHOD0(currentPeriod, nsecs_t()); nsecs_t nextVSyncTime(nsecs_t timePoint) const { if (timePoint % mPeriod == 0) { diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp index b4aebf0f19..c8784c686b 100644 --- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 +#include "Scheduler/TimeKeeper.h" #include "Scheduler/VSyncDispatch.h" #include "Scheduler/VSyncReactor.h" #include "Scheduler/VSyncTracker.h" @@ -36,6 +37,7 @@ class MockVSyncTracker : public VSyncTracker { public: MOCK_METHOD1(addVsyncTimestamp, void(nsecs_t)); MOCK_CONST_METHOD1(nextAnticipatedVSyncTimeFrom, nsecs_t(nsecs_t)); + MOCK_CONST_METHOD0(currentPeriod, nsecs_t()); }; class VSyncTrackerWrapper : public VSyncTracker { @@ -46,11 +48,27 @@ public: nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final { return mTracker->nextAnticipatedVSyncTimeFrom(timePoint); } + nsecs_t currentPeriod() const final { return mTracker->currentPeriod(); } private: std::shared_ptr<VSyncTracker> const mTracker; }; +class MockClock : public Clock { +public: + MOCK_CONST_METHOD0(now, nsecs_t()); +}; + +class ClockWrapper : public Clock { +public: + ClockWrapper(std::shared_ptr<Clock> const& clock) : mClock(clock) {} + + nsecs_t now() const { return mClock->now(); } + +private: + std::shared_ptr<Clock> const mClock; +}; + class MockVSyncDispatch : public VSyncDispatch { public: MOCK_METHOD2(registerCallback, CallbackToken(std::function<void(nsecs_t)> const&, std::string)); @@ -107,11 +125,14 @@ protected: VSyncReactorTest() : mMockDispatch(std::make_shared<MockVSyncDispatch>()), mMockTracker(std::make_shared<MockVSyncTracker>()), - mReactor(std::make_unique<VSyncDispatchWrapper>(mMockDispatch), + mMockClock(std::make_shared<NiceMock<MockClock>>()), + mReactor(std::make_unique<ClockWrapper>(mMockClock), + std::make_unique<VSyncDispatchWrapper>(mMockDispatch), std::make_unique<VSyncTrackerWrapper>(mMockTracker), kPendingLimit) {} std::shared_ptr<MockVSyncDispatch> mMockDispatch; std::shared_ptr<MockVSyncTracker> mMockTracker; + std::shared_ptr<MockClock> mMockClock; static constexpr size_t kPendingLimit = 3; static constexpr nsecs_t dummyTime = 47; VSyncReactor mReactor; @@ -181,4 +202,36 @@ TEST_F(VSyncReactorTest, ignoresPresentFencesWhenToldTo) { EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(dummyTime))); } +TEST_F(VSyncReactorTest, queriesTrackerForNextRefreshNow) { + nsecs_t const fakeTimestamp = 4839; + EXPECT_CALL(*mMockTracker, currentPeriod()).Times(0); + EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(_)) + .Times(1) + .WillOnce(Return(fakeTimestamp)); + + EXPECT_THAT(mReactor.computeNextRefresh(0), Eq(fakeTimestamp)); +} + +TEST_F(VSyncReactorTest, queriesTrackerForExpectedPresentTime) { + nsecs_t const fakeTimestamp = 4839; + EXPECT_CALL(*mMockTracker, currentPeriod()).Times(0); + EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(_)) + .Times(1) + .WillOnce(Return(fakeTimestamp)); + + EXPECT_THAT(mReactor.expectedPresentTime(), Eq(fakeTimestamp)); +} + +TEST_F(VSyncReactorTest, queriesTrackerForNextRefreshFuture) { + nsecs_t const fakeTimestamp = 4839; + nsecs_t const fakePeriod = 1010; + nsecs_t const fakeNow = 2214; + int const numPeriodsOut = 3; + EXPECT_CALL(*mMockClock, now()).WillOnce(Return(fakeNow)); + EXPECT_CALL(*mMockTracker, currentPeriod()).WillOnce(Return(fakePeriod)); + EXPECT_CALL(*mMockTracker, nextAnticipatedVSyncTimeFrom(fakeNow + numPeriodsOut * fakePeriod)) + .WillOnce(Return(fakeTimestamp)); + EXPECT_THAT(mReactor.computeNextRefresh(numPeriodsOut), Eq(fakeTimestamp)); +} + } // namespace android::scheduler |