Pass actual present time to ViewRootImpl

To measure end-to-end touch latency, we need to report the actual
present time to ViewRootImpl. ViewRootImpl, in turn, will report this
information to InputDispatcher. Finally, InputDispatcher will combine
all known information for a specific input event, and will report this
data to westworld.

In another patch, we will add a new call, 'reportLatencyInfo', to
InputPublisher. This call will allow the app to send this latency data
to InputDispatcher.

Bug: 169866723
Test: printed the input event present times inside ViewRootImpl
Change-Id: Ibd3a2cfeb1a340eb15cd2165071df1f8589634af
diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h
index b93f078..ef1f5aa 100644
--- a/libs/hwui/FrameMetricsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -24,6 +24,24 @@
 class FrameMetricsObserver : public VirtualLightRefBase {
 public:
     virtual void notify(const int64_t* buffer) = 0;
+    bool waitForPresentTime() const { return mWaitForPresentTime; };
+
+    /**
+     * Create a new metrics observer. An observer that watches present time gets notified at a
+     * different time than the observer that doesn't.
+     *
+     * The observer that doesn't want present time is notified about metrics just after the frame
+     * is completed. This is the default behaviour that's used by public API's.
+     *
+     * An observer that watches present time is notified about metrics after the actual display
+     * present time is known.
+     * WARNING! This observer may not receive metrics for the last several frames that the app
+     * produces.
+     */
+    FrameMetricsObserver(bool waitForPresentTime) : mWaitForPresentTime(waitForPresentTime) {}
+
+private:
+    const bool mWaitForPresentTime;
 };
 
 }  // namespace uirenderer
diff --git a/libs/hwui/FrameMetricsReporter.h b/libs/hwui/FrameMetricsReporter.h
index 0643e79..3f2dc12 100644
--- a/libs/hwui/FrameMetricsReporter.h
+++ b/libs/hwui/FrameMetricsReporter.h
@@ -55,13 +55,24 @@
         return mObservers.size() > 0;
     }
 
-    void reportFrameMetrics(const int64_t* stats) {
+    /**
+     * Notify observers about the metrics contained in 'stats'.
+     * If an observer is waiting for present time, notify when 'stats' has present time.
+     *
+     * If an observer does not want present time, only notify when 'hasPresentTime' is false.
+     * Never notify both types of observers from the same callback, because the callback with
+     * 'hasPresentTime' is sent at a different time than the one without.
+     */
+    void reportFrameMetrics(const int64_t* stats, bool hasPresentTime) {
         FatVector<sp<FrameMetricsObserver>, 10> copy;
         {
             std::lock_guard lock(mObserversLock);
             copy.reserve(mObservers.size());
             for (size_t i = 0; i < mObservers.size(); i++) {
-                copy.push_back(mObservers[i]);
+                const bool wantsPresentTime = mObservers[i]->waitForPresentTime();
+                if (hasPresentTime == wantsPresentTime) {
+                    copy.push_back(mObservers[i]);
+                }
             }
         }
         for (size_t i = 0; i < copy.size(); i++) {
diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
index 5b3e656..e5d5e75 100644
--- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
@@ -35,7 +35,9 @@
     return env;
 }
 
-HardwareRendererObserver::HardwareRendererObserver(JavaVM *vm, jobject observer) : mVm(vm) {
+HardwareRendererObserver::HardwareRendererObserver(JavaVM* vm, jobject observer,
+                                                   bool waitForPresentTime)
+        : uirenderer::FrameMetricsObserver(waitForPresentTime), mVm(vm) {
     mObserverWeak = getenv(mVm)->NewWeakGlobalRef(observer);
     LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
             "unable to create frame stats observer reference");
@@ -86,14 +88,16 @@
 }
 
 static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* env,
-                                                                      jobject observerObj) {
+                                                                      jobject observerObj,
+                                                                      jboolean waitForPresentTime) {
     JavaVM* vm = nullptr;
     if (env->GetJavaVM(&vm) != JNI_OK) {
         LOG_ALWAYS_FATAL("Unable to get Java VM");
         return 0;
     }
 
-    HardwareRendererObserver* observer = new HardwareRendererObserver(vm, observerObj);
+    HardwareRendererObserver* observer =
+            new HardwareRendererObserver(vm, observerObj, waitForPresentTime);
     return reinterpret_cast<jlong>(observer);
 }
 
@@ -110,10 +114,10 @@
 }
 
 static const std::array gMethods = {
-    MAKE_JNI_NATIVE_METHOD("nCreateObserver", "()J",
-                           android_graphics_HardwareRendererObserver_createObserver),
-    MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I",
-                           android_graphics_HardwareRendererObserver_getNextBuffer),
+        MAKE_JNI_NATIVE_METHOD("nCreateObserver", "(Z)J",
+                               android_graphics_HardwareRendererObserver_createObserver),
+        MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I",
+                               android_graphics_HardwareRendererObserver_getNextBuffer),
 };
 
 int register_android_graphics_HardwareRendererObserver(JNIEnv* env) {
diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
index 62111fd..d307614 100644
--- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
+++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
@@ -26,7 +26,7 @@
  */
 class HardwareRendererObserver : public uirenderer::FrameMetricsObserver {
 public:
-    HardwareRendererObserver(JavaVM *vm, jobject observer);
+    HardwareRendererObserver(JavaVM* vm, jobject observer, bool waitForPresentTime);
     ~HardwareRendererObserver();
 
     /**
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f69ddac..9793300 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -599,10 +599,41 @@
     // TODO (b/169858044): Move this into JankTracker to adjust deadline when queue is
     // double-stuffed.
     if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
-        mFrameMetricsReporter->reportFrameMetrics(frameInfo->data());
+        mFrameMetricsReporter->reportFrameMetrics(frameInfo->data(), false /*hasPresentTime*/);
     }
 }
 
+void CanvasContext::reportMetricsWithPresentTime() {
+    if (mFrameMetricsReporter == nullptr) {
+        return;
+    }
+    if (mNativeSurface == nullptr) {
+        return;
+    }
+    FrameInfo* forthBehind;
+    int64_t frameNumber;
+    {  // acquire lock
+        std::scoped_lock lock(mLast4FrameInfosMutex);
+        if (mLast4FrameInfos.size() != mLast4FrameInfos.capacity()) {
+            // Not enough frames yet
+            return;
+        }
+        // Surface object keeps stats for the last 8 frames.
+        std::tie(forthBehind, frameNumber) = mLast4FrameInfos.front();
+    }  // release lock
+
+    nsecs_t presentTime = 0;
+    native_window_get_frame_timestamps(
+            mNativeSurface->getNativeWindow(), frameNumber, nullptr /*outRequestedPresentTime*/,
+            nullptr /*outAcquireTime*/, nullptr /*outLatchTime*/,
+            nullptr /*outFirstRefreshStartTime*/, nullptr /*outLastRefreshStartTime*/,
+            nullptr /*outGpuCompositionDoneTime*/, &presentTime, nullptr /*outDequeueReadyTime*/,
+            nullptr /*outReleaseTime*/);
+
+    forthBehind->set(FrameInfoIndex::DisplayPresentTime) = presentTime;
+    mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/);
+}
+
 void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* control,
             ASurfaceControlStats* stats) {
 
@@ -624,6 +655,9 @@
             }
         }
     }
+
+    instance->reportMetricsWithPresentTime();
+
     if (frameInfo != nullptr) {
         if (gpuCompleteTime == -1) {
             gpuCompleteTime = frameInfo->get(FrameInfoIndex::SwapBuffersCompleted);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2e7b2f6..74f426e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -219,6 +219,12 @@
     SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
     void finishFrame(FrameInfo* frameInfo);
 
+    /**
+     * Invoke 'reportFrameMetrics' on the last frame stored in 'mLast4FrameInfos'.
+     * Populate the 'presentTime' field before calling.
+     */
+    void reportMetricsWithPresentTime();
+
     // The same type as Frame.mWidth and Frame.mHeight
     int32_t mLastFrameWidth = 0;
     int32_t mLastFrameHeight = 0;