[SF] Adds callback from the VsyncPredictor

Hooks up the NotifyExpectedPresentIfRequired with
expectedPresentTime

BUG: 296636253
BUG: 284845445
Test: atest HWComposerTest
Change-Id: Idfd30929a0f4931b1a9f943340932c655ddd5903
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1a8713d..d3db523 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -67,11 +67,12 @@
 namespace android::scheduler {
 
 Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
-                     sp<VsyncModulator> modulatorPtr)
+                     sp<VsyncModulator> modulatorPtr, IVsyncTrackerCallback& vsyncTrackerCallback)
       : impl::MessageQueue(compositor),
         mFeatures(features),
         mVsyncModulator(std::move(modulatorPtr)),
-        mSchedulerCallback(callback) {}
+        mSchedulerCallback(callback),
+        mVsyncTrackerCallback(vsyncTrackerCallback) {}
 
 Scheduler::~Scheduler() {
     // MessageQueue depends on VsyncSchedule, so first destroy it.
@@ -116,10 +117,10 @@
 }
 
 void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
-    auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures,
-                                                       [this](PhysicalDisplayId id, bool enable) {
-                                                           onHardwareVsyncRequest(id, enable);
-                                                       });
+    auto schedulePtr = std::make_shared<VsyncSchedule>(
+            displayId, mFeatures,
+            [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); },
+            mVsyncTrackerCallback);
 
     registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
 }
@@ -562,7 +563,19 @@
     ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
           to_string(mode.modePtr->getVsyncRate()).c_str());
 
-    display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
+    display.schedulePtr->getTracker().setDisplayModeData(
+            {.renderRate = renderFrameRate,
+             .notifyExpectedPresentTimeoutOpt = getNotifyExpectedPresentTimeout(mode)});
+}
+
+std::optional<Period> Scheduler::getNotifyExpectedPresentTimeout(const FrameRateMode& mode) {
+    if (mode.modePtr->getVrrConfig() && mode.modePtr->getVrrConfig()->notifyExpectedPresentConfig) {
+        return Period::fromNs(
+                mode.modePtr->getVrrConfig()
+                        ->notifyExpectedPresentConfig->notifyExpectedPresentTimeoutNs);
+    } else {
+        return std::nullopt;
+    }
 }
 
 void Scheduler::resync() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index b0520a6..a5a5e8d 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -102,7 +102,8 @@
     using Impl = android::impl::MessageQueue;
 
 public:
-    Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>);
+    Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>,
+              IVsyncTrackerCallback&);
     virtual ~Scheduler();
 
     void startTimers();
@@ -429,6 +430,9 @@
     Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
     void resync() override EXCLUDES(mDisplayLock);
 
+    std::optional<Period> getNotifyExpectedPresentTimeout(const FrameRateMode&)
+            REQUIRES(mDisplayLock);
+
     // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
     struct Connection {
         sp<EventThreadConnection> connection;
@@ -462,6 +466,8 @@
 
     ISchedulerCallback& mSchedulerCallback;
 
+    IVsyncTrackerCallback& mVsyncTrackerCallback;
+
     // mDisplayLock may be locked while under mPolicyLock.
     mutable std::mutex mPolicyLock;
 
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index e969fdc..799466b 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -35,6 +35,7 @@
 #include <gui/TraceUtils.h>
 #include <utils/Log.h>
 
+#include "FlagManager.h"
 #include "RefreshRateSelector.h"
 #include "VSyncPredictor.h"
 
@@ -47,12 +48,14 @@
 VSyncPredictor::~VSyncPredictor() = default;
 
 VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
-                               size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
+                               size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
+                               IVsyncTrackerCallback& callback)
       : mId(id),
         mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
         kHistorySize(historySize),
         kMinimumSamplesForPrediction(minimumSamplesForPrediction),
         kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
+        mVsyncTrackerCallback(callback),
         mIdealPeriod(idealPeriod) {
     resetModel();
 }
@@ -275,11 +278,11 @@
     mLastVsyncSequence = getVsyncSequenceLocked(timePoint);
 
     const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int {
-        if (!mRenderRate) return 0;
+        if (!mDisplayModeDataOpt) return 0;
 
         const auto divisor =
                 RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod),
-                                                         *mRenderRate);
+                                                         mDisplayModeDataOpt->renderRate);
         if (divisor <= 1) return 0;
 
         const int mod = mLastVsyncSequence->seq % divisor;
@@ -289,12 +292,24 @@
     }();
 
     if (renderRatePhase == 0) {
-        return mLastVsyncSequence->vsyncTime;
+        const auto vsyncTime = mLastVsyncSequence->vsyncTime;
+        if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
+            mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(vsyncTime),
+                                                   *mDisplayModeDataOpt,
+                                                   Period::fromNs(mIdealPeriod));
+        }
+        return vsyncTime;
     }
 
     auto const [slope, intercept] = getVSyncPredictionModelLocked();
     const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase;
-    return nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
+    const auto nextAnticipatedVsyncTime =
+            nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
+    if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
+        mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(nextAnticipatedVsyncTime),
+                                               *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod));
+    }
+    return nextAnticipatedVsyncTime;
 }
 
 /*
@@ -332,10 +347,14 @@
     return vsyncSequence.seq % divisor == 0;
 }
 
-void VSyncPredictor::setRenderRate(Fps fps) {
-    ALOGV("%s %s: %s", __func__, to_string(mId).c_str(), to_string(fps).c_str());
+void VSyncPredictor::setDisplayModeData(const DisplayModeData& displayModeData) {
+    ALOGV("%s %s: RenderRate %s notifyExpectedPresentTimeout %s", __func__, to_string(mId).c_str(),
+          to_string(displayModeData.renderRate).c_str(),
+          displayModeData.notifyExpectedPresentTimeoutOpt
+                  ? std::to_string(displayModeData.notifyExpectedPresentTimeoutOpt->ns()).c_str()
+                  : "N/A");
     std::lock_guard lock(mMutex);
-    mRenderRate = fps;
+    mDisplayModeDataOpt = displayModeData;
 }
 
 VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const {
@@ -358,6 +377,7 @@
         mRateMap.erase(mRateMap.begin());
     }
 
+    // TODO(b/308610306) mIdealPeriod to be updated with setDisplayModeData
     mIdealPeriod = period;
     if (mRateMap.find(period) == mRateMap.end()) {
         mRateMap[mIdealPeriod] = {period, 0};
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index c01c44d..c271eb7 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -36,9 +36,11 @@
      * \param [in] minimumSamplesForPrediction The minimum number of samples to collect before
      * predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
      * samples that fall outlierTolerancePercent from an anticipated vsync event.
+     * \param [in] IVsyncTrackerCallback The callback for the VSyncTracker.
      */
     VSyncPredictor(PhysicalDisplayId, nsecs_t idealPeriod, size_t historySize,
-                   size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent);
+                   size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
+                   IVsyncTrackerCallback&);
     ~VSyncPredictor();
 
     bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
@@ -69,7 +71,7 @@
 
     bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);
 
-    void setRenderRate(Fps) final EXCLUDES(mMutex);
+    void setDisplayModeData(const DisplayModeData&) final EXCLUDES(mMutex);
 
     void dump(std::string& result) const final EXCLUDES(mMutex);
 
@@ -99,6 +101,7 @@
     size_t const kHistorySize;
     size_t const kMinimumSamplesForPrediction;
     size_t const kOutlierTolerancePercent;
+    IVsyncTrackerCallback& mVsyncTrackerCallback;
     std::mutex mutable mMutex;
 
     nsecs_t mIdealPeriod GUARDED_BY(mMutex);
@@ -110,7 +113,7 @@
     size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
     std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
 
-    std::optional<Fps> mRenderRate GUARDED_BY(mMutex);
+    std::optional<DisplayModeData> mDisplayModeDataOpt GUARDED_BY(mMutex);
 
     mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex);
 };
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index bc0e3bc..7eedc31 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <ui/DisplayId.h>
 #include <utils/Timers.h>
 
 #include <scheduler/Fps.h>
@@ -23,6 +24,23 @@
 #include "VSyncDispatch.h"
 
 namespace android::scheduler {
+
+struct DisplayModeData {
+    Fps renderRate;
+    std::optional<Period> notifyExpectedPresentTimeoutOpt;
+
+    bool operator==(const DisplayModeData& other) const {
+        return isApproxEqual(renderRate, other.renderRate) &&
+                notifyExpectedPresentTimeoutOpt == other.notifyExpectedPresentTimeoutOpt;
+    }
+};
+
+struct IVsyncTrackerCallback {
+    virtual ~IVsyncTrackerCallback() = default;
+    virtual void onVsyncGenerated(PhysicalDisplayId, TimePoint expectedPresentTime,
+                                  const DisplayModeData&, Period vsyncPeriod) = 0;
+};
+
 /*
  * VSyncTracker is an interface for providing estimates on future Vsync signal times based on
  * historical vsync timing data.
@@ -80,16 +98,20 @@
     virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 0;
 
     /*
-     * Sets a render rate on the tracker. If the render rate is not a divisor
-     * of the period, the render rate is ignored until the period changes.
+     * Sets the metadata about the currently active display mode such as VRR
+     * timeout period, vsyncPeriod and framework property such as render rate.
+     * If the render rate is not a divisor of the period, the render rate is
+     * ignored until the period changes.
      * The tracker will continue to track the vsync timeline and expect it
      * to match the current period, however, nextAnticipatedVSyncTimeFrom will
      * return vsyncs according to the render rate set. Setting a render rate is useful
      * when a display is running at 120Hz but the render frame rate is 60Hz.
+     * When IVsyncTrackerCallback::onVsyncGenerated callback is made we will pass along
+     * the vsyncPeriod, render rate and timeoutNs.
      *
-     * \param [in] Fps   The render rate the tracker should operate at.
+     * \param [in] DisplayModeData The DisplayModeData the tracker will use.
      */
-    virtual void setRenderRate(Fps) = 0;
+    virtual void setDisplayModeData(const DisplayModeData&) = 0;
 
     virtual void dump(std::string& result) const = 0;
 
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index ff3f29d..5fb53f9 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -54,10 +54,11 @@
 };
 
 VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
-                             RequestHardwareVsync requestHardwareVsync)
+                             RequestHardwareVsync requestHardwareVsync,
+                             IVsyncTrackerCallback& callback)
       : mId(id),
         mRequestHardwareVsync(std::move(requestHardwareVsync)),
-        mTracker(createTracker(id)),
+        mTracker(createTracker(id, callback)),
         mDispatch(createDispatch(mTracker)),
         mController(createController(id, *mTracker, features)),
         mTracer(features.test(Feature::kTracePredictedVsync)
@@ -100,7 +101,8 @@
     mDispatch->dump(out);
 }
 
-VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
+VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id,
+                                                       IVsyncTrackerCallback& callback) {
     // TODO(b/144707443): Tune constants.
     constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
     constexpr size_t kHistorySize = 20;
@@ -108,7 +110,8 @@
     constexpr uint32_t kDiscardOutlierPercent = 20;
 
     return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
-                                            kMinSamplesForPrediction, kDiscardOutlierPercent);
+                                            kMinSamplesForPrediction, kDiscardOutlierPercent,
+                                            callback);
 }
 
 VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 47e92e1..ca61f87 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -31,6 +31,7 @@
 #include <scheduler/Time.h>
 
 #include "ThreadContext.h"
+#include "VSyncTracker.h"
 
 namespace android {
 class EventThreadTest;
@@ -56,7 +57,7 @@
 public:
     using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
 
-    VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync);
+    VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync, IVsyncTrackerCallback&);
     ~VsyncSchedule();
 
     // IVsyncSource overrides:
@@ -124,7 +125,7 @@
     friend class android::VsyncScheduleTest;
     friend class android::fuzz::SchedulerFuzzer;
 
-    static TrackerPtr createTracker(PhysicalDisplayId);
+    static TrackerPtr createTracker(PhysicalDisplayId, IVsyncTrackerCallback&);
     static DispatchPtr createDispatch(TrackerPtr);
     static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);