diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index ea2449d5485c3..716799d8318ec 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -810,6 +810,17 @@ public void onBeginFrame() { } platformViewsController.onBeginFrame(); } + + @SuppressWarnings("unused") + @UiThread + public void onEndFrame() { + ensureRunningOnMainThread(); + if (platformViewsController == null) { + throw new RuntimeException( + "platformViewsController must be set before attempting to end the frame"); + } + platformViewsController.onEndFrame(); + } // ----- End Engine Lifecycle Support ---- // @SuppressWarnings("unused") diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index ff5747bd5dcf1..8a394fa43fdc3 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -545,4 +545,8 @@ public void onDisplayOverlaySurface(int id, int x, int y, int width, int height) public void onBeginFrame() { // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 } + + public void onEndFrame() { + // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 + } } diff --git a/shell/platform/android/jni/platform_view_android_jni.h b/shell/platform/android/jni/platform_view_android_jni.h index ff87ee382cb11..5d00ef13b1fce 100644 --- a/shell/platform/android/jni/platform_view_android_jni.h +++ b/shell/platform/android/jni/platform_view_android_jni.h @@ -137,6 +137,14 @@ class PlatformViewAndroidJNI { /// @note Must be called from the platform thread. /// virtual void FlutterViewBeginFrame() = 0; + + //---------------------------------------------------------------------------- + /// @brief Indicates that the current frame ended. + /// It's used to clean up state. + /// + /// @note Must be called from the platform thread. + /// + virtual void FlutterViewEndFrame() = 0; }; } // namespace flutter diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index 331f0350230d0..182566d0ea17d 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -82,6 +82,8 @@ static jmethodID g_on_engine_restart_method = nullptr; static jmethodID g_on_begin_frame_method = nullptr; +static jmethodID g_on_end_frame_method = nullptr; + static jmethodID g_attach_to_gl_context_method = nullptr; static jmethodID g_update_tex_image_method = nullptr; @@ -728,6 +730,14 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } + g_on_end_frame_method = + env->GetMethodID(g_flutter_jni_class->obj(), "onEndFrame", "()V"); + + if (g_on_end_frame_method == nullptr) { + FML_LOG(ERROR) << "Could not locate onEndFrame method"; + return false; + } + g_on_display_overlay_surface_method = env->GetMethodID( g_flutter_jni_class->obj(), "onDisplayOverlaySurface", "(IIIII)V"); @@ -1057,4 +1067,17 @@ void PlatformViewAndroidJNIImpl::FlutterViewBeginFrame() { FML_CHECK(CheckException(env)); } +void PlatformViewAndroidJNIImpl::FlutterViewEndFrame() { + JNIEnv* env = fml::jni::AttachCurrentThread(); + + auto java_object = java_object_.get(env); + if (java_object.is_null()) { + return; + } + + env->CallVoidMethod(java_object.obj(), g_on_end_frame_method); + + FML_CHECK(CheckException(env)); +} + } // namespace flutter diff --git a/shell/platform/android/platform_view_android_jni_impl.h b/shell/platform/android/platform_view_android_jni_impl.h index 2a53e307ca12a..0ab94a28c685f 100644 --- a/shell/platform/android/platform_view_android_jni_impl.h +++ b/shell/platform/android/platform_view_android_jni_impl.h @@ -64,6 +64,8 @@ class PlatformViewAndroidJNIImpl final : public PlatformViewAndroidJNI { void FlutterViewBeginFrame() override; + void FlutterViewEndFrame() override; + private: // Reference to FlutterJNI object. const fml::jni::JavaObjectWeakGlobalRef java_object_; diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index cee3e985d4224..8918e4102aace 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -96,4 +96,19 @@ public void onBeginFrame__callsPlatformViewsController() { // --- Verify Results --- verify(platformViewsController, times(1)).onBeginFrame(); } + + @Test + public void onEndFrame__callsPlatformViewsController() { + PlatformViewsController platformViewsController = mock(PlatformViewsController.class); + + // --- Test Setup --- + FlutterJNI flutterJNI = new FlutterJNI(); + flutterJNI.setPlatformViewsController(platformViewsController); + + // --- Execute Test --- + flutterJNI.onEndFrame(); + + // --- Verify Results --- + verify(platformViewsController, times(1)).onEndFrame(); + } }