Loading libs/gui/DisplayEventDispatcher.cpp +11 −9 Original line number Diff line number Diff line Loading @@ -73,8 +73,8 @@ status_t DisplayEventDispatcher::scheduleVsync() { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; int64_t vsyncId; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { VsyncEventData vsyncEventData; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp))); } Loading Loading @@ -117,13 +117,14 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; int64_t vsyncId; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { VsyncEventData vsyncEventData; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d, vsyncId=%" PRId64, this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId); this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncEventData.id); mWaitingForVsync = false; dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId); dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); } return 1; // keep the callback Loading @@ -131,11 +132,11 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, int64_t* outVsyncId) { uint32_t* outCount, VsyncEventData* outVsyncEventData) { 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++) { Loading @@ -148,7 +149,8 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; *outVsyncId = ev.vsync.vsyncId; outVsyncEventData->id = ev.vsync.vsyncId; outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); Loading libs/gui/include/gui/DisplayEventDispatcher.h +13 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,17 @@ namespace android { struct VsyncEventData { // The Vsync Id corresponsing to this vsync event. This will be used to // populate ISurfaceComposer::setFrameTimelineVsync and // SurfaceComposerClient::setFrameTimelineVsync int64_t id = ISurfaceComposer::INVALID_VSYNC_ID; // The deadline in CLOCK_MONOTONIC that the app needs to complete its // frame by (both on the CPU and the GPU) int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max(); }; class DisplayEventDispatcher : public LooperCallback { public: explicit DisplayEventDispatcher( Loading @@ -44,7 +55,7 @@ private: bool mWaitingForVsync; virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, int64_t vsyncId) = 0; VsyncEventData vsyncEventData) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, Loading @@ -54,6 +65,6 @@ private: virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, int64_t* outVsyncId); uint32_t* outCount, VsyncEventData* outVsyncEventData); }; } // namespace android libs/nativedisplay/AChoreographer.cpp +15 −5 Original line number Diff line number Diff line Loading @@ -129,13 +129,14 @@ public: static Choreographer* getForThread(); virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); int64_t getVsyncId() const; int64_t getFrameDeadline() const; private: Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, int64_t vsyncId) override; VsyncEventData vsyncEventData) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) override; Loading @@ -149,7 +150,7 @@ private: std::vector<RefreshRateCallback> mRefreshRateCallbacks; nsecs_t mLatestVsyncPeriod = -1; int64_t mLastVsyncId = -1; VsyncEventData mLastVsyncEventData; const sp<Looper> mLooper; const std::thread::id mThreadId; Loading Loading @@ -354,7 +355,8 @@ void Choreographer::handleRefreshRateUpdates() { // TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the // internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for // the internal display implicitly. void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, int64_t vsyncId) { void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, VsyncEventData vsyncEventData) { std::vector<FrameCallback> callbacks{}; { std::lock_guard<std::mutex> _l{mLock}; Loading @@ -364,7 +366,7 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t mFrameCallbacks.pop(); } } mLastVsyncId = vsyncId; mLastVsyncEventData = vsyncEventData; for (const auto& cb : callbacks) { if (cb.callback64 != nullptr) { cb.callback64(timestamp, cb.data); Loading Loading @@ -410,7 +412,11 @@ void Choreographer::handleMessage(const Message& message) { } int64_t Choreographer::getVsyncId() const { return mLastVsyncId; return mLastVsyncEventData.id; } int64_t Choreographer::getFrameDeadline() const { return mLastVsyncEventData.deadlineTimestamp; } } // namespace android Loading Loading @@ -492,6 +498,10 @@ int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getVsyncId(); } int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline(); } } // namespace android /* Glue for the NDK interface */ Loading libs/nativedisplay/include-private/private/android/choreographer.h +7 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,13 @@ void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod); // this function from anywhere else will return an undefined value. int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer); // Returns the deadline timestamp (in CLOCK_MONOTONIC) of the last frame callback. // Client are expected to call this function from their frame callback function // to get the deadline and use it to know whether a frame is likely to miss // presentation. Calling this function from anywhere else will return an undefined // value. int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer); // Trampoline functions allowing libandroid.so to define the NDK symbols without including // the entirety of libnativedisplay as a whole static lib. As libnativedisplay // maintains global state, libnativedisplay can never be directly statically Loading libs/nativedisplay/libnativedisplay.map.txt +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographer_routeUnregisterRefreshRateCallback*; android::AChoreographer_signalRefreshRateCallbacks*; android::AChoreographer_getVsyncId*; android::AChoreographer_getFrameDeadline*; android::ADisplay_acquirePhysicalDisplays*; android::ADisplay_release*; android::ADisplay_getMaxSupportedFps*; Loading Loading
libs/gui/DisplayEventDispatcher.cpp +11 −9 Original line number Diff line number Diff line Loading @@ -73,8 +73,8 @@ status_t DisplayEventDispatcher::scheduleVsync() { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; int64_t vsyncId; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { VsyncEventData vsyncEventData; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp))); } Loading Loading @@ -117,13 +117,14 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; int64_t vsyncId; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { VsyncEventData vsyncEventData; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d, vsyncId=%" PRId64, this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId); this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncEventData.id); mWaitingForVsync = false; dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId); dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); } return 1; // keep the callback Loading @@ -131,11 +132,11 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, int64_t* outVsyncId) { uint32_t* outCount, VsyncEventData* outVsyncEventData) { 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++) { Loading @@ -148,7 +149,8 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; *outVsyncId = ev.vsync.vsyncId; outVsyncEventData->id = ev.vsync.vsyncId; outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); Loading
libs/gui/include/gui/DisplayEventDispatcher.h +13 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,17 @@ namespace android { struct VsyncEventData { // The Vsync Id corresponsing to this vsync event. This will be used to // populate ISurfaceComposer::setFrameTimelineVsync and // SurfaceComposerClient::setFrameTimelineVsync int64_t id = ISurfaceComposer::INVALID_VSYNC_ID; // The deadline in CLOCK_MONOTONIC that the app needs to complete its // frame by (both on the CPU and the GPU) int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max(); }; class DisplayEventDispatcher : public LooperCallback { public: explicit DisplayEventDispatcher( Loading @@ -44,7 +55,7 @@ private: bool mWaitingForVsync; virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, int64_t vsyncId) = 0; VsyncEventData vsyncEventData) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, Loading @@ -54,6 +65,6 @@ private: virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, int64_t* outVsyncId); uint32_t* outCount, VsyncEventData* outVsyncEventData); }; } // namespace android
libs/nativedisplay/AChoreographer.cpp +15 −5 Original line number Diff line number Diff line Loading @@ -129,13 +129,14 @@ public: static Choreographer* getForThread(); virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); int64_t getVsyncId() const; int64_t getFrameDeadline() const; private: Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, int64_t vsyncId) override; VsyncEventData vsyncEventData) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) override; Loading @@ -149,7 +150,7 @@ private: std::vector<RefreshRateCallback> mRefreshRateCallbacks; nsecs_t mLatestVsyncPeriod = -1; int64_t mLastVsyncId = -1; VsyncEventData mLastVsyncEventData; const sp<Looper> mLooper; const std::thread::id mThreadId; Loading Loading @@ -354,7 +355,8 @@ void Choreographer::handleRefreshRateUpdates() { // TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the // internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for // the internal display implicitly. void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, int64_t vsyncId) { void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, VsyncEventData vsyncEventData) { std::vector<FrameCallback> callbacks{}; { std::lock_guard<std::mutex> _l{mLock}; Loading @@ -364,7 +366,7 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t mFrameCallbacks.pop(); } } mLastVsyncId = vsyncId; mLastVsyncEventData = vsyncEventData; for (const auto& cb : callbacks) { if (cb.callback64 != nullptr) { cb.callback64(timestamp, cb.data); Loading Loading @@ -410,7 +412,11 @@ void Choreographer::handleMessage(const Message& message) { } int64_t Choreographer::getVsyncId() const { return mLastVsyncId; return mLastVsyncEventData.id; } int64_t Choreographer::getFrameDeadline() const { return mLastVsyncEventData.deadlineTimestamp; } } // namespace android Loading Loading @@ -492,6 +498,10 @@ int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getVsyncId(); } int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline(); } } // namespace android /* Glue for the NDK interface */ Loading
libs/nativedisplay/include-private/private/android/choreographer.h +7 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,13 @@ void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod); // this function from anywhere else will return an undefined value. int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer); // Returns the deadline timestamp (in CLOCK_MONOTONIC) of the last frame callback. // Client are expected to call this function from their frame callback function // to get the deadline and use it to know whether a frame is likely to miss // presentation. Calling this function from anywhere else will return an undefined // value. int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer); // Trampoline functions allowing libandroid.so to define the NDK symbols without including // the entirety of libnativedisplay as a whole static lib. As libnativedisplay // maintains global state, libnativedisplay can never be directly statically Loading
libs/nativedisplay/libnativedisplay.map.txt +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographer_routeUnregisterRefreshRateCallback*; android::AChoreographer_signalRefreshRateCallbacks*; android::AChoreographer_getVsyncId*; android::AChoreographer_getFrameDeadline*; android::ADisplay_acquirePhysicalDisplays*; android::ADisplay_release*; android::ADisplay_getMaxSupportedFps*; Loading