diff --git a/engine/src/flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/engine/src/flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 87a04f5671..68fc2f1599 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -314,6 +314,7 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega final int viewId = request.viewId; if (usesVirtualDisplay(viewId)) { + final float originalDisplayDensity = getDisplayDensity(); final VirtualDisplayController vdController = vdControllers.get(viewId); // Resizing involved moving the platform view to a new virtual display. Doing so // potentially results in losing an active input connection. To make sure we preserve @@ -325,10 +326,15 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega physicalHeight, () -> { unlockInputConnection(vdController); + // Converting back to logic pixels requires a context, which may no longer be + // available. If that happens, assume the same logic/physical relationship as + // was present when the request arrived. + final float displayDensity = + context == null ? originalDisplayDensity : getDisplayDensity(); onComplete.run( new PlatformViewsChannel.PlatformViewBufferSize( - toLogicalPixels(vdController.getBufferWidth()), - toLogicalPixels(vdController.getBufferHeight()))); + toLogicalPixels(vdController.getBufferWidth(), displayDensity), + toLogicalPixels(vdController.getBufferHeight(), displayDensity))); }); return; } @@ -1002,8 +1008,12 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega return (int) Math.round(logicalPixels * getDisplayDensity()); } + private int toLogicalPixels(double physicalPixels, float displayDensity) { + return (int) Math.round(physicalPixels / displayDensity); + } + private int toLogicalPixels(double physicalPixels) { - return (int) Math.round(physicalPixels / getDisplayDensity()); + return toLogicalPixels(physicalPixels, getDisplayDensity()); } private void diposeAllViews() { diff --git a/engine/src/flutter/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java b/engine/src/flutter/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java index 5dd43edc13..e896ecf0f7 100644 --- a/engine/src/flutter/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java +++ b/engine/src/flutter/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java @@ -124,6 +124,32 @@ public class PlatformViewsControllerTest { assertEquals(presentation.isShowing(), false); } + @Test + @Config(shadows = {ShadowFlutterJNI.class, ShadowPlatformTaskQueue.class}) + public void virtualDisplay_handlesResizeResponseWithoutContext() { + final int platformViewId = 0; + FlutterView fakeFlutterView = new FlutterView(ApplicationProvider.getApplicationContext()); + VirtualDisplayController fakeVdController = mock(VirtualDisplayController.class); + PlatformViewsController platformViewsController = new PlatformViewsController(); + platformViewsController.vdControllers.put(platformViewId, fakeVdController); + + platformViewsController.attachToView(fakeFlutterView); + + FlutterJNI jni = new FlutterJNI(); + attach(jni, platformViewsController); + + resize(jni, platformViewsController, platformViewId, 10.0, 20.0); + + ArgumentCaptor resizeCallbackCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(fakeVdController, times(1)).resize(anyInt(), anyInt(), resizeCallbackCaptor.capture()); + + // Simulate a detach call before the resize completes. + platformViewsController.detach(); + + // Trigger the callback to ensure that it doesn't crash. + resizeCallbackCaptor.getValue().run(); + } + @Test public void itUsesActionEventTypeFromFrameworkEventForVirtualDisplays() { MotionEventTracker motionEventTracker = MotionEventTracker.getInstance();