diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index c2f3d1f41e32fd2f3a82283397ce123c34e7e7ec..bfd6f47d5071d83a25096cba7eecaf781a7a2488 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -417,6 +417,7 @@ action("robolectric_tests") { "test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java", "test/io/flutter/embedding/android/FlutterActivityTest.java", "test/io/flutter/embedding/android/FlutterFragmentTest.java", + "test/io/flutter/embedding/android/FlutterViewTest.java", "test/io/flutter/embedding/engine/FlutterEngineCacheTest.java", "test/io/flutter/embedding/engine/FlutterJNITest.java", "test/io/flutter/embedding/engine/RenderingComponentTest.java", diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterView.java b/shell/platform/android/io/flutter/embedding/android/FlutterView.java index c6936c97f5aa311457db84db3953847cd2a55d32..2d10a20dba103b1e424a8711bd0092bb47cfcb29 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterView.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterView.java @@ -633,6 +633,8 @@ public class FlutterView extends FrameLayout { sendLocalesToFlutter(getResources().getConfiguration()); sendViewportMetricsToFlutter(); + flutterEngine.getPlatformViewsController().attachToView(this); + // Notify engine attachment listeners of the attachment. for (FlutterEngineAttachmentListener listener : flutterEngineAttachmentListeners) { listener.onFlutterEngineAttachedToFlutterView(flutterEngine); @@ -668,6 +670,8 @@ public class FlutterView extends FrameLayout { listener.onFlutterEngineDetachedFromFlutterView(); } + flutterEngine.getPlatformViewsController().detachFromView(); + // Disconnect the FlutterEngine's PlatformViewsController from the AccessibilityBridge. flutterEngine.getPlatformViewsController().detachAccessibiltyBridge(); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index 42b0129d7298f6e7b6e6caefea9b15c76b8519c1..5a4ec289ccf2f6d6ed865f9fb83912ade46ff60f 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -143,14 +143,19 @@ public class FlutterEngine implements LifecycleOwner { * and {@link FlutterLoader#ensureInitializationComplete(Context, String[])}. */ public FlutterEngine(@NonNull Context context) { - this(context, FlutterLoader.getInstance()); + this(context, FlutterLoader.getInstance(), new FlutterJNI()); } - /* package */ FlutterEngine(@NonNull Context context, @NonNull FlutterLoader flutterLoader) { + /** + * Constructs a new {@code FlutterEngine}. See {@link #FlutterEngine(Context)}. + * + * {@code flutterJNI} should be a new instance that has never been attached to an engine before. + */ + public FlutterEngine(@NonNull Context context, @NonNull FlutterLoader flutterLoader, @NonNull FlutterJNI flutterJNI) { + this.flutterJNI = flutterJNI; flutterLoader.startInitialization(context); flutterLoader.ensureInitializationComplete(context, null); - this.flutterJNI = new FlutterJNI(); flutterJNI.addEngineLifecycleListener(engineLifecycleListener); attachToJni(); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 3ab1745d44c9b2011772f420c7c97af48ccfa3e6..2bd663f03106aaad3acafb8036e81e1d988fe19e 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -121,7 +121,7 @@ public class FlutterJNI { // TODO(mattcarroll): add javadocs @UiThread - public static native boolean nativeGetIsSoftwareRenderingEnabled(); + public native boolean nativeGetIsSoftwareRenderingEnabled(); @Nullable // TODO(mattcarroll): add javadocs diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java b/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java index 306535a547a26485e6d9330e8aabf02a86bf94e1..a6675964e6bd1a62241328d4328b0eb433ea2f27 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java @@ -281,7 +281,7 @@ public class FlutterRenderer implements TextureRegistry { // TODO(mattcarroll): describe the native behavior that this invokes public boolean isSoftwareRenderingEnabled() { - return FlutterJNI.nativeGetIsSoftwareRenderingEnabled(); + return flutterJNI.nativeGetIsSoftwareRenderingEnabled(); } // TODO(mattcarroll): describe the native behavior that this invokes diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index d1037170e19111638514e4de3f9fe64ac2491669..1546be7daec699dbf1adb658c164119e84d79cc6 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -38,7 +38,6 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -162,7 +161,7 @@ public class FlutterView extends SurfaceView implements BinaryMessenger, Texture dartExecutor = mNativeView.getDartExecutor(); flutterRenderer = new FlutterRenderer(mNativeView.getFlutterJNI()); - mIsSoftwareRenderingEnabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled(); + mIsSoftwareRenderingEnabled = mNativeView.getFlutterJNI().nativeGetIsSoftwareRenderingEnabled(); mMetrics = new ViewportMetrics(); mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density; setFocusable(true); diff --git a/shell/platform/android/test/io/flutter/FlutterTestSuite.java b/shell/platform/android/test/io/flutter/FlutterTestSuite.java index 59980291db4899b158822c1d67e002080ffebcde..b400fb5625e1c4843545385d8b3cc6518482956b 100644 --- a/shell/platform/android/test/io/flutter/FlutterTestSuite.java +++ b/shell/platform/android/test/io/flutter/FlutterTestSuite.java @@ -10,6 +10,7 @@ import org.junit.runners.Suite.SuiteClasses; import io.flutter.embedding.android.FlutterActivityTest; import io.flutter.embedding.android.FlutterFragmentTest; +import io.flutter.embedding.android.FlutterViewTest; import io.flutter.embedding.engine.FlutterEngineCacheTest; import io.flutter.embedding.engine.FlutterJNITest; import io.flutter.embedding.engine.RenderingComponentTest; @@ -28,6 +29,7 @@ import io.flutter.util.PreconditionsTest; FlutterFragmentTest.class, FlutterJNITest.class, FlutterRendererTest.class, + FlutterViewTest.class, PlatformChannelTest.class, PreconditionsTest.class, RenderingComponentTest.class, diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fe87fc8954d45cb2e27795de70eba7fe2cb7bf13 --- /dev/null +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java @@ -0,0 +1,58 @@ +package io.flutter.embedding.android; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.flutter.embedding.engine.FlutterJNI; +import io.flutter.embedding.engine.loader.FlutterLoader; +import io.flutter.plugin.platform.PlatformViewsController; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import io.flutter.embedding.engine.FlutterEngine; + +@Config(manifest = Config.NONE) +@RunWith(RobolectricTestRunner.class) +public class FlutterViewTest { + @Mock FlutterJNI mockFlutterJni; + @Mock FlutterLoader mockFlutterLoader; + @Spy PlatformViewsController platformViewsController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mockFlutterJni.isAttached()).thenReturn(true); + } + + @Test + public void attachToFlutterEngine_alertsPlatformViews() { + FlutterView flutterView = new FlutterView(RuntimeEnvironment.application); + FlutterEngine flutterEngine = spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni)); + when(flutterEngine.getPlatformViewsController()).thenReturn(platformViewsController); + + flutterView.attachToFlutterEngine(flutterEngine); + + verify(platformViewsController, times(1)).attachToView(flutterView); + } + + @Test + public void detachFromFlutterEngine_alertsPlatformViews() { + FlutterView flutterView = new FlutterView(RuntimeEnvironment.application); + FlutterEngine flutterEngine = spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni)); + when(flutterEngine.getPlatformViewsController()).thenReturn(platformViewsController); + + flutterView.attachToFlutterEngine(flutterEngine); + flutterView.detachFromFlutterEngine(); + + verify(platformViewsController, times(1)).detachFromView(); + } +}