diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 987b23fdd1fd1058fffacd79564d0b61844f7d15..f258c27aa070c07a5409b5e1519e7a1b6229406d 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -345,6 +345,7 @@ LIBANDROID_PLATFORM {
     extern "C++" {
         ASurfaceControl_registerSurfaceStatsListener*;
         ASurfaceControl_unregisterSurfaceStatsListener*;
+        ASurfaceControl_getChoreographer*;
         ASurfaceControlStats_getAcquireTime*;
         ASurfaceControlStats_getFrameNumber*;
     };
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index ea20c6c9e0b14edbbc4a0e662dc6af2ad7869d23..b7f359602a5d9a3abf9c92b3cbcb3810b92f139f 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -180,6 +180,18 @@ void ASurfaceControl_unregisterSurfaceStatsListener(void* context,
             reinterpret_cast<void*>(func));
 }
 
+AChoreographer* ASurfaceControl_getChoreographer(ASurfaceControl* aSurfaceControl) {
+    LOG_ALWAYS_FATAL_IF(aSurfaceControl == nullptr, "aSurfaceControl should not be nullptr");
+    SurfaceControl* surfaceControl =
+            ASurfaceControl_to_SurfaceControl(reinterpret_cast<ASurfaceControl*>(aSurfaceControl));
+    if (!surfaceControl->isValid()) {
+        ALOGE("Attempted to get choreographer from invalid surface control");
+        return nullptr;
+    }
+    SurfaceControl_acquire(surfaceControl);
+    return reinterpret_cast<AChoreographer*>(surfaceControl->getChoreographer().get());
+}
+
 int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats) {
     if (const auto* fence = std::get_if<sp<Fence>>(&stats->acquireTimeOrFence)) {
         // We got a fence instead of the acquire time due to latch unsignaled.