@@ -498,6 +498,131 @@ public void onEndFrame__removesPlatformViewParent() {
498498 assertEquals (flutterView .getChildCount (), 1 );
499499 }
500500
501+ @ Test
502+ @ Config (shadows = {ShadowFlutterSurfaceView .class , ShadowFlutterJNI .class })
503+ public void detach__destroysOverlaySurfaces () {
504+ final PlatformViewsController platformViewsController = new PlatformViewsController ();
505+
506+ final int platformViewId = 0 ;
507+ assertNull (platformViewsController .getPlatformViewById (platformViewId ));
508+
509+ final PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
510+ final PlatformView platformView = mock (PlatformView .class );
511+ when (platformView .getView ()).thenReturn (mock (View .class ));
512+ when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
513+
514+ platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
515+
516+ final FlutterJNI jni = new FlutterJNI ();
517+ jni .attachToNative (false );
518+ attach (jni , platformViewsController );
519+
520+ jni .onFirstFrame ();
521+
522+ // Simulate create call from the framework.
523+ createPlatformView (jni , platformViewsController , platformViewId , "testType" );
524+
525+ // Produce a frame that displays a platform view and an overlay surface.
526+ platformViewsController .onBeginFrame ();
527+ platformViewsController .onDisplayPlatformView (
528+ platformViewId ,
529+ /* x=*/ 0 ,
530+ /* y=*/ 0 ,
531+ /* width=*/ 10 ,
532+ /* height=*/ 10 ,
533+ /* viewWidth=*/ 10 ,
534+ /* viewHeight=*/ 10 ,
535+ /* mutatorsStack=*/ new FlutterMutatorsStack ());
536+
537+ final FlutterImageView overlayImageView = mock (FlutterImageView .class );
538+ when (overlayImageView .acquireLatestImage ()).thenReturn (true );
539+
540+ final FlutterOverlaySurface overlaySurface =
541+ platformViewsController .createOverlaySurface (overlayImageView );
542+ // This is OK.
543+ platformViewsController .onDisplayOverlaySurface (
544+ overlaySurface .getId (), /* x=*/ 0 , /* y=*/ 0 , /* width=*/ 10 , /* height=*/ 10 );
545+
546+ platformViewsController .detach ();
547+
548+ assertThrows (
549+ IllegalStateException .class ,
550+ () -> {
551+ platformViewsController .onDisplayOverlaySurface (
552+ overlaySurface .getId (), /* x=*/ 0 , /* y=*/ 0 , /* width=*/ 10 , /* height=*/ 10 );
553+ });
554+ }
555+
556+ @ Test
557+ @ Config (shadows = {ShadowFlutterSurfaceView .class , ShadowFlutterJNI .class })
558+ public void detachFromView__removesOverlaySurfaces () {
559+ final PlatformViewsController platformViewsController = new PlatformViewsController ();
560+
561+ final int platformViewId = 0 ;
562+ assertNull (platformViewsController .getPlatformViewById (platformViewId ));
563+
564+ final PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
565+ final PlatformView platformView = mock (PlatformView .class );
566+ when (platformView .getView ()).thenReturn (mock (View .class ));
567+ when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
568+
569+ platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
570+
571+ final FlutterJNI jni = new FlutterJNI ();
572+ jni .attachToNative (false );
573+ attach (jni , platformViewsController );
574+
575+ final FlutterImageView overlayImageView = mock (FlutterImageView .class );
576+ when (overlayImageView .acquireLatestImage ()).thenReturn (true );
577+
578+ final FlutterOverlaySurface overlaySurface =
579+ platformViewsController .createOverlaySurface (overlayImageView );
580+
581+ platformViewsController .onDisplayOverlaySurface (
582+ overlaySurface .getId (), /* x=*/ 0 , /* y=*/ 0 , /* width=*/ 10 , /* height=*/ 10 );
583+
584+ platformViewsController .detachFromView ();
585+
586+ assertThrows (
587+ IllegalStateException .class ,
588+ () -> {
589+ platformViewsController .onDisplayOverlaySurface (
590+ overlaySurface .getId (), /* x=*/ 0 , /* y=*/ 0 , /* width=*/ 10 , /* height=*/ 10 );
591+ });
592+ }
593+
594+ @ Test
595+ @ Config (shadows = {ShadowFlutterSurfaceView .class , ShadowFlutterJNI .class })
596+ public void destroyOverlaySurfaces__doesNotThrowIfControllerIsDetached () {
597+ final PlatformViewsController platformViewsController = new PlatformViewsController ();
598+
599+ final int platformViewId = 0 ;
600+ assertNull (platformViewsController .getPlatformViewById (platformViewId ));
601+
602+ final PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
603+ final PlatformView platformView = mock (PlatformView .class );
604+ when (platformView .getView ()).thenReturn (mock (View .class ));
605+ when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
606+
607+ platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
608+
609+ final FlutterJNI jni = new FlutterJNI ();
610+ jni .attachToNative (false );
611+ attach (jni , platformViewsController );
612+
613+ final FlutterImageView overlayImageView = mock (FlutterImageView .class );
614+ when (overlayImageView .acquireLatestImage ()).thenReturn (true );
615+
616+ final FlutterOverlaySurface overlaySurface =
617+ platformViewsController .createOverlaySurface (overlayImageView );
618+
619+ platformViewsController .onDisplayOverlaySurface (
620+ overlaySurface .getId (), /* x=*/ 0 , /* y=*/ 0 , /* width=*/ 10 , /* height=*/ 10 );
621+
622+ platformViewsController .detachFromView ();
623+ platformViewsController .destroyOverlaySurfaces ();
624+ }
625+
501626 @ Test
502627 public void checkInputConnectionProxy__falseIfViewIsNull () {
503628 final PlatformViewsController platformViewsController = new PlatformViewsController ();
0 commit comments