Add Choreo method for vsync callback start time.

Currently store the start times globally.

Bug: 210043506
Test: perfetto log of with & w/o CL, using Chromium apk, bug 198192946
Change-Id: I33bd31adf72e3cb6c9979bf9e9a5518a03a03237
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index a3eebdd..8240b08 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -111,6 +111,7 @@
 struct {
     std::mutex lock;
     std::vector<Choreographer*> ptrs GUARDED_BY(lock);
+    std::map<AVsyncId, int64_t> startTimes GUARDED_BY(lock);
     bool registeredToDisplayManager GUARDED_BY(lock) = false;
 
     std::atomic<nsecs_t> mLastKnownVsync = -1;
@@ -160,6 +161,7 @@
     void scheduleCallbacks();
 
     ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
+    void registerStartTime() const;
 
     std::mutex mLock;
     // Protected by mLock
@@ -172,6 +174,9 @@
 
     const sp<Looper> mLooper;
     const std::thread::id mThreadId;
+
+    // Approximation of num_threads_using_choreographer * num_frames_of_history with leeway.
+    static constexpr size_t kMaxStartTimes = 250;
 };
 
 static thread_local Choreographer* gChoreographer;
@@ -392,6 +397,7 @@
         if (cb.vsyncCallback != nullptr) {
             const ChoreographerFrameCallbackDataImpl frameCallbackData =
                     createFrameCallbackData(timestamp);
+            registerStartTime();
             mInCallback = true;
             cb.vsyncCallback(reinterpret_cast<const AChoreographerFrameCallbackData*>(
                                      &frameCallbackData),
@@ -452,6 +458,16 @@
             .choreographer = this};
 }
 
+void Choreographer::registerStartTime() const {
+    std::scoped_lock _l(gChoreographers.lock);
+    for (VsyncEventData::FrameTimeline frameTimeline : mLastVsyncEventData.frameTimelines) {
+        while (gChoreographers.startTimes.size() >= kMaxStartTimes) {
+            gChoreographers.startTimes.erase(gChoreographers.startTimes.begin());
+        }
+        gChoreographers.startTimes[frameTimeline.vsyncId] = systemTime(SYSTEM_TIME_MONOTONIC);
+    }
+}
+
 } // namespace android
 using namespace android;
 
@@ -566,6 +582,16 @@
     return AChoreographer_to_Choreographer(choreographer)->getFrameInterval();
 }
 
+int64_t AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId) {
+    std::scoped_lock _l(gChoreographers.lock);
+    const auto iter = gChoreographers.startTimes.find(vsyncId);
+    if (iter == gChoreographers.startTimes.end()) {
+        ALOGW("Start time was not found for vsync id: %" PRId64, vsyncId);
+        return 0;
+    }
+    return iter->second;
+}
+
 } // namespace android
 
 /* Glue for the NDK interface */