Moving DispSync into Scheduler.

This change is part of go/surface-flinger-scheduler.

Test: SF tests pass.
Change-Id: I073a54c2111fa3146af3eb68f3294c3c5c95543c
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 54e19c7..18a8bb1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -20,15 +20,25 @@
 #include <cstdint>
 #include <memory>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
 #include <gui/ISurfaceComposer.h>
+#include <ui/DisplayStatInfo.h>
 
 #include "DispSync.h"
 #include "DispSyncSource.h"
+#include "EventControlThread.h"
 #include "EventThread.h"
 #include "InjectVSyncSource.h"
 
 namespace android {
 
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
 #define RETURN_VALUE_IF_INVALID(value) \
     if (handle == nullptr || mConnections.count(handle->id) == 0) return value
 #define RETURN_IF_INVALID() \
@@ -36,17 +46,34 @@
 
 std::atomic<int64_t> Scheduler::sNextId = 0;
 
+Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function)
+      : mHasSyncFramework(
+                getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasSyncFramework>(true)),
+        mDispSyncPresentTimeOffset(
+                getInt64<ISurfaceFlingerConfigs,
+                         &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0)),
+        mPrimaryHWVsyncEnabled(false),
+        mHWVsyncAvailable(false) {
+    // Note: We create a local temporary with the real DispSync implementation
+    // type temporarily so we can initialize it with the configured values,
+    // before storing it for more generic use using the interface type.
+    auto primaryDispSync = std::make_unique<impl::DispSync>("SchedulerDispSync");
+    primaryDispSync->init(mHasSyncFramework, mDispSyncPresentTimeOffset);
+    mPrimaryDispSync = std::move(primaryDispSync);
+    mEventControlThread = std::make_unique<impl::EventControlThread>(function);
+}
+
 Scheduler::~Scheduler() = default;
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const std::string& connectionName, int64_t phaseOffsetNs,
         impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
 
     std::unique_ptr<EventThread> eventThread =
-            makeEventThread(connectionName, dispSync, phaseOffsetNs, resyncCallback,
+            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs, resyncCallback,
                             interceptCallback);
     auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
                                                    eventThread->createEventConnection(),
@@ -108,4 +135,65 @@
     RETURN_IF_INVALID();
     mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
 }
+
+void Scheduler::getDisplayStatInfo(DisplayStatInfo* stats) {
+    stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+    stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
+}
+
+void Scheduler::enableHardwareVsync() {
+    std::lock_guard<std::mutex> lock(mHWVsyncLock);
+    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
+        mPrimaryDispSync->beginResync();
+        mEventControlThread->setVsyncEnabled(true);
+        mPrimaryHWVsyncEnabled = true;
+    }
+}
+
+void Scheduler::disableHardwareVsync(bool makeUnavailable) {
+    std::lock_guard<std::mutex> lock(mHWVsyncLock);
+    if (mPrimaryHWVsyncEnabled) {
+        mEventControlThread->setVsyncEnabled(false);
+        mPrimaryDispSync->endResync();
+        mPrimaryHWVsyncEnabled = false;
+    }
+    if (makeUnavailable) {
+        mHWVsyncAvailable = false;
+    }
+}
+
+void Scheduler::setVsyncPeriod(const nsecs_t period) {
+    mPrimaryDispSync->reset();
+    mPrimaryDispSync->setPeriod(period);
+    enableHardwareVsync();
+}
+
+void Scheduler::addResyncSample(const nsecs_t timestamp) {
+    bool needsHwVsync = false;
+    { // Scope for the lock
+        std::lock_guard<std::mutex> lock(mHWVsyncLock);
+        if (mPrimaryHWVsyncEnabled) {
+            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
+        }
+    }
+
+    if (needsHwVsync) {
+        enableHardwareVsync();
+    } else {
+        disableHardwareVsync(false);
+    }
+}
+
+void Scheduler::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
+    if (mPrimaryDispSync->addPresentFence(fenceTime)) {
+        enableHardwareVsync();
+    } else {
+        disableHardwareVsync(false);
+    }
+}
+
+void Scheduler::setIgnorePresentFences(bool ignore) {
+    mPrimaryDispSync->setIgnorePresentFences(ignore);
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index d7c9651..fdafe58 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -20,13 +20,17 @@
 #include <memory>
 
 #include <gui/ISurfaceComposer.h>
+#include <ui/DisplayStatInfo.h>
 
 #include "DispSync.h"
+#include "EventControlThread.h"
 #include "EventThread.h"
 #include "InjectVSyncSource.h"
 
 namespace android {
 
+class EventControlThread;
+
 class Scheduler {
 public:
     // Enum to indicate whether to start the transaction early, or at vsync time.
@@ -38,7 +42,9 @@
     class ConnectionHandle : public BBinder {
     public:
         ConnectionHandle(int64_t id) : id(id) {}
+
         ~ConnectionHandle() = default;
+
         const int64_t id;
     };
 
@@ -47,6 +53,7 @@
         Connection(sp<ConnectionHandle> handle, sp<BnDisplayEventConnection> eventConnection,
                    std::unique_ptr<EventThread> eventThread)
               : handle(handle), eventConnection(eventConnection), thread(std::move(eventThread)) {}
+
         ~Connection() = default;
 
         sp<ConnectionHandle> handle;
@@ -54,32 +61,48 @@
         const std::unique_ptr<EventThread> thread;
     };
 
-    Scheduler() = default;
+    explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function);
+
     virtual ~Scheduler();
 
     /** Creates an EventThread connection. */
     sp<ConnectionHandle> createConnection(
-            const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const std::string& connectionName, int64_t phaseOffsetNs,
             impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
+
     sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
+
     sp<BnDisplayEventConnection> getEventConnection(const sp<ConnectionHandle>& handle);
 
     // Should be called when receiving a hotplug event.
     void hotplugReceived(const sp<ConnectionHandle>& handle, EventThread::DisplayType displayType,
                          bool connected);
+
     // Should be called after the screen is turned on.
     void onScreenAcquired(const sp<ConnectionHandle>& handle);
+
     // Should be called before the screen is turned off.
     void onScreenReleased(const sp<ConnectionHandle>& handle);
+
     // Should be called when dumpsys command is received.
     void dump(const sp<ConnectionHandle>& handle, String8& result) const;
+
     // Offers ability to modify phase offset in the event thread.
     void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
 
+    void getDisplayStatInfo(DisplayStatInfo* stats);
+
+    void enableHardwareVsync();
+    void disableHardwareVsync(bool makeUnavailable);
+    void setVsyncPeriod(const nsecs_t period);
+    void addResyncSample(const nsecs_t timestamp);
+    void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
+    void setIgnorePresentFences(bool ignore);
+
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
             const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
@@ -87,8 +110,29 @@
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
+    // TODO(b/113612090): Instead of letting BufferQueueLayer to access mDispSync directly, it
+    // should make request to Scheduler to compute next refresh.
+    friend class BufferQueueLayer;
+
+    // If fences from sync Framework are supported.
+    const bool mHasSyncFramework;
+
+    // The offset in nanoseconds to use, when DispSync timestamps present fence
+    // signaling time.
+    const nsecs_t mDispSyncPresentTimeOffset;
+
+    // Each connection has it's own ID. This variable keeps track of the count.
     static std::atomic<int64_t> sNextId;
+
+    // Connections are stored in a map <connection ID, connection> for easy retrieval.
     std::unordered_map<int64_t, std::unique_ptr<Connection>> mConnections;
+
+    std::mutex mHWVsyncLock;
+    bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock);
+    bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock);
+
+    std::unique_ptr<DispSync> mPrimaryDispSync;
+    std::unique_ptr<EventControlThread> mEventControlThread;
 };
 
 } // namespace android
\ No newline at end of file