Shared timeline plumbing

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

Bug: 162890382
Bug: 162888881
Bug: 162890407

Test: manual using ALOG messages in SF
Change-Id: I85c5eb56d2fa933889518854e7b79b1e65e29af3
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 0698775..30ce537 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -22,6 +22,7 @@
 
 const std::string FrameInfoNames[] = {
         "Flags",
+        "FrameTimelineVsyncId",
         "IntendedVsync",
         "Vsync",
         "OldestInputEvent",
@@ -44,7 +45,7 @@
                       static_cast<int>(FrameInfoIndex::NumIndexes),
               "size mismatch: FrameInfoNames doesn't match the enum!");
 
-static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 17,
+static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 18,
               "Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
 
 void FrameInfo::importUiThreadInfo(int64_t* info) {
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index dc30617..f5bfedd 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -27,10 +27,11 @@
 namespace android {
 namespace uirenderer {
 
-#define UI_THREAD_FRAME_INFO_SIZE 9
+#define UI_THREAD_FRAME_INFO_SIZE 10
 
 enum class FrameInfoIndex {
     Flags = 0,
+    FrameTimelineVsyncId,
     IntendedVsync,
     Vsync,
     OldestInputEvent,
@@ -71,11 +72,15 @@
 
 class UiFrameInfoBuilder {
 public:
+    static constexpr int64_t INVALID_VSYNC_ID = -1;
+
     explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
         memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+        set(FrameInfoIndex::FrameTimelineVsyncId) = INVALID_VSYNC_ID;
     }
 
-    UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
+    UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync, int64_t vsyncId) {
+        set(FrameInfoIndex::FrameTimelineVsyncId) = vsyncId;
         set(FrameInfoIndex::Vsync) = vsyncTime;
         set(FrameInfoIndex::IntendedVsync) = intendedVsync;
         // Pretend the other fields are all at vsync, too, so that naive
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index e817ca7..c89463b 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -514,7 +514,7 @@
         proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
         nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
         UiFrameInfoBuilder(proxy.frameInfo())
-                .setVsync(vsync, vsync)
+                .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID)
                 .addFlag(FrameInfoFlags::SurfaceCanvas);
         proxy.syncAndDrawFrame();
     }
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 13d544c..c7560b2 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,6 +484,14 @@
 
     waitOnFences();
 
+    if (mNativeSurface) {
+        // TODO(b/165985262): measure performance impact
+        if (const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
+                vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
+            native_window_set_frame_timeline_vsync(mNativeSurface->getNativeWindow(), vsyncId);
+        }
+    }
+
     bool requireSwap = false;
     int error = OK;
     bool didSwap =
@@ -617,8 +625,11 @@
     ATRACE_CALL();
 
     nsecs_t vsync = mRenderThread.timeLord().computeFrameTimeNanos();
+    int64_t vsyncId = mRenderThread.timeLord().lastVsyncId();
     int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
-    UiFrameInfoBuilder(frameInfo).addFlag(FrameInfoFlags::RTAnimation).setVsync(vsync, vsync);
+    UiFrameInfoBuilder(frameInfo)
+        .addFlag(FrameInfoFlags::RTAnimation)
+        .setVsync(vsync, vsync, vsyncId);
 
     TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
     prepareTree(info, frameInfo, systemTime(SYSTEM_TIME_MONOTONIC), node);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1e59338..1ea595d 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -128,7 +128,9 @@
 bool DrawFrameTask::syncFrameState(TreeInfo& info) {
     ATRACE_CALL();
     int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
-    mRenderThread->timeLord().vsyncReceived(vsync);
+    int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
+    int64_t vsyncId = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameTimelineVsyncId)];
+    mRenderThread->timeLord().vsyncReceived(vsync, intendedVsync, vsyncId);
     bool canDraw = mContext->makeCurrent();
     mContext->unpinImages();
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 4dcbc44..9371656 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -51,8 +51,10 @@
 
 void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) {
     RenderThread* rt = reinterpret_cast<RenderThread*>(data);
+    int64_t vsyncId = AChoreographer_getVsyncId(rt->mChoreographer);
     rt->mVsyncRequested = false;
-    if (rt->timeLord().vsyncReceived(frameTimeNanos) && !rt->mFrameCallbackTaskPending) {
+    if (rt->timeLord().vsyncReceived(frameTimeNanos, frameTimeNanos, vsyncId) &&
+            !rt->mFrameCallbackTaskPending) {
         ATRACE_NAME("queue mFrameCallbackTask");
         rt->mFrameCallbackTaskPending = true;
         nsecs_t runAt = (frameTimeNanos + rt->mDispatchFrameDelay);
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index d7dc00b..4fbb0716 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -19,8 +19,8 @@
 
 #include <GrDirectContext.h>
 #include <SkBitmap.h>
-#include <apex/choreographer.h>
 #include <cutils/compiler.h>
+#include <private/android/choreographer.h>
 #include <thread/ThreadBase.h>
 #include <utils/Looper.h>
 #include <utils/Thread.h>
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index 784068f..7dc36c4 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -19,9 +19,17 @@
 namespace uirenderer {
 namespace renderthread {
 
-TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)), mFrameTimeNanos(0) {}
+TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)),
+                       mFrameTimeNanos(0),
+                       mFrameIntendedTimeNanos(0),
+                       mFrameVsyncId(-1) {}
 
-bool TimeLord::vsyncReceived(nsecs_t vsync) {
+bool TimeLord::vsyncReceived(nsecs_t vsync, nsecs_t intendedVsync, int64_t vsyncId) {
+    if (intendedVsync > mFrameIntendedTimeNanos) {
+        mFrameIntendedTimeNanos = intendedVsync;
+        mFrameVsyncId = vsyncId;
+    }
+
     if (vsync > mFrameTimeNanos) {
         mFrameTimeNanos = vsync;
         return true;
@@ -36,6 +44,8 @@
     if (jitterNanos >= mFrameIntervalNanos) {
         nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
         mFrameTimeNanos = now - lastFrameOffset;
+        // mFrameVsyncId is not adjusted here as we still want to send
+        // the vsync id that started this frame to the Surface Composer
     }
     return mFrameTimeNanos;
 }
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 68a0f7f..23c1e51 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -32,9 +32,10 @@
     nsecs_t frameIntervalNanos() const { return mFrameIntervalNanos; }
 
     // returns true if the vsync is newer, false if it was rejected for staleness
-    bool vsyncReceived(nsecs_t vsync);
+    bool vsyncReceived(nsecs_t vsync, nsecs_t indendedVsync, int64_t vsyncId);
     nsecs_t latestVsync() { return mFrameTimeNanos; }
     nsecs_t computeFrameTimeNanos();
+    int64_t lastVsyncId() const { return mFrameVsyncId; }
 
 private:
     friend class RenderThread;
@@ -44,6 +45,8 @@
 
     nsecs_t mFrameIntervalNanos;
     nsecs_t mFrameTimeNanos;
+    nsecs_t mFrameIntendedTimeNanos;
+    int64_t mFrameVsyncId;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 801cb7d..ed89c59 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -145,7 +145,8 @@
     for (int i = 0; i < warmupFrameCount; i++) {
         testContext.waitForVsync();
         nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
-        UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
+        UiFrameInfoBuilder(proxy->frameInfo())
+            .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID);
         proxy->syncAndDrawFrame();
     }
 
@@ -165,7 +166,8 @@
         nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
         {
             ATRACE_NAME("UI-Draw Frame");
-            UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
+            UiFrameInfoBuilder(proxy->frameInfo())
+                .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID);
             scene->doFrame(i);
             proxy->syncAndDrawFrame();
         }