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
diff --git a/services/surfaceflinger/Scheduler/TimeKeeper.h b/services/surfaceflinger/Scheduler/TimeKeeper.h
index 699cd50..38f0708 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 @@
      */
     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 643c5d2..3894992 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -54,6 +54,11 @@
     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 1590f49..4210b3c 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -39,6 +39,7 @@
 
     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 1398362..9ce440c 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 @@
     }
 }
 
+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 05fd0fd..8436e8a 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 97b9620..335042d 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -47,6 +47,13 @@
      */
     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 c012616..448954f 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -47,6 +47,8 @@
         return timePoint - floor + mPeriod;
     }
 
+    nsecs_t currentPeriod() const final { return mPeriod; }
+
 private:
     nsecs_t const mPeriod;
 };
@@ -73,6 +75,11 @@
         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 82950b5..82b1051 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -39,6 +39,7 @@
 
     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 b4aebf0..c8784c6 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 @@
 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 @@
     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 @@
     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 @@
     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