[AChoreographer] Move refresh rate callback headers into android
This is in parallel with exposing these apis into NDK from libandroid.
Also performing some cleanup:
* Add additional documentation.
* Pass an extra data pointer when unregistering a callback, so that
callbacks are keyed by callback function + data pointer. This way the
same callback method can be passed with different data pointers.
* Enforce in the implementation that the same callback + data pointer
can't be registered twice.
* Update cached vsync period once all callbacks have been fired for a
refresh rate change, not just when the first one fired.
Bug: 136262896
Test: ChorographerNativeTest
Change-Id: I9d1224bf05dcaf820166996b58a10b6e73d6adcd
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 15d937e..58fff8f 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -60,7 +60,7 @@
void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay);
void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
- void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb);
+ void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
enum {
MSG_SCHEDULE_CALLBACKS = 0,
@@ -152,21 +152,34 @@
void Choreographer::registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data) {
{
AutoMutex _l{mLock};
+ for (const auto& callback : mRefreshRateCallbacks) {
+ // Don't re-add callbacks.
+ if (cb == callback.callback && data == callback.data) {
+ return;
+ }
+ }
mRefreshRateCallbacks.emplace_back(RefreshRateCallback{cb, data});
toggleConfigEvents(ISurfaceComposer::ConfigChanged::eConfigChangedDispatch);
}
}
-void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb) {
+void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb,
+ void* data) {
{
AutoMutex _l{mLock};
mRefreshRateCallbacks.erase(std::remove_if(mRefreshRateCallbacks.begin(),
mRefreshRateCallbacks.end(),
[&](const RefreshRateCallback& callback) {
- return cb == callback.callback;
- }));
+ return cb == callback.callback &&
+ data == callback.data;
+ }),
+ mRefreshRateCallbacks.end());
if (mRefreshRateCallbacks.empty()) {
toggleConfigEvents(ISurfaceComposer::ConfigChanged::eConfigChangedSuppress);
+ // If callbacks are empty then clear out the most recently seen
+ // vsync period so that when another callback is registered then the
+ // up-to-date refresh rate can be communicated to the app again.
+ mVsyncPeriod = 0;
}
}
}
@@ -224,9 +237,9 @@
// on every single configuration change.
if (mVsyncPeriod != vsyncPeriod) {
cb.callback(vsyncPeriod, cb.data);
- mVsyncPeriod = vsyncPeriod;
}
}
+ mVsyncPeriod = vsyncPeriod;
}
}
@@ -285,8 +298,9 @@
AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data);
}
void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
- AChoreographer_refreshRateCallback callback) {
- AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback);
+ AChoreographer_refreshRateCallback callback,
+ void* data) {
+ AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback, data);
}
AChoreographer* AChoreographer_create() {
diff --git a/libs/nativedisplay/include/android/choreographer.h b/libs/nativedisplay/include/android/choreographer.h
index 0d97e8c..5fd3de9 100644
--- a/libs/nativedisplay/include/android/choreographer.h
+++ b/libs/nativedisplay/include/android/choreographer.h
@@ -54,6 +54,13 @@
*/
typedef void (*AChoreographer_frameCallback64)(int64_t frameTimeNanos, void* data);
+/**
+ * Prototype of the function that is called when the display refresh rate
+ * changes. It's passed the new vsync period in nanoseconds, as well as the data
+ * pointer provided by the application that registered a callback.
+ */
+typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
+
#if __ANDROID_API__ >= 24
/**
@@ -102,6 +109,42 @@
#endif /* __ANDROID_API__ >= 29 */
+#if __ANDROID_API__ >= 30
+
+/**
+ * Registers a callback to be run when the display refresh rate changes. The
+ * data pointer provided will be passed to the callback function when it's
+ * called. The same callback may be registered multiple times, provided that a
+ * different data pointer is provided each time.
+ *
+ * If an application registers a callback for this choreographer instance when
+ * no new callbacks were previously registered, that callback is guaranteed to
+ * be dispatched. However, if the callback and associated data pointer are
+ * unregistered prior to running the callback, then the callback may be silently
+ * dropped.
+ *
+ * This api is thread-safe. Any thread is allowed to register a new refresh
+ * rate callback for the choreographer instance.
+ */
+void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
+ AChoreographer_refreshRateCallback, void* data);
+
+/**
+ * Unregisters a callback to be run when the display refresh rate changes, along
+ * with the data pointer previously provided when registering the callback. The
+ * callback is only unregistered when the data pointer matches one that was
+ * previously registered.
+ *
+ * This api is thread-safe. Any thread is allowed to unregister an existing
+ * refresh rate callback for the choreographer instance. When a refresh rate
+ * callback and associated data pointer are unregistered, then there is a
+ * guarantee that when the unregistration completes that that callback will not
+ * be run with the data pointer passed.
+ */
+void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
+ AChoreographer_refreshRateCallback, void* data);
+#endif /* __ANDROID_API__ >= 30 */
+
__END_DECLS
#endif // ANDROID_CHOREOGRAPHER_H
diff --git a/libs/nativedisplay/include/apex/choreographer.h b/libs/nativedisplay/include/apex/choreographer.h
index 5251fd3..b17b497 100644
--- a/libs/nativedisplay/include/apex/choreographer.h
+++ b/libs/nativedisplay/include/apex/choreographer.h
@@ -22,25 +22,6 @@
__BEGIN_DECLS
/**
- * Prototype of the function that is called when the display refresh rate
- * changes. It's passed the new vsync period in nanoseconds, as well as the data
- * pointer provided by the application that registered a callback.
- */
-typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
-
-/**
- * Registers a callback to be run when the display refresh rate changes.
- */
-void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
- AChoreographer_refreshRateCallback, void* data);
-
-/**
- * Unregisters a callback to be run when the display refresh rate changes.
- */
-void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
- AChoreographer_refreshRateCallback);
-
-/**
* Creates an instance of AChoreographer.
*
* The key differences between this method and AChoreographer_getInstance are: