@@ -196,13 +196,7 @@ public void onFlutterUiNoLongerDisplayed() {
196
196
}
197
197
};
198
198
199
- private final Consumer <WindowLayoutInfo > windowInfoListener =
200
- new Consumer <WindowLayoutInfo >() {
201
- @ Override
202
- public void accept (WindowLayoutInfo layoutInfo ) {
203
- setWindowInfoListenerDisplayFeatures (layoutInfo );
204
- }
205
- };
199
+ private Consumer <WindowLayoutInfo > windowInfoListener ;
206
200
207
201
/**
208
202
* Constructs a {@code FlutterView} programmatically, without any XML attributes.
@@ -514,6 +508,10 @@ protected void onAttachedToWindow() {
514
508
this .windowInfoRepo = createWindowInfoRepo ();
515
509
Activity activity = ViewUtils .getActivity (getContext ());
516
510
if (windowInfoRepo != null && activity != null ) {
511
+ // Creating windowInfoListener on-demand instead of at initialization is necessary in order to
512
+ // prevent it from capturing the wrong instance of `this` when spying for testing.
513
+ // See https://github.com/mockito/mockito/issues/3479
514
+ windowInfoListener = this ::setWindowInfoListenerDisplayFeatures ;
517
515
windowInfoRepo .addWindowLayoutInfoListener (
518
516
activity , ContextCompat .getMainExecutor (getContext ()), windowInfoListener );
519
517
}
@@ -526,9 +524,10 @@ protected void onAttachedToWindow() {
526
524
*/
527
525
@ Override
528
526
protected void onDetachedFromWindow () {
529
- if (windowInfoRepo != null ) {
527
+ if (windowInfoRepo != null && windowInfoListener != null ) {
530
528
windowInfoRepo .removeWindowLayoutInfoListener (windowInfoListener );
531
529
}
530
+ windowInfoListener = null ;
532
531
this .windowInfoRepo = null ;
533
532
super .onDetachedFromWindow ();
534
533
}
@@ -539,12 +538,12 @@ protected void onDetachedFromWindow() {
539
538
*/
540
539
@ TargetApi (API_LEVELS .API_28 )
541
540
protected void setWindowInfoListenerDisplayFeatures (WindowLayoutInfo layoutInfo ) {
542
- List <DisplayFeature > displayFeatures = layoutInfo .getDisplayFeatures ();
543
- List <FlutterRenderer .DisplayFeature > result = new ArrayList <>();
541
+ List <DisplayFeature > newDisplayFeatures = layoutInfo .getDisplayFeatures ();
542
+ List <FlutterRenderer .DisplayFeature > flutterDisplayFeatures = new ArrayList <>();
544
543
545
544
// Data from WindowInfoTracker display features. Fold and hinge areas are
546
545
// populated here.
547
- for (DisplayFeature displayFeature : displayFeatures ) {
546
+ for (DisplayFeature displayFeature : newDisplayFeatures ) {
548
547
Log .v (
549
548
TAG ,
550
549
"WindowInfoTracker Display Feature reported with bounds = "
@@ -567,31 +566,17 @@ protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo)
567
566
} else {
568
567
state = DisplayFeatureState .UNKNOWN ;
569
568
}
570
- result .add (new FlutterRenderer .DisplayFeature (displayFeature .getBounds (), type , state ));
569
+ flutterDisplayFeatures .add (
570
+ new FlutterRenderer .DisplayFeature (displayFeature .getBounds (), type , state ));
571
571
} else {
572
- result .add (
572
+ flutterDisplayFeatures .add (
573
573
new FlutterRenderer .DisplayFeature (
574
574
displayFeature .getBounds (),
575
575
DisplayFeatureType .UNKNOWN ,
576
576
DisplayFeatureState .UNKNOWN ));
577
577
}
578
578
}
579
-
580
- // Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
581
- // populated here. DisplayCutout was introduced in API 28.
582
- if (Build .VERSION .SDK_INT >= API_LEVELS .API_28 ) {
583
- WindowInsets insets = getRootWindowInsets ();
584
- if (insets != null ) {
585
- DisplayCutout cutout = insets .getDisplayCutout ();
586
- if (cutout != null ) {
587
- for (Rect bounds : cutout .getBoundingRects ()) {
588
- Log .v (TAG , "DisplayCutout area reported with bounds = " + bounds .toString ());
589
- result .add (new FlutterRenderer .DisplayFeature (bounds , DisplayFeatureType .CUTOUT ));
590
- }
591
- }
592
- }
593
- }
594
- viewportMetrics .displayFeatures = result ;
579
+ viewportMetrics .setDisplayFeatures (flutterDisplayFeatures );
595
580
sendViewportMetricsToFlutter ();
596
581
}
597
582
@@ -784,6 +769,22 @@ navigationBarVisible && guessBottomKeyboardInset(insets) == 0
784
769
viewportMetrics .viewInsetLeft = 0 ;
785
770
}
786
771
772
+ // Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
773
+ // populated here. DisplayCutout was introduced in API 28.
774
+ List <FlutterRenderer .DisplayFeature > displayCutouts = new ArrayList <>();
775
+ if (Build .VERSION .SDK_INT >= API_LEVELS .API_28 ) {
776
+ DisplayCutout cutout = insets .getDisplayCutout ();
777
+ if (cutout != null ) {
778
+ for (Rect bounds : cutout .getBoundingRects ()) {
779
+ Log .v (TAG , "DisplayCutout area reported with bounds = " + bounds .toString ());
780
+ displayCutouts .add (
781
+ new FlutterRenderer .DisplayFeature (
782
+ bounds , DisplayFeatureType .CUTOUT , DisplayFeatureState .UNKNOWN ));
783
+ }
784
+ }
785
+ }
786
+ viewportMetrics .setDisplayCutouts (displayCutouts );
787
+
787
788
// The caption bar inset is a new addition, and the APIs called to query it utilize a list of
788
789
// bounding Rects instead of an Insets object, which is a newer API method, as compared to the
789
790
// existing Insets-based method calls above.
0 commit comments