diff options
author | 2022-05-31 20:05:40 +0800 | |
---|---|---|
committer | 2022-05-31 13:38:29 +0000 | |
commit | ea97f83f8fb7997d86a2fc30a5fe970d56dae317 (patch) | |
tree | 2b390b481836abaa417e67479431aa1e46f767bf | |
parent | 2e83cb0c22d9d6832137e61ad1dc4029683b1577 (diff) |
Fix InsetsState#calculateUncontrollableInsetsFromFrame
If a type of insets doesn't provide any insets to a window, the previous
logic would think the type is controllable. This is wrong.
If a type of insets provides the entire inset to a window, the previous
logic would think the type is not controllable when the width or height
doesn't match the display frame. This doesn't make much sense as well.
This CL fixes the issues mentioned above and also refines
WindowInsetsTests. It displays the name (string) of the controllable
types, not the value (number).
Fix: 234426300
Test: WindowInsetsTests
Test: atest InsetsControllerTest
Change-Id: Ice71db61cc4963c6d8489096bec9c295d58bfd78
5 files changed, 70 insertions, 29 deletions
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 9d6b982c3571..8f7a15e5fbe5 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -404,27 +404,20 @@ public class InsetsState implements Parcelable { if (source == null) { continue; } - if (!canControlSide(frame, getInsetSide( - source.calculateInsets(frame, true /* ignoreVisibility */)))) { + if (!canControlSource(frame, source)) { blocked |= toPublicType(type); } } return blocked; } - private boolean canControlSide(Rect frame, int side) { - switch (side) { - case ISIDE_LEFT: - case ISIDE_RIGHT: - return frame.left == mDisplayFrame.left && frame.right == mDisplayFrame.right; - case ISIDE_TOP: - case ISIDE_BOTTOM: - return frame.top == mDisplayFrame.top && frame.bottom == mDisplayFrame.bottom; - case ISIDE_FLOATING: - return true; - default: - return false; - } + private static boolean canControlSource(Rect frame, InsetsSource source) { + final Insets insets = source.calculateInsets(frame, true /* ignoreVisibility */); + final Rect sourceFrame = source.getFrame(); + final int sourceWidth = sourceFrame.width(); + final int sourceHeight = sourceFrame.height(); + return insets.left == sourceWidth || insets.right == sourceWidth + || insets.top == sourceHeight || insets.bottom == sourceHeight; } private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility, diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index c504f0cf2d94..dcb1835204dd 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -214,19 +214,23 @@ public class InsetsControllerTest { } @Test - public void testFrameDoesntMatchDisplay() { - mController.onFrameChanged(new Rect(0, 0, 100, 100)); - mController.getState().setDisplayFrame(new Rect(0, 0, 200, 200)); - InsetsSourceControl control = - new InsetsSourceControl( - ITYPE_STATUS_BAR, mLeash, new Point(), Insets.of(0, 10, 0, 0)); - mController.onControlsChanged(new InsetsSourceControl[] { control }); + public void testFrameDoesntOverlapWithInsets() { WindowInsetsAnimationControlListener controlListener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(0, 0 /* durationMs */, new LinearInterpolator(), - new CancellationSignal(), controlListener); - mController.addOnControllableInsetsChangedListener( - (controller, typeMask) -> assertEquals(0, typeMask)); + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + // The frame doesn't overlap with status bar. + mController.onFrameChanged(new Rect(0, 10, 100, 100)); + + InsetsSourceControl control = + new InsetsSourceControl( + ITYPE_STATUS_BAR, mLeash, new Point(), Insets.of(0, 10, 0, 0)); + mController.onControlsChanged(new InsetsSourceControl[]{control}); + mController.controlWindowInsetsAnimation(0, 0 /* durationMs */, + new LinearInterpolator(), + new CancellationSignal(), controlListener); + mController.addOnControllableInsetsChangedListener( + (controller, typeMask) -> assertEquals(0, typeMask)); + }); verify(controlListener).onCancelled(null); verify(controlListener, never()).onReady(any(), anyInt()); } diff --git a/tests/WindowInsetsTests/res/layout/controller_activity.xml b/tests/WindowInsetsTests/res/layout/controller_activity.xml index d51a4ddd43e8..5550eab61a33 100644 --- a/tests/WindowInsetsTests/res/layout/controller_activity.xml +++ b/tests/WindowInsetsTests/res/layout/controller_activity.xml @@ -88,7 +88,7 @@ <TextView android:id="@+id/textViewControllableInsets" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" /> diff --git a/tests/WindowInsetsTests/res/values/strings.xml b/tests/WindowInsetsTests/res/values/strings.xml index d6355f5a0464..516d4584426e 100644 --- a/tests/WindowInsetsTests/res/values/strings.xml +++ b/tests/WindowInsetsTests/res/values/strings.xml @@ -22,7 +22,7 @@ <!-- The item positions should match the flag values respectively. --> <string-array name="behaviors"> - <item>BEHAVIOR_SHOW_BARS_BY_TOUCH</item> + <item>BEHAVIOR_SHOW_BARS_BY_TOUCH (deprecated)</item> <item>BEHAVIOR_DEFAULT</item> <item>BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE</item> </string-array> diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java index 95fd959e5587..e6b60cfbe84f 100644 --- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java +++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java @@ -83,7 +83,51 @@ public class ControllerActivity extends Activity implements View.OnApplyWindowIn final View contentView = findViewById(R.id.content); contentView.setOnApplyWindowInsetsListener(this); contentView.getWindowInsetsController().addOnControllableInsetsChangedListener( - (c, types) -> mTextControllableInsets.setText("ControllableInsetsTypes=" + types)); + (c, types) -> mTextControllableInsets.setText( + "ControllableInsetsTypes:\n" + insetsTypesToString(types))); + } + + private static String insetsTypesToString(int types) { + if (types == 0) { + return "none"; + } + final StringBuilder sb = new StringBuilder(); + if ((types & Type.statusBars()) != 0) { + types &= ~Type.statusBars(); + sb.append("statusBars "); + } + if ((types & Type.navigationBars()) != 0) { + types &= ~Type.navigationBars(); + sb.append("navigationBars "); + } + if ((types & Type.captionBar()) != 0) { + types &= ~Type.captionBar(); + sb.append("captionBar "); + } + if ((types & Type.ime()) != 0) { + types &= ~Type.ime(); + sb.append("ime "); + } + if ((types & Type.systemGestures()) != 0) { + types &= ~Type.systemGestures(); + sb.append("systemGestures "); + } + if ((types & Type.mandatorySystemGestures()) != 0) { + types &= ~Type.mandatorySystemGestures(); + sb.append("mandatorySystemGestures "); + } + if ((types & Type.tappableElement()) != 0) { + types &= ~Type.tappableElement(); + sb.append("tappableElement "); + } + if ((types & Type.displayCutout()) != 0) { + types &= ~Type.displayCutout(); + sb.append("displayCutout "); + } + if (types != 0) { + sb.append("unknownTypes:").append(types); + } + return sb.toString(); } @Override |