From ffbafc852d2a868b6d27a354de1a6a0a417df11e Mon Sep 17 00:00:00 2001 From: amirh Date: Fri, 3 Aug 2018 08:54:12 -0700 Subject: [PATCH] Flush all embedded Android views on hot restart. (#5929) * Flush all embedded Android view on hot restart. Adds an OnEngineRestarted method to PlatformView, this is currently only implemented for Android where we need to use it for embedded views. * review comments followup * rename to OnPreEngineRestart, call before Clone --- shell/common/engine.cc | 1 + shell/common/engine.h | 2 ++ shell/common/platform_view.cc | 2 ++ shell/common/platform_view.h | 2 ++ shell/common/shell.cc | 19 +++++++++++++++++++ shell/common/shell.h | 3 +++ .../io/flutter/app/FlutterPluginRegistry.java | 4 ++++ .../platform/PlatformViewsController.java | 15 +++++++++++---- .../io/flutter/view/FlutterNativeView.java | 8 ++++++++ .../platform/android/platform_view_android.cc | 11 +++++++++++ .../platform/android/platform_view_android.h | 3 +++ .../android/platform_view_android_jni.cc | 13 +++++++++++++ .../android/platform_view_android_jni.h | 2 ++ 13 files changed, 81 insertions(+), 4 deletions(-) diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 2375d02d7728b..3c4bc493f1ec7 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -101,6 +101,7 @@ bool Engine::Restart(RunConfiguration configuration) { FML_LOG(ERROR) << "Engine run configuration was invalid."; return false; } + delegate_.OnPreEngineRestart(); runtime_controller_ = runtime_controller_->Clone(); UpdateAssetManager(nullptr); return Run(std::move(configuration)); diff --git a/shell/common/engine.h b/shell/common/engine.h index 1a2c75ee60191..2dfe73b78bd35 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -39,6 +39,8 @@ class Engine final : public blink::RuntimeDelegate { virtual void OnEngineHandlePlatformMessage( const Engine& engine, fml::RefPtr message) = 0; + + virtual void OnPreEngineRestart() = 0; }; Engine(Delegate& delegate, diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index 656fa91439e2d..dc04f6302717f 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -88,6 +88,8 @@ void PlatformView::HandlePlatformMessage( response->CompleteEmpty(); } +void PlatformView::OnPreEngineRestart() const {} + void PlatformView::RegisterTexture(std::shared_ptr texture) { delegate_.OnPlatformViewRegisterTexture(*this, std::move(texture)); } diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index a6fccae56313e..0d09a7c1657e7 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -108,6 +108,8 @@ class PlatformView { virtual void HandlePlatformMessage( fml::RefPtr message); + virtual void OnPreEngineRestart() const; + void SetNextFrameCallback(fml::closure closure); void DispatchPointerDataPacket( diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 1e3085ca1d894..c992bc4b3fc40 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -740,6 +740,25 @@ void Shell::OnEngineHandlePlatformMessage( }); } +// |shell::Engine::Delegate| +void Shell::OnPreEngineRestart() { + FML_DCHECK(is_setup_); + FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); + + fml::AutoResetWaitableEvent latch; + fml::TaskRunner::RunNowOrPostTask( + task_runners_.GetPlatformTaskRunner(), + [view = platform_view_->GetWeakPtr(), &latch]() { + if (view) { + view->OnPreEngineRestart(); + } + latch.Signal(); + }); + // This is blocking as any embedded platform views has to be flushed before + // we re-run the Dart code. + latch.Wait(); +} + // |blink::ServiceProtocol::Handler| fml::RefPtr Shell::GetServiceProtocolHandlerTaskRunner( fml::StringView method) const { diff --git a/shell/common/shell.h b/shell/common/shell.h index c8bd76731209f..41798664cda63 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -195,6 +195,9 @@ class Shell final : public PlatformView::Delegate, const Engine& engine, fml::RefPtr message) override; + // |shell::Engine::Delegate| + void OnPreEngineRestart() override; + // |blink::ServiceProtocol::Handler| fml::RefPtr GetServiceProtocolHandlerTaskRunner( fml::StringView method) const override; diff --git a/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java b/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java index ebf9b5f3ed3e6..67ef70a3c566e 100644 --- a/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java +++ b/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java @@ -82,6 +82,10 @@ public void detach() { mActivity = null; } + public void onPreEngineRestart() { + mPlatformViewsController.onPreEngineRestart(); + } + private class FlutterRegistrar implements Registrar { private final String pluginKey; diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 0515c0291b1cf..8c8993ccbd17f 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -69,10 +69,11 @@ public PlatformViewRegistry getRegistry() { } public void onFlutterViewDestroyed() { - for (VirtualDisplayController controller : vdControllers.values()) { - controller.dispose(); - } - vdControllers.clear(); + flushAllViews(); + } + + public void onPreEngineRestart() { + flushAllViews(); } @Override @@ -297,4 +298,10 @@ private int toPhysicalPixels(double logicalPixels) { return (int) Math.round(logicalPixels * density); } + private void flushAllViews() { + for (VirtualDisplayController controller : vdControllers.values()) { + controller.dispose(); + } + vdControllers.clear(); + } } diff --git a/shell/platform/android/io/flutter/view/FlutterNativeView.java b/shell/platform/android/io/flutter/view/FlutterNativeView.java index 46d8f5cb0d0d7..f7b0b1b362484 100644 --- a/shell/platform/android/io/flutter/view/FlutterNativeView.java +++ b/shell/platform/android/io/flutter/view/FlutterNativeView.java @@ -198,6 +198,14 @@ private void onFirstFrame() { mFlutterView.onFirstFrame(); } + // Called by native to notify when the engine is restarted (cold reload). + @SuppressWarnings("unused") + private void onPreEngineRestart() { + if (mPluginRegistry == null) + return; + mPluginRegistry.onPreEngineRestart(); + } + private static native long nativeAttach(FlutterNativeView view); private static native void nativeDestroy(long nativePlatformViewAndroid); private static native void nativeDetach(long nativePlatformViewAndroid); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 808b5fa72a32b..2df879cb40ad6 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -157,6 +157,17 @@ void PlatformViewAndroid::HandlePlatformMessage( } } +// |shell::PlatformView| +void PlatformViewAndroid::OnPreEngineRestart() const { + JNIEnv* env = fml::jni::AttachCurrentThread(); + fml::jni::ScopedJavaLocalRef view = java_object_.get(env); + if (view.is_null()) { + // The Java object died. + return; + } + FlutterViewOnPreEngineRestart(fml::jni::AttachCurrentThread(), view.obj()); +} + void PlatformViewAndroid::DispatchSemanticsAction(JNIEnv* env, jint id, jint action, diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index be7cf2c197322..c3903d59e712b 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -83,6 +83,9 @@ class PlatformViewAndroid final : public PlatformView { void HandlePlatformMessage( fml::RefPtr message) override; + // |shell::PlatformView| + void OnPreEngineRestart() const override; + // |shell::PlatformView| std::unique_ptr CreateVSyncWaiter() override; diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index 933a34dff9427..3426d5bbb5d3d 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -96,6 +96,12 @@ void FlutterViewOnFirstFrame(JNIEnv* env, jobject obj) { FML_CHECK(CheckException(env)); } +static jmethodID g_on_engine_restart_method = nullptr; +void FlutterViewOnPreEngineRestart(JNIEnv* env, jobject obj) { + env->CallVoidMethod(obj, g_on_engine_restart_method); + FML_CHECK(CheckException(env)); +} + static jmethodID g_attach_to_gl_context_method = nullptr; void SurfaceTextureAttachToGLContext(JNIEnv* env, jobject obj, jint textureId) { env->CallVoidMethod(obj, g_attach_to_gl_context_method, textureId); @@ -698,6 +704,13 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } + g_on_engine_restart_method = env->GetMethodID( + g_flutter_native_view_class->obj(), "onPreEngineRestart", "()V"); + + if (g_on_engine_restart_method == nullptr) { + return false; + } + g_attach_to_gl_context_method = env->GetMethodID( g_surface_texture_class->obj(), "attachToGLContext", "(I)V"); diff --git a/shell/platform/android/platform_view_android_jni.h b/shell/platform/android/platform_view_android_jni.h index 4927e35cc981b..9a4a411a9d303 100644 --- a/shell/platform/android/platform_view_android_jni.h +++ b/shell/platform/android/platform_view_android_jni.h @@ -34,6 +34,8 @@ void FlutterViewUpdateCustomAccessibilityActions(JNIEnv* env, void FlutterViewOnFirstFrame(JNIEnv* env, jobject obj); +void FlutterViewOnPreEngineRestart(JNIEnv* env, jobject obj); + void SurfaceTextureAttachToGLContext(JNIEnv* env, jobject obj, jint textureId); void SurfaceTextureUpdateTexImage(JNIEnv* env, jobject obj);