[AChoreographer] Add private api that decouples from ALooper.

For ease of use by HWUI, we'll get rid of the reliance of a thread-local
ALooper:
* Rather than using AChoreographer_getInstance to access a thread-local
AChoreographer instance, the caller will be expected to create and
destroy its own instnace.
* For use by HWUI's own looper instance, _getFd() will expose the
underlying file descriptor from which events can be listened. The
corresponding choreographer combined callback can be called to flush
pending display events.

Bug: 136262896
Test: builds
Change-Id: I94f102da22974cbad37f21a68d2f04ac0cec5c78
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 208d729..8af1a1c 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -50,17 +50,20 @@
         return result;
     }
 
-    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
-    if (rc < 0) {
-        return UNKNOWN_ERROR;
+    if (mLooper != nullptr) {
+        int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
+        if (rc < 0) {
+            return UNKNOWN_ERROR;
+        }
     }
+
     return OK;
 }
 
 void DisplayEventDispatcher::dispose() {
     ALOGV("dispatcher %p ~ Disposing display event dispatcher.", this);
 
-    if (!mReceiver.initCheck()) {
+    if (!mReceiver.initCheck() && mLooper != nullptr) {
         mLooper->removeFd(mReceiver.getFd());
     }
 }
@@ -101,6 +104,10 @@
     mConfigChangeFlag = configChangeFlag;
 }
 
+int DisplayEventDispatcher::getFd() {
+    return mReceiver.getFd();
+}
+
 int DisplayEventDispatcher::handleEvent(int, int events, void*) {
     if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
         ALOGE("Display event receiver pipe was closed or an error occurred.  "
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 0b71801..679d572 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -32,6 +32,8 @@
     void dispose();
     status_t scheduleVsync();
     void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag);
+    int getFd();
+    virtual int handleEvent(int receiveFd, int events, void* data);
 
 protected:
     virtual ~DisplayEventDispatcher() = default;
@@ -48,7 +50,6 @@
     virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
                                        int32_t configId, nsecs_t vsyncPeriod) = 0;
 
-    virtual int handleEvent(int receiveFd, int events, void* data);
     bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
                               uint32_t* outCount);
 };
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 7e71ede..1f77393 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -56,6 +56,7 @@
 
 class Choreographer : public DisplayEventDispatcher, public MessageHandler {
 public:
+    explicit Choreographer(const sp<Looper>& looper);
     void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
                                   AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay);
     void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
@@ -68,12 +69,9 @@
     virtual void handleMessage(const Message& message) override;
 
     static Choreographer* getForThread();
-
-protected:
     virtual ~Choreographer() = default;
 
 private:
-    explicit Choreographer(const sp<Looper>& looper);
     Choreographer(const Choreographer&) = delete;
 
     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
@@ -132,14 +130,22 @@
     }
     if (callback.dueTime <= now) {
         if (std::this_thread::get_id() != mThreadId) {
-            Message m{MSG_SCHEDULE_VSYNC};
-            mLooper->sendMessage(this, m);
+            if (mLooper != nullptr) {
+                Message m{MSG_SCHEDULE_VSYNC};
+                mLooper->sendMessage(this, m);
+            } else {
+                scheduleVsync();
+            }
         } else {
             scheduleVsync();
         }
     } else {
-        Message m{MSG_SCHEDULE_CALLBACKS};
-        mLooper->sendMessageDelayed(delay, this, m);
+        if (mLooper != nullptr) {
+            Message m{MSG_SCHEDULE_CALLBACKS};
+            mLooper->sendMessageDelayed(delay, this, m);
+        } else {
+            scheduleCallbacks();
+        }
     }
 }
 
@@ -238,7 +244,7 @@
 
 /* Glue for the NDK interface */
 
-using android::Choreographer;
+using namespace android;
 
 static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) {
     return reinterpret_cast<Choreographer*>(choreographer);
@@ -281,3 +287,32 @@
                                                   AChoreographer_refreshRateCallback callback) {
     AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback);
 }
+
+AChoreographer* AChoreographer_create() {
+    Choreographer* choreographer = new Choreographer(nullptr);
+    status_t result = choreographer->initialize();
+    if (result != OK) {
+        ALOGW("Failed to initialize");
+        return nullptr;
+    }
+    return Choreographer_to_AChoreographer(choreographer);
+}
+
+void AChoreographer_destroy(AChoreographer* choreographer) {
+    if (choreographer == nullptr) {
+        return;
+    }
+
+    delete AChoreographer_to_Choreographer(choreographer);
+}
+
+int AChoreographer_getFd(AChoreographer* choreographer) {
+    return AChoreographer_to_Choreographer(choreographer)->getFd();
+}
+
+void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) {
+    // Pass dummy fd and events args to handleEvent, since the underlying
+    // DisplayEventDispatcher doesn't need them outside of validating that a
+    // Looper instance didn't break, but these args circumvent those checks.
+    AChoreographer_to_Choreographer(choreographer)->handleEvent(-1, Looper::EVENT_INPUT, data);
+}
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index 7a497ea..d37b9a1 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 ndk_headers {
-    name: "libachoreographer_ndk_headers",
+    name: "libnativedisplay_ndk_headers",
     from: "include/android",
     to: "android",
     srcs: ["include/android/*.h"],
diff --git a/libs/nativedisplay/include/apex/choreographer.h b/libs/nativedisplay/include/apex/choreographer.h
index 352213e..5251fd3 100644
--- a/libs/nativedisplay/include/apex/choreographer.h
+++ b/libs/nativedisplay/include/apex/choreographer.h
@@ -40,4 +40,39 @@
 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
                                                   AChoreographer_refreshRateCallback);
 
+/**
+ * Creates an instance of AChoreographer.
+ *
+ * The key differences between this method and AChoreographer_getInstance are:
+ * 1. The returned AChoreographer instance is not a thread-local, and
+ * 2. This method does not require an existing ALooper attached to the thread.
+ */
+AChoreographer* AChoreographer_create();
+
+/**
+ * Destroys a choreographer instance created from AChoreographer_create.
+ */
+void AChoreographer_destroy(AChoreographer* choreographer);
+
+/**
+ * Returns the underlying file descriptor associated with this choreographer
+ * instance.
+ *
+ * The caller can listen to the file descriptor to respond to any AChoreographer
+ * events. One such way is registering the file descriptor to a Looper instance,
+ * although this is not a requirement.
+ */
+int AChoreographer_getFd(AChoreographer* choreographer);
+
+/**
+ * Provides a callback to handle all pending events emitted by this
+ * choreographer instance. Specifically, this delegates to the callbacks
+ * previously registered to choreographer.
+ *
+ * If the associated file descriptor is attached to a Looper instance, then the
+ * callback attached to that Looper is expected to handle exceptional Looper
+ * events.
+ */
+void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data);
+
 __END_DECLS