Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,6 @@ public void detach() {
if (platformViewsChannel != null) {
platformViewsChannel.setPlatformViewsHandler(null);
}
destroyOverlaySurfaces();
platformViewsChannel = null;
context = null;
textureRegistry = null;
Expand Down Expand Up @@ -501,7 +500,6 @@ public void attachToView(@NonNull View flutterView) {
* the previously attached {@code View}.
*/
public void detachFromView() {
destroyOverlaySurfaces();
this.flutterView = null;

// Inform all existing platform views that they are no longer associated with
Expand Down Expand Up @@ -827,7 +825,11 @@ public void onDisplayOverlaySurface(int id, int x, int y, int width, int height)
initializeRootImageViewIfNeeded();

final FlutterImageView overlayView = overlayLayerViews.get(id);
if (overlayView.getParent() == null) {
FlutterView overlayViewParent = (FlutterView) overlayView.getParent();
if (overlayViewParent != flutterView) {
if (overlayViewParent != null) {
overlayViewParent.removeView(overlayView);
}
((FlutterView) flutterView).addView(overlayView);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,62 +563,7 @@ public void onEndFrame__removesPlatformViewParent() {

@Test
@Config(shadows = {ShadowFlutterSurfaceView.class, ShadowFlutterJNI.class})
public void detach__destroysOverlaySurfaces() {
final PlatformViewsController platformViewsController = new PlatformViewsController();

final int platformViewId = 0;
assertNull(platformViewsController.getPlatformViewById(platformViewId));

final PlatformViewFactory viewFactory = mock(PlatformViewFactory.class);
final PlatformView platformView = mock(PlatformView.class);
when(platformView.getView()).thenReturn(mock(View.class));
when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView);

platformViewsController.getRegistry().registerViewFactory("testType", viewFactory);

final FlutterJNI jni = new FlutterJNI();
jni.attachToNative(false);
attach(jni, platformViewsController);

jni.onFirstFrame();

// Simulate create call from the framework.
createPlatformView(jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ true);

// Produce a frame that displays a platform view and an overlay surface.
platformViewsController.onBeginFrame();
platformViewsController.onDisplayPlatformView(
platformViewId,
/* x=*/ 0,
/* y=*/ 0,
/* width=*/ 10,
/* height=*/ 10,
/* viewWidth=*/ 10,
/* viewHeight=*/ 10,
/* mutatorsStack=*/ new FlutterMutatorsStack());

final FlutterImageView overlayImageView = mock(FlutterImageView.class);
when(overlayImageView.acquireLatestImage()).thenReturn(true);

final FlutterOverlaySurface overlaySurface =
platformViewsController.createOverlaySurface(overlayImageView);
// This is OK.
platformViewsController.onDisplayOverlaySurface(
overlaySurface.getId(), /* x=*/ 0, /* y=*/ 0, /* width=*/ 10, /* height=*/ 10);

platformViewsController.detach();

assertThrows(
IllegalStateException.class,
() -> {
platformViewsController.onDisplayOverlaySurface(
overlaySurface.getId(), /* x=*/ 0, /* y=*/ 0, /* width=*/ 10, /* height=*/ 10);
});
}

@Test
@Config(shadows = {ShadowFlutterSurfaceView.class, ShadowFlutterJNI.class})
public void detachFromView__removesOverlaySurfaces() {
public void destroyOverlaySurfaces__removesOverlaySurfaces() {
final PlatformViewsController platformViewsController = new PlatformViewsController();

final int platformViewId = 0;
Expand All @@ -644,7 +589,8 @@ public void detachFromView__removesOverlaySurfaces() {
platformViewsController.onDisplayOverlaySurface(
overlaySurface.getId(), /* x=*/ 0, /* y=*/ 0, /* width=*/ 10, /* height=*/ 10);

platformViewsController.detachFromView();
// Simulate |DestroyLayers| call from SurfacePool.
platformViewsController.destroyOverlaySurfaces();

assertThrows(
IllegalStateException.class,
Expand Down Expand Up @@ -787,6 +733,86 @@ public void dontConverRenderSurfaceWhenFlagIsTrue() {
disposePlatformView(jni, platformViewsController, platformViewId);
}

@Test
@Config(shadows = {ShadowFlutterSurfaceView.class, ShadowFlutterJNI.class})
public void onDisplayOverlaySurface__doesNotThrowWhenMultiFlutterViewShareEngine() {
final PlatformViewsController platformViewsController = new PlatformViewsController();

final int platformViewId = 0;
assertNull(platformViewsController.getPlatformViewById(platformViewId));

final PlatformViewFactory viewFactory = mock(PlatformViewFactory.class);
final PlatformView platformView = mock(PlatformView.class);
when(platformView.getView()).thenReturn(mock(View.class));
when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView);

platformViewsController.getRegistry().registerViewFactory("testType", viewFactory);

final FlutterJNI jni = new FlutterJNI();
jni.attachToNative(false);
final FlutterView flutterView1 = attach(jni, platformViewsController);

jni.onFirstFrame();

// Simulate create call from the framework.
createPlatformView(jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ true);

// Produce a frame that displays a platform view and an overlay surface.
platformViewsController.onBeginFrame();
platformViewsController.onDisplayPlatformView(
platformViewId,
/* x=*/ 0,
/* y=*/ 0,
/* width=*/ 10,
/* height=*/ 10,
/* viewWidth=*/ 10,
/* viewHeight=*/ 10,
/* mutatorsStack=*/ new FlutterMutatorsStack());

final FlutterImageView overlayImageView1 = mock(FlutterImageView.class);
when(overlayImageView1.acquireLatestImage()).thenReturn(true);

final FlutterOverlaySurface overlaySurface1 =
platformViewsController.createOverlaySurface(overlayImageView1);
platformViewsController.onDisplayOverlaySurface(
overlaySurface1.getId(), /* x=*/ 0, /* y=*/ 0, /* width=*/ 10, /* height=*/ 10);

platformViewsController.onEndFrame();

FlutterEngine flutterEngine = flutterView1.getAttachedFlutterEngine();
flutterView1.detachFromFlutterEngine();

FlutterView flutterView2 = new FlutterView(RuntimeEnvironment.application);
flutterView2.attachToFlutterEngine(flutterEngine);

jni.onFirstFrame();

// Simulate create call from the framework.
createPlatformView(jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ true);

// Produce a frame that displays a platform view and an overlay surface.
platformViewsController.onBeginFrame();
platformViewsController.onDisplayPlatformView(
platformViewId,
/* x=*/ 0,
/* y=*/ 0,
/* width=*/ 10,
/* height=*/ 10,
/* viewWidth=*/ 10,
/* viewHeight=*/ 10,
/* mutatorsStack=*/ new FlutterMutatorsStack());

final FlutterImageView overlayImageView2 = mock(FlutterImageView.class);
when(overlayImageView2.acquireLatestImage()).thenReturn(true);

final FlutterOverlaySurface overlaySurface2 =
platformViewsController.createOverlaySurface(overlayImageView2);
platformViewsController.onDisplayOverlaySurface(
overlaySurface2.getId(), /* x=*/ 0, /* y=*/ 0, /* width=*/ 10, /* height=*/ 10);

platformViewsController.onEndFrame();
}

private static ByteBuffer encodeMethodCall(MethodCall call) {
final ByteBuffer buffer = StandardMethodCodec.INSTANCE.encodeMethodCall(call);
buffer.rewind();
Expand Down