diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 817c1c29250f8..b922bf23170f3 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -129,6 +129,8 @@ java_library("flutter_shell_java") { "io/flutter/plugin/platform/PlatformViewRegistry.java", "io/flutter/plugin/platform/PlatformViewRegistryImpl.java", "io/flutter/plugin/platform/PlatformViewsController.java", + "io/flutter/plugin/platform/SingleViewPresentation.java", + "io/flutter/plugin/platform/VirtualDisplayController.java", "io/flutter/util/PathUtils.java", "io/flutter/util/Preconditions.java", "io/flutter/view/AccessibilityBridge.java", diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformView.java b/shell/platform/android/io/flutter/plugin/platform/PlatformView.java index 9b60d1fdbf4ea..6e379e96a6ba0 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformView.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformView.java @@ -14,4 +14,14 @@ public interface PlatformView { * Returns the Android view to be embedded in the Flutter hierarchy. */ View getView(); + + /** + * Dispose this platform view. + * + *
The {@link PlatformView} object is unusable after this method is called. + * + *
Plugins implementing {@link PlatformView} must clear all references to the View object and the PlatformView
+ * after this method is called. Failing to do so will result in a memory leak.
+ */
+ void dispose();
}
diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewFactory.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewFactory.java
index ac70b1776d2af..9cb7731e1ccb6 100644
--- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewFactory.java
+++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewFactory.java
@@ -7,5 +7,11 @@
import android.content.Context;
public interface PlatformViewFactory {
- PlatformView create(Context context);
+ /**
+ * Creates a new Android view to be embedded in the Flutter hierarchy.
+ *
+ * @param context the context to be used when creating the view, this is different than FlutterView's context.
+ * @param viewId unique identifier for the created instance, this value is known on the Dart side.
+ */
+ PlatformView create(Context context, int viewId);
}
diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java
index 2d10a45d81fbf..77051ee37087f 100644
--- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java
+++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java
@@ -4,11 +4,15 @@
package io.flutter.plugin.platform;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
import android.util.Log;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMethodCodec;
import io.flutter.view.FlutterView;
+import io.flutter.view.TextureRegistry;
import java.util.HashMap;
import java.util.Map;
@@ -20,14 +24,22 @@
* A platform views controller can be attached to at most one Flutter view.
*/
public class PlatformViewsController implements MethodChannel.MethodCallHandler {
+ private static final String TAG = "PlatformViewsController";
+
private static final String CHANNEL_NAME = "flutter/platform_views";
+ // API level 20 is required for VirtualDisplay#setSurface which we use when resizing a platform view.
+ private static final int MINIMAL_SDK = Build.VERSION_CODES.KITKAT_WATCH;
+
private final PlatformViewRegistryImpl mRegistry;
private FlutterView mFlutterView;
+ private final HashMap The display's density must match the density of the context used
+ * when the view was created.
+ */
+ public SingleViewPresentation(Context outerContext, Display display, PlatformView view) {
+ super(outerContext, display);
+ mViewFactory = null;
+ mView = view;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (mView == null) {
+ mView = mViewFactory.create(getContext(), mViewId);
+ }
+ mContainer = new FrameLayout(getContext());
+ mContainer.addView(mView.getView());
+ setContentView(mContainer);
+ }
+
+ public PlatformView detachView() {
+ mContainer.removeView(mView.getView());
+ return mView;
+ }
+}
diff --git a/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java b/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java
new file mode 100644
index 0000000000000..5514d4334e091
--- /dev/null
+++ b/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java
@@ -0,0 +1,102 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugin.platform;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.os.Build;
+import android.view.Surface;
+import android.view.View;
+
+@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
+class VirtualDisplayController {
+
+ public static VirtualDisplayController create(
+ Context context,
+ PlatformViewFactory viewFactory,
+ SurfaceTexture surfaceTexture,
+ int width,
+ int height,
+ int viewId
+ ) {
+ surfaceTexture.setDefaultBufferSize(width, height);
+ Surface surface = new Surface(surfaceTexture);
+ DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+
+ int densityDpi = context.getResources().getDisplayMetrics().densityDpi;
+ VirtualDisplay virtualDisplay = displayManager.createVirtualDisplay(
+ "flutter-vd",
+ width,
+ height,
+ densityDpi,
+ surface,
+ 0
+ );
+
+ if (virtualDisplay == null) {
+ return null;
+ }
+
+ return new VirtualDisplayController(context, virtualDisplay, viewFactory, surface, surfaceTexture, viewId);
+ }
+
+ private final Context mContext;
+ private final int mDensityDpi;
+ private final SurfaceTexture mSurfaceTexture;
+ private VirtualDisplay mVirtualDisplay;
+ private SingleViewPresentation mPresentation;
+ private Surface mSurface;
+
+
+ private VirtualDisplayController(
+ Context context,
+ VirtualDisplay virtualDisplay,
+ PlatformViewFactory viewFactory,
+ Surface surface,
+ SurfaceTexture surfaceTexture,
+ int viewId
+ ) {
+ mSurfaceTexture = surfaceTexture;
+ mSurface = surface;
+ mContext = context;
+ mVirtualDisplay = virtualDisplay;
+ mDensityDpi = context.getResources().getDisplayMetrics().densityDpi;
+ mPresentation = new SingleViewPresentation(context, mVirtualDisplay.getDisplay(), viewFactory, viewId);
+ mPresentation.show();
+ }
+
+ public void resize(int width, int height) {
+ PlatformView view = mPresentation.detachView();
+ mPresentation.hide();
+ // We detach the surface to prevent it being destroyed when releasing the vd.
+ //
+ // setSurface is only available starting API 20. We could support API 19 by re-creating a new
+ // SurfaceTexture here. This will require refactoring the TextureRegistry to allow recycling texture
+ // entry IDs.
+ mVirtualDisplay.setSurface(null);
+ mVirtualDisplay.release();
+
+ mSurfaceTexture.setDefaultBufferSize(width, height);
+ DisplayManager displayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+ mVirtualDisplay = displayManager.createVirtualDisplay(
+ "flutter-vd",
+ width,
+ height,
+ mDensityDpi,
+ mSurface,
+ 0
+ );
+ mPresentation = new SingleViewPresentation(mContext, mVirtualDisplay.getDisplay(), view);
+ mPresentation.show();
+ }
+
+ public void dispose() {
+ mPresentation.detachView().dispose();
+ mVirtualDisplay.release();
+ }
+}
diff --git a/travis/licenses_golden/licenses_flutter b/travis/licenses_golden/licenses_flutter
index 29035a43eb7ae..3cdcba8d4ac5f 100644
--- a/travis/licenses_golden/licenses_flutter
+++ b/travis/licenses_golden/licenses_flutter
@@ -501,6 +501,8 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Platfor
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewRegistryImpl.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java
+FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java
+FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm