Loading libs/gui/DisplayEventDispatcher.cpp +11 −4 Original line number Diff line number Diff line Loading @@ -50,17 +50,20 @@ status_t DisplayEventDispatcher::initialize() { return result; } if (mLooper != nullptr) { int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } } return OK; } void DisplayEventDispatcher::dispose() { ALOGV("dispatcher %p ~ Disposing display event dispatcher.", this); if (!mReceiver.initCheck()) { if (!mReceiver.initCheck() && mLooper != nullptr) { mLooper->removeFd(mReceiver.getFd()); } } Loading Loading @@ -101,6 +104,10 @@ void DisplayEventDispatcher::toggleConfigEvents(ISurfaceComposer::ConfigChanged mConfigChangeFlag = configChangeFlag; } int DisplayEventDispatcher::getFd() { return mReceiver.getFd(); } int DisplayEventDispatcher::handleEvent(int, int events, void*) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. " Loading libs/gui/include/gui/DisplayEventDispatcher.h +2 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ public: void dispose(); status_t scheduleVsync(); void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag); int getFd(); virtual int handleEvent(int receiveFd, int events, void* data); protected: virtual ~DisplayEventDispatcher() = default; Loading @@ -48,7 +50,6 @@ private: virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) = 0; virtual int handleEvent(int receiveFd, int events, void* data); bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount); }; Loading libs/nativedisplay/AChoreographer.cpp +43 −8 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ struct RefreshRateCallback { class Choreographer : public DisplayEventDispatcher, public MessageHandler { public: explicit Choreographer(const sp<Looper>& looper); void postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay); void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data); Loading @@ -68,12 +69,9 @@ public: virtual void handleMessage(const Message& message) override; static Choreographer* getForThread(); protected: virtual ~Choreographer() = default; private: explicit Choreographer(const sp<Looper>& looper); Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override; Loading Loading @@ -132,14 +130,22 @@ void Choreographer::postFrameCallbackDelayed( } if (callback.dueTime <= now) { if (std::this_thread::get_id() != mThreadId) { if (mLooper != nullptr) { Message m{MSG_SCHEDULE_VSYNC}; mLooper->sendMessage(this, m); } else { scheduleVsync(); } } else { scheduleVsync(); } } else { if (mLooper != nullptr) { Message m{MSG_SCHEDULE_CALLBACKS}; mLooper->sendMessageDelayed(delay, this, m); } else { scheduleCallbacks(); } } } Loading Loading @@ -238,7 +244,7 @@ void Choreographer::handleMessage(const Message& message) { /* Glue for the NDK interface */ using android::Choreographer; using namespace android; static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) { return reinterpret_cast<Choreographer*>(choreographer); Loading Loading @@ -281,3 +287,32 @@ void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, AChoreographer_refreshRateCallback callback) { AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback); } AChoreographer* AChoreographer_create() { Choreographer* choreographer = new Choreographer(nullptr); status_t result = choreographer->initialize(); if (result != OK) { ALOGW("Failed to initialize"); return nullptr; } return Choreographer_to_AChoreographer(choreographer); } void AChoreographer_destroy(AChoreographer* choreographer) { if (choreographer == nullptr) { return; } delete AChoreographer_to_Choreographer(choreographer); } int AChoreographer_getFd(AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getFd(); } void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) { // Pass dummy fd and events args to handleEvent, since the underlying // DisplayEventDispatcher doesn't need them outside of validating that a // Looper instance didn't break, but these args circumvent those checks. AChoreographer_to_Choreographer(choreographer)->handleEvent(-1, Looper::EVENT_INPUT, data); } libs/nativedisplay/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ // limitations under the License. ndk_headers { name: "libachoreographer_ndk_headers", name: "libnativedisplay_ndk_headers", from: "include/android", to: "android", srcs: ["include/android/*.h"], Loading libs/nativedisplay/include/apex/choreographer.h +35 −0 Original line number Diff line number Diff line Loading @@ -40,4 +40,39 @@ void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, AChoreographer_refreshRateCallback); /** * Creates an instance of AChoreographer. * * The key differences between this method and AChoreographer_getInstance are: * 1. The returned AChoreographer instance is not a thread-local, and * 2. This method does not require an existing ALooper attached to the thread. */ AChoreographer* AChoreographer_create(); /** * Destroys a choreographer instance created from AChoreographer_create. */ void AChoreographer_destroy(AChoreographer* choreographer); /** * Returns the underlying file descriptor associated with this choreographer * instance. * * The caller can listen to the file descriptor to respond to any AChoreographer * events. One such way is registering the file descriptor to a Looper instance, * although this is not a requirement. */ int AChoreographer_getFd(AChoreographer* choreographer); /** * Provides a callback to handle all pending events emitted by this * choreographer instance. Specifically, this delegates to the callbacks * previously registered to choreographer. * * If the associated file descriptor is attached to a Looper instance, then the * callback attached to that Looper is expected to handle exceptional Looper * events. */ void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data); __END_DECLS Loading
libs/gui/DisplayEventDispatcher.cpp +11 −4 Original line number Diff line number Diff line Loading @@ -50,17 +50,20 @@ status_t DisplayEventDispatcher::initialize() { return result; } if (mLooper != nullptr) { int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } } return OK; } void DisplayEventDispatcher::dispose() { ALOGV("dispatcher %p ~ Disposing display event dispatcher.", this); if (!mReceiver.initCheck()) { if (!mReceiver.initCheck() && mLooper != nullptr) { mLooper->removeFd(mReceiver.getFd()); } } Loading Loading @@ -101,6 +104,10 @@ void DisplayEventDispatcher::toggleConfigEvents(ISurfaceComposer::ConfigChanged mConfigChangeFlag = configChangeFlag; } int DisplayEventDispatcher::getFd() { return mReceiver.getFd(); } int DisplayEventDispatcher::handleEvent(int, int events, void*) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. " Loading
libs/gui/include/gui/DisplayEventDispatcher.h +2 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ public: void dispose(); status_t scheduleVsync(); void toggleConfigEvents(ISurfaceComposer::ConfigChanged configChangeFlag); int getFd(); virtual int handleEvent(int receiveFd, int events, void* data); protected: virtual ~DisplayEventDispatcher() = default; Loading @@ -48,7 +50,6 @@ private: virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) = 0; virtual int handleEvent(int receiveFd, int events, void* data); bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount); }; Loading
libs/nativedisplay/AChoreographer.cpp +43 −8 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ struct RefreshRateCallback { class Choreographer : public DisplayEventDispatcher, public MessageHandler { public: explicit Choreographer(const sp<Looper>& looper); void postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay); void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data); Loading @@ -68,12 +69,9 @@ public: virtual void handleMessage(const Message& message) override; static Choreographer* getForThread(); protected: virtual ~Choreographer() = default; private: explicit Choreographer(const sp<Looper>& looper); Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override; Loading Loading @@ -132,14 +130,22 @@ void Choreographer::postFrameCallbackDelayed( } if (callback.dueTime <= now) { if (std::this_thread::get_id() != mThreadId) { if (mLooper != nullptr) { Message m{MSG_SCHEDULE_VSYNC}; mLooper->sendMessage(this, m); } else { scheduleVsync(); } } else { scheduleVsync(); } } else { if (mLooper != nullptr) { Message m{MSG_SCHEDULE_CALLBACKS}; mLooper->sendMessageDelayed(delay, this, m); } else { scheduleCallbacks(); } } } Loading Loading @@ -238,7 +244,7 @@ void Choreographer::handleMessage(const Message& message) { /* Glue for the NDK interface */ using android::Choreographer; using namespace android; static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) { return reinterpret_cast<Choreographer*>(choreographer); Loading Loading @@ -281,3 +287,32 @@ void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, AChoreographer_refreshRateCallback callback) { AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback); } AChoreographer* AChoreographer_create() { Choreographer* choreographer = new Choreographer(nullptr); status_t result = choreographer->initialize(); if (result != OK) { ALOGW("Failed to initialize"); return nullptr; } return Choreographer_to_AChoreographer(choreographer); } void AChoreographer_destroy(AChoreographer* choreographer) { if (choreographer == nullptr) { return; } delete AChoreographer_to_Choreographer(choreographer); } int AChoreographer_getFd(AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getFd(); } void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) { // Pass dummy fd and events args to handleEvent, since the underlying // DisplayEventDispatcher doesn't need them outside of validating that a // Looper instance didn't break, but these args circumvent those checks. AChoreographer_to_Choreographer(choreographer)->handleEvent(-1, Looper::EVENT_INPUT, data); }
libs/nativedisplay/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ // limitations under the License. ndk_headers { name: "libachoreographer_ndk_headers", name: "libnativedisplay_ndk_headers", from: "include/android", to: "android", srcs: ["include/android/*.h"], Loading
libs/nativedisplay/include/apex/choreographer.h +35 −0 Original line number Diff line number Diff line Loading @@ -40,4 +40,39 @@ void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, AChoreographer_refreshRateCallback); /** * Creates an instance of AChoreographer. * * The key differences between this method and AChoreographer_getInstance are: * 1. The returned AChoreographer instance is not a thread-local, and * 2. This method does not require an existing ALooper attached to the thread. */ AChoreographer* AChoreographer_create(); /** * Destroys a choreographer instance created from AChoreographer_create. */ void AChoreographer_destroy(AChoreographer* choreographer); /** * Returns the underlying file descriptor associated with this choreographer * instance. * * The caller can listen to the file descriptor to respond to any AChoreographer * events. One such way is registering the file descriptor to a Looper instance, * although this is not a requirement. */ int AChoreographer_getFd(AChoreographer* choreographer); /** * Provides a callback to handle all pending events emitted by this * choreographer instance. Specifically, this delegates to the callbacks * previously registered to choreographer. * * If the associated file descriptor is attached to a Looper instance, then the * callback attached to that Looper is expected to handle exceptional Looper * events. */ void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data); __END_DECLS