Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 103a58a7 authored by Rachel Lee's avatar Rachel Lee
Browse files

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
parent 877bc778
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct ChoreographerFrameCallbackDataImpl {
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 @@ private:
    void scheduleCallbacks();

    ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
    void registerStartTime() const;

    std::mutex mLock;
    // Protected by mLock
@@ -172,6 +174,9 @@ private:

    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 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t
        if (cb.vsyncCallback != nullptr) {
            const ChoreographerFrameCallbackDataImpl frameCallbackData =
                    createFrameCallbackData(timestamp);
            registerStartTime();
            mInCallback = true;
            cb.vsyncCallback(reinterpret_cast<const AChoreographerFrameCallbackData*>(
                                     &frameCallbackData),
@@ -452,6 +458,16 @@ ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_
            .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 @@ int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
    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 */
+5 −0
Original line number Diff line number Diff line
@@ -71,4 +71,9 @@ int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentatio
int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
        const AChoreographerFrameCallbackData* data, size_t index);

// Gets the start time (dispatch time) in nanos of the callback, given a vsync ID. This does not
// account for clients that use multiple choreographers, because callbacks that give the same vsync
// ID may be dispatched at different times.
int64_t AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId);

} // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ LIBNATIVEDISPLAY_PLATFORM {
      android::AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId*;
      android::AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos*;
      android::AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos*;
      android::AChoreographer_getStartTimeNanosForVsyncId*;
      android::AChoreographer_signalRefreshRateCallbacks*;
      android::AChoreographer_getFrameInterval*;
      android::ADisplay_acquirePhysicalDisplays*;