From fde93e4a9530e4b30fa724b770fc9d627ccea76b Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Fri, 6 Aug 2021 22:04:57 +0800 Subject: [PATCH] Fix the SurfaceTexture related crash by Replacing the JNI weak global reference with a WeakReference --- .../android/android_external_texture_gl.cc | 14 ++-- .../android/android_external_texture_gl.h | 5 +- .../flutter/embedding/engine/FlutterJNI.java | 8 ++- shell/platform/android/jni/jni_mock.h | 8 +-- .../android/jni/platform_view_android_jni.h | 21 +++--- .../platform/android/platform_view_android.cc | 2 +- .../platform/android/platform_view_android.h | 3 +- .../android/platform_view_android_jni_impl.cc | 72 ++++++++++++++----- .../android/platform_view_android_jni_impl.h | 9 ++- 9 files changed, 92 insertions(+), 50 deletions(-) diff --git a/shell/platform/android/android_external_texture_gl.cc b/shell/platform/android/android_external_texture_gl.cc index 63b52d76b39c0..3dd85946b4c1a 100644 --- a/shell/platform/android/android_external_texture_gl.cc +++ b/shell/platform/android/android_external_texture_gl.cc @@ -13,7 +13,7 @@ namespace flutter { AndroidExternalTextureGL::AndroidExternalTextureGL( int64_t id, - const fml::jni::JavaObjectWeakGlobalRef& surface_texture, + const fml::jni::ScopedJavaGlobalRef& surface_texture, std::shared_ptr jni_facade) : Texture(id), jni_facade_(jni_facade), @@ -74,7 +74,8 @@ void AndroidExternalTextureGL::Paint(SkCanvas& canvas, } void AndroidExternalTextureGL::UpdateTransform() { - jni_facade_->SurfaceTextureGetTransformMatrix(surface_texture_, transform); + jni_facade_->SurfaceTextureGetTransformMatrix( + fml::jni::ScopedJavaLocalRef(surface_texture_), transform); } void AndroidExternalTextureGL::OnGrContextDestroyed() { @@ -86,16 +87,19 @@ void AndroidExternalTextureGL::OnGrContextDestroyed() { } void AndroidExternalTextureGL::Attach(jint textureName) { - jni_facade_->SurfaceTextureAttachToGLContext(surface_texture_, textureName); + jni_facade_->SurfaceTextureAttachToGLContext( + fml::jni::ScopedJavaLocalRef(surface_texture_), textureName); } void AndroidExternalTextureGL::Update() { - jni_facade_->SurfaceTextureUpdateTexImage(surface_texture_); + jni_facade_->SurfaceTextureUpdateTexImage( + fml::jni::ScopedJavaLocalRef(surface_texture_)); UpdateTransform(); } void AndroidExternalTextureGL::Detach() { - jni_facade_->SurfaceTextureDetachFromGLContext(surface_texture_); + jni_facade_->SurfaceTextureDetachFromGLContext( + fml::jni::ScopedJavaLocalRef(surface_texture_)); } void AndroidExternalTextureGL::OnTextureUnregistered() {} diff --git a/shell/platform/android/android_external_texture_gl.h b/shell/platform/android/android_external_texture_gl.h index a3127bf0b5495..cbf24f11490bf 100644 --- a/shell/platform/android/android_external_texture_gl.h +++ b/shell/platform/android/android_external_texture_gl.h @@ -8,7 +8,6 @@ #include #include "flutter/common/graphics/texture.h" -#include "flutter/fml/platform/android/jni_weak_ref.h" #include "flutter/shell/platform/android/platform_view_android_jni_impl.h" namespace flutter { @@ -17,7 +16,7 @@ class AndroidExternalTextureGL : public flutter::Texture { public: AndroidExternalTextureGL( int64_t id, - const fml::jni::JavaObjectWeakGlobalRef& surface_texture, + const fml::jni::ScopedJavaGlobalRef& surface_texture, std::shared_ptr jni_facade); ~AndroidExternalTextureGL() override; @@ -49,7 +48,7 @@ class AndroidExternalTextureGL : public flutter::Texture { std::shared_ptr jni_facade_; - fml::jni::JavaObjectWeakGlobalRef surface_texture_; + fml::jni::ScopedJavaGlobalRef surface_texture_; AttachmentState state_ = AttachmentState::uninitialized; diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 6ad9e97ee92e2..5c314d5bd3a74 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -34,6 +34,7 @@ import io.flutter.view.AccessibilityBridge; import io.flutter.view.FlutterCallbackInformation; import java.io.IOException; +import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -756,11 +757,14 @@ public void setAccessibilityFeatures(int flags) { public void registerTexture(long textureId, @NonNull SurfaceTextureWrapper textureWrapper) { ensureRunningOnMainThread(); ensureAttachedToNative(); - nativeRegisterTexture(nativeShellHolderId, textureId, textureWrapper); + nativeRegisterTexture( + nativeShellHolderId, textureId, new WeakReference(textureWrapper)); } private native void nativeRegisterTexture( - long nativeShellHolderId, long textureId, @NonNull SurfaceTextureWrapper textureWrapper); + long nativeShellHolderId, + long textureId, + @NonNull WeakReference textureWrapper); /** * Call this method to inform Flutter that a texture previously registered with {@link diff --git a/shell/platform/android/jni/jni_mock.h b/shell/platform/android/jni/jni_mock.h index 9b1e02ad71cbd..aaa52b80d7bd4 100644 --- a/shell/platform/android/jni/jni_mock.h +++ b/shell/platform/android/jni/jni_mock.h @@ -46,22 +46,22 @@ class JNIMock final : public PlatformViewAndroidJNI { MOCK_METHOD(void, SurfaceTextureAttachToGLContext, - (JavaWeakGlobalRef surface_texture, int textureId), + (JavaLocalRef surface_texture, int textureId), (override)); MOCK_METHOD(void, SurfaceTextureUpdateTexImage, - (JavaWeakGlobalRef surface_texture), + (JavaLocalRef surface_texture), (override)); MOCK_METHOD(void, SurfaceTextureGetTransformMatrix, - (JavaWeakGlobalRef surface_texture, SkMatrix& transform), + (JavaLocalRef surface_texture, SkMatrix& transform), (override)); MOCK_METHOD(void, SurfaceTextureDetachFromGLContext, - (JavaWeakGlobalRef surface_texture), + (JavaLocalRef surface_texture), (override)); MOCK_METHOD(void, diff --git a/shell/platform/android/jni/platform_view_android_jni.h b/shell/platform/android/jni/platform_view_android_jni.h index f04d1c72fb226..cb838b2c200df 100644 --- a/shell/platform/android/jni/platform_view_android_jni.h +++ b/shell/platform/android/jni/platform_view_android_jni.h @@ -14,15 +14,15 @@ #include "third_party/skia/include/core/SkMatrix.h" #if OS_ANDROID -#include "flutter/fml/platform/android/jni_weak_ref.h" +#include "flutter/fml/platform/android/scoped_java_ref.h" #endif namespace flutter { #if OS_ANDROID -using JavaWeakGlobalRef = fml::jni::JavaObjectWeakGlobalRef; +using JavaLocalRef = fml::jni::ScopedJavaLocalRef; #else -using JavaWeakGlobalRef = std::nullptr_t; +using JavaLocalRef = std::nullptr_t; #endif //------------------------------------------------------------------------------ @@ -86,31 +86,28 @@ class PlatformViewAndroidJNI { /// @brief Attach the SurfaceTexture to the OpenGL ES context that is /// current on the calling thread. /// - virtual void SurfaceTextureAttachToGLContext( - JavaWeakGlobalRef surface_texture, - int textureId) = 0; + virtual void SurfaceTextureAttachToGLContext(JavaLocalRef surface_texture, + int textureId) = 0; //---------------------------------------------------------------------------- /// @brief Updates the texture image to the most recent frame from the /// image stream. /// - virtual void SurfaceTextureUpdateTexImage( - JavaWeakGlobalRef surface_texture) = 0; + virtual void SurfaceTextureUpdateTexImage(JavaLocalRef surface_texture) = 0; //---------------------------------------------------------------------------- /// @brief Gets the transform matrix from the SurfaceTexture. /// Then, it updates the `transform` matrix, so it fill the canvas /// and preserve the aspect ratio. /// - virtual void SurfaceTextureGetTransformMatrix( - JavaWeakGlobalRef surface_texture, - SkMatrix& transform) = 0; + virtual void SurfaceTextureGetTransformMatrix(JavaLocalRef surface_texture, + SkMatrix& transform) = 0; //---------------------------------------------------------------------------- /// @brief Detaches a SurfaceTexture from the OpenGL ES context. /// virtual void SurfaceTextureDetachFromGLContext( - JavaWeakGlobalRef surface_texture) = 0; + JavaLocalRef surface_texture) = 0; //---------------------------------------------------------------------------- /// @brief Positions and sizes a platform view if using hybrid diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 698aee991478e..1cf74795e599b 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -291,7 +291,7 @@ void PlatformViewAndroid::UpdateSemantics( void PlatformViewAndroid::RegisterExternalTexture( int64_t texture_id, - const fml::jni::JavaObjectWeakGlobalRef& surface_texture) { + const fml::jni::ScopedJavaGlobalRef& surface_texture) { RegisterTexture(std::make_shared( texture_id, surface_texture, std::move(jni_facade_))); } diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 6ea2abb8a1a19..3bb4195126373 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -11,7 +11,6 @@ #include #include "flutter/fml/memory/weak_ptr.h" -#include "flutter/fml/platform/android/jni_weak_ref.h" #include "flutter/fml/platform/android/scoped_java_ref.h" #include "flutter/lib/ui/window/platform_message.h" #include "flutter/shell/common/platform_view.h" @@ -97,7 +96,7 @@ class PlatformViewAndroid final : public PlatformView { void RegisterExternalTexture( int64_t texture_id, - const fml::jni::JavaObjectWeakGlobalRef& surface_texture); + const fml::jni::ScopedJavaGlobalRef& surface_texture); // |PlatformView| void LoadDartDeferredLibrary( diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index eda01bf6366b4..840f71317bd98 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -42,6 +42,9 @@ static fml::jni::ScopedJavaGlobalRef* g_flutter_callback_info_class = static fml::jni::ScopedJavaGlobalRef* g_flutter_jni_class = nullptr; +static fml::jni::ScopedJavaGlobalRef* g_java_weak_reference_class = + nullptr; + static fml::jni::ScopedJavaGlobalRef* g_texture_wrapper_class = nullptr; static fml::jni::ScopedJavaGlobalRef* g_java_long_class = nullptr; @@ -87,6 +90,8 @@ static jmethodID g_on_begin_frame_method = nullptr; static jmethodID g_on_end_frame_method = nullptr; +static jmethodID g_java_weak_reference_get_method = nullptr; + static jmethodID g_attach_to_gl_context_method = nullptr; static jmethodID g_update_tex_image_method = nullptr; @@ -452,8 +457,8 @@ static void RegisterTexture(JNIEnv* env, jlong texture_id, jobject surface_texture) { ANDROID_SHELL_HOLDER->GetPlatformView()->RegisterExternalTexture( - static_cast(texture_id), // - fml::jni::JavaObjectWeakGlobalRef(env, surface_texture) // + static_cast(texture_id), // + fml::jni::ScopedJavaGlobalRef(env, surface_texture) // ); } @@ -714,8 +719,8 @@ bool RegisterApi(JNIEnv* env) { }, { .name = "nativeRegisterTexture", - .signature = "(JJLio/flutter/embedding/engine/renderer/" - "SurfaceTextureWrapper;)V", + .signature = "(JJLjava/lang/ref/" + "WeakReference;)V", .fnPtr = reinterpret_cast(&RegisterTexture), }, { @@ -1007,6 +1012,20 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } + g_java_weak_reference_class = new fml::jni::ScopedJavaGlobalRef( + env, env->FindClass("java/lang/ref/WeakReference")); + if (g_java_weak_reference_class->is_null()) { + FML_LOG(ERROR) << "Could not locate WeakReference class"; + return false; + } + + g_java_weak_reference_get_method = env->GetMethodID( + g_java_weak_reference_class->obj(), "get", "()Ljava/lang/Object;"); + if (g_java_weak_reference_get_method == nullptr) { + FML_LOG(ERROR) << "Could not locate WeakReference.get method"; + return false; + } + g_texture_wrapper_class = new fml::jni::ScopedJavaGlobalRef( env, env->FindClass( "io/flutter/embedding/engine/renderer/SurfaceTextureWrapper")); @@ -1215,12 +1234,18 @@ void PlatformViewAndroidJNIImpl::FlutterViewOnPreEngineRestart() { } void PlatformViewAndroidJNIImpl::SurfaceTextureAttachToGLContext( - JavaWeakGlobalRef surface_texture, + JavaLocalRef surface_texture, int textureId) { JNIEnv* env = fml::jni::AttachCurrentThread(); - fml::jni::ScopedJavaLocalRef surface_texture_local_ref = - surface_texture.get(env); + if (surface_texture.is_null()) { + return; + } + + fml::jni::ScopedJavaLocalRef surface_texture_local_ref( + env, env->CallObjectMethod(surface_texture.obj(), + g_java_weak_reference_get_method)); + if (surface_texture_local_ref.is_null()) { return; } @@ -1232,11 +1257,16 @@ void PlatformViewAndroidJNIImpl::SurfaceTextureAttachToGLContext( } void PlatformViewAndroidJNIImpl::SurfaceTextureUpdateTexImage( - JavaWeakGlobalRef surface_texture) { + JavaLocalRef surface_texture) { JNIEnv* env = fml::jni::AttachCurrentThread(); - fml::jni::ScopedJavaLocalRef surface_texture_local_ref = - surface_texture.get(env); + if (surface_texture.is_null()) { + return; + } + + fml::jni::ScopedJavaLocalRef surface_texture_local_ref( + env, env->CallObjectMethod(surface_texture.obj(), + g_java_weak_reference_get_method)); if (surface_texture_local_ref.is_null()) { return; } @@ -1260,12 +1290,17 @@ SkSize ScaleToFill(float scaleX, float scaleY) { } void PlatformViewAndroidJNIImpl::SurfaceTextureGetTransformMatrix( - JavaWeakGlobalRef surface_texture, + JavaLocalRef surface_texture, SkMatrix& transform) { JNIEnv* env = fml::jni::AttachCurrentThread(); - fml::jni::ScopedJavaLocalRef surface_texture_local_ref = - surface_texture.get(env); + if (surface_texture.is_null()) { + return; + } + + fml::jni::ScopedJavaLocalRef surface_texture_local_ref( + env, env->CallObjectMethod(surface_texture.obj(), + g_java_weak_reference_get_method)); if (surface_texture_local_ref.is_null()) { return; } @@ -1290,11 +1325,16 @@ void PlatformViewAndroidJNIImpl::SurfaceTextureGetTransformMatrix( } void PlatformViewAndroidJNIImpl::SurfaceTextureDetachFromGLContext( - JavaWeakGlobalRef surface_texture) { + JavaLocalRef surface_texture) { JNIEnv* env = fml::jni::AttachCurrentThread(); - fml::jni::ScopedJavaLocalRef surface_texture_local_ref = - surface_texture.get(env); + if (surface_texture.is_null()) { + return; + } + + fml::jni::ScopedJavaLocalRef surface_texture_local_ref( + env, env->CallObjectMethod(surface_texture.obj(), + g_java_weak_reference_get_method)); if (surface_texture_local_ref.is_null()) { return; } diff --git a/shell/platform/android/platform_view_android_jni_impl.h b/shell/platform/android/platform_view_android_jni_impl.h index 3c8e60f72c65d..624fa00a27535 100644 --- a/shell/platform/android/platform_view_android_jni_impl.h +++ b/shell/platform/android/platform_view_android_jni_impl.h @@ -41,16 +41,15 @@ class PlatformViewAndroidJNIImpl final : public PlatformViewAndroidJNI { void FlutterViewOnPreEngineRestart() override; - void SurfaceTextureAttachToGLContext(JavaWeakGlobalRef surface_texture, + void SurfaceTextureAttachToGLContext(JavaLocalRef surface_texture, int textureId) override; - void SurfaceTextureUpdateTexImage(JavaWeakGlobalRef surface_texture) override; + void SurfaceTextureUpdateTexImage(JavaLocalRef surface_texture) override; - void SurfaceTextureGetTransformMatrix(JavaWeakGlobalRef surface_texture, + void SurfaceTextureGetTransformMatrix(JavaLocalRef surface_texture, SkMatrix& transform) override; - void SurfaceTextureDetachFromGLContext( - JavaWeakGlobalRef surface_texture) override; + void SurfaceTextureDetachFromGLContext(JavaLocalRef surface_texture) override; void FlutterViewOnDisplayPlatformView(int view_id, int x,