SurfaceFlinger: Shared timeline plumbing

Add plumbing to get shared timeline data from Surface Flinger to HWUI
and back.

Bug: 162890382
Bug: 162888881

Test: SF unit tests
Change-Id: Ifb76e6bf28d43c051e6c8ff568437ec9a106b865
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 2cc7c34..7e894b4 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -73,7 +73,8 @@
         nsecs_t vsyncTimestamp;
         PhysicalDisplayId vsyncDisplayId;
         uint32_t vsyncCount;
-        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
+        int64_t vsyncId;
+        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) {
             ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
                   ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
         }
@@ -116,11 +117,13 @@
     nsecs_t vsyncTimestamp;
     PhysicalDisplayId vsyncDisplayId;
     uint32_t vsyncCount;
-    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
-        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d", this,
-              ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount);
+    int64_t vsyncId;
+    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) {
+        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
+              ", displayId=%s, count=%d, vsyncId=%" PRId64,
+              this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId);
         mWaitingForVsync = false;
-        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
+        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId);
     }
 
     return 1; // keep the callback
@@ -128,10 +131,11 @@
 
 bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
                                                   PhysicalDisplayId* outDisplayId,
-                                                  uint32_t* outCount) {
+                                                  uint32_t* outCount, int64_t* outVsyncId) {
     bool gotVsync = false;
     DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
     ssize_t n;
+    *outVsyncId = 0;
     while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
         ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
         for (ssize_t i = 0; i < n; i++) {
@@ -144,6 +148,7 @@
                     *outTimestamp = ev.header.timestamp;
                     *outDisplayId = ev.header.displayId;
                     *outCount = ev.vsync.count;
+                    *outVsyncId = ev.vsync.vsyncId;
                     break;
                 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                     dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 0ac493d..8b65ea1 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1150,6 +1150,38 @@
 
         return NO_ERROR;
     }
+
+    virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
+                                           int64_t frameTimelineVsyncId) {
+        Parcel data, reply;
+        status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (err != NO_ERROR) {
+            ALOGE("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err),
+                  -err);
+            return err;
+        }
+
+        err = data.writeStrongBinder(IInterface::asBinder(surface));
+        if (err != NO_ERROR) {
+            ALOGE("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err),
+                  -err);
+            return err;
+        }
+
+        err = data.writeInt64(frameTimelineVsyncId);
+        if (err != NO_ERROR) {
+            ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err);
+            return err;
+        }
+
+        err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply);
+        if (err != NO_ERROR) {
+            ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err);
+            return err;
+        }
+
+        return reply.readInt32();
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -1950,6 +1982,33 @@
             }
             return NO_ERROR;
         }
+        case SET_FRAME_TIMELINE_VSYNC: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> binder;
+            status_t err = data.readStrongBinder(&binder);
+            if (err != NO_ERROR) {
+                ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)",
+                      strerror(-err), -err);
+                return err;
+            }
+            sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
+            if (!surface) {
+                ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)",
+                      strerror(-err), -err);
+                return err;
+            }
+            int64_t frameTimelineVsyncId;
+            err = data.readInt64(&frameTimelineVsyncId);
+            if (err != NO_ERROR) {
+                ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err),
+                      -err);
+                return err;
+            }
+
+            status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e45b3d1..9ce8442 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1207,6 +1207,9 @@
     case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER:
         res = dispatchGetLastQueuedBuffer(args);
         break;
+    case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC:
+        res = dispatchSetFrameTimelineVsync(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -1513,6 +1516,14 @@
     return result;
 }
 
+int Surface::dispatchSetFrameTimelineVsync(va_list args) {
+    ATRACE_CALL();
+    auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
+
+    ALOGV("Surface::dispatchSetFrameTimelineVsync");
+    return composerService()->setFrameTimelineVsync(mGraphicBufferProducer, frameTimelineVsyncId);
+}
+
 bool Surface::transformToDisplayInverse() {
     return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
             NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index eb5b004..cf598ea 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -43,7 +43,8 @@
     DisplayEventReceiver mReceiver;
     bool mWaitingForVsync;
 
-    virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0;
+    virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
+                               int64_t vsyncId) = 0;
     virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
                                  bool connected) = 0;
     virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
@@ -53,6 +54,6 @@
     virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;
 
     bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
-                              uint32_t* outCount);
+                              uint32_t* outCount, int64_t* outVsyncId);
 };
 } // namespace android
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 0d0d102..df3118f 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -73,6 +73,7 @@
             uint32_t count;
             nsecs_t expectedVSyncTimestamp __attribute__((aligned(8)));
             nsecs_t deadlineTimestamp __attribute__((aligned(8)));
+            int64_t vsyncId;
         };
 
         struct Hotplug {
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e057b68..7c25b97 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -479,6 +479,13 @@
      * for tests. Release the token by releasing the returned IBinder reference.
      */
     virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) = 0;
+
+    /*
+     * Sets the frame timeline vsync id received from choreographer that corresponds to next
+     * buffer submitted on that surface.
+     */
+    virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
+                                           int64_t frameTimelineVsyncId) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -538,6 +545,7 @@
         SET_GAME_CONTENT_TYPE,
         SET_FRAME_RATE,
         ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
+        SET_FRAME_TIMELINE_VSYNC,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 55b4101..a68f2e7 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -265,6 +265,7 @@
     int dispatchAddQueueInterceptor(va_list args);
     int dispatchAddQueryInterceptor(va_list args);
     int dispatchGetLastQueuedBuffer(va_list args);
+    int dispatchSetFrameTimelineVsync(va_list args);
     bool transformToDisplayInverse();
 
 protected:
diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index 4bcb795..7210910 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -33,6 +33,8 @@
 
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, count, 0);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, expectedVSyncTimestamp, 8);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, deadlineTimestamp, 16);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncId, 24);
 
     CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0);
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index aedba2a..8d69997 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -868,7 +868,14 @@
         return NO_ERROR;
     }
 
-    status_t acquireFrameRateFlexibilityToken(sp<IBinder>* /*outToken*/) { return NO_ERROR; }
+    status_t acquireFrameRateFlexibilityToken(sp<IBinder>* /*outToken*/) override {
+        return NO_ERROR;
+    }
+
+    status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& /*surface*/,
+                                   int64_t /*frameTimelineVsyncId*/) override {
+        return NO_ERROR;
+    }
 
 protected:
     IBinder* onAsBinder() override { return nullptr; }