SurfaceFlinger: use setActiveConfigWithConstraints

Remove setActiveConfig and use setActiveConfigWithConstraints
instead. Use the return parameter of setActiveConfigWithConstraints to know
whether a refresh is required and when.

Fixes: 142753004
Bug: 141329414
Test: observe refresh rate switching thru systrace
Change-Id: Ie67a3be9180e7a367fc9e73425598d53a5fd6578
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1d50fe1..71a6a2f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -59,11 +59,13 @@
 namespace android {
 
 Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
-                     const scheduler::RefreshRateConfigs& refreshRateConfig)
+                     const scheduler::RefreshRateConfigs& refreshRateConfig,
+                     ISchedulerCallback& schedulerCallback)
       : mPrimaryDispSync(new impl::DispSync("SchedulerDispSync",
                                             sysprop::running_without_sync_framework(true))),
         mEventControlThread(new impl::EventControlThread(std::move(function))),
         mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
+        mSchedulerCallback(schedulerCallback),
         mRefreshRateConfigs(refreshRateConfig) {
     using namespace sysprop;
 
@@ -104,10 +106,12 @@
 
 Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
                      std::unique_ptr<EventControlThread> eventControlThread,
-                     const scheduler::RefreshRateConfigs& configs)
+                     const scheduler::RefreshRateConfigs& configs,
+                     ISchedulerCallback& schedulerCallback)
       : mPrimaryDispSync(std::move(primaryDispSync)),
         mEventControlThread(std::move(eventControlThread)),
         mSupportKernelTimer(false),
+        mSchedulerCallback(schedulerCallback),
         mRefreshRateConfigs(configs) {}
 
 Scheduler::~Scheduler() {
@@ -368,12 +372,7 @@
         mFeatures.configId = newConfigId;
     };
     auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
-    changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
-}
-
-void Scheduler::setSchedulerCallback(android::Scheduler::ISchedulerCallback* callback) {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    mSchedulerCallback = callback;
+    mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
 }
 
 void Scheduler::resetIdleTimer() {
@@ -486,7 +485,7 @@
         }
     }
     const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
-    changeRefreshRate(newRefreshRate, event);
+    mSchedulerCallback.changeRefreshRate(newRefreshRate, event);
 }
 
 HwcConfigIndexType Scheduler::calculateRefreshRateType() {
@@ -526,10 +525,36 @@
     return mFeatures.configId;
 }
 
-void Scheduler::changeRefreshRate(const RefreshRate& refreshRate, ConfigEvent configEvent) {
-    std::lock_guard<std::mutex> lock(mCallbackLock);
-    if (mSchedulerCallback) {
-        mSchedulerCallback->changeRefreshRate(refreshRate, configEvent);
+void Scheduler::onNewVsyncPeriodChangeTimeline(const HWC2::VsyncPeriodChangeTimeline& timeline) {
+    if (timeline.refreshRequired) {
+        mSchedulerCallback.repaintEverythingForHWC();
+    }
+
+    std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
+    mLastVsyncPeriodChangeTimeline = std::make_optional(timeline);
+
+    const auto maxAppliedTime = systemTime() + MAX_VSYNC_APPLIED_TIME.count();
+    if (timeline.newVsyncAppliedTimeNanos > maxAppliedTime) {
+        mLastVsyncPeriodChangeTimeline->newVsyncAppliedTimeNanos = maxAppliedTime;
+    }
+}
+
+void Scheduler::onDisplayRefreshed(nsecs_t timestamp) {
+    bool callRepaint = false;
+    {
+        std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
+        if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
+            if (mLastVsyncPeriodChangeTimeline->refreshTimeNanos < timestamp) {
+                mLastVsyncPeriodChangeTimeline->refreshRequired = false;
+            } else {
+                // We need to send another refresh as refreshTimeNanos is still in the future
+                callRepaint = true;
+            }
+        }
+    }
+
+    if (callRepaint) {
+        mSchedulerCallback.repaintEverythingForHWC();
     }
 }
 
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 04a8390..15277ce 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -41,22 +41,24 @@
 class InjectVSyncSource;
 struct DisplayStateInfo;
 
+class ISchedulerCallback {
+public:
+    virtual ~ISchedulerCallback() = default;
+    virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
+                                   scheduler::RefreshRateConfigEvent) = 0;
+    virtual void repaintEverythingForHWC() = 0;
+};
+
 class Scheduler {
 public:
     using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
     using ConfigEvent = scheduler::RefreshRateConfigEvent;
 
-    class ISchedulerCallback {
-    public:
-        virtual ~ISchedulerCallback() = default;
-        virtual void changeRefreshRate(const RefreshRate&, ConfigEvent) = 0;
-    };
-
     // Indicates whether to start the transaction early, or at vsync time.
     enum class TransactionStart { EARLY, NORMAL };
 
     Scheduler(impl::EventControlThread::SetVSyncEnabledFunction,
-              const scheduler::RefreshRateConfigs&);
+              const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback);
 
     virtual ~Scheduler();
 
@@ -114,9 +116,6 @@
     // Detects content using layer history, and selects a matching refresh rate.
     void chooseRefreshRateForContent();
 
-    // Called by Scheduler to control SurfaceFlinger operations.
-    void setSchedulerCallback(ISchedulerCallback*);
-
     bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
     void resetIdleTimer();
 
@@ -131,6 +130,12 @@
     // Get the appropriate refresh for current conditions.
     std::optional<HwcConfigIndexType> getPreferredConfigId();
 
+    // Notifies the scheduler about a refresh rate timeline change.
+    void onNewVsyncPeriodChangeTimeline(const HWC2::VsyncPeriodChangeTimeline& timeline);
+
+    // Notifies the scheduler when the display was refreshed
+    void onDisplayRefreshed(nsecs_t timestamp);
+
 private:
     friend class TestableScheduler;
 
@@ -142,7 +147,7 @@
 
     // Used by tests to inject mocks.
     Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
-              const scheduler::RefreshRateConfigs&);
+              const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback);
 
     std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs,
                                                            nsecs_t offsetThresholdForNextVsync);
@@ -165,8 +170,6 @@
     void setVsyncPeriod(nsecs_t period);
 
     HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock);
-    // Acquires a lock and calls the ChangeRefreshRateCallback with given parameters.
-    void changeRefreshRate(const RefreshRate&, ConfigEvent);
 
     // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
     struct Connection {
@@ -203,8 +206,7 @@
     // Timer used to monitor display power mode.
     std::optional<scheduler::OneShotTimer> mDisplayPowerTimer;
 
-    std::mutex mCallbackLock;
-    ISchedulerCallback* mSchedulerCallback GUARDED_BY(mCallbackLock) = nullptr;
+    ISchedulerCallback& mSchedulerCallback;
 
     // In order to make sure that the features don't override themselves, we need a state machine
     // to keep track which feature requested the config change.
@@ -223,6 +225,11 @@
     } mFeatures GUARDED_BY(mFeatureStateLock);
 
     const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
+
+    std::mutex mVsyncTimelineLock;
+    std::optional<HWC2::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
+            GUARDED_BY(mVsyncTimelineLock);
+    static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
 };
 
 } // namespace android