From ae42535e1a010827e9f7f1738c541696b92e6c54 Mon Sep 17 00:00:00 2001 From: Heemin Seog Date: Wed, 9 Sep 2020 09:14:45 -0700 Subject: DO NOT MERGE Ensure mapping between internal and public insets Bug: 166149440 Test: manual (flash automotive device with all system bars and show/hide insets using WindowInsetsController), atest InsetsStateTest InsetsStateControllerTest Change-Id: I500b2fb0129739c6fc609561377d90cca6e45f7e --- core/java/android/view/InsetsState.java | 2 + .../src/android/view/InsetsStateTest.java | 20 +++++++ .../java/com/android/server/wm/DisplayPolicy.java | 70 +++++++++++++++++++++- .../android/server/wm/InsetsSourceProvider.java | 5 +- .../android/server/wm/InsetsStateController.java | 35 +++++++++-- .../server/wm/DisplayPolicyLayoutTests.java | 13 +++- .../server/wm/InsetsStateControllerTest.java | 9 ++- 7 files changed, 141 insertions(+), 13 deletions(-) diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 593b37af26ad..0b43547f03de 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -453,9 +453,11 @@ public class InsetsState implements Parcelable { final ArraySet result = new ArraySet<>(); if ((types & Type.STATUS_BARS) != 0) { result.add(ITYPE_STATUS_BAR); + result.add(ITYPE_CLIMATE_BAR); } if ((types & Type.NAVIGATION_BARS) != 0) { result.add(ITYPE_NAVIGATION_BAR); + result.add(ITYPE_EXTRA_NAVIGATION_BAR); } if ((types & Type.CAPTION_BAR) != 0) { result.add(ITYPE_CAPTION_BAR); diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index c7d835ca7c7e..576cd78606d7 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -123,6 +123,24 @@ public class InsetsStateTest { } } + @Test + public void testCalculateInsets_extraNavRightClimateTop() throws Exception { + try (final InsetsModeSession session = + new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) { + mState.getSource(ITYPE_CLIMATE_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_CLIMATE_BAR).setVisible(true); + mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); + mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null); + // ITYPE_CLIMATE_BAR is a type of status bar and ITYPE_EXTRA_NAVIGATION_BAR is a type + // of navigation bar. + assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); + assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars())); + assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars())); + } + } + @Test public void testCalculateInsets_imeIgnoredWithoutAdjustResize() { try (final InsetsModeSession session = @@ -331,6 +349,8 @@ public class InsetsStateTest { public void testGetDefaultVisibility() { assertTrue(InsetsState.getDefaultVisibility(ITYPE_STATUS_BAR)); assertTrue(InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR)); + assertTrue(InsetsState.getDefaultVisibility(ITYPE_CLIMATE_BAR)); + assertTrue(InsetsState.getDefaultVisibility(ITYPE_EXTRA_NAVIGATION_BAR)); assertTrue(InsetsState.getDefaultVisibility(ITYPE_CAPTION_BAR)); assertFalse(InsetsState.getDefaultVisibility(ITYPE_IME)); } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index dbc579940e14..4a40fc6e572c 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -29,6 +29,8 @@ import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES; import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static android.view.InsetsState.ITYPE_CAPTION_BAR; +import static android.view.InsetsState.ITYPE_CLIMATE_BAR; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; @@ -248,7 +250,8 @@ public class DisplayPolicy { | View.STATUS_BAR_TRANSPARENT | View.NAVIGATION_BAR_TRANSPARENT; - private static final int[] SHOW_TYPES_FOR_SWIPE = {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR}; + private static final int[] SHOW_TYPES_FOR_SWIPE = + {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR}; private static final int[] SHOW_TYPES_FOR_PANIC = {ITYPE_NAVIGATION_BAR}; private final WindowManagerService mService; @@ -334,6 +337,16 @@ public class DisplayPolicy { private WindowState mNavigationBarAlt = null; @WindowManagerPolicy.AltBarPosition private int mNavigationBarAltPosition = ALT_BAR_UNKNOWN; + // Alternative climate bar for when flexible insets mapping is used to place a climate bar on + // the screen. + private WindowState mClimateBarAlt = null; + @WindowManagerPolicy.AltBarPosition + private int mClimateBarAltPosition = ALT_BAR_UNKNOWN; + // Alternative extra nav bar for when flexible insets mapping is used to place an extra nav bar + // on the screen. + private WindowState mExtraNavBarAlt = null; + @WindowManagerPolicy.AltBarPosition + private int mExtraNavBarAltPosition = ALT_BAR_UNKNOWN; /** See {@link #getNavigationBarFrameHeight} */ private int[] mNavigationBarFrameHeightForRotationDefault = new int[4]; @@ -670,6 +683,12 @@ public class DisplayPolicy { if (mNavigationBarAlt != null && mNavigationBarAltPosition == pos) { requestTransientBars(mNavigationBarAlt); } + if (mClimateBarAlt != null && mClimateBarAltPosition == pos) { + requestTransientBars(mClimateBarAlt); + } + if (mExtraNavBarAlt != null && mExtraNavBarAltPosition == pos) { + requestTransientBars(mExtraNavBarAlt); + } } void systemReady() { @@ -941,6 +960,12 @@ public class DisplayPolicy { if (mNavigationBarAlt == win) { mNavigationBarAltPosition = getAltBarPosition(attrs); } + if (mClimateBarAlt == win) { + mClimateBarAltPosition = getAltBarPosition(attrs); + } + if (mExtraNavBarAlt == win) { + mExtraNavBarAltPosition = getAltBarPosition(attrs); + } } /** @@ -1048,6 +1073,16 @@ public class DisplayPolicy { return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; } break; + case ITYPE_CLIMATE_BAR: + if (mClimateBarAlt != null && mClimateBarAlt.isAlive()) { + return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; + } + break; + case ITYPE_EXTRA_NAVIGATION_BAR: + if (mExtraNavBarAlt != null && mExtraNavBarAlt.isAlive()) { + return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; + } + break; } } } @@ -1153,6 +1188,14 @@ public class DisplayPolicy { mNavigationBarController.setWindow(mNavigationBarAlt); mNavigationBarAltPosition = getAltBarPosition(attrs); break; + case ITYPE_CLIMATE_BAR: + mClimateBarAlt = win; + mClimateBarAltPosition = getAltBarPosition(attrs); + break; + case ITYPE_EXTRA_NAVIGATION_BAR: + mExtraNavBarAlt = win; + mExtraNavBarAltPosition = getAltBarPosition(attrs); + break; } mDisplayContent.setInsetProvider(insetsType, win, null); } @@ -1201,6 +1244,8 @@ public class DisplayPolicy { switch (insetsType) { case ITYPE_NAVIGATION_BAR: case ITYPE_STATUS_BAR: + case ITYPE_CLIMATE_BAR: + case ITYPE_EXTRA_NAVIGATION_BAR: case ITYPE_CAPTION_BAR: if (++count > 1) { throw new IllegalArgumentException( @@ -1232,6 +1277,12 @@ public class DisplayPolicy { if (mDisplayContent.isDefaultDisplay) { mService.mPolicy.setKeyguardCandidateLw(null); } + } else if (mClimateBarAlt == win) { + mClimateBarAlt = null; + mDisplayContent.setInsetProvider(ITYPE_CLIMATE_BAR, null, null); + } else if (mExtraNavBarAlt == win) { + mExtraNavBarAlt = null; + mDisplayContent.setInsetProvider(ITYPE_EXTRA_NAVIGATION_BAR, null, null); } if (mLastFocusedWindow == win) { mLastFocusedWindow = null; @@ -1320,7 +1371,8 @@ public class DisplayPolicy { return R.anim.dock_left_enter; } } - } else if (win == mStatusBarAlt || win == mNavigationBarAlt) { + } else if (win == mStatusBarAlt || win == mNavigationBarAlt || win == mClimateBarAlt + || win == mExtraNavBarAlt) { if (win.getAttrs().windowAnimations != 0) { return ANIMATION_STYLEABLE; } @@ -3347,6 +3399,10 @@ public class DisplayPolicy { (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR) ? Type.navigationBars() : 0) | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR) + ? Type.statusBars() : 0) + | (requestedState.getSourceOrDefaultVisibility(ITYPE_EXTRA_NAVIGATION_BAR) + ? Type.navigationBars() : 0) + | (requestedState.getSourceOrDefaultVisibility(ITYPE_CLIMATE_BAR) ? Type.statusBars() : 0); if (swipeTarget == mNavigationBar @@ -4046,6 +4102,16 @@ public class DisplayPolicy { pw.print(prefix); pw.print("mNavigationBarAltPosition="); pw.println(mNavigationBarAltPosition); } + if (mClimateBarAlt != null) { + pw.print(prefix); pw.print("mClimateBarAlt="); pw.println(mClimateBarAlt); + pw.print(prefix); pw.print("mClimateBarAltPosition="); + pw.println(mClimateBarAltPosition); + } + if (mExtraNavBarAlt != null) { + pw.print(prefix); pw.print("mExtraNavBarAlt="); pw.println(mExtraNavBarAlt); + pw.print(prefix); pw.print("mExtraNavBarAltPosition="); + pw.println(mExtraNavBarAltPosition); + } if (mFocusedWindow != null) { pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow); } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 8e6a2656fce3..9fdfbd0a09da 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static android.view.InsetsState.ITYPE_CLIMATE_BAR; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; @@ -94,7 +96,8 @@ class InsetsSourceProvider { new Point()); final int type = source.getType(); - if (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR) { + if (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR || type == ITYPE_CLIMATE_BAR + || type == ITYPE_EXTRA_NAVIGATION_BAR) { mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL; } else if (type == ITYPE_IME) { mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME; diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index c2c04d9f70ac..68405c40ce37 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -19,6 +19,8 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.InsetsState.ITYPE_CAPTION_BAR; +import static android.view.InsetsState.ITYPE_CLIMATE_BAR; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_INVALID; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; @@ -43,6 +45,7 @@ import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.WindowManager; +import android.view.WindowManager.LayoutParams.WindowType; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.protolog.common.ProtoLog; @@ -112,7 +115,7 @@ class InsetsStateController { } InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) { - final @InternalInsetsType int type = getInsetsTypeForWindowType(attrs.type); + final @InternalInsetsType int type = getInsetsTypeForLayoutParams(attrs); final WindowToken token = mDisplayContent.getWindowToken(attrs.token); final @WindowingMode int windowingMode = token != null ? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED; @@ -132,7 +135,9 @@ class InsetsStateController { return false; } - private static @InternalInsetsType int getInsetsTypeForWindowType(int type) { + private static @InternalInsetsType + int getInsetsTypeForLayoutParams(WindowManager.LayoutParams attrs) { + @WindowType int type = attrs.type; switch (type) { case TYPE_STATUS_BAR: return ITYPE_STATUS_BAR; @@ -140,9 +145,22 @@ class InsetsStateController { return ITYPE_NAVIGATION_BAR; case TYPE_INPUT_METHOD: return ITYPE_IME; - default: - return ITYPE_INVALID; } + + // If not one of the types above, check whether an internal inset mapping is specified. + if (attrs.providesInsetsTypes != null) { + for (@InternalInsetsType int insetsType : attrs.providesInsetsTypes) { + switch (insetsType) { + case ITYPE_STATUS_BAR: + case ITYPE_NAVIGATION_BAR: + case ITYPE_CLIMATE_BAR: + case ITYPE_EXTRA_NAVIGATION_BAR: + return insetsType; + } + } + } + + return ITYPE_INVALID; } /** @see #getInsetsForDispatch */ @@ -155,14 +173,15 @@ class InsetsStateController { state.removeSource(type); // Navigation bar doesn't get influenced by anything else - if (type == ITYPE_NAVIGATION_BAR) { + if (type == ITYPE_NAVIGATION_BAR || type == ITYPE_EXTRA_NAVIGATION_BAR) { state.removeSource(ITYPE_IME); state.removeSource(ITYPE_STATUS_BAR); + state.removeSource(ITYPE_CLIMATE_BAR); state.removeSource(ITYPE_CAPTION_BAR); } // Status bar doesn't get influenced by caption bar - if (type == ITYPE_STATUS_BAR) { + if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) { state.removeSource(ITYPE_CAPTION_BAR); } @@ -332,8 +351,12 @@ class InsetsStateController { @Nullable InsetsControlTarget fakeNavControlling) { onControlChanged(ITYPE_STATUS_BAR, statusControlling); onControlChanged(ITYPE_NAVIGATION_BAR, navControlling); + onControlChanged(ITYPE_CLIMATE_BAR, statusControlling); + onControlChanged(ITYPE_EXTRA_NAVIGATION_BAR, navControlling); onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling); onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling); + onControlFakeTargetChanged(ITYPE_CLIMATE_BAR, fakeStatusControlling); + onControlFakeTargetChanged(ITYPE_EXTRA_NAVIGATION_BAR, fakeNavControlling); notifyPendingInsetsControlChanged(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 2d3b74b75826..cb9b49abfe2b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -20,6 +20,8 @@ import static android.view.Gravity.BOTTOM; import static android.view.Gravity.LEFT; import static android.view.Gravity.RIGHT; import static android.view.Gravity.TOP; +import static android.view.InsetsState.ITYPE_CLIMATE_BAR; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.ITYPE_TOP_GESTURES; @@ -198,10 +200,15 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void addingWindow_throwsException_WithMultipleInsetTypes() { - WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel"); - win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}; + WindowState win1 = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel"); + win1.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}; + + expectThrows(IllegalArgumentException.class, () -> addWindow(win1)); + + WindowState win2 = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel"); + win2.mAttrs.providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR}; - expectThrows(IllegalArgumentException.class, () -> addWindow(win)); + expectThrows(IllegalArgumentException.class, () -> addWindow(win2)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 0a27e1a1da68..73ac408f7980 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -20,6 +20,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.view.InsetsState.ITYPE_CLIMATE_BAR; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; @@ -292,12 +294,17 @@ public class InsetsStateControllerTest extends WindowTestsBase { public void testBarControllingWinChanged() { final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar"); final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); + final WindowState climateBar = createWindow(null, TYPE_APPLICATION, "climateBar"); + final WindowState extraNavBar = createWindow(null, TYPE_APPLICATION, "extraNavBar"); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null); + getController().getSourceProvider(ITYPE_CLIMATE_BAR).setWindow(climateBar, null, null); + getController().getSourceProvider(ITYPE_EXTRA_NAVIGATION_BAR).setWindow(extraNavBar, null, + null); getController().onBarControlTargetChanged(app, null, app, null); InsetsSourceControl[] controls = getController().getControlsForDispatch(app); - assertEquals(2, controls.length); + assertEquals(4, controls.length); } @Test -- cgit v1.2.3-59-g8ed1b